feat: web screenshot CDP fallback (#13) + non-fatal FlutterError capture (#14) + artisan 0.0.7#15
Conversation
0.0.7 hardens the start --cdp-port web flow (issue #25) that the upcoming dusk:screenshot CDP fallback relies on. Non-breaking: all consumed artisan surfaces (CommandBoot, ArtisanCommand, ArtisanContext.callExtension, McpToolDescriptor, registerExtensionIdempotent, StateFile) are signature-identical to 0.0.6.
DuskPlugin.install() now installs a FlutterError.onError chain (installErrorCapture) that records non-fatal presentations (incl. RenderFlex overflow) into a bounded ring buffer, preserving the prior handler. Backs dusk:exceptions surfacing layout errors without telescope (issue #14). install()/uninstall guarded independently of _installCount; prior handler re-captured per cycle for flutter_test safety.
…t on web When state.json has cdpPort and no ref/rect, dusk:screenshot now captures over Chrome DevTools Protocol (Page.enable + Page.captureScreenshot) instead of the in-isolate ext.dusk.screenshot, which hangs under CanvasKit/DWDS (issue #13). Native path unchanged.
ext.dusk.snap now emits an additive 'overflow: true' line on interactive nodes inside a currently-overflowing render ancestor, via a live RenderObject.toStringShort() check (no retained state). Surfaces RenderFlex overflow per-ref for the agent QA loop (issue #14).
ext.dusk.exceptions now returns the union of the in-package non-fatal capture buffer and the telescope-wired recentExceptionsReader, deduped by (type, message, stackHead) and clipped to limit. Non-fatal FlutterErrors (incl. overflow) surface even without telescope (issue #14).
…, artisan 0.0.7 CHANGELOG [Unreleased] Added (3 features) + Changed (artisan ^0.0.7 caret note); README and ARCHITECTURE updated for the web screenshot path and in-package error capture. Counts unchanged (32 CLI / 31 MCP / 28 ext.dusk.*).
…-fatal exceptions
…descriptions Descriptor description text only; names, extensionMethod values, and tool counts unchanged.
There was a problem hiding this comment.
Pull request overview
This PR addresses two QA gaps for Flutter web/diagnostics workflows in fluttersdk_dusk and bumps the fluttersdk_artisan dependency, with accompanying tests and documentation updates.
Changes:
- Add a Flutter web fallback for
dusk:screenshotthat uses Chrome DevTools Protocol (Page.captureScreenshot) when acdpPortis available and no region capture is requested. - Capture non-fatal
FlutterErrors (including RenderFlex overflow) and surface them viadusk:exceptions, plus annotate snapshot YAML with a liveoverflow: truehint. - Bump
fluttersdk_artisanto^0.0.7and update docs/tests to cover the new behavior.
Reviewed changes
Copilot reviewed 17 out of 20 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| test/src/extensions/ext_snapshot_dispatcher_test.dart | Adds widget tests asserting the new overflow: true snapshot annotation behavior. |
| test/src/extensions/ext_exceptions_test.dart | Adds tests for merging the in-package FlutterError buffer with the telescope exceptions reader. |
| test/src/dusk_error_capture_test.dart | Introduces tests for installing/uninstalling the FlutterError capture hook and buffer behavior (dedupe/cap). |
| test/src/commands/dusk_screenshot_command_test.dart | Adds tests for the new CDP screenshot path, error handling, and fallthrough behavior. |
| README.md | Updates the overview text to mention the new web screenshot and error capture behavior. |
| pubspec.yaml | Bumps fluttersdk_artisan dependency to ^0.0.7. |
| llms.txt | Updates the tool summary list to include overflow and screenshot routing notes. |
| lib/src/extensions/ext_snapshot.dart | Adds the live overflow ancestor check and emits overflow: true under affected interactive nodes. |
| lib/src/dusk_plugin.dart | Installs the FlutterError capture hook during DuskPlugin.install(). |
| lib/src/dusk_artisan_provider.dart | Updates MCP tool descriptions (snap/screenshot/exceptions) to reflect new behaviors. |
| lib/src/commands/dusk_screenshot_command.dart | Implements the CDP full-viewport screenshot fallback and keeps native/region capture on ext.dusk.screenshot. |
| lib/dusk.dart | Exposes recentCapturedExceptions from the public barrel. |
| example/pubspec.lock | Updates resolved dependency versions (notably artisan) for the example app. |
| doc/mcp/tool-reference.md | Updates MCP tool reference text for exceptions/screenshot/snap. |
| doc/commands/dusk-snap.md | Documents the new overflow: true snapshot annotation. |
| doc/commands/dusk-screenshot.md | Documents the CDP fallback behavior for the CLI dusk:screenshot command on web. |
| CHANGELOG.md | Adds unreleased entries describing the new screenshot fallback, error capture, overflow annotation, and artisan bump. |
| ARCHITECTURE.md | Updates architecture notes to include the error capture module and web screenshot behavior. |
Read cdpPort defensively (int/num/numeric-String -> int?, else null) so a corrupt or cross-version state file falls back to the native VM-extension path instead of throwing on a force-cast. Validate Page.captureScreenshot result['data'] is a String before decoding, returning a clear error on a malformed CDP response. Adds regression tests for both. Addresses Copilot review on PR #15.
The CDP Page.captureScreenshot fallback lives in the CLI dusk:screenshot command; the dusk_screenshot MCP tool dispatches ext.dusk.screenshot in-isolate and can still hang on web. Docs/descriptor/llms.txt/README updated to state this accurately and point web users to the CLI. Also fixes the documented defaults (jpeg/70, not png/80) and the return shape ({format, base64, width, height}, not {format, bytes}). Addresses Copilot review on PR #15.
|
Addressed all 9 Copilot review comments in 10fa56c (code) and b02999f (docs). Full suite green (726 tests, +2 regression), analyze + format clean. Code
Docs accuracy (the important one): MCP vs CLI dispatch
Defaults / return shape
Follow-up (not in this PR): making the MCP |
…shot dusk:screenshot captures the full app frame; cdpPort set -> CDP, else native ext.dusk.screenshot. The command never declared or forwarded --ref/--rect, so the defensive read was dead routing. Region capture stays deferred (plan D2). Removes the two obsolete ref/rect-fallthrough tests. Addresses Copilot review on PR #15.
…nces The command does not expose region capture, so the descriptor, tool-reference, command doc, ARCHITECTURE, and CHANGELOG no longer reference --ref/--rect on dusk:screenshot. Addresses Copilot review on PR #15.
|
Addressed the 2 new Copilot comments in b7b221a (code) and dc71411 (docs). Suite green (724 tests), analyze + format clean. Both comments flagged the same real inconsistency: Resolution: I made the command honest rather than adding a new capability. Region (
If you'd prefer to actually expose region capture instead (declare |
…nshot-exceptions # Conflicts: # example/pubspec.lock
Summary
Resolves two agent-QA gaps and bumps the artisan dependency.
dusk:screenshottimed out on Flutter web because the in-isolateOffsetLayer.toImage()never completes under CanvasKit+DWDS. When~/.artisan/state.jsoncarries acdpPortand no--ref/--rectis supplied, the command now captures the full viewport over CDP (Page.enable+Page.captureScreenshot,fromSurface: true) and writes the decoded bytes directly. Native targets and web+ref/rect keep usingext.dusk.screenshotunchanged.dusk:exceptionsmissed non-fatalFlutterErrors (RenderFlex overflow).DuskPlugin.install()now chains aFlutterError.onErrorhandler into a bounded in-package buffer (cap 50, dedup by message+stackHead), andext.dusk.exceptionsmerges that buffer with the telescope reader.dusk:snapadditionally annotates currently-overflowing nodes with a liveoverflow: truesub-line.fluttersdk_artisan^0.0.6->^0.0.7(non-breaking; 0.0.7 hardensstart --cdp-port, issue #25).Verification
dart format/dart analyze: clean across lib, test, bin.flutter test --exclude-tags=integration: 724 pass.dusk_screenshot/ext.dusk.screenshot,dusk_exceptions,DuskSnapshotEnricher,DuskPlugin.install()signature, command/MCP counts (32/31/28).Follow-ups (non-blocking, from code-review + oracle)
ext_snapshot.dartat the nearest distinct-SemanticsNoderender parent so a high-up overflow does not flag every descendant.cdpPort as intcast and add aresult['data']null-check in the CDP screenshot path.Closes #13
Closes #14