Write Flow Guide
A product walk is a human driving the real app through every user-facing
ability and judging what they see. The deliverable is a run file, a
rendered human guide, and a vet-flow-guide report — grounded in the
app's own rendering, one row per ability case, each tagged with the requirement
ID and a case kind. Cases and verdicts live in the same file, so what the
agent proves is what the person reads. Build the artifacts; a chat message is
not the deliverable. A guide of only happy paths is not done. Authoring is not
complete until the vet report exists.
Case taxonomy (every guide uses these kinds)
kind |
Meaning |
Typical source |
happy |
Feature does what it is for |
Primary story in requirements |
edge |
Boundary / empty / duplicate / max length / whitespace |
Edge criteria in the same ID or sibling criteria |
error |
User-visible failure path (validation chip, 4xx message, retained input) |
Error criteria in requirements |
nonbehavior |
What must not happen |
Out-of-Scope; negative SHALLs |
persist |
Survives reload / re-open / restart of the client |
Criteria that say "persists" or store-owned state |
visual |
Layout, color, empty-state copy, feel — human eyeball |
Presentational requirements; no server write |
journey |
Multi-step workflow stitching atomic cases (optional, ≤2 per guide) |
Cross-story user path |
Do not invent chaos, load, race, or security-fuzz suites here — those are not
a one-seat user pass. Permission/role cases belong when the UI exposes them
(edge or error + setup for the role).
Todos — GATE
Before §1, put one item per section (1–4) on a visible list — the harness's
todo / task-list tool when it exposes one, otherwise a checklist written into your
reply and restated at each section boundary — and one terminal
todo Vet flow guide (vet-flow-guide on the run file — created now, not
later). Check the vet todo off only when
.skills/<CODE>/vet-flow-guide.md exists for this run file.
Done when: the list exists before scoping and includes the vet todo.
1. Scope every ability — coverage gate
Read the feature's requirements.md, design.md, tasks.md. List every
user-observable ability. Include adjacent capabilities in the same user
workflow, not only the new feature.
Coverage rules (all must hold before §4 is done):
- Every user-facing requirement ID has ≥1 case.
- Every ability area (section of the guide) has ≥1
happy and ≥1
non-happy among edge | error | nonbehavior | persist.
- Every Out-of-Scope / deliberate non-behavior that a user could try has a
nonbehavior case (or an explicit note in the hand-off: no user-facing way
to attempt this — skipped).
- Every criterion that claims persistence has a
persist case (or a
happy/edge whose Expect + backend prove reload/store — prefer a
dedicated persist row so it cannot be skipped).
- If the area has no edge, error, nonbehavior, or persist material in the
spec, write one line under that section: Coverage exception: no edge/error/
nonbehavior/persist cited in spec — do not invent product behavior. The
exception is greppable honesty, not a free pass when the triad has edges.
One happy case per ID is not enough when the ID or its siblings name edges.
Done when: the coverage rules above hold, or every exception is written on the
guide.
2. Ground each case in the real code
For each case, read the code to get what the user will ACTUALLY see: the exact
vocabulary (keywords, command names, labels), keyboard shortcuts, and the real
rendering — badge colors, chip styles, icons — pulled from the source (theme
tokens, CSS), never guessed. Where the code reveals an honest caveat
(a delimiter dimmed not removed, a status with no UI yet), the case says so.
3. Boot the real app and find the honest observation point
Start the app with the Run locally (dev) command from docs/agents/project.md
(discover and record it if missing — see validate-ui). Surface any degraded
area up front: a feature needing a key, a sub-feature not built yet. A behavior
with no UI surface still gets a case — with a real way to observe it (a devtools
invoke(...), a read-only DB peek), never a pretend screen. Done when: the app
is running and every not-yet-visible behavior has an observation method.
4. Write cases + render the shell (do not invent CSS)
Authoring SSOT is the run file, not hand-rolled HTML.
Write .skills/<CODE>/flow-guide.json (schema: load sibling
references/cases-schema.md when unsure). Every case carries all required
slots: id, req, kind, title, setup, try, expect, backend
(backend is the server-side assertion, or the literal presentational).
Run state (run, human) is filled in for you — author the eight slots.
Render the human guide from the checked-in shell — do not load
craft-page or invent a palette/layout unless the user explicitly asks for
custom craft:
python3 <skill-root>/scripts/flow-guide render .skills/<CODE>/flow-guide.json \
-o .skills/<CODE>/flow-guide.html
Resolve <skill-root> to this skill's install path (in this monorepo:
skills/acceptance/write-flow-guide). The shell is shell/guide.html — theme-aware
CSS/JS, kind chips, verdict badges, and data-* attributes. The rendered page
carries the verdicts as of render time and says so, so it is correct on a
double-click with nothing running.
Coverage self-check: count cases by kind per section. If any ability
area lacks a non-happy kind and has no Coverage exception line, add the
missing cases before hand-off.
Optional: at most two journey rows; they do not replace atomic coverage.
Never ship a chat-only checklist. Never regenerate a full custom HTML
page as the default path — cases + render is the path.
Done when: the run file and rendered HTML are on disk at known paths, coverage
holds, every case has all required slots.
5. Hand over
Order: artifacts → run vet → optional serve → dogfood only after clean vet.
Artifacts — give both paths (run file + HTML), the fastest way in — a
~30-second first pass that lights the feature up (usually the first happy
row) — then degraded-feature notes and coverage exceptions.
Vet IMMEDIATELY. After the run file and rendered HTML are on disk and §4
coverage holds, IMMEDIATELY REQUIRED SUB-SKILL: use vet-flow-guide on
the run file — before serve, dogfood, or any “authoring done” claim. Mark the
Vet flow guide todo done only when .skills/<CODE>/vet-flow-guide.md
exists. §1 / §4 coverage self-check is authoring hygiene, not a substitute
for this report.
Optional serve — offer the live guide when they will be testing by hand
alongside the agent:
python3 <skill-root>/scripts/flow-guide serve .skills/<CODE>/flow-guide.json
It binds 127.0.0.1:8787, follows verdicts as the agent records them, and
writes their ticks back where the agent can see them. Tell them plainly what
a tick means: it records that they looked, and never becomes a pass.
Stopping it is serve --stop. Opened as a plain file instead, the guide still
shows the verdicts it was rendered with — the server only buys freshness.
Agent dogfood — run it. After a clean vet-flow-guide report (or a
named override on open findings), REQUIRED SUB-SKILL: use run-flow-guide
on this run file. Before the report exists, do not name it at all.
The hand-off is a route, not a gate: a control measured on 2026-09-09
drove the app unprompted rather than stopping at the artifact it had just
written, so nothing here needs to argue it into verifying. What it does need
is the address — verification done ad hoc produces no run file, no per-case
verdicts, and no server probes, so downstream has nothing to read.
Ends here instead when the user asked for a hand walk: step 3's serve is the
deliverable and their ticks are the record.
Done when: artifacts are on disk, grounded, the §1 coverage gate holds, every
case is fully slotted, .skills/<CODE>/vet-flow-guide.md exists for this run
file, and the guide has been handed to run-flow-guide — or a hand walk is
recorded as the user's explicit choice.
Rationalizations
| Thought |
Reality |
| "A markdown checklist in chat is enough" |
It saves no tick, cannot show the real badge being checked against, and scrolls away. The deliverable is the run file + rendered guide. |
| "I'll craft-page a unique layout for this feature" |
Default is the checked-in shell. Custom craft only when the user asks. |
| "They're in a native desktop app, not a browser, so an artifact doesn't fit" |
The artifact is a companion reference kept open beside the app; the app being native is no reason to inline the guide into chat. |
| "I'll describe the badge in words" |
The user checks against what they SEE. Mirror the real rendering, or the Expect is unverifiable. |
| "One happy case per requirement is enough" |
The coverage gate requires non-happy kinds (or a written exception). Happy-only is a demo, not write-flow-guide. |
| "Edges belong in unit tests, not the guide" |
Write Flow Guide is the user-facing surface. If the user can hit the edge, it gets a row. |
| "Worse cases mean load/chaos/fuzz" |
Those are other harnesses. Write Flow Guide worse cases are edge, error, nonbehavior, persist. |
| "§4 coverage self-check already ran — skip vet" |
Self-check is same-session authoring hygiene, not an isolated implementation-surface judgment. It is not a substitute for vet. |
| "I'll name vet as next and stop — the controller will run it" |
Step 2 runs vet-flow-guide; naming is not completion |
| "Artifacts are on disk — authoring is done" |
Done when the vet report exists, not when the JSON/HTML land |
Red Flags
- Hand-writing a full HTML/CSS page instead of the run file +
flow-guide render
- Missing
backend / setup / kind on any case
- Happy-only section without a greppable coverage exception
- Telling the agent to mark progress via guide ticks instead of
write-flow-guide mark
- Treating §4 coverage self-check as a substitute for
vet-flow-guide
- Declaring this skill done without
.skills/<CODE>/vet-flow-guide.md for this run file
- Naming
run-flow-guide (or offering dogfood) before a vet report exists
- Verifying the feature ad hoc instead of through
run-flow-guide, leaving no run file
- Checking off the Vet flow guide todo when the report path does not exist
1---2name: write-flow-guide3description: Use when a finished feature needs a hands-on product walk in the real running app — visuals, feel, and eyeball edge cases. Produces a checkable flow guide (run file + HTML) plus its vet report. Not for executing an already-written guide (`run-flow-guide`).4---56# Write Flow Guide78A product walk is a human driving the real app through every user-facing9ability and judging what they see. The deliverable is a **run file**, a10**rendered human guide**, and a **`vet-flow-guide` report** — grounded in the11app's own rendering, one row per ability case, each tagged with the requirement12ID and a **case kind**. Cases and verdicts live in the same file, so what the13agent proves is what the person reads. Build the artifacts; a chat message is14not the deliverable. A guide of only happy paths is not done. Authoring is not15complete until the vet report exists.1617## Case taxonomy (every guide uses these kinds)1819| `kind` | Meaning | Typical source |20|---|---|---|21| `happy` | Feature does what it is for | Primary story in requirements |22| `edge` | Boundary / empty / duplicate / max length / whitespace | Edge criteria in the same ID or sibling criteria |23| `error` | User-visible failure path (validation chip, 4xx message, retained input) | Error criteria in requirements |24| `nonbehavior` | What must **not** happen | Out-of-Scope; negative SHALLs |25| `persist` | Survives reload / re-open / restart of the client | Criteria that say "persists" or store-owned state |26| `visual` | Layout, color, empty-state copy, feel — human eyeball | Presentational requirements; no server write |27| `journey` | Multi-step workflow stitching atomic cases (optional, ≤2 per guide) | Cross-story user path |2829Do **not** invent chaos, load, race, or security-fuzz suites here — those are not30a one-seat user pass. Permission/role cases belong when the UI exposes them31(`edge` or `error` + `setup` for the role).3233## Todos — GATE3435Before §1, put one item per section (1–4) on a **visible list** — the harness's36todo / task-list tool when it exposes one, otherwise a checklist written into your37reply and restated at each section boundary — **and** one terminal38todo **Vet flow guide** (`vet-flow-guide` on the run file — created now, not39later). Check the vet todo off **only** when40`.skills/<CODE>/vet-flow-guide.md` exists for this run file.41*Done when: the list exists before scoping and includes the vet todo.*4243## 1. Scope every ability — coverage gate4445Read the feature's `requirements.md`, `design.md`, `tasks.md`. List every46user-observable ability. Include adjacent capabilities in the same user47workflow, not only the new feature.4849**Coverage rules** (all must hold before §4 is done):50511. **Every user-facing requirement ID** has ≥1 case.522. **Every ability area** (section of the guide) has ≥1 `happy` **and** ≥153 non-happy among `edge` | `error` | `nonbehavior` | `persist`.543. **Every Out-of-Scope / deliberate non-behavior** that a user could try has a55 `nonbehavior` case (or an explicit note in the hand-off: *no user-facing way56 to attempt this — skipped*).574. **Every criterion that claims persistence** has a `persist` case (or a58 `happy`/`edge` whose Expect + `backend` prove reload/store — prefer a59 dedicated `persist` row so it cannot be skipped).605. If the area has **no** edge, error, nonbehavior, or persist material in the61 spec, write one line under that section: *Coverage exception: no edge/error/62 nonbehavior/persist cited in spec* — do not invent product behavior. The63 exception is greppable honesty, not a free pass when the triad has edges.6465One happy case per ID is **not** enough when the ID or its siblings name edges.6667*Done when: the coverage rules above hold, or every exception is written on the68guide.*6970## 2. Ground each case in the real code7172For each case, read the code to get what the user will ACTUALLY see: the exact73vocabulary (keywords, command names, labels), keyboard shortcuts, and the real74rendering — badge colors, chip styles, icons — pulled from the source (theme75tokens, CSS), never guessed. Where the code reveals an honest caveat76(a delimiter dimmed not removed, a status with no UI yet), the case says so.7778## 3. Boot the real app and find the honest observation point7980Start the app with the `Run locally (dev)` command from `docs/agents/project.md`81(discover and record it if missing — see `validate-ui`). Surface any degraded82area up front: a feature needing a key, a sub-feature not built yet. A behavior83with no UI surface still gets a case — with a real way to observe it (a devtools84`invoke(...)`, a read-only DB peek), never a pretend screen. *Done when: the app85is running and every not-yet-visible behavior has an observation method.*8687## 4. Write cases + render the shell (do not invent CSS)8889**Authoring SSOT is the run file**, not hand-rolled HTML.90911. Write `.skills/<CODE>/flow-guide.json` (schema: load sibling92 `references/cases-schema.md` when unsure). Every case carries all required93 slots: `id`, `req`, `kind`, `title`, `setup`, `try`, `expect`, `backend`94 (`backend` is the server-side assertion, or the literal `presentational`).95 Run state (`run`, `human`) is filled in for you — author the eight slots.962. Render the human guide from the checked-in shell — **do not** load97 `craft-page` or invent a palette/layout unless the user explicitly asks for98 custom craft:99100 ```bash101 python3 <skill-root>/scripts/flow-guide render .skills/<CODE>/flow-guide.json \102 -o .skills/<CODE>/flow-guide.html103 ```104105 Resolve `<skill-root>` to this skill's install path (in this monorepo:106 `skills/acceptance/write-flow-guide`). The shell is `shell/guide.html` — theme-aware107 CSS/JS, kind chips, verdict badges, and `data-*` attributes. The rendered page108 carries the verdicts as of render time and says so, so it is correct on a109 double-click with nothing running.1103. **Coverage self-check:** count cases by `kind` per section. If any ability111 area lacks a non-happy kind and has no *Coverage exception* line, add the112 missing cases before hand-off.113114Optional: at most two `journey` rows; they do not replace atomic coverage.115116**Never** ship a chat-only checklist. **Never** regenerate a full custom HTML117page as the default path — cases + `render` is the path.118119*Done when: the run file and rendered HTML are on disk at known paths, coverage120holds, every case has all required slots.*121122## 5. Hand over123124Order: artifacts → **run** vet → optional serve → dogfood only after clean vet.1251261. **Artifacts** — give both paths (run file + HTML), the fastest way in — a127 ~30-second first pass that lights the feature up (usually the first `happy`128 row) — then degraded-feature notes and coverage exceptions.1291302. **Vet IMMEDIATELY.** After the run file and rendered HTML are on disk and §4131 coverage holds, **IMMEDIATELY** REQUIRED SUB-SKILL: use `vet-flow-guide` on132 the run file — before serve, dogfood, or any “authoring done” claim. Mark the133 **Vet flow guide** todo done only when `.skills/<CODE>/vet-flow-guide.md`134 exists. §1 / §4 coverage self-check is authoring hygiene, not a substitute135 for this report.1361373. **Optional serve** — offer the live guide when they will be testing by hand138 alongside the agent:139140 ```bash141 python3 <skill-root>/scripts/flow-guide serve .skills/<CODE>/flow-guide.json142 ```143144 It binds `127.0.0.1:8787`, follows verdicts as the agent records them, and145 writes their ticks back where the agent can see them. Tell them plainly what146 a tick means: it records that they looked, and never becomes a `pass`.147 Stopping it is `serve --stop`. Opened as a plain file instead, the guide still148 shows the verdicts it was rendered with — the server only buys freshness.1491504. **Agent dogfood — run it.** After a clean `vet-flow-guide` report (or a151 named override on open findings), REQUIRED SUB-SKILL: use `run-flow-guide`152 on this run file. Before the report exists, do not name it at all.153154 The hand-off is a **route, not a gate**: a control measured on 2026-09-09155 drove the app unprompted rather than stopping at the artifact it had just156 written, so nothing here needs to argue it into verifying. What it does need157 is the address — verification done ad hoc produces no run file, no per-case158 verdicts, and no server probes, so downstream has nothing to read.159160 Ends here instead when the user asked for a hand walk: step 3's serve is the161 deliverable and their ticks are the record.162163*Done when: artifacts are on disk, grounded, the §1 coverage gate holds, every164case is fully slotted, `.skills/<CODE>/vet-flow-guide.md` exists for this run165file, and the guide has been handed to `run-flow-guide` — or a hand walk is166recorded as the user's explicit choice.*167168## Rationalizations169170| Thought | Reality |171|---|---|172| "A markdown checklist in chat is enough" | It saves no tick, cannot show the real badge being checked against, and scrolls away. The deliverable is the run file + rendered guide. |173| "I'll craft-page a unique layout for this feature" | Default is the checked-in shell. Custom craft only when the user asks. |174| "They're in a native desktop app, not a browser, so an artifact doesn't fit" | The artifact is a companion reference kept open beside the app; the app being native is no reason to inline the guide into chat. |175| "I'll describe the badge in words" | The user checks against what they SEE. Mirror the real rendering, or the Expect is unverifiable. |176| "One happy case per requirement is enough" | The coverage gate requires non-happy kinds (or a written exception). Happy-only is a demo, not write-flow-guide. |177| "Edges belong in unit tests, not the guide" | Write Flow Guide is the user-facing surface. If the user can hit the edge, it gets a row. |178| "Worse cases mean load/chaos/fuzz" | Those are other harnesses. Write Flow Guide worse cases are edge, error, nonbehavior, persist. |179| "§4 coverage self-check already ran — skip vet" | Self-check is same-session authoring hygiene, not an isolated implementation-surface judgment. It is **not a substitute for vet**. |180| "I'll name vet as next and stop — the controller will run it" | Step 2 **runs** `vet-flow-guide`; naming is not completion |181| "Artifacts are on disk — authoring is done" | Done when the vet report exists, not when the JSON/HTML land |182183## Red Flags184185- Hand-writing a full HTML/CSS page instead of the run file + `flow-guide render`186- Missing `backend` / `setup` / `kind` on any case187- Happy-only section without a greppable coverage exception188- Telling the agent to mark progress via guide ticks instead of `write-flow-guide mark`189- Treating §4 coverage self-check as a substitute for `vet-flow-guide`190- Declaring this skill done without `.skills/<CODE>/vet-flow-guide.md` for this run file191- Naming `run-flow-guide` (or offering dogfood) before a vet report exists192- Verifying the feature ad hoc instead of through `run-flow-guide`, leaving no run file193- Checking off the **Vet flow guide** todo when the report path does not exist