Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD across contents and paths, upstream package/repo coordinates -> @golem15/msd-core and golem15com/msd-core. Deep links into upstream history, sibling upstream packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is. Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line, package/plugin identity, regenerated lockfile, install-tree fixtures, derived registries and benchmark baseline; migration checksum baseline re-locked (MSD keeps its own install state, so no install had applied the old sums); sort-order and regex-escaped expectations in tests adjusted.
5.5 KiB
How to enable UI interaction capture
Let /msd-ui-review's auditor capture what a page looks like after an interaction — a hover
state, a focus ring, an open menu, a filled form's validation state — instead of only the first
paint, without configuring an MCP server or widening the agent's tool surface.
Default-off, and deliberately so. The static capture path is unchanged in every configuration; this key adds captures on top of it. You opt in per project with one key. The gap it closes is #4223: the auditor is chartered to audit interaction, and
npx playwright screenshothas no interaction verb.
What you need:
- An installed Chrome or Chromium. The driver launches the system browser (Puppeteer
channel: 'chrome'); it does not download one. Discovery triesgoogle-chrome,google-chrome-stable,chromium,chromium-browserandchromeonPATH, then the standard macOS and Windows install paths.CHROME_BIN=/path/to/chromeoverrides it. npxable to fetchchrome-devtools-mcp(the package that ships thechrome-devtoolsCLI). It is resolved at the documented floor^1.9.0(the release that added--workspace, which confines the driver's file writes to the capture directory);CHROME_DEVTOOLS_MCP_VERSIONoverrides it.- Nothing else. Every driver call runs under a ceiling —
CHROME_DEVTOOLS_START_TIMEOUT(default 180 s, for the npx fetch plus the Chrome launch) andCHROME_DEVTOOLS_STEP_TIMEOUT(default 60 s, per capture verb). At the ceiling the client's whole process group is killed (TERM, then KILL two seconds later) and the step is counted as failed, so a cold npm cache or a Chrome that never comes up costs a failed step rather than an open-ended wait. The one exception is a watchdog whose own clock (sleep) cannot launch: it stands down instead of killing a healthy call, and that call is then unbounded, as every call was before the ceilings existed. - A dev server the static capture already reaches — interaction capture runs against the same URL and skips itself when the static block reached nothing.
Step 1 — Turn the key on
msd-tools query config-set workflow.ui_interaction_capture true
Verify it took:
msd-tools query config-get workflow.ui_interaction_capture
# → true
/msd-ui-review reads the key and passes interaction_capture: true in the auditor's
<config> block — the auditor itself never reads config.
Step 2 — Run a review and read the report
/msd-ui-review 3
The audit's static captures land where they always did. With the key on and a Chrome
resolved, an interaction/ directory beside them holds baseline.png, focus-first.png
(focus ring on the first focusable element), one capture per interaction the auditor drove
from your UI-SPEC's interactive components, the accessibility snapshot it used for element
ids, and the page's console output. The audit's .gitignore gate covers that interaction/
directory as a whole — the snapshot carries whatever was typed into forms and the console output
can carry tokens — so a git add . never commits it, and a project whose .gitignore predates
the directory is upgraded on the next audit. UI-REVIEW.md carries the outcome on its own line:
**Interaction captures:** captured (4 state(s), 0 failed) in .planning/ui-reviews/03-.../interaction
The other values it can hold are honest, not decorative:
**Interaction captures:** |
Meaning |
|---|---|
off |
The key is false. Nothing else changed. |
skipped (no dev server reached) |
The static capture found no dev server; there was nothing to interact with. |
skipped (no Chrome binary resolved) |
The key is on but no browser resolved. Set CHROME_BIN. |
not captured (driver or capture failure) |
The key was on and Chrome resolved, but no state landed on disk — npx could not fetch the driver, Chrome did not launch, the page never opened, or every capture failed. The audit output names the failing step. |
An interaction state that does not appear in that directory is not reported as observed; the Experience Design pillar says when its findings are code-derived.
What this does not do
- It does not replace the static captures.
npx playwright screenshotstays the driver for the three viewport shots; it has--wait-for-selector,--device,--color-schemeand cross-engine-b firefox|webkit, none of which the CLI driver offers. Firefox and WebKit needs stay on Playwright. - It does not touch
msd-dom-verifierorworkflow.live_dom_uat. That capability drives a browser MCP server at execute time; this one drives a CLI from Bash at review time. They are independent keys. - It does not share the
chrome-devtools-mcpbrowser profile. The auditor starts the daemon with--isolated, so it never contends for the profile lock a registered MCP server holds, and stops it when the capture ends — under anEXITtrap, so an aborted audit still stops it. - It does not let the driver write outside the capture directory. The daemon starts with
--workspaceset to the run'sinteraction/directory; that is the only place its file-writing verbs may land. - It does not wait on selectors.
wait_foris MCP-only; the auditor pollsdocument.readyStatethroughevaluate_scriptwhere a state needs settling.
Turning it back off
msd-tools query config-set workflow.ui_interaction_capture false
The next review runs the Playwright-only path and reports **Interaction captures:** off.