@sylad/cadence 0.28.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@
8
8
  {
9
9
  "name": "cadence",
10
10
  "description": "Session start and close rituals driven by a versioned plan (raf), and deliveries proven by their effect. Needs the cadence CLI (npm i -g @sylad/cadence).",
11
- "version": "0.28.0",
11
+ "version": "1.1.0",
12
12
  "source": "./",
13
13
  "author": {
14
14
  "name": "Sylvain Ladoire"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cadence",
3
3
  "description": "A repo-native working method: session start and close rituals driven by a versioned plan (raf), deliveries proven by their effect, and three reviewer agents (UX, code, QA).",
4
- "version": "0.28.0",
4
+ "version": "1.1.0",
5
5
  "author": { "name": "Sylvain Ladoire" },
6
6
  "homepage": "https://github.com/Sylad/cadence",
7
7
  "repository": "https://github.com/Sylad/cadence",
package/README.md CHANGED
@@ -22,9 +22,25 @@ reports a page left empty or in error.
22
22
  And a second plugin, [`cadence-hud`](#cadence-hud): a status band above the Claude
23
23
  Code prompt that shows the session's context, quota, cost and the orchestrate waves running.
24
24
 
25
+ ### Spec step (design, first steps delivered)
26
+
27
+ For a visible lot that adds a page, a component or changes a journey, `orchestrate` gets a step
28
+ before the code: a static HTML mockup in the project's own style (1440 and 390 px; empty, loading and
29
+ error states) and a machine-readable screen sheet (fields, numbered rules `R1…` each marked *sourced*
30
+ or *hypothesis*, actions → API calls). The `ux-reviewer` agent reads the mockup before any code; the
31
+ acceptance tests are written from the sheet, red, by a session other than the implementer's; the
32
+ implementation gets the sheet, the code review checks rule → test → green, the hypotheses go into the
33
+ lot's news entry, and a human is asked only about a choice that is costly to undo. The design is in
34
+ `docs/superpowers/specs/2026-10-10-etape-spec-design.md` (with an example sheet and the plan of the
35
+ lots that deliver it). Delivered so far: the sheet template `templates/fiche.yaml`, `cadence spec check`
36
+ (the sheet's invariants) and `cadence spec qa` (the screen's `docs/qa/expectations.md` section, derived
37
+ from the sheet), see [spec](#spec) below, and the `spec` step of `orchestrate` itself (the `spec-writer` agent, the
38
+ render at 1440 and 390 px, the commit of the spec), see [The spec step](#the-spec-step-of-a-lot-with-screen) in `orchestrate`; the `accept` step (red acceptance tests and the lock that protects them), see [The accept step](#the-accept-step-red-acceptance-tests-and-their-lock); the UX review of
39
+ the mockup (the `ux-reviewer` agent in mockup mode), see [The mockup review](#the-mockup-review-before-any-code); and the downstream briefs (the sheet given to `implement`, rule → test → green in the code review, a light UX conformity pass, the `## Hypothèses` section of the news entry), see [The downstream briefs](#the-downstream-briefs-sheet-rule--test--green-conformity-hypothèses).
40
+
25
41
  ## What's new
26
42
 
27
- **0.28.0**: `orchestrate.precheck: local` runs the « deliverable already present? » pre-check of `cadence orchestrate` on the local model (`claude-local`, Ollama), off the Anthropic quota, Sonnet staying the default and the fallback (L146); the `qa-reviewer` agent walks only the pages a lot touched, with a **Scope** line in its report (L123); the sub-tasks a review closes are also read in a lot's neighbouring repositories (L156) and a commit's sub-task list is read with the plan's left guard (L155); an unstable test is fixed (L90). **0.27.1**: `cadence orchestrate` no longer leaves a session's child processes alive: a dev server started in its own process group, or orphaned by a shell that exits (`nohup srv &`), is killed with the session through its process tree and its `CADENCE_SESSION` mark, a tmux server, `screen`, `gpg-agent` or `dirmngr` started on demand being spared; a session that exits with code 0 while a descendant holds its output open is no longer reported as « délai dépassé » (L83); the `ux-reviewer` and `qa-reviewer` agents carry the briefs' Playwright rule outside `cadence orchestrate` (L84). **0.27.0**: a compliant review of `cadence orchestrate` settles the open sub-tasks that commits of the lot cite (`feat(L3/t2): …`, comma lists included), closed in the same plan commit as the verdict or, on a read-only plan, returned as `[sous-tâche clore]` proposals, so `raf done` no longer refuses a lot over sub-tasks whose work is done; on a foreign-format plan the ids are read as the plan reads them (L82); the test suite stays green with two full suites running in parallel (L150). **0.26.0**: `cadence orchestrate` raises the floor of a lot's budget from 200 k to 450 k tokens, enough to pay a write pass, its review, one fix pass and the short review that follows, so a lot of 0.5 or 1 day is no longer handed back at its second or third pass; a `--continue` wave draws fewer lots as a result (L128). **0.25.0**: the project line of the plans' progress in the `cadence-hud` band names the lots in progress after their count, three at most then `…` (L153, `cadence-hud` 0.4.2); the progress follows the folder the session was launched from, so a `cd` into a sub-project no longer shrinks the band, and the session context keeps the `session.start` folder (L154). **0.24.0**: `cadence orchestrate --drop <project:lot>` and `--stop-after-current` steer a live wave from another terminal, `--resume --drop` removes a lot before replaying a stopped wave (L79); the final table of a wave says « livrable jusqu'à <sha> » for a ready lot stacked under a lot handed back, with `git push origin <sha>:main && cadence deliver --sha <sha>` (L76); a version commit (version fields, `CHANGELOG.md`, the README's « What's new ») no longer asks for a new code review (L72). **0.23.0**: the progress bar of each project in the `cadence-hud` band is coloured by the share of lots done, red below 33 %, orange below 66 %, green beyond (L152, `cadence-hud` 0.4.1); `cadence deliver` under a wave lock refuses only when a lot of the wave still works in that very repository, a linked worktree included (L127). **0.22.0**: `cadence orchestrate --continue` draws the next ready lot of the plan itself, in the declared priority, until the budget, the time window or a question stops it (L147); `cadence session context` prints the context of the session, which the `cadence-hud` band publishes, and the `lead` skill chains lots without the human while it stays under 60 % (L148); the band shows the progress of each project's plan, and `cadence lead tour --json` gains `progress` (L149, `cadence-hud` 0.4.0); the final review of a lot is always played, the lot's own budget bounding the writing passes only, with 65 k tokens reserved for it (L145); the cause « tests rouges après … » names the pass whose tests were red (L151). **0.21.0**: `cadence orchestrate --status` and `cadence lead tour` print the free session slots, which the `lead` skill reads (L141); `orchestrate.effort` sets the effort level of each pass of a wave (L137); `docs.sync` makes `raf check`, `lead tour` and the review brief report a document that does not follow the code (L143); `docs.articles` opens, after a green `cadence deliver`, a lot `Article <project> à rafraîchir` in the neighbouring repository (L144). **0.20.0**: `cadence-hud` no longer misleads once the work is over: `/hud cmd` lists the background commands it counts (id, tool, origin, age, name), any other argument answers `argument inconnu` instead of hiding the band, commands with no end seen for an hour or no record go to a grey `N cmd sans fin vue`, a finished subagent takes its commands with it, two races that left a `1 cmd` counted forever are closed, and a finished wave shows grey without its budget then disappears after 30 minutes (L142); the `qa-reviewer` and `ux-reviewer` agents are read-only for real, their frontmatter listing Read, Grep, Glob, Bash and the Playwright tools (L140). **0.19.1**: `cadence-hud`'s `N cmd` counter goes back down when a Monitor expires, when the background commands a subagent started end with it, and at session start or plugin reload (L135); its `tool.call` and `prompt.submit` guard hooks carry a `.catch` on registration, which clears the `claude plugin validate` warning (L136). **0.19.0**: `cadence orchestrate` lifts a repository's lock and `pre-push` guard as soon as every lot of the wave that touches it is finished, so `cadence deliver` works there while the wave continues elsewhere (L132); a review that leaves a repository dirty hands back that lot only, suspends the lots still queued in that repository and keeps the other repositories running, its verdict reported instead of lost (L133); `cadence session close` re-run without a `session start` keeps the window since the last opening (L131); `cadence-hud` draws the lot rows of a wave in aligned columns on every surface (L134). **0.18.0**: `cadence session next` prints what it records (issue #6); `cadence session close` covers the period since the last `session start` (or the last close) and says so in its title, `--since` still wins (issue #7). **0.17.0**: `cadence-hud` shows an `N cmd` segment next to the agents, the background commands of the session (Bash run in the background and Monitor, subagents' included), tracked from the tool results and ended by the task's notification or `TaskStop`. **0.16.0**: a lot can declare **neighbouring repositories** (`repos:` key of the lot, `{ path, cite }` for a repository shared between projects): `cadence orchestrate` refuses, locks and guards them, gives them to every session as `--add-dir`, and `raf commits`, `raf show` and the review verdict read the commits that cite the lot there too. **0.15.0**: `hook.autostart` in `cadence.yaml` (`warn` by default, `refuse` or `start`): a pre-commit hook that refuses, or starts in the same commit, a lot still todo that the commit cites; `cadence session start|close --all [--depth n]`, one section per project under a folder. **0.14.0**: `cadence lead tour`, the lead's morning table of every project in a folder, printed by a program (one line per project: lots in progress, gaps, last notes, next ready lot, repository) in place of one subagent per project; the `lead` skill calls it. **0.13.1**: `cadence-hud` takes back the segments that fit once a big one has dropped (reset times, then the per-model consumption, now short: `opus 1.2M sonnet 800k`); `CADENCE_HUD_AMBIGUOUS=1` for a terminal that draws `▰ ▱ ⚙ │ ↻` in one cell. **0.13.0**: `cadence orchestrate --status --watch` (a wave's table redrawn in the terminal, which
43
+ **1.1.0**: the spec step of `cadence orchestrate`: a lot that declares `screen:` gets a machine-readable screen sheet (`cadence spec check|qa`), a mockup reviewed against it, acceptance tests committed red and locked before the implementation, and briefs that carry the sheet and rule → test → green to `implement`, `fix` and the code review; the news entry gains a *Hypothèses* section (L166, L169–L174, L177–L184). **1.0.0**: the first major release, a stable contract: the commands and options, the keys of `cadence.yaml`, the plan file and the names of the skills and agents follow semantic versioning, and the README's *Stability* section lists what is guaranteed and what is not (L164). **0.28.0**: `orchestrate.precheck: local` runs the « deliverable already present? » pre-check of `cadence orchestrate` on the local model (`claude-local`, Ollama), off the Anthropic quota, Sonnet staying the default and the fallback (L146); the `qa-reviewer` agent walks only the pages a lot touched, with a **Scope** line in its report (L123); the sub-tasks a review closes are also read in a lot's neighbouring repositories (L156) and a commit's sub-task list is read with the plan's left guard (L155); an unstable test is fixed (L90). **0.27.1**: `cadence orchestrate` no longer leaves a session's child processes alive: a dev server started in its own process group, or orphaned by a shell that exits (`nohup srv &`), is killed with the session through its process tree and its `CADENCE_SESSION` mark, a tmux server, `screen`, `gpg-agent` or `dirmngr` started on demand being spared; a session that exits with code 0 while a descendant holds its output open is no longer reported as « délai dépassé » (L83); the `ux-reviewer` and `qa-reviewer` agents carry the briefs' Playwright rule outside `cadence orchestrate` (L84). **0.27.0**: a compliant review of `cadence orchestrate` settles the open sub-tasks that commits of the lot cite (`feat(L3/t2): …`, comma lists included), closed in the same plan commit as the verdict or, on a read-only plan, returned as `[sous-tâche clore]` proposals, so `raf done` no longer refuses a lot over sub-tasks whose work is done; on a foreign-format plan the ids are read as the plan reads them (L82); the test suite stays green with two full suites running in parallel (L150). **0.26.0**: `cadence orchestrate` raises the floor of a lot's budget from 200 k to 450 k tokens, enough to pay a write pass, its review, one fix pass and the short review that follows, so a lot of 0.5 or 1 day is no longer handed back at its second or third pass; a `--continue` wave draws fewer lots as a result (L128). **0.25.0**: the project line of the plans' progress in the `cadence-hud` band names the lots in progress after their count, three at most then `…` (L153, `cadence-hud` 0.4.2); the progress follows the folder the session was launched from, so a `cd` into a sub-project no longer shrinks the band, and the session context keeps the `session.start` folder (L154). **0.24.0**: `cadence orchestrate --drop <project:lot>` and `--stop-after-current` steer a live wave from another terminal, `--resume --drop` removes a lot before replaying a stopped wave (L79); the final table of a wave says « livrable jusqu'à <sha> » for a ready lot stacked under a lot handed back, with `git push origin <sha>:main && cadence deliver --sha <sha>` (L76); a version commit (version fields, `CHANGELOG.md`, the README's « What's new ») no longer asks for a new code review (L72). **0.23.0**: the progress bar of each project in the `cadence-hud` band is coloured by the share of lots done, red below 33 %, orange below 66 %, green beyond (L152, `cadence-hud` 0.4.1); `cadence deliver` under a wave lock refuses only when a lot of the wave still works in that very repository, a linked worktree included (L127). **0.22.0**: `cadence orchestrate --continue` draws the next ready lot of the plan itself, in the declared priority, until the budget, the time window or a question stops it (L147); `cadence session context` prints the context of the session, which the `cadence-hud` band publishes, and the `lead` skill chains lots without the human while it stays under 60 % (L148); the band shows the progress of each project's plan, and `cadence lead tour --json` gains `progress` (L149, `cadence-hud` 0.4.0); the final review of a lot is always played, the lot's own budget bounding the writing passes only, with 65 k tokens reserved for it (L145); the cause « tests rouges après … » names the pass whose tests were red (L151). **0.21.0**: `cadence orchestrate --status` and `cadence lead tour` print the free session slots, which the `lead` skill reads (L141); `orchestrate.effort` sets the effort level of each pass of a wave (L137); `docs.sync` makes `raf check`, `lead tour` and the review brief report a document that does not follow the code (L143); `docs.articles` opens, after a green `cadence deliver`, a lot `Article <project> à rafraîchir` in the neighbouring repository (L144). **0.20.0**: `cadence-hud` no longer misleads once the work is over: `/hud cmd` lists the background commands it counts (id, tool, origin, age, name), any other argument answers `argument inconnu` instead of hiding the band, commands with no end seen for an hour or no record go to a grey `N cmd sans fin vue`, a finished subagent takes its commands with it, two races that left a `1 cmd` counted forever are closed, and a finished wave shows grey without its budget then disappears after 30 minutes (L142); the `qa-reviewer` and `ux-reviewer` agents are read-only for real, their frontmatter listing Read, Grep, Glob, Bash and the Playwright tools (L140). **0.19.1**: `cadence-hud`'s `N cmd` counter goes back down when a Monitor expires, when the background commands a subagent started end with it, and at session start or plugin reload (L135); its `tool.call` and `prompt.submit` guard hooks carry a `.catch` on registration, which clears the `claude plugin validate` warning (L136). **0.19.0**: `cadence orchestrate` lifts a repository's lock and `pre-push` guard as soon as every lot of the wave that touches it is finished, so `cadence deliver` works there while the wave continues elsewhere (L132); a review that leaves a repository dirty hands back that lot only, suspends the lots still queued in that repository and keeps the other repositories running, its verdict reported instead of lost (L133); `cadence session close` re-run without a `session start` keeps the window since the last opening (L131); `cadence-hud` draws the lot rows of a wave in aligned columns on every surface (L134). **0.18.0**: `cadence session next` prints what it records (issue #6); `cadence session close` covers the period since the last `session start` (or the last close) and says so in its title, `--since` still wins (issue #7). **0.17.0**: `cadence-hud` shows an `N cmd` segment next to the agents, the background commands of the session (Bash run in the background and Monitor, subagents' included), tracked from the tool results and ended by the task's notification or `TaskStop`. **0.16.0**: a lot can declare **neighbouring repositories** (`repos:` key of the lot, `{ path, cite }` for a repository shared between projects): `cadence orchestrate` refuses, locks and guards them, gives them to every session as `--add-dir`, and `raf commits`, `raf show` and the review verdict read the commits that cite the lot there too. **0.15.0**: `hook.autostart` in `cadence.yaml` (`warn` by default, `refuse` or `start`): a pre-commit hook that refuses, or starts in the same commit, a lot still todo that the commit cites; `cadence session start|close --all [--depth n]`, one section per project under a folder. **0.14.0**: `cadence lead tour`, the lead's morning table of every project in a folder, printed by a program (one line per project: lots in progress, gaps, last notes, next ready lot, repository) in place of one subagent per project; the `lead` skill calls it. **0.13.1**: `cadence-hud` takes back the segments that fit once a big one has dropped (reset times, then the per-model consumption, now short: `opus 1.2M sonnet 800k`); `CADENCE_HUD_AMBIGUOUS=1` for a terminal that draws `▰ ▱ ⚙ │ ↻` in one cell. **0.13.0**: `cadence orchestrate --status --watch` (a wave's table redrawn in the terminal, which
28
44
  stops with the wave) and the lead skill that names the wave and follows its journal; lot ids with `/`
29
45
  (sub-tasks of a read-only plan) accepted by `orchestrate`; `cadence-hud`'s first line measured in
30
46
  terminal cells and kept to ASCII; `publish.yml` on the v5 actions. **0.12.0**: the `cadence-hud` plugin (a status band above the Claude Code prompt),
@@ -86,7 +102,7 @@ raf gantt # docs/plan/gantt.html
86
102
  | Command | Effect |
87
103
  |---|---|
88
104
  | `raf init [--project name] [--prefix L] [--no-hook]` | create the plan, install the hook, add `.playwright-mcp/` to `.gitignore` |
89
- | `raf add "title" [--estimate d] [--quickwin] [--visible] [--public "title"] [--after L2,L4] [--parent L3]` | add a lot or a sub-task, print its id (`--public`: the lot's title in the public's words, written as `public:` right after `title:`) |
105
+ | `raf add "title" [--estimate d] [--quickwin] [--visible [--screen page\|component\|journey]] [--public "title"] [--after L2,L4] [--parent L3]` | add a lot or a sub-task, print its id (`--public`: the lot's title in the public's words, written as `public:` right after `title:`; `--screen`: the screen a visible lot creates or changes — a new `page`, a new `component` or a modified `journey` — written as `screen:` right after `visible:`, shown by `raf show`; it requires `--visible`, and `raf check` reports a `screen:` without `visible:` or with another value as an error. It is what will trigger the spec step of `orchestrate`, never inferred from the title) |
90
106
  | `raf add "title" --every <days>` · `raf did <id> ["text"]` | recurring lot: `every` (days) and `last` (last time done) fields; the lot stays `todo`, `raf now` and `session start` list it under « Récurrent » with « dû depuis N j » / « prochain dans N j »; `raf did` resets the count (spec: `docs/superpowers/specs/2026-10-04-L11-tache-recurrente.md`) |
91
107
  | `raf public <id> "title"` · `raf public <id> --clear` | set, replace or remove the public title of a lot |
92
108
  | `raf start <id>` · `raf done <id> [--force]` · `raf drop <id> [--reason text]` | dated transitions (`done` refuses open sub-tasks unless `--force`) |
@@ -189,6 +205,7 @@ plan:
189
205
  fields: # raf field: key in the file (a list = first one present)
190
206
  title: titre
191
207
  public: titre_public # the lot's title for the public; read when it is text, else ignored
208
+ screen: ecran # page, component or journey; only on a visible lot
192
209
  status: etat
193
210
  estimate: effort
194
211
  created: cree_le
@@ -205,7 +222,7 @@ plan:
205
222
  estimates: { S: 0.5, M: 1, L: 3 } # their effort labels, in working days
206
223
  ```
207
224
 
208
- - Fields: `id`, `title`, `status`, `estimate`, `quickwin`, `visible`, `public`, `every`, `last`, `after`, `created`, `started`,
225
+ - Fields: `id`, `title`, `status`, `estimate`, `quickwin`, `visible`, `screen`, `public`, `every`, `last`, `after`, `created`, `started`,
209
226
  `finished`, `notes`, `repos`, `parent`; one left out is read under its own name. A timestamp counts for
210
227
  its day; a note written as plain text is one note.
211
228
  - `parent`: an entry `B33/t1-fusion` whose parent is `B33` becomes the sub-task `t1-fusion` of `B33`.
@@ -268,12 +285,12 @@ captures:
268
285
  |---|---|
269
286
  | `cadence news new <lot…> [--title t]` | entry skeleton, dated and timed now (`date`, `created`), titled after the lot's public title (`public`), else its title; `--title` wins |
270
287
  | `cadence news list` | entries, newest first (see *Order* below) |
271
- | `cadence news check` | visible lots done without entry, unknown lots, missing or undeclared screenshots, entries without creation time, bad headers |
288
+ | `cadence news check` | visible lots done without entry, unknown lots, missing or undeclared screenshots, entries without creation time, bad headers, a lot whose screen sheet has hypotheses and whose entry lacks the `## Hypothèses` section (or a line for one of them) |
272
289
  | `cadence news stamp` | migration: writes `created:` into entries without one (or with an empty one), from the author date of the commit that added the file under its current name (now if not committed yet) |
273
290
  | `cadence news build [-o dir]` | `nouveautes.json` + `index.html` + screenshots (default `docs/nouveautes/site`) |
274
291
 
275
292
  `--dir` changes the entries folder (default `docs/nouveautes` at the git root).
276
- The Markdown is deliberately small: paragraphs, `-` lists, `**bold**`,
293
+ The Markdown is deliberately small: headings (`#` to `######`, rendered one level lower, `<h2>` to `<h6>`; a heading takes its own line and cuts the paragraph or list around it), paragraphs, `-` lists (a bullet may continue on the next lines, indented), `**bold**`,
277
294
  `` `code` ``, `[links](url)`; everything else is escaped text. The JSON holds
278
295
  `{ project, generated, entries: [{ slug, title, date, lots, captures, html }] }`,
279
296
  with screenshot paths relative to the JSON file. `captures` is always a list of
@@ -606,6 +623,55 @@ a `priority:` that is not a list of names (`priority: ol`, `priority: []`) keeps
606
623
  no plan. It exits 0 even when a project is in error — that project's line reads
607
624
  `beta · ✗ erreur : <cause>`. The `lead` skill runs it instead of one subagent per project.
608
625
 
626
+ ## corrections
627
+
628
+ `cadence corrections [folder] [--classify [--model m]] [--cache file] [--sample n] [--until date] [--json]` measures how often a wave
629
+ has to correct itself. From the folder a wave was launched from (default: the current one) it reads the journals
630
+ `<folder>/.cadence/runs/<wave>/<project>--<lot>.json` of **every project** and prints:
631
+
632
+ - the **lots with a correction**: of the lots that went through a successful write session, the share with at least one
633
+ and at least two `fix` passes, per project and for visible versus non-visible lots (`61 %` and `29 %` of 263 lots in the 10-10 baseline);
634
+ - the **passes by cause**, in total and per project. The cause of a pass is read from the findings of the review that
635
+ precedes it, among: unclear spec or missing criterion (`spec-floue`), invented business rule (`regle-inventee`),
636
+ architecture drift (`derive-architecture`), data / SQL (`donnees-sql`), code bug (`bug-code`), missing test
637
+ (`test-manquant`), false review finding (`faux-constat`). One cause per pass: the root of what forced the fix. A pass with no review finding to read (triggered by red tests right after the write session) is counted apart as `sans-constat` and never sent to the model.
638
+
639
+ Without `--classify` the command calls no model: the passes not yet classified count as `non classé`. With `--classify`
640
+ each pass is classified by a **local model served by Ollama** (`OLLAMA_HOST`, default `http://localhost:11434`;
641
+ `--model`, default `mistral-small3.2:24b`; temperature 0, output constrained to the seven causes), off the Anthropic quota.
642
+ The classification is cached in `<folder>/.cadence/corrections.json` (or `--cache file`): a re-run classifies only the
643
+ new passes, and a pass the model could not answer stays out of the cache. `--sample n` prints `n` passes with findings spread
644
+ evenly over the sorted keys, with their findings and the model's cause, to be read by hand; a `manual` field written
645
+ beside a pass in the cache file (one of the seven causes, else the command refuses the file) overrides the model's cause in every table and gives the **agreement rate** of the model
646
+ on the reviewed sample. `--until date` (ISO, e.g. `2026-10-10T18:31Z`) reads only the waves created up to then (`created` in the wave's `wave.json`) and, in them, only the steps ended by then (`ended`), so that neither later waves nor a wave still running at that time change a published baseline; a wave or a step with no readable date is left out. `--json` prints the measure as data. The command reads the journals and writes nothing but the cache.
647
+ The first baseline is in [docs/mesures/corrections-2026-10-10.md](docs/mesures/corrections-2026-10-10.md); `test/corrections-mesure.test.ts` replays its command on the journals and checks the document's results word for word (skipped when the journals are not there).
648
+
649
+ ## spec
650
+
651
+ `cadence spec check <fiche.yaml>` checks a **screen sheet** (`fiche.yaml`, the machine-readable output of the spec step designed in
652
+ [docs/superpowers/specs/2026-10-10-etape-spec-design.md](docs/superpowers/specs/2026-10-10-etape-spec-design.md)). Start from the template
653
+ [`templates/fiche.yaml`](templates/fiche.yaml) (it passes the check as is), a worked example sits next to the design. It prints one
654
+ `✗ …` line per violation and exits **0** when the sheet is valid, **1** with violations, **2** when the file is missing, is not YAML or the usage is wrong. The invariants:
655
+
656
+ - `ecran` has `id`, `titre`, `route` (starts with `/`), `lot`, `maquette`, and `largeurs: [1440, 390]`; `etats` holds at least `vide`, `chargement`, `erreur`, none twice;
657
+ - `champs[]`: a unique kebab-case `id` (it is also the mockup's `data-testid`), `libelle`, `type`, `source`, and a boolean `obligatoire`;
658
+ - `regles[]` are numbered `R1`, `R2`… in order with no gap; each has an `etat` that is one of `etats`, an `enonce`, a `message` (the exact text on screen, or `null`),
659
+ a `statut` — `sourcee` with the `source` it comes from, or `hypothese` with the `si_faux` that says what would change — and at least one planned test, named `Rn — …`;
660
+ - `masque` (optional, only on a rule of state `vide`) lists the fields the rule makes disappear: every id must be a field of the sheet and none may be one the rule shows in `champs`;
661
+ - `actions[]` are numbered `A1`… in order, their `declencheur` is a field id (or `null` for the page load), their `appel` reads `VERB /path`, and the `regles` they carry exist.
662
+
663
+ `cadence spec qa <fiche.yaml>` derives from a valid sheet the section of `docs/qa/expectations.md` for its screen and prints it on the standard output
664
+ (it never writes the file: you paste the section, and the lead commits it like the rest of the plan files). A sheet with violations prints them on the
665
+ error output, nothing on the standard one, and exits 1. The derivation is built so that the planned empty and error states are never reported as defects:
666
+
667
+ - `## <route>` is the screen's route;
668
+ - `shows:` — one line per mandatory field (its `libelle`), **except** the fields that belong to a state (listed in `champs` of a rule of state `vide` or `erreur`, like the empty-state message);
669
+ the line of a field listed in the `masque` of a `sourcee` rule of state `vide` ends with `— unless <the rule's statement>`; the other fields (a static title) never get one;
670
+ - `never:` — the messages of the rules of state `erreur`, on one line; the message of a rule of state `vide` is a planned display and never goes there;
671
+ - `api:` — the load actions only (`declencheur: null`) in `GET` (the QA pass never sends a POST); the line ends with `may be empty when <the rule's statement>` when a `sourcee` rule of state `vide` carries the action.
672
+ Actions triggered by a field stay with the acceptance tests.
673
+
674
+
609
675
  ## deliver
610
676
 
611
677
  A delivery is done when its checks pass, not when a tool says "success".
@@ -930,7 +996,7 @@ without `--effort` (see below), so `effort.precheck` has no effect on it and the
930
996
 
931
997
  ```yaml
932
998
  orchestrate:
933
- effort: { precheck: low, implement: medium, fix: medium, review: high, ux: high } # defaults
999
+ effort: { precheck: low, spec: medium, maquette: high, accept: medium, implement: medium, fix: medium, review: high, ux: high } # defaults
934
1000
  ```
935
1001
 
936
1002
  To measure what a level costs, run the same kind of wave before and after changing the key: each step of
@@ -945,6 +1011,103 @@ with proofs), `partiel` or `non`: on `oui` no implementation session is opened a
945
1011
  implementation brief and a warning; on `non` — or an unreadable report, which only adds a warning — the wave goes on. A
946
1012
  lot that already has commits is never pre-checked (resuming it is legitimate). `orchestrate.precheck: false` turns it off.
947
1013
 
1014
+ ### The spec step of a lot with `screen:`
1015
+
1016
+ A lot that declares `screen:` (`raf add … --visible --screen page|component|journey`, see [raf](#raf)) gets one more session, `spec`, **after** the pre-check and **before**
1017
+ the first implementation: `precheck → spec → maquette → accept → implement → ux → review` (`maquette` unless `orchestrate.maquette: false`, see [The mockup review](#the-mockup-review-before-any-code); `accept` only when the project declares `orchestrate.accept`, see below). A lot without `screen:` follows the usual path, unchanged. `--dry-run` lists the step
1018
+ (`spec (sonnet)`), its command line and its brief `templates/orchestrate/spec.md`.
1019
+
1020
+ - **The session** (L171): Sonnet, the `spec-writer` agent (it writes only the spec folder, never application code), Playwright loaded like for `implement`. It reads the lot,
1021
+ the project's CLAUDE.md and its charter (CSS, neighbouring components, `docs/qa/expectations.md`, existing routes and API contracts), then writes in
1022
+ `<orchestrate.spec.dir>/<écran>/` (`docs/specs` by default): `maquette.html` (static HTML + CSS to the project's own style; one section `#etat-vide`, `#etat-chargement`,
1023
+ `#etat-erreur` and `#etat-charge` per state; every field of the sheet carries `data-testid="<field id>"`), one capture per state and per width
1024
+ `maquette-<état>-<largeur>.png` (1440 and 390), and `fiche.yaml` (the template `templates/fiche.yaml` is part of its brief). The mockup is rendered by
1025
+ `orchestrate.spec.render` when the project declares it (the session runs that command), otherwise with Playwright; the captures land in the wave's output directory and the session copies the
1026
+ kept ones into the folder. `effort.spec` (default `medium`) sets its effort level. It commits the whole spec in one commit that cites the lot (`spec(L7): …`).
1027
+ - **What the program checks** afterwards, with no model: the sheet passes `cadence spec check`, is the lot's (`ecran.lot`) and sits in the folder named by `ecran.id`; `maquette.html` exists with a
1028
+ `#etat-<état>` section per state and a `data-testid` per field; every state has its capture at both widths; everything is committed and the tree is clean. Anything missing is listed back to **one second
1029
+ `spec` session** (a fresh session whose brief names the points); if the second spec is still not valid the lot is handed back (`spec non conforme après 2 passes : …`).
1030
+ - **A costly choice is a question, not a hypothesis.** A rule marked `hypothese` whose `si_faux` involves a data model or storage, a public or shared API contract or an already published route,
1031
+ a destructive or irreversible action, or a contradiction with a sourced rule, puts the lot in `question` (the program recognises these by keywords as a safety net behind the agent's own
1032
+ judgement; a keyword right after a negation — « rien d'irréversible », « sans suppression », « pas de paiement » — does not count); `--resume --answer <lot> "…"` gives the answer to the resumed `spec` session. Every other hypothesis (wording, order of fields, error state, spacing) stays written in the sheet.
1033
+ The agent can also ask a question itself in its report.
1034
+ - **Under the threshold**: if the session finds that the lot changes no screen, it gives the reason in one line (`sousSeuil`), writes no mockup, and the lot goes on to `implement` as before; the reason is
1035
+ kept as a warning of the lot. On resume the spec step is skipped only when a sheet of the lot (`ecran.lot` is the lot) already passes the program's checks (`cadence spec check`, mockup, captures) and carries no costly hypothesis; otherwise the spec is played again. The sheet path in the report is relative to the repository (an absolute or `./` path is normalised, a path outside the repository is a finding).
1036
+
1037
+ ### The mockup review: before any code
1038
+
1039
+ After a valid spec, a lot with a sheet gets a UX review of its mockup, `maquette` (L172), unless `cadence.yaml` sets `orchestrate.maquette: false` (default `true`): `precheck → spec → maquette → accept → implement → ux → review`.
1040
+ `--dry-run` lists the step (`maquette (opus)`, the `review.full` model), its `ux-reviewer` command line and its brief `templates/orchestrate/maquette.md`.
1041
+
1042
+ - **The session**: the `ux-reviewer` agent in **mockup mode**, read-only, Playwright loaded, a fresh session. It opens `maquette.html` as a local file (no application, no server), looks at the captures
1043
+ `maquette-<état>-<largeur>.png` (1440 and 390 px) of every state, reads `fiche.yaml`, and reports findings ranked blocking / major / minor, each grounded in a rule (Nielsen, WCAG 2.2 AA) or a measurement. On top of
1044
+ that it checks the **consistency mockup ↔ sheet**: every field of the sheet in the mockup with its `data-testid`, every rule message visible, word for word, in the state its `etat` names, every state with its
1045
+ `#etat-<état>` section, the `masque` of an empty-state rule really hiding the fields it names. `effort.maquette` (default `high`) sets its effort level. Its verdict is **not** `raf ux`: the conformity pass after the code keeps that role.
1046
+ - **The loop, two reviews at most.** A blocking or major finding sends the mockup back to the spec writer: a **second `spec` session** (fresh, its brief carries the findings), then the mockup is reviewed again. If the second review is
1047
+ still not conforming, the lot is handed back with what remains (`maquette non conforme après 2 revues : …`) and nothing is implemented. A conforming review goes on to `accept` (or `implement`). On a resume, a **sealed** `acceptation.json` (its `empreintes` set by the program), still red or already green (`vert: true`), proves the review was done and is not replayed; an unsealed one proves nothing. A `maquette` step with no sheet warns (`revue de la maquette ignorée : aucune fiche …`) and goes to `implement`.
1048
+ - **Sample data** (L181): the spec brief asks the writer to compute the weekday of every date of the mockup (not to write it from memory), and the review recomputes them. A wrong sample datum (weekday, date, figure that does not add up) is a **minor** finding, never a major one, so it cannot by itself send the mockup back for a second review.
1049
+ - **Minor findings** are not sent back: they are kept as proposals of the lot (`[mineur maquette] …`), like the minors of the other reviews. A report whose totals announce a major finding is not taken for conforming.
1050
+ - **On resume**, a sheet already committed is reviewed before the next step, unless the lot already has a sealed, conforming `acceptation.json` (it can only have been written after the review), or already has code committed after the sheet (a commit citing the lot that touches a file outside the sheet's folder: `implement` only started once the review was done), including without `orchestrate.accept`.
1051
+
1052
+ ### The accept step: red acceptance tests and their lock
1053
+
1054
+ After a valid spec, and only when `cadence.yaml` declares `orchestrate.accept` (the project's **dedicated command**, which runs *only* the acceptance tests of one lot), a lot with a sheet gets one more
1055
+ session, `accept` (L173): `precheck → spec → maquette → accept → implement → ux → review`. Without `orchestrate.accept` the step is skipped, with a warning on the lot (`étape accept ignorée …`), and the lot goes from `spec` to `implement` as before.
1056
+ `--dry-run` lists the step (`accept (sonnet)`) and its brief `templates/orchestrate/accept.md`.
1057
+
1058
+ - **The session**: Sonnet, the `acceptance-writer` agent, a session other than the implementer's. Its brief gives it the sheet, the mockup and how to run the project's tests (the dedicated command, and the runner template below) — not the lot's objective, notes or
1059
+ sub-tasks, and no implementation. It writes one or more cases per rule, **named as the sheet plans them** (`regles[].tests`, e.g. `R3 — erreur : message et bouton Réessayer`), selectors = the `data-testid` of the fields, API calls simulated from `actions[]`,
1060
+ and commits them **red** in one commit (`test(L7): acceptation R1–Rn (rouge)`) with `<spec.dir>/<écran>/acceptation-<lot>.json` (**one file per lot**: two lots on the same screen never share a lock or a file; the id is reduced to `A-Za-z0-9._-`, so `app/L7` gives `acceptation-app-L7.json`; an older `acceptation.json` is still read, by its `lot` key) — `{ "lot", "fiche", "fichiers": [...], "vert": false }` — and the runner configuration. A second lot's tests that rewrite the first lot's test files hand the lot back, with the file named (the lock below). `effort.accept` (default `medium`) sets its effort.
1061
+ - **Out of the ordinary test run and the CI while the lot is not green.** Red tests committed would fail `orchestrate.test` (after every `implement`/`fix`) and the project's CI (which `cadence deliver` waits for), for lots that are not theirs. So the
1062
+ runner configuration shared by `orchestrate.test` and the CI excludes the files listed in every acceptation file (`acceptation-<lot>.json`) whose `vert` is `false`, and only the dedicated command runs them. `templates/acceptation-runner.mjs` is the helper the session copies
1063
+ into the project: `acceptationIgnored()` (Vitest `exclude`; `acceptationIgnored(root, dir, 'regex')` for Jest `testPathIgnorePatterns`) and `acceptationOnly()` (the `include` of the dedicated config, which reads the environment variable `CADENCE_ACCEPTATION`:
1064
+ the program sets it to the absolute path of the lot's acceptation file when it runs `orchestrate.accept`, and also replaces `{acceptation}` in the command with that path — quote it if the path may hold spaces). If the CI or the test command do not use that config
1065
+ (paths hard-coded), the session must not commit red tests and puts the question in its report.
1066
+ **Run by hand, outside a wave**, the dedicated command fails: `acceptationOnly()` requires `CADENCE_ACCEPTATION`, which only the program sets. Set it yourself, to the path of the lot's acceptation file:
1067
+ `CADENCE_ACCEPTATION=<path of the acceptation file> <command>` (with a `{acceptation}` in the command, write the path there too). Once the lot's tests are green (`vert: true`), they join the ordinary runner and the CI, so the usual test command runs them without that variable.
1068
+ - **What the program checks** afterwards, with no model: `acceptation.json` is the lot's (`lot`, `fiche`, listed files committed, `vert: false`), every test name planned in the sheet appears in the listed files, **each listed test file is new** (absent from the head before the first `accept` session: tests written into an existing test file would leave the ordinary run and the CI while the lot is red, so the check refuses `existait avant la session accept`), the other lots' acceptation tests are untouched, the dedicated command
1069
+ **fails** (a test green before the code proves nothing), `orchestrate.test` stays **green** with the red tests committed (proof that they are excluded; without `orchestrate.test` nothing proves it, and the step passes with a lot warning only), and the tree is clean. Anything missing goes to **one second `accept` session**; still not valid, the lot is handed back
1070
+ (`accept non conforme après 2 passes : …`). A question in the report puts the lot in `question`, like the other steps. The check that each listed test *individually* fails is not made: only the dedicated command's exit code is (it fails if any of them fails).
1071
+ - **The seal.** Once the checks pass, **the program** (not the session) adds to `acceptation.json` the git fingerprint of each listed file (`empreintes`) and commits it (`test(L7): acceptation scellée …`): that commit is the **red commit**. Its sha is written nowhere in the file (a session could rewrite it): it is
1072
+ the latest commit in git history that changed the file otherwise than by its `vert` key, and the wave keeps it in the lot's state (`accept.rouge`) too.
1073
+ - **The lock, for every session of the repository.** At the end of each `implement` and `fix` the cycle compares, for the acceptation files of **all** lots found under `orchestrate.spec.dir` (a repository has one queue: the next lot runs on the same branch), the listed test files with the red commit
1074
+ (`git diff <red commit> -- <files>`, empty expected, working tree included, and the fingerprints), and each `acceptation.json` with its version before the session. The only difference tolerated on `acceptation.json` is the `vert` key, and only **the cycle** sets it: a session that changes it, rewrites the
1075
+ file, deletes it, creates one outside the accept step, or modifies a locked test hands the lot back (`verrou des tests d'acceptation : …`) — a useful change is a question to the lead or a review finding, never a silent gesture. The lock does not depend on `orchestrate.accept` being declared. **Exception — a delivered lot (`vert: true`):** a later lot that makes the rule evolve may modify the listed tests of that acceptation when **the sheet of the screen changes in the commits of the same lot** (compared with the head before the lot's first session, working tree included, or in a commit that cites the lot, even made before the wave): the sheet is what evolves the rules, and tests and sheet change together. The exception never covers the acceptation of the lot in progress (its `vert: true` is set right after the implement): that one keeps the whole lock. Without a sheet change the difference is still a deviation — except one narrow case (L184): a listed file whose content is identical to what it was at the head before the lot's first **work** commit (commits found by the plan's refs) is not a deviation, the lot having taken its own addition back (a lot handed back for writing in a locked file and resumed in a new wave, which then removes that addition). This applies to every acceptation, `vert: false` included, but only to a file that **exists** at that head and now: a file absent at that head (e.g. created by the lot's own red commit) or deleted since is never exempted, so deleting a locked test stays a deviation; nor when the sheet of the screen has changed since that head (an evolution admitted for another lot: going back to the old content would cancel it, not the lot's addition); apart from that, with `vert: false` the whole lock applies, sheet change or not; `acceptation.json` itself stays locked (only its `vert` key moves).
1076
+ - **Back to green, set by the cycle.** At the end of each `implement`/`fix`, once the session reports green, the cycle runs the dedicated command. Red: the findings go to a `fix` pass (the tests are made green without editing the locked files). Green: the cycle sets `vert: true` and commits it (`chore(L7): acceptation verte …`;
1077
+ `commitPlan` may commit the `acceptation.json` files, otherwise the dirty tree would stop the lot). The files then join `orchestrate.test` and the CI, which keep the lot green from then on; the following lot, running with `vert: true`, is compared with the head before its own work, not with the red commit, only once the sheet has changed between the red commit and that head: after an admitted evolution (tests changed along with the sheet) it sees no difference either; only a test changed *during* that lot without the sheet is a deviation.
1078
+ - **When the lot is handed back** (question, budget, passes exhausted) its tests stay red but excluded from the project's runner and CI: the next lots and `cadence deliver` do not see them; `--resume` continues with the same lock. On resume, the step is skipped when the lot already has a valid committed **and sealed** `acceptation.json` (its `empreintes` set by the program); a conforming file without them proves nothing and `accept` runs again. The fingerprints are keyed by normalised path, so a listed `./test/x.ts` is recognised like `test/x.ts`, on resume and by the lock (which compares it to its fingerprint).
1079
+
1080
+ ### The downstream briefs: sheet, rule → test → green, conformity, Hypothèses
1081
+
1082
+ Once the sheet exists, the steps after it all read it (L174, `src/orchestrate/aval.ts`, the `{{fiche}}` marker of the templates `implement.md`, `fix.md`, `fix-minors.md`, `review.md`, `review-small.md` and `ux.md`). A lot without a sheet (no `screen:`, or under the threshold) keeps exactly the briefs it had.
1083
+
1084
+ - **`implement` and `fix`** get the path of the sheet and of the mockup, and **one line per rule** (`- R3 [erreur, hypothese] statement. Message: « … ». Tests: « R3 — … »`). The session makes the acceptance tests green **without modifying them** (they are named when the `accept` step ran; the lock above hands the lot back otherwise), **the tests it writes in addition cite the rule** in their name (`R2 — …`), and it **does not invent a rule**: a case the sheet does not cover is written in the report (`nonVerifie` or `choix`), not coded. In a `fix` the sheet stays the reference: a finding that contradicts it is contested under `choix`.
1085
+ - **The code review (`review`, `review-small`) checks rule → test → green** (`règle → test → vert`). For each `Rn` of the sheet the reviewer checks that its test exists (named after the rule), that it is green, and that the behaviour is in the diff; when an acceptance file is named, that each listed test is unchanged since the red commit (`git diff <red commit> -- <file>` empty; the brief gives the red commit). A rule without a test, an acceptance test modified since the red commit, a rule coded that is not in the sheet, and a test that is green without exercising its rule are **major** findings. The reviewer no longer rebuilds the cases from the code.
1086
+ - **The UX pass becomes a conformity pass.** For a lot with a sheet, the `ux` session (the `ux-reviewer` agent, **conformity mode**) no longer audits the whole screen: it compares the running app to the mockup and to its captures `maquette-<état>-<largeur>.png`, state by state, at 1440 and 390 px, and reports the differences of rendering and ergonomics the tests do not cover, each tied to a rule or a measure. The rules of the sheet are the tests' job. Its verdict feeds `raf ux`, which stays the lead's, decided on the captures. A small visible lot (single `review-small` pass) gets the conformity instruction in that pass.
1087
+ - **The `## Hypothèses` section of the news entry.** The `implement` brief asks for an entry that ends with `## Hypothèses`: one line `- Rn — …` per rule whose status is `hypothese`, with what changes if it is wrong (its `si_faux`) — it is what the lead shows for the `raf ux` decision, the choices nobody validated.
1088
+
1089
+ ```markdown
1090
+ ## Hypothèses
1091
+ - R3 — erreur de chargement : message « Impossible de charger le prochain match. » et bouton Réessayer. À confirmer ; sinon seul ce bloc change.
1092
+ ```
1093
+
1094
+ **`cadence news check`** (not `build`) flags a lot whose sheet has hypotheses — found under `orchestrate.spec.dir` (default `docs/specs`), by `ecran.lot` — when none of its entries has the section, or when the section lacks a `- Rn` line for one of the rules (`L7 : la fiche a des hypothèses (R3, R4) mais l'entrée … n'a pas la section « ## Hypothèses »`). A lot without hypothesis needs no section.
1095
+
1096
+ **Production access of the sessions** (L168): a session of a wave (`implement`, `fix`, `precheck`, `spec`, `review`, `ux`) is
1097
+ started with no *default* access to the production cluster (a guard against the ordinary path, not a barrier). What a session inherits was measured on the dev machine: `KUBECONFIG` (pointing at
1098
+ `~/.kube/config`, the production cluster), the `kubectl` of the `PATH` (a link to `k3s`, which without `KUBECONFIG`
1099
+ falls back on `/etc/rancher/k3s/k3s.yaml`) and the cloud and GitHub tokens of the environment. `cadence orchestrate` now
1100
+ starts every session with `KUBECONFIG=/dev/null` (`kubectl get pods` answers « connection refused » on `localhost:8080`)
1101
+ and without `KUBERNETES_SERVICE_HOST`, `KUBERNETES_SERVICE_PORT`, `KUBE_TOKEN`, `ARGOCD_SERVER`, `ARGOCD_AUTH_TOKEN`, `ARGOCD_OPTS`, `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_API_KEY`, `CF_API_TOKEN`, `CF_API_KEY`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN` (exactly these names: `AWS_PROFILE` or `AWS_WEB_IDENTITY_TOKEN_FILE` are kept), `GOOGLE_APPLICATION_CREDENTIALS`,
1102
+ `AZURE_CLIENT_SECRET`, `GH_TOKEN`, `GITHUB_TOKEN`, `GH_ENTERPRISE_TOKEN` (idea taken from the sandbox of docker/docker-agent,
1103
+ closed by default). `HOME` is left alone, so the credential files `gh` keeps under `~/.config` stay readable (a session
1104
+ can neither push nor deliver anyway) and so does `~/.kube/config`: a session that deliberately runs
1105
+ `kubectl --kubeconfig ~/.kube/config …` or `KUBECONFIG=~/.kube/config kubectl …` still reaches the cluster. The restriction
1106
+ stops the accidental access, not a deliberate workaround; making the file unreadable needs a filesystem sandbox
1107
+ (a mount namespace, or the file sandbox of Claude Code), which cadence does not set up. `cadence deliver` and `cadence verify` are the lead's and keep their access; so do
1108
+ the project's own `test`, `build` and `ux.command`, which the program launches. A lot that really needs the cluster is run in a
1109
+ project with `orchestrate.prodAccess: true`: the restriction is lifted for all its sessions (default `false`).
1110
+
948
1111
  `orchestrate.precheck: local` (L146) runs the pre-check on the local model of the dev machine instead of Sonnet: the
949
1112
  orchestrator launches `claude-local` with the same brief, the `precheck-reader` prompt and tools, no quota used and nothing counted in the
950
1113
  lot's budget (the step shows `local` as its model). `claude-local` is **not shipped with cadence**: it is a personal wrapper (a script on the `PATH`, `qwen3-coder:30b` by default) around
@@ -1083,8 +1246,7 @@ a time (above); `Agent`, `git push`, `cadence deliver`, `raf done|review|ux` are
1083
1246
  temporary `pre-push` hook, installed for the duration of the wave and removed at its end (or, for a repository, as soon as all the lots that touch it are finished), refuses any push
1084
1247
  from a session (`CADENCE_ORCHESTRATED` is in their environment; a repository that already has another
1085
1248
  `pre-push` hook is refused before anything starts — `pushurl` is never touched); after every session the
1086
- upstream ref and `git ls-remote` are compared with the "before", and a review that changed `HEAD` or the
1087
- tree (screenshots left at the root, a commit) is an incident of that lot only: the lot is handed back to the lead, the lots of the other repositories carry on while the lots still queued behind it in the same repository are suspended (resumable, nothing started on a dirty tree), and a verdict the review had already produced is reported in the outcome and the lot's warnings (never recorded in the plan). A push or a removed guard hook still stops the wave. `raf done|ux|review` and `cadence deliver` refuse when
1249
+ upstream ref and `git ls-remote` are compared with the "before", and a read-only step that left only UNTRACKED files (screenshots written at the root by a script with a relative path) is not an incident: the files are moved to `.cadence/runs/<wave>/<project>--<lot>/stray/` (kept in their tree; for a neighbour repository, under `stray/<its relative path, `/` replaced by `_`>/`, e.g. `stray/.._gitops/`), a warning naming them goes to the lot's warnings and the wave log, the verdict is kept and the lot continues (L162; a move that is impossible, or an untracked file that vanished during the step, stays an incident); a review that changed `HEAD` or a tracked file (a commit, a modified file) is an incident of that lot only: the lot is handed back to the lead, the lots of the other repositories carry on while the lots still queued behind it in the same repository are suspended (resumable, nothing started on a dirty tree), and a verdict the review had already produced is reported in the outcome and the lot's warnings (never recorded in the plan). A push or a removed guard hook still stops the wave. `raf done|ux|review` and `cadence deliver` refuse when
1088
1250
  `CADENCE_ORCHESTRATED` is set.
1089
1251
 
1090
1252
  **Budget**: the wave counts input + cache writes + output tokens (default 2 M); cache reads are kept and
@@ -1153,7 +1315,11 @@ orchestrate:
1153
1315
  test: npm test # run by the orchestrator after a work step (optional)
1154
1316
  build: npm run build # run after the tests; both results go to the reviewer, who does not redo them (optional)
1155
1317
  precheck: true # default: before the first implementation of a lot with no commit, a read-only Sonnet session checks whether the deliverable is already in the repository (see below); false skips it, local runs it on claude-local (Ollama) with Sonnet as fallback
1156
- effort: { review: xhigh } # effort level per pass (see « Effort level per pass »): precheck, implement, fix, review, ux
1318
+ accept: npx vitest run -c vitest.acceptation.config.ts # accept step (see « The accept step »): the dedicated command that runs ONLY the acceptance tests of the lot (optional; without it the step is skipped with a warning)
1319
+ maquette: true # default: UX review of the mockup between spec and accept (see « The mockup review »); false skips it
1320
+ spec: { dir: docs/specs } # spec step (see « The spec step of a lot with screen: »): folder of the screen specs, relative to the repository (default docs/specs); render: the command the spec session runs to render the mockups at 1440 and 390 px (optional, Playwright otherwise)
1321
+ prodAccess: false # default: wave sessions get no access to production (see « Production access of the sessions »); true lifts it for this project
1322
+ effort: { review: xhigh } # effort level per pass (see « Effort level per pass »): precheck, spec, maquette, accept, implement, fix, review, ux
1157
1323
  ux: http://localhost:4200 # a URL, a launch command, or { command, url, timeout? } — for the UX review (see below)
1158
1324
  permissionMode: auto # default
1159
1325
  addDirs: [/home/me/projects/tmp] # extra directories the sessions may use
@@ -1223,12 +1389,13 @@ version and the folder searched — there is no silent fallback to the default N
1223
1389
  source (user, project, plugin servers: Serena, context7, Cloudflare…), so a session no longer starts a handful of
1224
1390
  `npx`/`uvx` servers it does not use. `review` and `review-recheck` always get an empty set
1225
1391
  (`{"mcpServers":{}}`); so do `implement`, `fix` and `fix-minors` on a lot without a screen. Playwright, launched as
1226
- `npx -y @playwright/mcp@latest --output-dir <wave>/<project>--<lot>/playwright`, is loaded for the `ux` step and, on a
1227
- `visible` lot, for `implement` and `fix` (`fix-minors` included) and, on a small `visible` lot, for `review-small` (its only
1392
+ `npx -y @playwright/mcp@latest --output-dir <wave>/<project>--<lot>/playwright`, is loaded for the `ux` and `maquette` steps and, on a
1393
+ `visible` lot, for `spec`, `implement` and `fix` (`fix-minors` included) and, on a small `visible` lot, for `review-small` (its only
1228
1394
  usability review; `review-small` of a small lot without a screen loads nothing), so the screenshots and snapshots of the work and of
1229
1395
  the review stay with the wave, outside the repository, where the lead can look at them; the final table prints that
1230
1396
  folder whenever Playwright was loaded for the lot, even if no `ux` step ran
1231
- (`<project>:<lot> — captures Playwright : <dir>`; `uxCaptures` in the wave state). The `implement`, `fix`,
1397
+ (`<project>:<lot> — captures Playwright : <dir>`; `uxCaptures` in the wave state). For `maquette` and `spec` the server also gets
1398
+ `--allow-unrestricted-file-access`: the mockup is a local file, and by default the server blocks every `file://` URL. The `implement`, `fix`,
1232
1399
  `fix-minors`, `review-small` and `ux` briefs tell the session to give relative file names if a Playwright server is available, and
1233
1400
  otherwise to keep any Playwright CLI output outside the repository.
1234
1401
  `--dry-run` prints, under each step, `mcp : aucun` or `mcp : playwright (…)`. There is no per-project override in
@@ -1274,11 +1441,12 @@ repository with `cadence skills install` (to `.claude/skills/cadence-*` and
1274
1441
  no model: see [lead tour](#lead-tour)) prints one line of facts per project, you choose the priorities, the lots are delegated with
1275
1442
  `cadence orchestrate` (fresh short sessions with a standard brief — test first,
1276
1443
  README and usage documentation updated with the change, commits citing the lot, no push — reviewed by the `code-reviewer` agent, see
1277
- [orchestrate](#orchestrate)), re-verified by the lead, then delivered
1444
+ [orchestrate](#orchestrate); a lot with a `screen:` first goes through the [spec, mockup review and accept steps](#the-spec-step-of-a-lot-with-screen)), re-verified by the lead, then delivered
1278
1445
  one project at a time; a delivery that changes what a page shows or what it is
1279
1446
  served is then checked in the running app by the `qa-reviewer` agent, whose
1280
1447
  blocking findings come back to you. Two
1281
- subagents at most, never two in the same repository.
1448
+ subagents at most, never two in the same repository. The whole flow is drawn in
1449
+ [docs/lead.md](docs/lead.md).
1282
1450
  - **ux-reviewer** (agent): captures at 1440 and 390 px, findings grounded in a
1283
1451
  named rule (Nielsen, WCAG 2.2 AA) or a measurement, ranked, turned into
1284
1452
  `raf add --parent` sub-tasks, and a one-line verdict for `raf ux`. It never
@@ -1375,13 +1543,15 @@ A version exists in three places and is published in two; a release does all of
1375
1543
  in that commit, not before the review. A commit that touches any other file
1376
1544
  — or another field of a manifest, or a dependency in `package-lock.json` — is work like any other and has
1377
1545
  to be reviewed.
1378
- 2. `git tag v<version> && git push origin main v<version>` — the tag starts `.github/workflows/publish.yml`,
1546
+ 2. Run the plugin evaluation, `npm run eval:plugin` (billed, see [Evaluating the plugin](#evaluating-the-plugin-before-a-release)),
1547
+ on that version commit; a case below the threshold stops the release until you have read it in the report.
1548
+ 3. `git tag v<version> && git push origin main v<version>` — the tag starts `.github/workflows/publish.yml`,
1379
1549
  which publishes to npm through Trusted Publishing (OIDC, no token stored anywhere): it checks the tag
1380
1550
  matches `package.json`, `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json` and that `CHANGELOG.md` has a `## [x.y.z]` section for it (no section, no publication), then `npm publish --provenance`, where `prepublishOnly` runs the type-check and the
1381
1551
  tests and `prepare` builds `dist/`; a red suite stops the publication; then it creates the GitHub release with that CHANGELOG section as its text. The trusted publisher is declared
1382
1552
  once on npmjs.com (package settings → Trusted Publisher → GitHub Actions, `Sylad/cadence`, `publish.yml`).
1383
- 3. Watch the run: `gh run watch` (or `gh run list --workflow publish.yml`).
1384
- 4. Check the effect: `npm view @sylad/cadence version` answers the new version.
1553
+ 4. Watch the run: `gh run watch` (or `gh run list --workflow publish.yml`).
1554
+ 5. Check the effect: `npm view @sylad/cadence version` answers the new version.
1385
1555
  A run is safe to re-run, and two runs for one tag queue instead of racing (`concurrency` per ref, never cancelling the one that publishes):
1386
1556
  a version already on npm skips `npm publish`, and a GitHub release that is missing is created (`--verify-tag`)
1387
1557
  while an existing one is left alone. If the package is on npm but the release is still missing, re-run the job;
@@ -1390,7 +1560,63 @@ A version exists in three places and is published in two; a release does all of
1390
1560
  The Claude Code plugin is read from the repository, so pushing `main` is what updates it; npm is what
1391
1561
  `npx @sylad/cadence` and a global install read, and only the tag publishes there. A missing tag, or a red
1392
1562
  publish run, leaves npm behind without any other error — 0.3.0 and 0.4.0 were never published — hence
1393
- step 4.
1563
+ step 5.
1564
+
1565
+ ### Evaluating the plugin (before a release)
1566
+
1567
+ `evals/` holds an evaluation suite for the plugin itself, run by `claude plugin eval` (Claude Code 2.1.263 and later). Each case is
1568
+ a folder with a `prompt.md` and `graders/*.md`, and replays a trap found by hand: `raf-done-sans-revue` (`raf done` refused on a lot whose
1569
+ commits have no code review, with no `--force` to get round it), `deliver-sha` (`git push origin <sha>:main` then
1570
+ `cadence deliver --sha <sha>` for a pushed commit that is not `HEAD`), `orchestrate-id-avec-slash` (`maritime-atlas:Q4/accueil-4-ux12@haiku`
1571
+ keeps its `/`) and `livrer-sh-sans-bloc` (a `./livrer.sh` without a `deliver:` block in `cadence.yaml` is not
1572
+ run by `cadence deliver`). Every case also runs a **baseline without the plugin**, so the report gives the score of each arm and the
1573
+ difference: a trap the baseline already avoids proves nothing about the plugin. The cases are read-only questions (tools `Read`, `Glob`, `Grep`,
1574
+ `Skill`, no scaffold script), each graded by a regular expression and by a model-judged criterion.
1575
+
1576
+ ```sh
1577
+ npm run eval:plugin # claude plugin eval . --max-cost-usd 5 --no-publish; 4 cases × 3 runs × 2 arms = 24 runs
1578
+ claude plugin eval . --case deliver-sha --runs 1 --trust-plugin --no-publish --max-cost-usd 1 # one case, one run (the first run asks to trust the plugin)
1579
+ ```
1580
+
1581
+ **Every run is billed** (a full `claude` session on your own credential, plus the judge): the suite is run at the release, once the
1582
+ version commit is ready, never in `npm test`, in `prepublishOnly` or in CI, and `--max-cost-usd 5` aborts a runaway. A case below
1583
+ the threshold (1.0 by default, `--threshold`) makes the command exit 1: read the case in the report before deciding it is the plugin
1584
+ and not the wording of the case. `npm test` only checks that the
1585
+ files are well formed (`test/plugin-evals.test.ts`); `evals/` is not part of the npm package.
1586
+
1587
+ ## Stability
1588
+
1589
+ From 1.0.0 cadence follows [semantic versioning](https://semver.org): what is listed under
1590
+ *Guaranteed* only changes incompatibly in a major version; a minor or a patch never breaks it.
1591
+
1592
+ **Guaranteed**
1593
+
1594
+ - **Commands and options** of `raf` and `cadence` (`cadence raf …` is `raf …`): `init`, `add`, `start`, `done`, `drop`,
1595
+ `note`, `did`, `public`, `ux`, `review`, `commits`, `show`, `list`, `now`, `ignore`, `check`, `gantt`, `hook`;
1596
+ `cadence news`, `session` (`start`, `close`, `next`, `context`), `lead tour`, `corrections`, `deliver`, `verify`, `orchestrate`,
1597
+ `skills`, `spec` (`check`, `qa`: exit **0** when the sheet is valid and the section is printed, **1** with violations, **2** on a missing or unreadable file or a wrong usage);
1598
+ their options and exit codes as this README documents them. A new command or option is a minor change.
1599
+ - **The keys of `cadence.yaml`**: `plan`, `news`, `hook`, `session`, `deliver`, `orchestrate`, `docs`, `qa`, `priority`
1600
+ and the keys each of them takes. A key is not renamed nor removed, nor does its meaning change; a new key is a minor change.
1601
+ - **The plan file** (`docs/plan/raf.yaml`): `project`, `prefix`, `since`, `ignore`, `lots` (with their
1602
+ fields, `tasks`, `notes`, `repos`) and `acknowledged`, and the plan formats `plan:` in `cadence.yaml` can read.
1603
+ The `version` key is kept in the file but ignored (`src/plan.ts` does not read it): it is not a schema version.
1604
+ - **The names of the skills** (`session-start`, `session-close`, `deliver`, `lead`) **and of the agents**
1605
+ (`ux-reviewer`, `code-reviewer`, `qa-reviewer`).
1606
+
1607
+ **Not guaranteed** (may change in any release)
1608
+
1609
+ - The **text of the outputs**: wording, layout, order of the lines and columns of every report, table and message
1610
+ (the `--json` outputs and the exit codes are part of the commands above). In a `--json` output a new field is a
1611
+ minor change, so consumers must tolerate unknown fields; removing or renaming a field is a major change.
1612
+ - The **`precheck-reader`**, **`spec-writer`** and **`acceptance-writer`** agents, and the mockup and conformity modes of **`ux-reviewer`**: internal to `cadence orchestrate`, not meant to be called by hand.
1613
+ - The **`cadence-hud` band**: its segments, colours and layout; it is versioned on its own.
1614
+ - The **wave journals** under `.cadence/runs` and the files `cadence orchestrate` keeps there.
1615
+ - The wording of the briefs and of the instructions inside the skills and the agents.
1616
+ - The **format of the screen sheet** (`fiche.yaml`, `templates/fiche.yaml`) and so the invariants `cadence spec check` enforces: experimental while the next bricks of the spec step (S3–S6) still reshape it, a sheet that passes today may be refused by a later release. The `spec` commands and their exit codes are guaranteed, the keys they read are not yet.
1617
+
1618
+ There is no schema version and no migration: a file written by an earlier release keeps working, and a key a
1619
+ release adds is optional.
1394
1620
 
1395
1621
  ## License
1396
1622
 
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: acceptance-writer
3
+ description: Acceptance test writer. Before a lot that adds or changes a screen is implemented, writes from the screen sheet and the mockup only (never the implementation) the acceptance tests of every rule, committed RED, and lists them in acceptation.json. Wires the project's test runner config so red files stay out of the ordinary test run and the CI. Used by the orchestrator, not by hand.
4
+ tools: Read, Write, Edit, Grep, Glob, Bash
5
+ ---
6
+
7
+ You write the oracle of one screen before it is built. You never write the application.
8
+
9
+ Follow the brief you are given. The method:
10
+
11
+ 1. **Read the sheet and the mockup, then the project's way of testing.** `fiche.yaml` (fields, rules, actions), `maquette.html` (the `data-testid`), and the existing tests of the project to copy its conventions (runner, helpers, how API calls are simulated). Do not read the implementation you would be tempted to imitate: you specify what the screen must do, not how it does it.
12
+ 2. **One test per planned name.** Each rule has `tests[]` names (`R3 — …`): write exactly those cases, with exactly those names, selectors = `data-testid` = field ids, API calls simulated from `actions[]`.
13
+ 3. **Wire the runner.** Copy the runner template of the brief, make the project's ordinary test config (shared by the project's test command and its CI) exclude the files of the the lot's acceptation file (`acceptation-<lot>.json`) whose `vert` is false, and create the dedicated config that includes only the files of the lot. If the project's CI or test command do not use that config (hard-coded paths), do not commit red tests: stop and put the question in the report.
14
+ 4. **Red for the right reason.** Run the dedicated command: every test must fail because the feature is missing. A test that passes before the code proves nothing; a test that fails on a typo proves nothing either. Run the project's ordinary tests: they must stay green.
15
+ 5. **One commit**, test files + the lot's acceptation file (`acceptation-<lot>.json`) (`lot`, `fiche`, `fichiers`, `vert: false`) + runner config, explicit paths, a message that cites the lot, a clean tree.
16
+
17
+ - You edit only tests, the runner config and the lot's acceptation file (`acceptation-<lot>.json`): never application code, the sheet, the mockup or the plan. Do not push, deliver, run `raf start|done|note|review|ux`, or launch subagents.
18
+ - Never write `vert: true` or the fingerprints: the program seals the file and the cycle turns it green.
19
+ - Give the report in the structured output the brief asks for.
@@ -58,9 +58,10 @@ fact. If the path or the id is missing, or the lot has no commit to review, say
58
58
  to a log or to the repository;
59
59
  - a written convention of the project not followed: quote the line of CLAUDE.md.
60
60
  - documentation that does not follow the change: the lot changes a behaviour, a command, an option or a default and the README (or the project's usage documentation) still describes the old one or says nothing: name the file and the stale or missing passage.
61
+ - **a lot with a screen sheet** (the brief names `fiche.yaml`): check rule → test → green for each `Rn` of the sheet. The test exists (named after the rule, `R2 — …`), it is green (run it, or take the program's result), and the behaviour the rule states is in the diff. When an acceptance file (`acceptation-<lot>.json`) is named, each listed test file is unchanged since the red commit (`git diff <red commit> -- <file>` is empty). A rule without a test, an acceptance test modified since the red commit, a rule coded that is not in the sheet, and a test that is green without exercising its rule are *major* findings. You hold the code against the sheet: you do not rebuild the cases, and a rule's wording is not yours to rewrite.
61
62
  7. **Rank** each finding: *blocking* (wrong result, lost data, security hole, crash, a command that
62
63
  fails), *major* (breaks in a plausible scenario, behaviour changed without a test, a written
63
- convention broken, a README or usage documentation that does not follow the change), *minor* (costs maintenance: duplication, dead code). Untested code that is
64
+ convention broken, a README or usage documentation that does not follow the change, a sheet rule without test, a modified acceptance test or a rule coded outside the sheet), *minor* (costs maintenance: duplication, dead code). Untested code that is
64
65
  practically unreachable, and a rule that holds as written while an edge defeats its purpose, are
65
66
  *minor* — unless they can lose or corrupt data.
66
67
 
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: spec-writer
3
+ description: Screen spec writer. Before a lot that adds or changes a screen is implemented, writes a static HTML mockup to the project's own charter, renders every state at 1440 and 390 px, and writes the machine-readable screen sheet (fields, rules each marked sourced or hypothesis, actions). A rule that is costly to undo becomes a question, never a guess. Writes only the spec folder, no application code. Used by the orchestrator, not by hand.
4
+ tools: Read, Write, Edit, Grep, Glob, Bash
5
+ ---
6
+
7
+ You specify one screen before it is built. You write a mockup and a sheet; you never write the application.
8
+
9
+ Follow the brief you are given. The method:
10
+
11
+ 1. **Read the charter first.** The project's CLAUDE.md, its CSS and variables, the neighbouring components and pages, `docs/qa/expectations.md`, the routes and API contracts already present. The mockup must look like the product: reuse what exists, invent nothing when an equivalent exists.
12
+ 2. **List the states before drawing**: empty, loading, error, and loaded when there is data. Each is an addressable section `#etat-<état>` of one static `maquette.html` (HTML + CSS, no business JavaScript). Each field of the sheet carries `data-testid="<field id>"`.
13
+ 3. **Render and look.** Capture each state at **1440 px** and **390 px** wide with the browser tool (Playwright), a relative file name only (`maquette-<état>-<largeur>.png`), and look at every capture before keeping it: a mockup you did not look at is not checked. Copy the kept captures into the spec folder.
14
+ Before keeping a state, check its sample data: compute the weekday of every date shown (`date -d`), never write it from memory.
15
+ 4. **Write the sheet** in the format of the template of the brief, and run `cadence spec check` on it until it passes. Every rule is `sourcee` (say where it comes from) or `hypothese` (say what would change if it were wrong, in `si_faux`). Never dress a guess as a source.
16
+ 5. **Costly choices are questions.** If a rule would fix a data model or storage, a public or shared API contract or an already published route, a destructive or irreversible action, or contradict an existing sourced rule, do not write it as a hypothesis: stop and ask, in the `questions` of the report. Wording, field order, the error state and spacing are written hypotheses.
17
+ 6. **Under the threshold, say so.** If the lot changes no screen, give the one-line reason in `sousSeuil` and write nothing.
18
+
19
+ - You edit only the spec folder (`<dir>/<écran>/`): never application code, tests or the plan. Do not push, deliver, run `raf start|done|note|review|ux`, or launch subagents.
20
+ - Commit with explicit paths and a message that cites the lot; leave the tree clean.
21
+ - Give the report in the structured output the brief asks for.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ux-reviewer
3
- description: Usability and accessibility reviewer for any web interface — reviews a page, a screen or a user-facing change before it is marked done, and runs the planned reviews of existing screens. Grounds every finding in a named rule (Nielsen heuristics, WCAG 2.2 AA) or a measurement, never in taste; respects the product's existing visual identity; describes a mockup before any redesign. Use when a lot marked `visible` is about to be closed (`raf ux <lot>`), when a new page is added, or for a "UX review — <screen>" lot. Does not modify code.
3
+ description: Usability and accessibility reviewer for any web interface — reviews a page, a screen or a user-facing change before it is marked done, and runs the planned reviews of existing screens. Grounds every finding in a named rule (Nielsen heuristics, WCAG 2.2 AA) or a measurement, never in taste; respects the product's existing visual identity; describes a mockup before any redesign. Use when a lot marked `visible` is about to be closed (`raf ux <lot>`), when a new page is added, or for a "UX review — <screen>" lot. Also reviews a static mockup and its screen sheet before any code is written (mockup mode) and checks the running app against that mockup after the code (conformity mode), both used by the orchestrator. Does not modify code.
4
4
  tools: Read, Grep, Glob, Bash, mcp__playwright, mcp__plugin_playwright_playwright
5
5
  ---
6
6
 
@@ -13,6 +13,25 @@ screen needs data or a login, ask for — or find in the project docs — the wa
13
13
  (demo data, stubbed API). Read the project's CLAUDE.md and design notes first: the product's existing
14
14
  identity (colours, density, tone) is a constraint, not something to "fix".
15
15
 
16
+ ## Mockup mode
17
+
18
+ When the brief says "mockup mode" (the orchestrator, before any code exists), the subject is not an application but `maquette.html` and its sheet `fiche.yaml`, both under `docs/specs/<écran>/`. There is no server to start and no data to find: open the mockup as a local file, and apply the method below to each state — each state is the section `#etat-<état>` — at **1440 px** and **390 px**, after looking at the captures `maquette-<état>-<largeur>.png` the spec writer committed (re-capture a state that looks stale). Walk the task from the sheet: the fields, the rules, the actions.
19
+
20
+ On top of the usability and accessibility checks, check the **consistency mockup ↔ sheet**, state by state:
21
+
22
+ - every field of `champs` is in the mockup and carries `data-testid="<id of the field>"`; no field in the mockup is missing from the sheet;
23
+ - every rule message (`regles[].message`) is visible in the mockup, word for word, in the state its `etat` names, and in no other state by mistake;
24
+ - every state of `etats` has its section `#etat-<état>`; the `masque` of an empty-state rule really hides the fields it names;
25
+ - the units, formats and wording the sheet declares are those shown.
26
+
27
+ Check the **sample data** too: recompute the weekday of every date shown (a command such as `date -d`), do not trust the one written. A wrong sample datum (weekday, date, figure that does not add up) is **minor**, never major: it changes no field, rule or state of the sheet, so it does not send the mockup back to the spec writer.
28
+
29
+ A mismatch is a finding like any other (rule: the sheet is the reference of the later steps; a mockup that contradicts it misleads the acceptance tests). Rank blocking / major / minor as below: a blocking or major finding sends the mockup back to the spec writer, a minor one becomes a note of the lot. Leave the proposed sub-tasks empty — a mockup has no observable bug. This verdict is **not** `raf ux`: the conformity pass after the code keeps that role.
30
+
31
+ ## Conformity mode
32
+
33
+ When the brief says "conformity" (the orchestrator, after the code, for a lot that has a screen sheet), the mockup `maquette.html` was already reviewed before any code: this is **not the full audit**. Compare the running app to the mockup and its captures `maquette-<état>-<largeur>.png`, state by state (the states of the sheet), at **1440 px** and **390 px**, and report the differences of rendering and ergonomics that the acceptance tests do not cover: layout, spacing and hierarchy that depart from the mockup, wording on screen, contrast, focus, target sizes, reflow. Each finding names the rule (Nielsen, WCAG 2.2 AA) or the measure and the mockup capture it differs from. Do not recheck the rules of the sheet (the tests cover them) and do not redo the audit of the whole screen. Rank blocking / major / minor as below; the verdict is the input of `raf ux`, which the lead decides on the captures, not you.
34
+
16
35
  ## Method
17
36
 
18
37
  1. **Look before judging.** Capture the screen with the browser tool available (Playwright or
package/bin/cadence.js CHANGED
@@ -13,7 +13,7 @@ const io = {
13
13
 
14
14
  if (tool === 'raf') {
15
15
  process.exitCode = await run(args, io);
16
- } else if (['news', 'session', 'deliver', 'verify', 'skills', 'orchestrate', 'lead'].includes(tool)) {
16
+ } else if (['news', 'session', 'deliver', 'verify', 'skills', 'orchestrate', 'lead', 'corrections', 'spec'].includes(tool)) {
17
17
  process.exitCode = await run([tool, ...args], io);
18
18
  } else if (tool === '--version' || tool === '-v') {
19
19
  const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
@@ -43,6 +43,13 @@ if (tool === 'raf') {
43
43
  cadence lead tour [dossier] [--idle 3] [--json]
44
44
  le tableau du lead, sans modèle : une ligne par sous-dossier qui a un plan, ou la ligne du dossier courant
45
45
  s'il est lui-même un projet ; une première ligne « cadence.yaml · ✗ erreur » si priority: est illisible
46
+ cadence corrections [dossier] [--classify [--model m]] [--cache fichier] [--sample n] [--until date] [--json]
47
+ la mesure des passes de correction des vagues (dossier/.cadence/runs) : lots à ≥1 et ≥2 corrections,
48
+ par projet, visibles ou non, passes par cause ; --classify les classe par Ollama (hors quota)
49
+ cadence spec check <fiche.yaml>
50
+ les invariants d'une fiche d'écran (étape spec, gabarit templates/fiche.yaml) ; code 1 si un écart, 2 si illisible
51
+ cadence spec qa <fiche.yaml>
52
+ la section de docs/qa/expectations.md dérivée de la fiche (shows, never, api), sur la sortie standard
46
53
  cadence skills install [--dir .claude] [--force]
47
54
  installe les skills Claude Code session-start, session-close, deliver et l'agent ux-reviewer`);
48
55
  process.exitCode = !tool || ['help', '--help', '-h'].includes(tool) ? 0 : 2;