@sylad/cadence 1.12.1 → 1.14.1

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.
Files changed (59) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +3 -0
  4. package/agents/reference-planner.md +26 -0
  5. package/bin/cadence.js +8 -1
  6. package/dist/cli.js +197 -22
  7. package/dist/config-set.js +252 -0
  8. package/dist/config.js +49 -9
  9. package/dist/corrections.js +2 -0
  10. package/dist/git.js +42 -1
  11. package/dist/lead.js +5 -1
  12. package/dist/orchestrate/accept.js +63 -1
  13. package/dist/orchestrate/baseline.js +39 -3
  14. package/dist/orchestrate/briefs.js +1 -1
  15. package/dist/orchestrate/changelog-merge.js +40 -1
  16. package/dist/orchestrate/command.js +120 -19
  17. package/dist/orchestrate/continue.js +5 -2
  18. package/dist/orchestrate/cycle.js +318 -74
  19. package/dist/orchestrate/decisions.js +33 -0
  20. package/dist/orchestrate/guard.js +16 -0
  21. package/dist/orchestrate/integrate.js +26 -3
  22. package/dist/orchestrate/launch.js +4 -1
  23. package/dist/orchestrate/state.js +1 -1
  24. package/dist/orchestrate/workers.js +71 -0
  25. package/dist/orchestrate/worktree.js +15 -4
  26. package/dist/perf.js +12 -2
  27. package/dist/plan-commit.js +88 -0
  28. package/dist/plan.js +41 -3
  29. package/dist/ref/analyse.js +34 -4
  30. package/dist/ref/command.js +2 -1
  31. package/dist/ref/coverage.js +136 -0
  32. package/dist/ref/diff.js +99 -15
  33. package/dist/release.js +249 -0
  34. package/dist/session.js +7 -1
  35. package/dist/stale-notes.js +22 -0
  36. package/dist/verify-gate.js +138 -0
  37. package/docs/deliver.md +37 -0
  38. package/docs/fonctionnement.md +3 -1
  39. package/docs/lead.md +18 -1
  40. package/docs/orchestrate.md +71 -13
  41. package/docs/overview.md +5 -2
  42. package/docs/perf.md +4 -1
  43. package/docs/raf.md +49 -1
  44. package/docs/ref.md +61 -3
  45. package/docs/releasing.md +43 -2
  46. package/docs/session.md +8 -0
  47. package/docs/skills.md +1 -0
  48. package/docs/spec.md +2 -0
  49. package/docs/stabilite.md +2 -0
  50. package/docs/whats-new.md +9 -0
  51. package/package.json +3 -3
  52. package/skills/lead/SKILL.md +6 -4
  53. package/skills/orchestrate/SKILL.md +1 -1
  54. package/skills/session-close/SKILL.md +2 -0
  55. package/skills/session-start/SKILL.md +2 -1
  56. package/templates/orchestrate/fix-docs.md +1 -0
  57. package/templates/orchestrate/fix-minors.md +1 -0
  58. package/templates/orchestrate/fix.md +2 -0
  59. package/templates/orchestrate/implement.md +4 -0
package/docs/overview.md CHANGED
@@ -64,9 +64,10 @@ The two plugins are independent. `cadence@cadence` carries the rituals, which ca
64
64
  | [docs/raf.md](raf.md) | the plan: commands, plan file, foreign plan formats, Gantt |
65
65
  | [docs/orchestrate.md](orchestrate.md) | waves of sessions: budgets, spec, accept and review steps, neighbouring repositories, one worktree per lot (`orchestrate.worktrees: true`, on in cadence's own `cadence.yaml`, off by default elsewhere; `--integrate`, `--replay`, `--remove-worktree`; recovery of a handed-back lot's branch and the `CHANGELOG.md` union at the integration are described there) |
66
66
  | [docs/deliver.md](deliver.md) | delivery: wait for CI, deploy, verify the effect |
67
- | [docs/spec.md](spec.md) | the screen and back-end sheets, `cadence spec check\|qa\|reseal` |
67
+ | [docs/releasing.md](releasing.md) | releasing: `cadence release patch\|minor\|major` prepares the version commit (version fields, CHANGELOG, `docs/whats-new.md` check) and prints the lead's steps; nothing is published by it |
68
+ | [docs/spec.md](spec.md) | the screen and back-end sheets, `cadence spec check\|qa\|reseal\|green` |
68
69
  | [docs/lead.md](lead.md) | the lead workflow and `cadence lead tour` |
69
- | [docs/ref.md](ref.md) | reference documents: `cadence ref add` (rendered pages, positioned text, images, figure index), `cadence ref measure` (colours, WCAG contrast, boxes, OCR, font size), `cadence ref check` (the inventory schema, `templates/inventaire.json`), `cadence ref eval` (recall, precision, false « read », tokens per page against a known inventory), `cadence ref corpus` (the synthetic corpus with a known truth, rendered by Playwright) `cadence ref diff` (reconciles two readings of a document by program) and `cadence ref analyse` (one reading by the `reference-analyst` agent; `--double` for two independent readings, `ref diff`, a third look by `reference-verifier` and the reconciled inventory, an option whose measurement showed no gain; 20 pages at most per reading) |
70
+ | [docs/ref.md](ref.md) | reference documents: `cadence ref add` (rendered pages, positioned text, images, figure index), `cadence ref measure` (colours, WCAG contrast, boxes, OCR, font size), `cadence ref check` (the inventory schema, `templates/inventaire.json`), `cadence ref eval` (recall, precision, false « read », tokens per page against a known inventory), `cadence ref corpus` (the synthetic corpus with a known truth, rendered by Playwright) `cadence ref coverage` (which elements of the inventory no done lot covers, nor a written exclusion), `cadence ref diff` (reconciles two readings of a document by program) and `cadence ref analyse` (one reading by the `reference-analyst` agent; `--double` for two independent readings, `ref diff`, a third look by `reference-verifier` and the reconciled inventory, an option whose measurement showed no gain; 20 pages at most per reading) |
70
71
  | [docs/stabilite.md](stabilite.md) | what is guaranteed from 1.0.0 and what is not |
71
72
 
72
73
  Also: [news](news.md) (changelog, UX, code and QA reviews, documentation that follows the code), [session](session.md), [corrections](corrections.md), [perf](perf.md), [skills and agents](skills.md), [cadence-hud](cadence-hud.md), [releasing](releasing.md), [overview](overview.md), [how it all works](fonctionnement.md) (four figures).
