Files
msd-core/docs/how-to/enable-ui-interaction-capture.md
Jakub Zych a9a7a328e6 refactor: hard-fork GSD -> MSD (Make Software Done)
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.
2026-10-06 01:47:40 +02:00

112 lines
5.5 KiB
Markdown

# 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](https://github.com/open-gsd/gsd-core/issues/4223): the auditor
> is chartered to audit interaction, and `npx playwright screenshot` has 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 tries `google-chrome`,
`google-chrome-stable`, `chromium`, `chromium-browser` and `chrome` on `PATH`, then the
standard macOS and Windows install paths. `CHROME_BIN=/path/to/chrome` overrides it.
- `npx` able to fetch `chrome-devtools-mcp` (the package that ships the `chrome-devtools` CLI).
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_VERSION`
overrides 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) and `CHROME_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
```bash
msd-tools query config-set workflow.ui_interaction_capture true
```
Verify it took:
```bash
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
```bash
/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 screenshot` stays the driver for
the three viewport shots; it has `--wait-for-selector`, `--device`, `--color-scheme` and
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-verifier` or `workflow.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-mcp` browser 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 an `EXIT` trap, so an aborted audit still stops it.
- **It does not let the driver write outside the capture directory.** The daemon starts with
`--workspace` set to the run's `interaction/` directory; that is the only place its file-writing
verbs may land.
- **It does not wait on selectors.** `wait_for` is MCP-only; the auditor polls
`document.readyState` through `evaluate_script` where a state needs settling.
---
## Turning it back off
```bash
msd-tools query config-set workflow.ui_interaction_capture false
```
The next review runs the Playwright-only path and reports `**Interaction captures:** off`.