@@ -79,8 +80,10 @@ Also: [news](news.md) (changelog, UX, code and QA reviews, documentation that fo
79
80
  - **session**: `session start` and `session close` gather the facts of a work session (each lot in progress shows its commit count, `0 commit` included, next to its last activity).
80
81
  - **deliver**: wait for the CI of the pushed commit, run the deploy commands, then **verify the effect**; a delivery is done only when its checks pass. A failed delivery is logged as a *red delivery* with its class (refusal, CI, deploy, check) and the last lines of the failing command's output. While a wave runs, `cadence deliver --sha <sha>` is accepted when no commit of the sha belongs to a lot that is not ready, so a ready lot ships while the wave runs.
81
82
  - **auto-verification** (L236): before it reports, an `implement` or `fix` session re-reads the complete diff of its lot (of its fix commits, in `fix`) against the grid of the `code-reviewer` (code bug, architecture drift, architecture documentation, edge cases, one test per changed behaviour), fixes what it finds and writes an « auto-vérification » paragraph in its report; the measure is `cadence corrections --classify` and the share right the first time of `cadence perf`.
83
+ - **real walkthrough and decisions** (L344): once the tests are green an `implement` session plays what it delivered as a user (the command in a throwaway repository following its own documentation, the screen in each state with the failure in view) and reports it under « parcours réel »; the notes of the lot and of its parent that record a decision of the human reach the `implement` and `fix` briefs under « Decisions to respect », a departure being a question, never a choice (`docs/orchestrate.md`).
82
84
  - **perf**: `cadence perf` is the dashboard of the workflow (speed next to quality, `⚠` on a trend), including the red deliveries and the blocking QA findings; `cadence lead tour` opens with its *perf header*, one line per `⚠`, nothing when stable; a rise of the tokens per lot names the step that carries it, and when the share right the first time rose too it reads as quality paid for, not a wrong estimate ([docs/perf.md](perf.md)).
83
85
  - **doc-keeper** (L306): a generic agent that reads the diff of a lot and the project's map of documents (`docs.sync`, README, `docs/`, CHANGELOG, news), says which documents must change and updates them (or only lists them, read-only); `cadence orchestrate` calls it before the review when `docs.sync` reports a document behind the lot (a lot never ends ready with that gap open: the documentation is written, or the gap is acknowledged with `raf docs-ok <lot> --reason`, L317), the lead by hand; a document outside the repository only through the `docs.articles` key of the project's `cadence.yaml` (it then proposes a lot, never writes it) ([docs/news.md](news.md#the-librarian-doc-keeper)).
86
+ - **reference-planner** (L367): an agent that reads an inventory and the plan and proposes lots that cite the ids they cover, feasible or blocked, with their dependencies; it creates nothing (`cadence ref coverage` lists what is left).
84
87
  - **reference-analyst** (L265): an agent that reads one reference document (mock-ups, a spec with figures, a norm) page by page and zone by zone, measures with `cadence ref measure`, and writes a reading (`lectures/a.json`) in the format of `templates/inventaire.json`; `cadence ref analyse` launches it for one reading and has the program check the file and count the tokens (once by default; with `--double` (L266) twice, readings A and B in `lectures/a.json` and `b.json`, which must not see each other; [docs/ref.md](ref.md#cadence-ref-analyse-documentpdf---sections-3-59---slug-name---model-sonnetopushaiku---model-b-sonnetopushaiku---seuil-30---double)).
85
88
  Reviews are opt-in gates: `ux-reviewer` (no user-facing change is done before its usability review), `code-reviewer` (no lot with commits is done before its code review) and `qa-reviewer`, which walks the delivered app in a real browser.
86
89
 
package/docs/perf.md CHANGED
@@ -35,10 +35,13 @@ current window, with at least 10 classified passes) is flagged by a `⚠` even w
35
35
  `part des lots visibles revus par une étape ux` is the share of the visible lots rendered in the window with at least one `ux` step that ended `ok` (so a small visible lot, reviewed in `review-small`, is not in it). It is informational: no `⚠`, no quality twin (`interventions.dedicatedUx` in `--json`), `n/d` without a visible lot.
36
36
  - **Pre-check share of `oui`** (L288). `part de « oui » du précheck` is the share of the lots rendered in the window whose journal records a pre-check verdict (`precheckVerdict`) that is `oui` (the deliverable was already there; an unproven `oui` is recorded `partiel`). Compare the current window with the previous one before and after a change of `orchestrate.precheck` or of the pre-check criterion (the title rule of L288): a share that stays low means the pre-check costs more than it saves. A journal older than L288 has no `precheckVerdict`: its verdict is read back from the lot (`livrable déjà présent` → `oui`, pre-check finding in the brief → `partiel`, otherwise `non`), so the window before the change is measurable. A journal written since L288 whose pre-check report was unreadable (it keeps the `contrôle préalable illisible` warning, no `precheckVerdict`) has no verdict and is not counted, not read back as `non` (L293). Lots with no successful `precheck` step are not counted; informational, no `⚠`, no quality twin (`precheck.yes` in `--json`), `n/d` without a verdict.
37
37
  - **Pre-check measured per lot** (L322). Under the section « Contrôle préalable », for the current window: the split `oui` / `partiel` / `non` of the rendered lots (`précheck : oui 1 · partiel 0 · non 1`); the local sessions (`précheck local : n sessions, k échecs, m min`: how many, how many ended without a usable report, wall time; a local session that ended `ok` but whose report was unreadable, so that the lot fell back on Sonnet, counts as a failure, and its line says `local échec`, `--json` `local.status: "illisible"`); the Sonnet sessions of the pre-check, which are the fallback of a local failure and the confirmation of a local `oui` (`précheck Sonnet : n sessions, t k tokens, m min`; the local model counts no token); the gain of the `oui` (`gain des « oui » : n sessions d'implémentation évitées (≈ t k tokens)`: the lots handed back without implementation, times the median of the `implement` steps of the window; without any, the tokens read `(gain en tokens : n/d)` and are `null` in `--json`); then one line per lot (`projet:lot · verdict · local échec 10 min · Sonnet 2 min, 20 k tokens`). Nothing is printed for a window without pre-check session or verdict. In `--json`: `precheck.verdicts`, `precheck.cost` (`local`, `sonnet`, `avoided`, each `{ current, previous }` as a whole) and `precheck.lots` (current window). Read it before changing `orchestrate.precheck` or the lots it applies to: the cost of the pre-check is what it spends (`local` minutes, `sonnet` tokens), its worth is `avoided`.
38
+ - **Share within budget** (L349). `part des rendus sur budget` counts a lot against its budget **minus the share kept for the escalation** (`escalationReserve` of the journal, `docs/orchestrate.md`) as long as its escalation was not engaged: the ordinary passes stop that share earlier, so counting them against the whole budget would call a lot that hit its limit « within budget ». Once the escalation is engaged (a journal `escalation` whose issue is not `non jouée`) the share is released at run time, so all the steps of the lot, whatever their model, are counted against the whole budget. An escalation `non jouée` engaged nothing: the ordinary passes ate the share, so the lot stays counted against its budget minus the share. A journal with no `escalationReserve` (a wave before L349, or no `orchestrate.escalation`) is counted against its whole budget, as before.
38
39
  - **Model escalations** (L337). Under the section « Escalade de modèle », for the current window: `escalades de modèle : n lots · k conforme · r rendu malgré l'escalade · b non jouée · e en échec` — the finished lots whose journal carries an `escalation` (`orchestrate.escalation`, `docs/orchestrate.md`) and how it ended: the fresh review on the escalation model was compliant (`conforme`), the lot was handed back despite it (`rendu`), the lot's budget did not cover it (`non jouée`), or an escalated session returned nothing — model unavailable to the account, cut, timeout (`en échec`, the model never judged the lot); a lot interrupted during its escalation, withdrawn from the wave (`--drop`) or stopped by an incident of the repository is counted among the lots but in no outcome, never as `en échec`. Nothing is printed without an escalation. In `--json`: `escalations` (`{ current, previous }`, each `{ lots, conforme, rendu, nonJouee, echec }`). Read it to see whether the escalation model earns its cost: many `rendu` means the stronger model does not settle what the passes could not, so the brief or the sheet is at fault.
40
+
41
+ - **Tests unstable under load** (L354). Under the section « Porte de tests sous charge », for the current window: `tests instables sous charge : n tests dans k lots (rouges dans la suite, verts rejoués seuls ; précédente m)` — the tests of the rendered lots that were red in the gate's whole suite and green when the gate replayed them alone (`instables` of the lot journal, only for a project that declares `orchestrate.testReplay`, `docs/orchestrate.md`): they were neither counted nor corrected. Nothing is printed without one. In `--json`: `instables` (`{ current, previous }`, each `{ lots, tests }`). A rise says the machine is too loaded for the suite: lower the session cap or the `CADENCE_TEST_WORKERS` share before reading it as flaky tests.
39
42
  - **`--since date`** is an ISO date that ignores everything before that day in both windows (a wave created before that day is not read, even if its lots end after it); a window starting before it is *truncated* (its per-day rates divide by the days covered, no `⚠`).
40
43
  It is **not** the instant of `cadence corrections --since` (waves created strictly after).
41
- - **`--json`** prints one object `{ since, today, windows: { current, previous }, throughput, corrections, interventions, precheck, escalations, tokens, delays, durations, cost, quality, orphans, warnings }`; every indicator carries
44
+ - **`--json`** prints one object `{ since, today, windows: { current, previous }, throughput, corrections, interventions, precheck, escalations, instables, tokens, delays, durations, cost, quality, orphans, warnings }`; every indicator carries
42
45
  `{ current, previous, change, warn, twin, lots, note }` (`twin`: the path of its quality twin, e.g. `throughput.escaped`). Same values as the text.
43
46
 
44
47
  ## Tokens, delays, wall time and cost (L226)
package/docs/raf.md CHANGED
@@ -55,7 +55,8 @@ raf gantt # .cadence/gantt.html (next to the plan)
55
55
  | `raf spec <id> on\|off` | set or remove `spec:` on an existing lot (a lot that changes a behaviour, for the back-end spec step of `cadence orchestrate`, see [The spec step of a lot with `spec: true`](orchestrate.md#the-spec-step-of-a-lot-with-spec-true)); refused on a sub-task; `off` is refused on a lot that has `screen: page` (the page implies the spec: remove `screen:` first) and `on` there only says so and changes nothing; on `component` and `journey` (ordinary path since L209) both work and set or remove the back-end `spec:`. `raf spec` only takes `on`/`off`: `cadence spec check\|qa <fiche.yaml>` keeps its own subcommands. `raf check` reports a `spec:` that is neither `true` nor `false` (`spec : true ou false attendu`) |
56
56
  | `raf uses <lot> [<resource>…]` | replace the `uses:` list of a lot of any status (`done` and `dropped` included) by the names given (duplicates removed, order kept); with no name, remove the key. Prints nothing. A name is a word of lowercase letters, digits, `-` and `_` (else `ressource invalide : <name> (lettres minuscules, chiffres, - et _)`, plan unchanged); a sub-task is refused (`uses se pose sur un lot, pas sur une sous-tâche : L1/t1`); an unknown lot is `lot inconnu : <id>`. A name not yet declared is accepted: `raf check` refuses it (L251) |
57
57
  | `raf public <id> "title"` · `raf public <id> --clear` | set, replace or remove the public title of a lot |
58
- | `raf start <id>` · `raf done <id> [--force]` · `raf drop <id> [--reason text]` | dated transitions (`done` refuses open sub-tasks unless `--force`) |
58
+ | `raf start <id>` · `raf done <id> [--force]` · `raf drop <id> [--reason text]` | dated transitions (`done` refuses open sub-tasks unless `--force`, and a lot whose `acceptation-<lot>.json` is still `vert: false`, L366: closed like that it would lock every later wave of the repository, see `cadence spec green`; with `--force` it only warns on stderr) |
59
+ | `cadence spec green <lot>` | L366: run the dedicated acceptance command (`orchestrate.accept`) on a lot driven or closed by hand; green, set `vert: true` in its `acceptation-<lot>.json` and commit that file alone (subject `chore(<lot>): acceptation verte, vert: true posé par cadence spec green` or the `plan.commit` template; the resealed tests are listed in the commit body, never in the subject), resealing the fingerprints of the listed tests refined since the red commit (journal `resceaux`) so the lock goes quiet; a listed test changed but not committed is refused. Red: exit 1, nothing changed. Refused for a `todo` lot, during a wave, and while an unfinished wave keeps a lot of the repository open; see [orchestrate](orchestrate.md) |
59
60
  | `raf todo <id> [--reason text]` | put a started lot back to `todo` (`doing` → `todo`, `started:` removed, dated note « remis en attente : reason »): refused when work commits cite the lot (plan-only and version commits do not count, as `raf commits`), when the lot is not `doing` (a `done` or `dropped` lot is reopened by hand), or on a sub-task; sub-tasks and other keys are left as they are |
60
61
  | `raf migrate [--dry-run]` | move `docs/plan/raf.yaml` to `.cadence/raf.yaml` and rewrite the readers of the old path in the repository, see [Moving the plan: `raf migrate`](#moving-the-plan-raf-migrate) |
61
62
  | `raf note <id> "text"` | dated note — keep decisions next to the work |
@@ -142,6 +143,26 @@ then the legacy `docs/plan/raf.yaml`.
142
143
  - `cadence lead tour`, `session --all` and `cadence orchestrate` recognise a project by `.cadence/raf.yaml`, `docs/plan/raf.yaml` or a
143
144
  `cadence.yaml` with `plan:`.
144
145
 
146
+ ## The subject of the plan commits: `plan.commit` (L343)
147
+
148
+ `cadence orchestrate` (the lot started, the code review recorded or noted, the hypotheses and minors of a lot noted) and `cadence spec reseal` (the lot's note) commit
149
+ the plan on their own. Their subject has always been `plan: <lot> <action> (orchestrate <wave>)` (`plan: <lot> <action>` outside a wave), which a `commit-msg` hook
150
+ that enforces Conventional Commits (commitlint with `config-conventional`, husky) refuses: `plan` is not one of its types, the lot failed before any session and the next one
151
+ was handed back with the plan left staged (GitHub issue #15). `plan.commit` in `cadence.yaml` sets the subject of **all** of them:
152
+
153
+ ```yaml
154
+ plan:
155
+ commit: 'chore({lot}): {action} (orchestrate {vague})'
156
+ ```
157
+
158
+ - `{lot}` is required (a commit must cite its lot); `{action}` is what was done (`démarré`, `revue de code enregistrée`, `revue de code notée`, `hypothèses de la fiche <sujet> notées`, `mineurs de la revue de <revue> notés`, `règles R1, R2 sourcées par la réponse du lead`, `test d'acceptation rescellé (<test>)`);
159
+ `{vague}` is the wave id. A word between braces that is none of these, an empty template or one on several lines is refused when the config is read.
160
+ - Outside a wave (`spec reseal`) there is no wave: the parenthesised group that holds `{vague}` is dropped, so the template above gives `chore(L17): test d'acceptation rescellé (…)`.
161
+ - Absent, the subject is the one above, unchanged. The key needs `plan:` to be an object (`plan: .cadence/raf.yaml` as a plain path has nowhere to put it: write `plan: { path: …, commit: … }`).
162
+ - `cadence spec green` (L366) commits its `acceptation-<lot>.json` with the template too when there is one (`{action}` = `acceptation verte, vert: true posé par cadence spec green`); without one its subject stays `chore(<lot>): …`. The tests it reseals are listed in the commit body, never in the subject, which therefore does not grow with them.
163
+ - The commit of the fiche sourced by the lead's answer takes the template too (its default, `docs(<lot>): règle R3 sourcée par la réponse du lead (orchestrate <wave>)`, is already Conventional but can exceed `header-max-length` with several rules and a wave id). The `test(<lot>): …` and `chore(<lot>): …` commits of the cycle (acceptation sealed, `vert: true` set) and the work commits are already Conventional and are not templated.
164
+ - `cadence orchestrate … --dry-run` runs every plan subject each lot would write through the repository's real `commit-msg` hook (found as git finds it: `core.hooksPath` and husky included), the sheet subjects measured with a subject of real length (the lot's sheet, or the longest of the folder) and the lead's answer with the costly hypotheses it would source, and names the one it would refuse — see [docs/orchestrate.md](orchestrate.md#the-subject-of-the-plan-commits-plancommit-l343).
165
+
145
166
  ## Moving the plan: `raf migrate`
146
167
 
147
168
  `raf migrate [--dry-run]` moves a legacy `docs/plan/raf.yaml` to `.cadence/raf.yaml` and updates what reads the old path, so the
@@ -213,6 +234,31 @@ plan:
213
234
  files: [frontend/public/plan-data/plan.json]
214
235
  ```
215
236
 
237
+ ### Regenerate the published copy on every write (`plan.onWrite`, L346)
238
+
239
+ Declaring the published file is not enough when it is generated: a hand-regenerated
240
+ `plan.json` that drifts from the plan (a flag forgotten) turns the project's
241
+ « published plan up to date » check red. `plan.onWrite` makes the program run the
242
+ generator itself, after **every** write of the plan:
243
+
244
+ ```yaml
245
+ plan:
246
+ onWrite: { command: npm run plan, files: [frontend/public/plan-data/plan.json] }
247
+ ```
248
+
249
+ - `command` runs through `sh -c` at the repository root (the folder of `cadence.yaml`, whatever folder `raf` is run from), with a
250
+ 2-minute limit. It runs after `raf add|start|done|drop|todo|note|did|title|uses|public|screen|visible|spec|ux|review|ignore|docs-ok`, after the writes of `cadence orchestrate`
251
+ (start of the lot, notes of the review and of the sheet, review recorded), after the plan note of `cadence spec reseal`, after `cadence deliver` opens an article lot, and after the config lot
252
+ of `cadence config set --all`. There is one code path for all of them, so a new command that writes the plan gets it for free.
253
+ - `files` (optional list of files, relative to the repository, never outside it; a folder is refused with `plan.onWrite.files « <path> » est un dossier`) are the files the command produces. They are **kept with the plan**, like `plan.files`: a commit that touches only
254
+ them and the plan is plan upkeep, and they go **in the same commit as the plan** everywhere the program commits the plan (`cadence orchestrate`, `cadence config set`, `cadence spec reseal`, the
255
+ `hook.autostart: start` pre-commit). A produced file that is not tracked yet is added. `raf` itself never commits: for its commands, `git add` the plan and the produced files together.
256
+ - A command that fails (non-zero code, cannot start, time limit) **refuses the write**: the plan and the declared files are put back as they were, the command stops with
257
+ `plan.onWrite en échec (<command>, code 7) : <last lines of its output> — écriture refusée, plan inchangé`, and in a wave the lot is handed back with that message. With `hook.autostart: start`, the pre-commit hook says `démarrage automatique refusé : plan.onWrite en échec …`, the lot stays todo and the commit goes through without the plan (never the « raf start fait par le hook » line).
258
+ `cadence spec reseal` commits the reseal before writing its note: if `plan.onWrite` then fails, the error says `le rescellé a eu lieu (commit <sha>) mais la note du lot n’a pas été écrite` (exit 2, plan unchanged); running the command again answers « rien à resceller », so add the note by hand with `raf note` once the generator works.
259
+ A command that succeeds without producing a declared file (a wrong path in `files`) does not refuse the write, but says `raf: plan.onWrite a réussi mais le fichier déclaré est absent : <path>` on stderr — the file it really wrote would otherwise stay out of the plan's commit.
260
+ - A read-only plan (kept by another tool) never runs the command: the project's tool owns the write.
261
+
216
262
  Until the file is declared, such a commit is reported as a "commit without a
217
263
  lot" when it cites none, and counts as work on the lots it cites.
218
264
 
@@ -243,6 +289,8 @@ plan:
243
289
  notes: note
244
290
  repos: depots # the lot's neighbouring repositories (a list of paths and/or { path, cite }, or one of them)
245
291
  parent: parent
292
+ add: 'mytool add {title}' # optional: the command that creates a lot here (L342: `cadence config set --all` uses it; {title} is replaced by the quoted title)
293
+ commit: 'chore({lot}): {action}' # optional (L343): the subject of the plan commits cadence writes — see « The subject of the plan commits » below
246
294
  statuses: # raf status: their states
247
295
  todo: [prevu, specifie]
248
296
  doing: [en_cours, teste]
package/docs/ref.md CHANGED
@@ -7,7 +7,7 @@ tables drawn as pictures, message templates, figures of a norm (WMO, ICAO…). `
7
7
  turns such a document into files a session can read without losing the pictures. The whole
8
8
  design is in
9
9
  [`docs/superpowers/specs/2026-10-23-ref-documents-de-reference-design.md`](superpowers/specs/2026-10-23-ref-documents-de-reference-design.md)
10
- (issue #14); this page describes what is delivered so far: **`cadence ref add`** (lot 1 of 10), **`cadence ref measure`** (lot 2 of 10) **`cadence ref check`** with the inventory schema (lot 3 of 10), **`cadence ref eval`** (lot 4 of 10, with the synthetic corpus `cadence ref corpus`) **`cadence ref analyse`** (lot 5 of 10: the `reference-analyst` agent, one single reading) and **`cadence ref diff`** with the double reading (lot 6 of 10). **The series stops at lot 6**: the stopping point of the double reading (hypothesis H1) was not met, so lots 7 to 10 are dropped and the double reading stays an option, `--double` ([measurement and conclusion](mesures/ref-double-lecture-2026-10-25.md)).
10
+ (issue #14); this page describes what is delivered so far: **`cadence ref add`** (lot 1 of 10), **`cadence ref measure`** (lot 2 of 10) **`cadence ref check`** with the inventory schema (lot 3 of 10), **`cadence ref coverage`** (the coverage of the document by the lots of the plan), **`cadence ref eval`** (lot 4 of 10, with the synthetic corpus `cadence ref corpus`) **`cadence ref analyse`** (lot 5 of 10: the `reference-analyst` agent, one single reading) and **`cadence ref diff`** with the double reading (lot 6 of 10). **The series stops at lot 6**: the stopping point of the double reading (hypothesis H1) was not met, so lots 7 to 10 are dropped and the double reading stays an option, `--double` ([measurement and conclusion](mesures/ref-double-lecture-2026-10-25.md)).
11
11
 
12
12
  ## `cadence ref add <document.pdf> [--sections 3-5,9] [--slug name]`
13
13
 
@@ -290,7 +290,7 @@ text of a `texte`, role and content of a `composant`, figure of a `lien`…), si
290
290
  | **silence** | a question, in either reading | gathered (one question once), never sent to a third look and not counted below: a silence is not a reading that someone else contradicts |
291
291
 
292
292
  More than **30 %** of the paired-or-single elements unpaired (silences left out, `--seuil` changes it, in percent) means the two readings do not describe the same document: no reconciliation, the question goes to the lead (exit 1, nothing written).
293
- The ids of the result are renumbered `<slug>#<type>-<n>` (reading A in its order, then what B alone carries) and the references (`composant.ecran`, `etat.cible`, `statut.couvre`) follow; an element that referred to a discarded one is discarded with it, **except a paired element** (both readings carry it): it holds while one of its two versions points to a kept element, and is then `incertain` with the cause when only one version does; it is discarded only when both versions point to discarded elements (see `ref analyse`, « Reconciliation »).
293
+ The ids of the result are renumbered `<slug>#<type>-<n>` (reading A in its order, then what B alone carries), except that an element read again keeps the id it had in the inventory `--out` replaces (see `ref coverage`) and the references (`composant.ecran`, `etat.cible`, `statut.couvre`) follow; an element that referred to a discarded one is discarded with it, **except a paired element** (both readings carry it): it holds while one of its two versions points to a kept element, and is then `incertain` with the cause when only one version does; it is discarded only when both versions point to discarded elements (see `ref analyse`, « Reconciliation »).
294
294
 
295
295
  ```
296
296
  $ cadence ref diff a.json b.json --out inventaire.json
@@ -334,7 +334,7 @@ and output tokens of the session (the count of the orchestrate budget; cache rea
334
334
  in the list counts as **no answer**: the element stays `incertain` (`troisième regard sans réponse`), never a `lu` by default. No element carried by one reading only: no third look, no session;
335
335
  - the **silences** of both readings are gathered, once per question, and never sent to a third look.
336
336
 
337
- The result is **`<references.dir>/<slug>/inventaire.json`**: `genre: "inventaire"`, valid for `ref check`, ids renumbered, `usage` = `{ tokens, lectures: { a, b, regard } }` (the total of the three sessions and each one's tokens and model, what `ref eval` reads for the tokens per page)
337
+ The result is **`<references.dir>/<slug>/inventaire.json`**: `genre: "inventaire"`, valid for `ref check`, ids renumbered (an element already in the previous `inventaire.json` keeps its id), `usage` = `{ tokens, lectures: { a, b, regard } }` (the total of the three sessions and each one's tokens and model, what `ref eval` reads for the tokens per page)
338
338
  and `reconciliation` = the counts, the unpaired ratio and, for each element the third look ruled on, `{ lecture, id (in its reading), verdict, raison }`.
339
339
 
340
340
  A session cut by a signal with nothing written is started again once in a fresh session (like a review); cut twice, it is a failure (exit 2). Without `--double` the single reading is written to `lectures/a.json` and checked as above; `--model-b` and `--seuil` are refused then (exit 2).
@@ -372,6 +372,64 @@ the same number for a corpus case read whole. Without `--double` the output is t
372
372
  `docs/mesures/ref-lecture-unique-2026-10-24.md` states what the single reading is measured on and with which commands (recall, false « read », tokens per page against the corpus of `ref corpus`, the declared ceiling), and what was measured.
373
373
  The double reading is measured the same way, `ref eval` on `inventaire.json` instead of `lectures/a.json`, and compared with that baseline: `docs/mesures/ref-double-lecture-2026-10-25.md` (hypothesis H1, the stopping point of lot 6: not met, which is why `--double` is an option).
374
374
 
375
+ ## `cadence ref coverage <inventaire.json>`
376
+
377
+ Answers one question without a model: **what of the reference document is covered by a lot?** (L367, GitHub issue #19). It takes the
378
+ inventory of `ref analyse --double` / `ref diff --out`, or the reading `lectures/a.json` that `ref analyse` writes by default (a reading carries
379
+ the same elements and ids). Each element has an **id** `<slug>#<type>-<n>`, and the id **stays the element's address from one reading of the
380
+ document to the next**: `ref diff --out` reads the inventory it replaces, and every `ref analyse` (single reading or `--double`) reads what it replaces
381
+ (the `inventaire.json` of the document, else its `lectures/a.json`); they give an element read again (same type, same page, same identity, the zone that overlaps most)
382
+ its old id, the references (`ecran`, `cible`, `couvre`) following; a new element takes a number above the highest of its type, a number of a vanished
383
+ element is never reused, so a lot that quotes `doc#texte-3` keeps pointing at the same element when one is inserted before it. The written `exclusions`
384
+ come along. (`ref diff` on two readings that were never reconciled before, or a `ref analyse` of a document with no valid previous file, numbers by order.) `ref check` refuses two elements with the same id, and
385
+ `source` says the page and zone of the element. A lot **covers** an element by quoting its id in its title, its goal (`goal:`) or a note
386
+ the lead wrote on it; the sub-tasks' notes and the notes the program writes itself (title replaced, minors of a review, hypotheses, put back on hold) do not count.
387
+
388
+ ```
389
+ $ cadence ref coverage inventaire.json
390
+ ✗ exemple#texte-3 (texte p.1 zone 120,600,240,64 « Valider ») : aucun lot, aucune exclusion écrite
391
+ ✗ exemple#composant-1 (composant p.2 zone 80,40,300,60 « Layers ») : lot non fait (L12 doing)
392
+ ✗ exemple#texte-5 (texte p.1 zone 10,10,90,20 « Aide ») : justifié non pris par la fiche de L12 : service absent, sans exclusion écrite
393
+ 3 élément(s) sans lot fait ni exclusion écrite sur 11
394
+ $ echo $?
395
+ 1
396
+ ```
397
+
398
+ An element is **covered** when a lot **done** quotes its id and its sheet does not justify it as not taken, or when the file carries a **written exclusion** with its reason:
399
+
400
+ ```json
401
+ "exclusions": [{ "id": "exemple#texte-7", "raison": "décor du document, pas du produit" }]
402
+ ```
403
+
404
+ A line `<id> : <reason>` in `sujet.perimetre.hors_perimetre` of the sheet of a lot (`docs/specs/<sujet>/fiche.yaml`, `sujet.lot`) is how the spec-writer justifies an element it
405
+ does not take: that lot does not cover it, it stays a gap until the lead writes its exclusion or another done lot quotes it. (A justification written
406
+ only in the report, or in a sheet with no back part, is not read: the lead removes the id from the lot or writes the exclusion.)
407
+
408
+ `exclusions` is a key of the root of the file (`ref check` ignores it, as it ignores any unknown key). An exclusion without a
409
+ reason, or of an id that is not in the file, excludes nothing and is listed (`✗ exclusions[0].raison : …`). A lot `dropped` covers
410
+ nothing, a lot `todo` or `doing` is named in the line of the element but does not cover it. **The exclusions are written in a file that `ref analyse`
411
+ replaces** (`references.dir` is outside the repository): before it removes or rewrites `inventaire.json`, `lectures/a.json` or `lectures/b.json`, `ref analyse` copies the
412
+ `exclusions` they carry into `exclusions-<date>.json` next to them and says so (`attention : …`); `ref analyse --double` and `ref diff --out` carry those of the inventory they replace into the new one (an id that no
413
+ longer exists is then listed by this command).
414
+
415
+ Exit codes: **0** every element is covered (`couverture complète : N éléments (n par un lot fait, k exclus avec leur raison)`), **1** at
416
+ least one is not (the `✗` lines, then the count, **on the standard output**), **2** wrong call, unreadable file, a file that does not pass `ref check` or no plan. It launches no model and no system tool, reads the plan like `raf` does (`cadence.yaml` `plan:`) and the sheets under `orchestrate.spec.dir`, and writes nothing.
417
+
418
+ ### Planning the coverage: the `reference-planner` agent
419
+
420
+ The lead runs `cadence ref coverage` to see the gaps, then has the [`reference-planner`](../agents/reference-planner.md) agent read the inventory
421
+ and the plan. It **only proposes**: lots that cite the ids they cover, each **feasible** or **blocked** (`bloque_par` names the missing datum or
422
+ service, never « missing information »), what each depends on, the elements it would exclude and the silences that are questions for a human. It creates
423
+ no lot and writes no file; the lead creates the lots (`raf add "… exemple#texte-3 …"`) and writes the exclusions. Run
424
+ `cadence ref coverage` again until it exits 0.
425
+
426
+ ### Briefs of a wave
427
+
428
+ When the title, the goal or a note of a lot quotes ids of an inventory, `cadence orchestrate` puts them in two briefs (and in `--dry-run`): the
429
+ **spec-writer** takes each into its sheet (the field, rule or state that shows it quotes the id in its `source`) and **justifies each element it does not
430
+ take** (`<id> : <reason>` under « choix » of its report, and in `perimetre.hors_perimetre` when the sheet has a back part); the **ux-reviewer**
431
+ checks each of them on the finished screen and reports a missing or different one as a finding naming its id. A small visible lot has no `ux` pass: its single `review-small` pass carries the same instruction and checks the ids on the finished screen. A lot that quotes no id has the same briefs as before.
432
+
375
433
  ## `cadence ref corpus <dossier> [--sans-rendu]`
376
434
 
377
435
  Writes the **synthetic corpus with a known truth** that `ref eval` scores against (design §« Évaluation »): seven small documents,
package/docs/releasing.md CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  # Releasing
4
4
 
5
- A version exists in three places and is published in two; a release does all of it, in this order:
5
+ A version exists in three places and is published in two; a release does all of it, in this order.
6
+ `cadence release patch|minor|major [--dry-run]` (L341) prepares step 1 and prints steps 2 to 5 in order; it publishes nothing.
6
7
 
7
8
  1. Bump `version` in `package.json` (then `npm install` to refresh `package-lock.json`),
8
9
  `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json`, and write the version's section of
@@ -29,13 +30,53 @@ A version exists in three places and is published in two; a release does all of
29
30
  while an existing one is left alone. If the package is on npm but the release is still missing, re-run the job;
30
31
  the by-hand fallback is `gh release create v<version> --title v<version> --notes-file <the section of CHANGELOG.md> --verify-tag`.
31
32
 
32
- `.github/workflows/tests.yml` runs the type-check and the test suite on the same runner image, Node 24 and `npm ci` as the publish job, and never publishes: start it with `gh workflow run tests.yml --ref <branch>` or by pushing a `diag/**` branch, to see on the runner what a red publish run saw.
33
+ `.github/workflows/tests.yml` runs the type-check and the test suite on the same runner image and `npm ci` as the publish job, in a matrix of Node 22 and 24 (the minimum `engines.node` allows, and the Node the publish job uses), and never publishes: start it with `gh workflow run tests.yml --ref <branch>` or by pushing a `diag/**` branch, to see on the runner what a red publish run saw.
33
34
 
34
35
  The Claude Code plugin is read from the repository, so pushing `main` is what updates it; npm is what
35
36
  `npx @sylad/cadence` and a global install read, and only the tag publishes there. A missing tag, or a red
36
37
  publish run, leaves npm behind without any other error — 0.3.0 and 0.4.0 were never published — hence
37
38
  step 5.
38
39
 
40
+ ## `cadence release`
41
+
42
+ ```sh
43
+ cadence release minor --dry-run # says what it would write and prints the steps; writes nothing
44
+ cadence release minor # writes the version files, checks docs/whats-new.md, prints the steps
45
+ ```
46
+
47
+ It computes the next `x.y.z` from `package.json` and writes it, **only the version fields**, in `package.json`,
48
+ `package-lock.json` (the root and `packages[""]`), `.claude-plugin/plugin.json` and the `.claude-plugin/marketplace.json`
49
+ plugin that carries the name of `plugin.json` (the other plugins of the marketplace keep their own version); a file that does
50
+ not exist is skipped. In `CHANGELOG.md` the `## [Unreleased]` section becomes `## [x.y.z] - <date>` and **an empty
51
+ `## [Unreleased]` is kept above it** (without it, the `CHANGELOG.md` union of the worktree mode of `cadence orchestrate`, L314,
52
+ has nowhere to put the next lots' entries).
53
+
54
+ It refuses, with exit code 2 and nothing written:
55
+
56
+ - a tracked file modified, `docs/whats-new.md` excepted (an untracked file does not count: the commit names its paths);
57
+ - a missing `CHANGELOG.md` (the one file that is not skipped: the release renames its `[Unreleased]` section);
58
+ - an `[Unreleased]` section that is missing or holds nothing but sub-section titles;
59
+ - a version already tagged (`v<x.y.z>`);
60
+ - a `package-lock.json` that is not at the version of `package.json`, or whose dependencies differ from those of `package.json`
61
+ (a `npm install` would move them: commit that apart, before the release);
62
+ - a version in `package.json` that is not `x.y.z`.
63
+
64
+ Write the two forms of the new version in `docs/whats-new.md` **before** running the command: the file may be modified (it is the one tracked file allowed to be, since the version commit holds it) and the command then reads the forms it finds. Run after the forms are written, it exits 0; if it exits 1 the version files are already written, so fix `docs/whats-new.md` by hand and do not run the command again (it would bump once more).
65
+
66
+ `docs/whats-new.md` is **not written by the command** (the two forms are prose, written by hand or by a session): it checks that
67
+ both are there and in their place, and says where to write what is missing. The « In two lines » line of the version is the
68
+ first of the list and at most 240 characters; the long paragraph is the first of « Version by version », right after its
69
+ introduction (the newest version first, as the file is read). Exit code 1 when a form is missing, misplaced or too long: the
70
+ version files are written, the commit is not ready. `--dry-run` reads the forms the same way (nothing is written) and exits 1 on the same findings, so the forms can be checked before the real run.
71
+
72
+ It prints the lead's steps, in order, and runs none: the `git add` of exactly the files of the version commit and the commit,
73
+ `npm run eval:plugin -- --trust-plugin` (only when `package.json` has that script), `git tag v<x.y.z>`, `git push origin <branch> v<x.y.z>`,
74
+ `gh run watch`, `npm view <package> version` (not for a private package) and, only with a `.claude-plugin/plugin.json`,
75
+ the plugin update: `claude plugin marketplace update <marketplace>` first (without it the installed plugin stays at the old
76
+ version; skipped when the marketplace has no name), then `claude plugin update <plugin>@<marketplace>`, then `/reload-plugins`
77
+ in the open Claude Code session. The 2026-10-25 releases (1.10.0 to 1.12.1) were this chain done four times by hand,
78
+ once with the long paragraph inserted at the wrong place of `docs/whats-new.md`.
79
+
39
80
  ## Evaluating the plugin (before a release)
40
81
 
41
82
  `evals/` holds an evaluation suite for the plugin itself, run by `claude plugin eval` (Claude Code 2.1.263 and later). Each case is
package/docs/session.md CHANGED
@@ -42,6 +42,14 @@ loop over the sub-folders. A project that is not the root of its own git reposit
42
42
  (and exit 2) instead of the parent repository's plan. `--all` and `--depth` are refused outside `session` (`--depth` is also read by `cadence lead tour`),
43
43
  and `--all` refuses `--file`, `--config` and `RAF_FILE`: each project reads its own plan. For a one-line-per-project overview, `cadence lead tour`.
44
44
 
45
+ A note that quotes a lot already `done` or `dropped` is not relayed as it stands (L347): `session start`
46
+ prints it with the lot beside it, `- L217 à faire ⚠ note périmée : L217 done le 24-10` (`dropped` the same
47
+ way; the date is the lot's `finished`, left out when it has none; an id is read whole, so `L2` is not found in
48
+ `L217`). `session close` lists those notes under `Notes de la dernière clôture à réécrire` — nothing
49
+ changes in the verdict — and the `session-close` skill offers to rewrite them with `cadence session next`.
50
+ Generic: the check reads the ids of the project's plan, whatever their form. A note that
51
+ quotes no finished lot is shown unchanged.
52
+
45
53
  `cadence session next` without a line refuses (exit 2) and leaves the notes of the
46
54
  last close as they are — it used to erase them silently; erasing is `--clear`.
47
55
 
package/docs/skills.md CHANGED
@@ -74,6 +74,7 @@ repository with `cadence skills install` (to `.claude/skills/cadence-*` and
74
74
  `Grep`, `Glob`: it writes only its reading, never the tokens (the program counts them), never an expected inventory, and it never opens
75
75
  another file of `lectures/` (L266: with `--double`, `cadence ref analyse` launches it twice, readings A and B, which must stay independent).
76
76
  `cadence ref analyse` launches it ([ref](ref.md#cadence-ref-analyse-documentpdf---sections-3-59---slug-name---model-sonnetopushaiku---model-b-sonnetopushaiku---seuil-30---double)).
77
+ - **reference-planner** (agent, L367): reads an inventory and the plan, starts from `cadence ref coverage`, and **proposes** lots that cite the ids they cover, each feasible or blocked (the missing datum or service named) with its dependencies. Its tools are `Read`, `Grep`, `Glob` and `Bash`: it creates no lot and writes no file, the lead decides ([ref](ref.md#planning-the-coverage-the-reference-planner-agent)).
77
78
  - **reference-verifier** (agent, L266): the third look of `cadence ref analyse`. It receives only the elements that one of the two readings wrote and the
78
79
  other did not, each with the rendered page and a crop of its zone, and answers `confirme` or `ecarte` with a reason, measuring with
79
80
  `cadence ref measure` rather than by eye and never guessing (what it cannot tell is `ecarte`). Its tools are `Read` and `Bash`: it writes nothing and never sees the readings
package/docs/spec.md CHANGED
@@ -28,6 +28,8 @@
28
28
 
29
29
  `cadence spec reseal <lot> <test> --reason texte` is the lead's way to correct one sealed acceptance test of the lot in progress that contradicts its sheet (unchanged, or amended by commits of the lot, L217; of a delivered lot, also by commits of another delivered lot, L229) (of a delivered lot: add `--porteur <lot in progress>`); refused while a wave of the repository is running, or a wave that is not `done` keeps open (question waiting, suspended, queued) any lot of this repository still `doing` in its plan, the resealed lot or another (L238: one error, also when a live wave holds the lock, names each wave (live ones to wait for), its launch folder and, for each stopped wave, the single `cd <folder> && cadence orchestrate --resume --wave <wave> --drop <project>:<lot> --drop …` that closes all its open lots of the repository, the queued ones that are not `doing` in the plan included (L239); a lot `done` or absent in the plan never refuses), see [The accept step](orchestrate.md#the-accept-step-red-acceptance-tests-and-their-lock).
30
30
 
31
+ `cadence spec green <lot>` (L366, GitHub issue #18) is the lead's way to put back to green a lot driven and closed by hand (`raf done`) whose `acceptation-<lot>.json` stayed at `vert: false`: closed like that, its tests keep the lock total and every later wave of the repository is handed back with `verrou des tests d'acceptation … premier commit fautif` on lots that never touched them, and `spec reseal` does not cover it (it takes a lot `doing`, or a delivered lot at `vert: true` with `--porteur`). The program runs the lot's acceptance command (`orchestrate.accept`, same rules as the cycle) and, green, sets `vert: true`, reseals the listed tests refined since the red commit (one `resceaux` entry each) and commits the file alone, citing the lot (`chore(<lot>): acceptation verte, vert: true posé par cadence spec green`, or the project's `plan.commit` template when it has one; the subject stays short and fixed, the tests resealed are listed in the commit body, one `- <path>` line each, so a `header-max-length` hook accepts it); red, the tail of the output goes to stderr, exit 1, nothing changed; already green, nothing to do. Refused for a `todo` lot, from a session (`CADENCE_ORCHESTRATED`), during a wave of the repository and while an unfinished wave keeps a lot of the repository open (the same refusals as `spec reseal`, worded for `spec green`); a listed test changed but not committed is refused before anything runs. `raf done` refuses such a lot without `--force`, and `cadence orchestrate --dry-run` prints `acceptation rouge d'un lot clos` once per repository, see [A closed lot left at vert: false](orchestrate.md#the-accept-step-red-acceptance-tests-and-their-lock).
32
+
31
33
  `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
32
34
  (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
33
35
  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:
package/docs/stabilite.md CHANGED
@@ -31,5 +31,7 @@ From 1.0.0 cadence follows [semantic versioning](https://semver.org): what is li
31
31
  - The wording of the briefs and of the instructions inside the skills and the agents.
32
32
  - The **format of the sheets** (`fiche.yaml`: the screen sheet `templates/fiche.yaml`, the back-end sheet `templates/fiche-back.yaml`, the mixed sheet) 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.
33
33
 
34
+ **Node**: `engines.node` is `>=22.18` (the first Node that runs `.ts` files without a tool, which the test suite relies on). The minimum Node version follows the maintained LTS lines: when a Node line leaves maintenance, cadence raises its minimum in a **minor** release, announced under *Changed* in the [CHANGELOG](../CHANGELOG.md) with an explicit warning. Node 20, out of maintenance since April 2026, is no longer supported.
35
+
34
36
  There is no schema version and no migration: a file written by an earlier release keeps working, and a key a
35
37
  release adds is optional.
package/docs/whats-new.md CHANGED
@@ -4,6 +4,9 @@
4
4
 
5
5
  ## In two lines
6
6
 
7
+ - **1.14.1**: publishes 1.14.0 (tagged, never published): Node 22.18 or later is required; `plan.commit`, `plan.onWrite`, `orchestrate.testReplay`, `spec green`, `ref coverage` and `verify --gate --sha`.
8
+ - **1.14.0**: Node 22.18 or later is now required (Node 20 dropped). `plan.commit`, `plan.onWrite` and `orchestrate.testReplay` fit a wave to your hooks, files and load; `spec green`, `ref coverage` and `verify --gate --sha` are new.
9
+ - **1.13.0**: `cadence release` prepares the version commit; `cadence config set --all` sets one key in every project; waves share the machine between sessions, reserve a budget for the escalation and tolerate the lead's delivery push.
7
10
  - **1.12.1**: the escalation line of the final table follows the lot's state (a lot withdrawn or failed during its escalation no longer reads « en cours »), and a test that raced on the GitHub runner is deterministic.
8
11
  - **1.12.0**: `orchestrate.escalation: { model: fable }` plays one correction and one fresh review on that model before a wave hands a lot back; absent, nothing changes.
9
12
  - **1.11.0**: a new `orchestrate` skill gives the command line of a wave without `/lead`; the `deliver` skill says how to deliver a commit that is not `HEAD` (push that sha alone first, never forced).
@@ -32,6 +35,12 @@ Each is a paragraph in [docs/whats-new.md](whats-new.md) and a full section in [
32
35
 
33
36
  The long form of « In two lines » above (the README no longer carries a « What's new » section since L326: it links here). The full history, with the date of each version, is in [CHANGELOG.md](../CHANGELOG.md).
34
37
 
38
+ **1.14.1**: 1.14.0 was tagged but never published (a test of the Node minimum read only `[Unreleased]`, which the version commit empties, a fault of the test and not of the tool, L368); 1.14.1 publishes it as it stands, so everything listed under 1.14.0 below arrives with it, Node 22.18 or later first.
39
+
40
+ **1.14.0**: **Node 22.18 or later is now required (Node 20 dropped)** (L365, `docs/stabilite.md`, `docs/releasing.md`): `engines.node` goes from `>=20` to `>=22.18`, the first release that runs `.ts` files without a tool, which the test suite depends on, and Node 20 is out of maintenance; it ships in a minor version because the minimum Node version now follows the maintained LTS lines. Upgrade Node before installing it. A wave fits the project it runs in. `plan.commit` in `cadence.yaml` (L343) is a template (`{lot}`, `{action}`, `{vague}`) for the subject of every plan commit, so a `commit-msg` hook that enforces Conventional Commits no longer fails a lot before any session, and `--dry-run` plays each subject through the repository's real hook. `plan.onWrite: { command, files }` (L346) regenerates the files derived from the plan after every write and commits them with it; a failing command refuses the write. Models are free (L345): `@<model>` of a lot and `orchestrate.review.light` / `full` take any name `claude --model` accepts. The gate runs under the project's Node, the `.nvmrc` first (L351). Fewer lots lost for nothing. `orchestrate.testReplay` (L354, `docs/orchestrate.md`) replays a red test of the gate alone before it counts, so a test that fails only under load is reported as unstable instead of triggering correction passes; a lot whose gate is green is no longer corrected (L361); the integration rebases again, up to twice, when the branch moved meanwhile (L364), and files the entries under the right `[Unreleased]` (L362). For the lead. `cadence spec green <lot>` and a refusal of `raf done` on a lot whose acceptance is still red (L366) stop a lot closed by hand from locking the tests of every later wave. `cadence ref coverage <inventaire.json>` and the `reference-planner` agent (L367) list the elements of a reference document that no lot covers. `cadence verify --gate --sha <sha>` (L348) replays the gate at a commit in a throwaway worktree. `lead tour` and `session` flag a close note that quotes a lot already done (L347). `cadence release` now prints the whole plugin update (L359), the test suite no longer depends on `TMPDIR` (L360), and the measured walk of a new user (L357) is in `docs/mesures/`.
41
+
42
+ **1.13.0**: a lead of several projects loses less time on what is not the lot's fault. `cadence release patch|minor|major` (L341, `docs/releasing.md`) prepares the version commit (versions, CHANGELOG, checks of `docs/whats-new.md`) and prints the publication steps in order, without publishing anything. `cadence config set <key> <value> --all` (L342, `docs/lead.md`) sets one key in the `cadence.yaml` of every project of the folder, comments and order kept, with a config lot and a commit per project. In a wave, every session and the test gate get their share of the machine (`CADENCE_TEST_WORKERS`, cores ÷ session cap, L350), so suites no longer time out under the load of their neighbours; the lot's budget keeps a share for the escalation when `orchestrate.escalation` is declared (L349), so the escalation can actually play; the lead's own push of a ready lot during a wave no longer stops a running lot (L352, guards tested by L353); the `implement` brief asks for a real walkthrough of what was delivered and lists the human's decisions found in the notes of the lot and its parent (L344). Two tests of cadence that turned red only inside a wave are deterministic again (L355, L356).
43
+
35
44
  **1.12.1**: fixes after 1.12.0. The « escalade » line of the final table follows the lot's state (L338): a lot handed back or failed during its escalation before the model's verdict (`--resume --drop`, step exception, incident of the repository) reads « engagée, lot rendu avant le verdict du modèle » instead of « en cours », and only an escalated session that returned nothing (model unavailable to the account, cut, timeout) counts as `échec` in the table and in `cadence perf`, whose `--json` key list in `docs/perf.md` now names `escalations` and `quality`. Two tests of the worktree integration that raced on the order in which two lots take the integration lock — one of them failed the first publication run of 1.11.0 — now force that order (L339).
36
45
 
37
46
  **1.12.0**: a wave no longer hands a lot back after its planned correction passes without trying a stronger model, when the project asks for it (L337, `docs/orchestrate.md`). With `orchestrate.escalation: { model: <name> }` in `cadence.yaml` (no default: absent, nothing changes, since an account may not have the model; the name goes as it stands to `claude --model`), a review still not compliant after the planned passes — or tests still red — gets one more correction and one fresh review on that model; the lot is handed back only if that review is not compliant either. The final table says « escalade <model> » and its outcome, and `cadence perf` counts the escalations and how they ended. On 2026-10-25 two lots handed back after two passes had been taken up by hand on the ordinary models while the lead's rule was to escalate.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sylad/cadence",
3
- "version": "1.12.1",
3
+ "version": "1.14.1",
4
4
  "description": "A small, repo-native working method: a versioned plan linked to your commits, a changelog with screenshots, session rituals and deliveries proven by their effect.",
5
5
  "license": "MIT",
6
6
  "author": "Sylvain Ladoire",
@@ -49,7 +49,7 @@
49
49
  "LICENSE"
50
50
  ],
51
51
  "engines": {
52
- "node": ">=20"
52
+ "node": ">=22.18"
53
53
  },
54
54
  "scripts": {
55
55
  "build": "tsc -p tsconfig.build.json --noEmit",
@@ -64,7 +64,7 @@
64
64
  "yaml": "^2.5.0"
65
65
  },
66
66
  "devDependencies": {
67
- "@types/node": "^20.14.0",
67
+ "@types/node": "^22.0.0",
68
68
  "typescript": "^5.5.0",
69
69
  "vitest": "^2.0.0"
70
70
  },
@@ -44,7 +44,7 @@ commands (its CLAUDE.md names them), never with `raf start|done|note|ux|review`.
44
44
 
45
45
  Run `cadence lead tour` from the parent folder (one command, no subagent, no model: it reads the same
46
46
  facts as `cadence session start` for every project). It prints one line per project — lots in progress with their commit count
47
- (`0 commit` included; `silencieux Nj` when idle for more than three days), drift, notes from the last close, the next ready lot,
47
+ (`0 commit` included; `silencieux Nj` when idle for more than three days), drift, notes from the last close (a `⚠ note périmée : L217 done le 24-10` beside a note means it quotes a lot already finished: relay it as stale, never ask for that lot), the next ready lot,
48
48
  repository state — and exits 0 even when a project is in error (its line says so). `--json` gives the same
49
49
  content. Read the lines yourself; open a project's own `cadence session start` only for the one you need to
50
50
  look at closer.
@@ -109,7 +109,7 @@ ends `interrupted`, and `--resume --wave <wave>` takes it up again (the command
109
109
 
110
110
  **One worktree per lot** (`orchestrate.worktrees`, L279) is on by default in cadence's own `cadence.yaml` since 2026-10-25 (L320) and off in a project that does not set the key (the key is the whole switch: no environment variable). Two independent lots of one repository then play at once, each in its own worktree, and the program integrates them. Its options belong to that mode: `--resume --wave <wave> --integrate <project:lot>` replays a lot handed back at the integration step (the wave's output names that exact command), `--replay <project:lot>` also after a refused plan write, `--remove-worktree <project:lot> [--abandon-commits]` removes a kept worktree and branch, and `cadence orchestrate --status` and `cadence lead tour` list the worktrees kept by waves (nothing to list in the default mode).
111
111
 
112
- **Delivering while the wave runs.** A lot that turns **ready** in the journal is not left waiting: once the lead has re-verified it (section 3, point 2) and recorded its verdict (`raf done`), it delivers that lot at once, without waiting for the end of the wave. The re-check runs at that sha in a throwaway `git worktree add --detach <tmp> <sha>` (removed afterwards), never in the shared tree, which holds the lots still running. Take the sha to deliver from `git log`: the last commit of the ready lot such that no commit of a lot that is not ready (running, queued, in question, handed back) sits beneath it — the same « livrable jusqu'à » the final table prints. Push that sha alone (`git push origin <sha>:main`, never HEAD, which holds the code of lots still running), then `cadence deliver --dry-run --sha <sha>` and `cadence deliver --sha <sha>`: `deliver` accepts a `--sha` during a wave of the same repository when none of its commits belongs to a lot that is not ready, and refuses otherwise, naming the lots. Without `--sha` it stays refused until every lot of the repository is ready or handed back. The wave's sessions keep committing in the working tree: `--sha` never reads it. What the log keeps is `<sha>`, unless the delivery script declares another deployed commit in `CADENCE_DEPLOYED_FILE`; if HEAD moved during the delivery without that declaration, `deliver` warns (« la tête a avancé pendant la livraison ») and the log keeps `<sha>`: it is not a failure. This is the measured gain: a ready lot used to wait for the slowest lot of its wave (1,554 lot-minutes between « ready » and the end of the wave over 28 waves).
112
+ **Delivering while the wave runs.** A lot that turns **ready** in the journal is not left waiting: once the lead has re-verified it (section 3, point 2) and recorded its verdict (`raf done`), it delivers that lot at once, without waiting for the end of the wave. The re-check runs at that sha with `cadence verify --gate --sha <sha>` (a throwaway worktree whose untracked dependencies are linked from the main tree, removed afterwards), never in the shared tree, which holds the lots still running. Take the sha to deliver from `git log`: the last commit of the ready lot such that no commit of a lot that is not ready (running, queued, in question, handed back) sits beneath it — the same « livrable jusqu'à » the final table prints. Push that sha alone (`git push origin <sha>:main`, never HEAD, which holds the code of lots still running; the wave tolerates exactly this push — the journal says « push du lead (livraison de <lot>) toléré » — because the sha is an ancestor of HEAD holding no commit of a lot of the wave that is not ready (a commit that cites no lot passes), whereas any other push still stops the wave as an incident), then `cadence deliver --dry-run --sha <sha>` and `cadence deliver --sha <sha>`: `deliver` accepts a `--sha` during a wave of the same repository when none of its commits belongs to a lot that is not ready, and refuses otherwise, naming the lots. Without `--sha` it stays refused until every lot of the repository is ready or handed back. The wave's sessions keep committing in the working tree: `--sha` never reads it. What the log keeps is `<sha>`, unless the delivery script declares another deployed commit in `CADENCE_DEPLOYED_FILE`; if HEAD moved during the delivery without that declaration, `deliver` warns (« la tête a avancé pendant la livraison ») and the log keeps `<sha>`: it is not a failure. This is the measured gain: a ready lot used to wait for the slowest lot of its wave (1,554 lot-minutes between « ready » and the end of the wave over 28 waves).
113
113
 
114
114
  **Free resources.** While a wave is live or a session is held with `cadence lead hold`, `cadence lead tour` and `cadence orchestrate --continue` print, after the free slots line, `prêts, ressources libres : <project>:<lot> <title> (<resources>) · …`: the ready lots whose shared resources (`uses:`) nothing holds. Read it again each time an agent comes back (a session ended, a lot handed back or ready) and each time a lot is blocked (a question, a refusal, a resource taken), **before waiting** for the next transition: a lot listed there can start now, so start it (with the free slots line saying a slot is free) instead of waiting behind the blocked one. The line is a display: nothing is locked, and it never raises the cap — no `créneaux libres`, no new session. No line means no ready lot is free: wait.
115
115
 
@@ -126,7 +126,7 @@ suspended (budget or usage limit; `--resume --budget …` continues).
126
126
  What the orchestrator does **not** do, and stays with the lead: choose the lots (with the human), bring the
127
127
  questions back (`--resume --wave <wave> --answer <project>:<lot> "…"`, naming the wave: a bare `--resume` is refused when several waves are unfinished), look at the UX reviewer's captures and record
128
128
  `raf ux` (the orchestrator reports its verdict, it never records it; who decides it is the `lead.ux` setting, section 2c), re-verify (section 3, point 2),
129
- `raf done`, push and deliver. **A locked acceptance test that contradicts the sheet** (the lot is handed back with `verrou des tests d'acceptation`, or the session's question says its own test is wrong, e.g. a regex that rejects a sentence the sheet allows) has a path, and it is the lead's, never a session's: correct the test in the working tree (the sheet is left as it is; if it was amended, **commit it first, citing the lot**: an amended sheet whose every commit cites the lot is accepted, L217, never put it back to the red state), then `cadence spec reseal <lot> <test> --reason "why it contradicts the sheet"` (outside any wave): the program redoes the fingerprint of that one test, writes the reason in `acceptation.json` (`resceaux`) and as a note of the lot, commits both, and the lock keeps everything else. For a **delivered** lot (`vert: true`) whose contract does not change but whose test is unstable, add `--porteur <the lot in progress that carries the fix>`: the commit and the note cite that lot, `vert` stays true (L212). It refuses a lot that is neither in progress nor delivered, a sheet with uncommitted changes or touched by a commit that does not cite the lot, and any other listed test touched, and during a wave of that repository. It is atomic (a refused commit restores `acceptation.json` and the test), with a plan kept read-only by another tool it leaves the plan untouched and says a note is to be added by hand, with an untracked plan or one outside the repository it writes the note but does not commit it (`plan à commiter`: do not add it again), and if the commit of the note is refused the reseal stays done and the error says to commit the plan by hand. It is also refused while a wave that is not `done` (stopped on a question or the quota, or still alive) keeps open any lot of that repository still `doing` in its plan, **the resealed lot, the porteur or any other lot of the repository** (the lock hands back all of them, L238; a lot `done` or absent in the plan, an old abandoned wave, a lot of another repository with the same id never block): the error is a single message, also when a live wave holds the repository lock: it lists every wave (the live ones and the stopped ones) with its launch folder and its lots and gives, for each stopped wave, ONE command to run as it stands, `cd <launch folder> && cadence orchestrate --resume --wave <wave> --drop <project>:<lot> --drop <project>:<lot>` (a `--drop` per open lot of the repository, queued ones not yet `doing` in the plan included, since `--resume` replays the whole wave; or `--resume --wave <wave> --answer …` to let it go on); a wave still alive is waited for. Close them **first**, reseal afterwards. Do it **between two sessions**, never inside one: a resealed commit that belongs to a session of the wave is not adopted (still a lock violation), and sessions are forbidden the command. Then continue the lot: a new wave `cadence orchestrate <project>:<lot>` when it was handed back (`--resume` skips finished lots). Minor findings and proposed sub-tasks come back in the table: adding them to
129
+ `raf done`, push and deliver. **A locked acceptance test that contradicts the sheet** (the lot is handed back with `verrou des tests d'acceptation`, or the session's question says its own test is wrong, e.g. a regex that rejects a sentence the sheet allows) has a path, and it is the lead's, never a session's: correct the test in the working tree (the sheet is left as it is; if it was amended, **commit it first, citing the lot**: an amended sheet whose every commit cites the lot is accepted, L217, never put it back to the red state), then `cadence spec reseal <lot> <test> --reason "why it contradicts the sheet"` (outside any wave): the program redoes the fingerprint of that one test, writes the reason in `acceptation.json` (`resceaux`) and as a note of the lot, commits both, and the lock keeps everything else. For a **delivered** lot (`vert: true`) whose contract does not change but whose test is unstable, add `--porteur <the lot in progress that carries the fix>`: the commit and the note cite that lot, `vert` stays true (L212). It refuses a lot that is neither in progress nor delivered, a sheet with uncommitted changes or touched by a commit that does not cite the lot, and any other listed test touched, and during a wave of that repository. It is atomic (a refused commit restores `acceptation.json` and the test), with a plan kept read-only by another tool it leaves the plan untouched and says a note is to be added by hand, with an untracked plan or one outside the repository it writes the note but does not commit it (`plan à commiter`: do not add it again), and if the commit of the note is refused the reseal stays done and the error says to commit the plan by hand. It is also refused while a wave that is not `done` (stopped on a question or the quota, or still alive) keeps open any lot of that repository still `doing` in its plan, **the resealed lot, the porteur or any other lot of the repository** (the lock hands back all of them, L238; a lot `done` or absent in the plan, an old abandoned wave, a lot of another repository with the same id never block): the error is a single message, also when a live wave holds the repository lock: it lists every wave (the live ones and the stopped ones) with its launch folder and its lots and gives, for each stopped wave, ONE command to run as it stands, `cd <launch folder> && cadence orchestrate --resume --wave <wave> --drop <project>:<lot> --drop <project>:<lot>` (a `--drop` per open lot of the repository, queued ones not yet `doing` in the plan included, since `--resume` replays the whole wave; or `--resume --wave <wave> --answer …` to let it go on); a wave still alive is waited for. Close them **first**, reseal afterwards. Do it **between two sessions**, never inside one: a resealed commit that belongs to a session of the wave is not adopted (still a lock violation), and sessions are forbidden the command. Then continue the lot: a new wave `cadence orchestrate <project>:<lot>` when it was handed back (`--resume` skips finished lots). **A lot closed by hand and left at `vert: false`: `cadence spec green <lot>` (L366).** `spec reseal` does not cover it (it takes a lot `doing`, or a delivered lot at `vert: true` with `--porteur`): a lot closed with `raf done` while its `acceptation-<lot>.json` stayed at `vert: false` keeps the lock total on its tests, and every later wave of the repository is handed back with `verrou des tests d'acceptation … premier commit fautif` on lots that never touched them (issue #18). The way out is `cadence spec green <lot>`, outside any wave: the program runs the lot's acceptance command (`orchestrate.accept`), and, green, sets `vert: true`, reseals the listed tests refined since the red commit and commits the file alone, citing the lot; red, nothing changes (exit 1). `raf done` now refuses such a lot without `--force`, and `cadence orchestrate --dry-run` prints `acceptation rouge d'un lot clos` for each one before the wave starts; a lot handed back for a test of a **closed** lot it never touched is this case, not a test to reseal. Minor findings and proposed sub-tasks come back in the table: adding them to
130
130
  the plan is the lead's decision. A minor finding becomes a lot of its own only if it describes an observable bug (a wrong output, a crash, a measured regression); otherwise it stays a note of the originating lot, so that a review never feeds the next one. If an orchestrated wave is running in a repository, do not commit there
131
131
  and do not deliver it (`cadence deliver` refuses).
132
132
 
@@ -191,7 +191,9 @@ is always recorded by the lead's own `raf ux`, never by a subagent.
191
191
  itself from the commits that cite the lot, runs the checks, and returns real defects only,
192
192
  ranked, with what it could not verify and a one-line verdict.
193
193
  2. **The lead re-verifies itself**: `git log` shows the commits, the test suite and build pass when
194
- run by the lead, `raf check` is clean. A subagent is green on what it *could* test; say plainly
194
+ run by the lead, `raf check` is clean. During a wave, or in any tree that is not the lead's own, replay the gate at the lot's last sha with
195
+ `cadence verify --gate --sha <sha> [--project <dir>]` (exit 0 green, 1 red with the failing tests, 2 nothing to replay): a bare
196
+ `git worktree add` has no `node_modules` or `.venv` and reddens suites that only miss their dependencies. A subagent is green on what it *could* test; say plainly
195
197
  what nobody could verify.
196
198
  3. Fix or re-delegate what the review found; then record the verdict, `raf review <lot> "…"` with
197
199
  the code reviewer's last line brought up to date (and `raf ux <lot> "…"` for a visible lot, with
@@ -18,7 +18,7 @@ cadence orchestrate finance-tracker:L41 cadence:L18@haiku --budget 1.5M
18
18
  ```
19
19
 
20
20
  - One positional argument per lot: `<project>:<lot>`, then `@<model>` to give that lot a model (`@haiku`, `@sonnet`,
21
- `@opus`). The project is what comes before the **first `:`**, the model what comes after the **last `@`**.
21
+ `@opus`, or any model name the account has, such as `@fable`, passed as it stands to `claude --model`; `--dry-run` warns for a name outside the three aliases). The project is what comes before the **first `:`**, the model what comes after the **last `@`**.
22
22
  - **A lot id may contain « / »** (sub-tasks of a plan kept read-only by another tool, `Q4/accueil-4-ux12`): write it as is, never escape
23
23
  it, never replace it, never split it. Quote the whole argument only if the shell needs it.
24
24
  - There is no `--lot` and no `--model`: the lot and its model are always in the same argument, `<project>:<lot>@<model>`.
@@ -68,6 +68,8 @@ With no project named, run `cadence session close --all` from the parent folder,
68
68
  6. **Clean state**: everything committed and pushed, no delivery running. If the command still exits 1,
69
69
  say what remains and do NOT say the session is closed.
70
70
  7. **Three lines for next time**: `cadence session next "…" "…" "…"` — the next `session-start` shows them. The command prints the lines as recorded: report them from that output, do not run `session start` again.
71
+ If the report has a "Notes de la dernière clôture à réécrire" section, those notes quote a lot already
72
+ finished (`⚠ note périmée`): propose their rewrite in the lines below, never carry them over as they are.
71
73
  The lines replace the previous notes. Without a line the command refuses and keeps them; erase
72
74
  them on purpose with `cadence session next --clear`, only when nothing is left to say.
73
75
 
@@ -34,7 +34,8 @@ three most useful items across projects and wait. With a project named, work in
34
34
  - **Effects in production** ("Effets en production"): a red `✗` line is the first thing to say —
35
35
  a delivered feature that no longer works outranks any new lot; re-run `cadence verify` to confirm
36
36
  (a network blip also shows as red).
37
- - **Notes from the last close**, if any.
37
+ - **Notes from the last close**, if any. A note followed by `⚠ note périmée : L217 done le 24-10`
38
+ quotes a lot already finished: say it is stale, do not propose that lot.
38
39
  - **Project facts** ("Faits propres au projet"), when the project plugs its own morning script in
39
40
  (`session.start` in `cadence.yaml`): summarise what bears on today's choice — deadlines, the
40
41
  project's own planning, documentation drift — and leave the rest.
@@ -15,4 +15,5 @@ Do not stop to ask: an interpretation you settle yourself goes under "choix" wit
15
15
  You are one short session of an orchestrated wave: do not launch subagents (the Agent tool is disabled).
16
16
  Give your final report as the structured output (commits, tests, build, what you could not verify, choices).
17
17
  {{reponse}}
18
+ {{workers}}
18
19
  {{tmp}}
@@ -26,4 +26,5 @@ Give your final report as the structured output (commits, tests, build, what you
26
26
  {{reponse}}
27
27
  {{captures}}
28
28
  Browser (Playwright): if a Playwright MCP server is available in this session (only in an orchestrated wave: a brief delegated by hand has none), the orchestrator launched it with its own output directory, in the orchestrator's run directory outside the repository. {{shots}} If no such server is available, do not install or start one; if you use the Playwright CLI, write its outputs under the OS temp directory (or the temporary folder the project's CLAUDE.md names), never inside the repository, which must stay clean.
29
+ {{workers}}
29
30
  {{tmp}}
@@ -2,6 +2,7 @@ Work in `{{chemin}}` on lot `{{lot}}` — "{{titre}}" — of its plan. A fresh r
2
2
  of this lot found the defects below; fix them, and nothing else.
3
3
  {{repos}}
4
4
  {{fiche}}
5
+ {{decisions}}
5
6
  Commits of the lot so far:
6
7
  {{commits}}
7
8
 
@@ -38,4 +39,5 @@ Give your final report as the structured output (commits, tests, build, what you
38
39
  {{reponse}}
39
40
  {{captures}}
40
41
  Browser (Playwright): if a Playwright MCP server is available in this session (only in an orchestrated wave: a brief delegated by hand has none), the orchestrator launched it with its own output directory, in the orchestrator's run directory outside the repository. {{shots}} If no such server is available, do not install or start one; if you use the Playwright CLI, write its outputs under the OS temp directory (or the temporary folder the project's CLAUDE.md names), never inside the repository, which must stay clean.
42
+ {{workers}}
41
43
  {{tmp}}
@@ -3,6 +3,7 @@ Work in `{{chemin}}` on lot `{{lot}}` — "{{titre}}" — of its plan
3
3
  Goal: {{objectif}}
4
4
  {{repos}}
5
5
  {{fiche}}
6
+ {{decisions}}
6
7
  Rules: test first; commit each sub-part as soon as its tests pass, with explicit paths (never
7
8
  `git add -A` or `commit -a`), and a message that cites the lot (`feat({{lot}}): …`); run the project's
8
9
  full test suite and build before reporting; do not push, deliver, run `raf done`, `raf ux` or
@@ -18,6 +19,8 @@ Self-check before handing back (the recurring findings of the reviews). Go throu
18
19
  - no false comment: a comment, a docstring or a message never describes a behaviour the code no longer has or does not have.
19
20
  A point you cannot hold is written under "choix" or "nonVerifie" of your report, not left unsaid.
20
21
 
22
+ Real walkthrough once the tests are green, before the auto-verification below: play what you delivered as a user would, not by re-reading the diff. A command: run it in a throwaway repository (`git init` in a fresh folder of the session's temporary folder, never inside the repository), following step by step the documentation the lot wrote (README, `docs/`), every command exactly as written there; a command the documentation cannot run, or whose documented path is impossible from the state the previous steps leave, is broken. A screen: open it in each of its states, failure included, the failure shown where the action takes place (in view from the control the user just used, not above or below the fold), and take a capture of each. What breaks, fix in this same session (test first, a `fix({{lot}}): …` commit) and play it again. Then write in "resume" a paragraph that starts with « parcours réel »: what you played, what broke and was fixed, what you could not play (also under "nonVerifie"); a lot with nothing to play (no command, no screen) says so in that paragraph.
23
+
21
24
  Auto-verification once the tests are green, before the review: when the full test suite and the build pass, re-read the complete diff of the lot, commit by commit (the commits `raf commits {{lot}}` lists, each with `git show <sha>`; never a `git diff` range, which would take in the commits of other lots) against the grid of the code-reviewer agent: code bug (wrong result, unhandled error, input trusted); architecture drift (a responsibility put in the wrong module, a duplicated block, a layer skipped); docs/architecture.md (or the project's architecture documentation) up to date; edge cases (empty, absent, twice, wrong order, refused); one test per changed behaviour. What you find, fix it at once (test first, a `fix({{lot}}): …` commit) and rerun the suite and the build. Then write in "resume" a paragraph that starts with « auto-vérification »: what you re-read, what you found and fixed, what you could not hold. It is one reading of the diff, not a second review: no subagent, no new exploration, no re-reading of files the diff does not touch.
22
25
 
23
26
  Decide minor interpretation questions yourself (the wording of a message, a name, a default, the
@@ -42,4 +45,5 @@ Give your final report as the structured output, not as free text. If the plan i
42
45
  {{commits}}
43
46
  {{reponse}}
44
47
  Browser (Playwright): if a Playwright MCP server is available in this session (only in an orchestrated wave: a brief delegated by hand has none), the orchestrator launched it with its own output directory, in the orchestrator's run directory outside the repository. {{shots}} If no such server is available, do not install or start one; if you use the Playwright CLI, write its outputs under the OS temp directory (or the temporary folder the project's CLAUDE.md names), never inside the repository, which must stay clean.
48
+ {{workers}}
45
49
  {{tmp}}