@sylad/cadence 1.1.0 → 1.2.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +114 -21
- package/agents/acceptance-writer.md +3 -1
- package/agents/code-reviewer.md +6 -0
- package/agents/spec-writer.md +3 -1
- package/bin/cadence.js +4 -1
- package/dist/cli.js +145 -15
- package/dist/config.js +16 -4
- package/dist/lead.js +72 -19
- package/dist/orchestrate/accept.js +90 -4
- package/dist/orchestrate/aval.js +25 -6
- package/dist/orchestrate/briefs.js +3 -0
- package/dist/orchestrate/command.js +59 -26
- package/dist/orchestrate/continue.js +1 -1
- package/dist/orchestrate/cycle.js +260 -53
- package/dist/orchestrate/fiche.js +22 -0
- package/dist/orchestrate/launch.js +7 -7
- package/dist/orchestrate/spec.js +71 -14
- package/dist/orchestrate/state.js +2 -2
- package/dist/orchestrate/table.js +2 -0
- package/dist/plan.js +58 -1
- package/dist/spec.js +304 -77
- package/package.json +4 -3
- package/skills/lead/SKILL.md +33 -8
- package/templates/acceptation-runner.mjs +13 -5
- package/templates/fiche-back.yaml +75 -0
- package/templates/orchestrate/accept-back.md +16 -0
- package/templates/orchestrate/fiche.md +14 -0
- package/templates/orchestrate/spec-back.md +25 -0
|
@@ -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": "1.
|
|
11
|
+
"version": "1.2.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": "1.
|
|
4
|
+
"version": "1.2.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
|
@@ -32,7 +32,7 @@ acceptance tests are written from the sheet, red, by a session other than the im
|
|
|
32
32
|
implementation gets the sheet, the code review checks rule → test → green, the hypotheses go into the
|
|
33
33
|
lot's news entry, and a human is asked only about a choice that is costly to undo. The design is in
|
|
34
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
|
|
35
|
+
lots that deliver it). Delivered so far: the sheet templates `templates/fiche.yaml` (screen) and `templates/fiche-back.yaml` (a lot without a screen: `sujet`, `cas`, `regles`, `contrats`, `donnees`), `cadence spec check`
|
|
36
36
|
(the sheet's invariants) and `cadence spec qa` (the screen's `docs/qa/expectations.md` section, derived
|
|
37
37
|
from the sheet), see [spec](#spec) below, and the `spec` step of `orchestrate` itself (the `spec-writer` agent, the
|
|
38
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
|
|
@@ -40,7 +40,7 @@ the mockup (the `ux-reviewer` agent in mockup mode), see [The mockup review](#th
|
|
|
40
40
|
|
|
41
41
|
## What's new
|
|
42
42
|
|
|
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
|
|
43
|
+
**1.2.0**: the spec step reaches lots without a screen: a lot that declares `spec: true` (`raf add --spec`, `raf spec`) gets a back-end sheet of cases, rules, contracts and data (`cadence spec check`), reviewed before any code, then acceptance tests locked before the implementation, and `raf screen` lets a plan already written adopt the step; `orchestrate.accept` may be a list of runners (front and back), each run under its own root; `cadence spec reseal <lot> <test> --reason` is the lead's way out when a sealed test contradicts its unchanged sheet; `lead.ux: lead` lets the lead form the UX verdict itself; `cadence lead tour --depth n` looks for projects deeper in the folder; the budgets of a wave are recalibrated on the measured runs (750 k for an ordinary lot of 0.5 to 1 day, 1.3 M for a lot with a screen); the code in service on the cadence repository is a separate worktree, updated only by `npm run service`, so a wave can no longer put unreviewed code in service (L185–L189, L191, L192, L194–L198, L200, L201). **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
|
|
44
44
|
stops with the wave) and the lead skill that names the wave and follows its journal; lot ids with `/`
|
|
45
45
|
(sub-tasks of a read-only plan) accepted by `orchestrate`; `cadence-hud`'s first line measured in
|
|
46
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),
|
|
@@ -102,8 +102,10 @@ raf gantt # docs/plan/gantt.html
|
|
|
102
102
|
| Command | Effect |
|
|
103
103
|
|---|---|
|
|
104
104
|
| `raf init [--project name] [--prefix L] [--no-hook]` | create the plan, install the hook, add `.playwright-mcp/` to `.gitignore` |
|
|
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) |
|
|
105
|
+
| `raf add "title" [--estimate d] [--quickwin] [--visible [--screen page\|component\|journey]] [--spec] [--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; `--spec`: the lot changes a behaviour (something a user, an API client or another service can observe), written as `spec: true` right after `screen:`, `visible:`, `quickwin:` or `estimate:` (whichever comes last), shown by `raf show`, refused on a sub-task. Also set by the lead at planning time, never inferred from the title) |
|
|
106
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`) |
|
|
107
|
+
| `raf screen <id> page\|component\|journey\|none` | set, replace or remove `screen:` on an existing lot, to adopt the [spec step](#the-spec-step-of-a-lot-with-screen) on a plan already written; refused on a lot without `visible:` (like `raf add --screen`) and on a sub-task; `none` removes the key and leaves `visible:` alone |
|
|
108
|
+
| `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`](#the-spec-step-of-a-lot-with-spec-true)); refused on a sub-task; `off` is refused on a lot that has `screen:` (the screen implies the spec: remove `screen:` first) and `on` there only says so and changes nothing. `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`) |
|
|
107
109
|
| `raf public <id> "title"` · `raf public <id> --clear` | set, replace or remove the public title of a lot |
|
|
108
110
|
| `raf start <id>` · `raf done <id> [--force]` · `raf drop <id> [--reason text]` | dated transitions (`done` refuses open sub-tasks unless `--force`) |
|
|
109
111
|
| `raf note <id> "text"` | dated note — keep decisions next to the work |
|
|
@@ -206,6 +208,7 @@ plan:
|
|
|
206
208
|
title: titre
|
|
207
209
|
public: titre_public # the lot's title for the public; read when it is text, else ignored
|
|
208
210
|
screen: ecran # page, component or journey; only on a visible lot
|
|
211
|
+
spec: fiche # true or false: the lot changes a behaviour
|
|
209
212
|
status: etat
|
|
210
213
|
estimate: effort
|
|
211
214
|
created: cree_le
|
|
@@ -222,9 +225,10 @@ plan:
|
|
|
222
225
|
estimates: { S: 0.5, M: 1, L: 3 } # their effort labels, in working days
|
|
223
226
|
```
|
|
224
227
|
|
|
225
|
-
- Fields: `id`, `title`, `status`, `estimate`, `quickwin`, `visible`, `screen`, `public`, `every`, `last`, `after`, `created`, `started`,
|
|
228
|
+
- Fields: `id`, `title`, `status`, `estimate`, `quickwin`, `visible`, `screen`, `spec`, `public`, `every`, `last`, `after`, `created`, `started`,
|
|
226
229
|
`finished`, `notes`, `repos`, `parent`; one left out is read under its own name. A timestamp counts for
|
|
227
230
|
its day; a note written as plain text is one note.
|
|
231
|
+
- `spec` is the exception to « a left-out field is read under its own name »: a read-only plan's `spec:` is often the path of a spec document, so it is read only when `plan.fields.spec` maps it, and then only `true` counts (any other value is neither an error nor a spec step). Natively, `spec:` stays `true` or `false` (L198).
|
|
228
232
|
- `parent`: an entry `B33/t1-fusion` whose parent is `B33` becomes the sub-task `t1-fusion` of `B33`.
|
|
229
233
|
- Ids need no prefix: a commit belongs to a lot when its message cites one of the plan's ids as a
|
|
230
234
|
whole word (`E-A2`, `NC2.4`, `B33/t1-fusion`).
|
|
@@ -522,7 +526,7 @@ them without running `session start` again.
|
|
|
522
526
|
to look for another. `--since` and `--idle` go to every project; an error in one
|
|
523
527
|
project is printed in its section and the others still run. It replaces the shell
|
|
524
528
|
loop over the sub-folders. A project that is not the root of its own git repository gets a `✗` line
|
|
525
|
-
(and exit 2) instead of the parent repository's plan. `--all` and `--depth` are refused outside `session
|
|
529
|
+
(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`),
|
|
526
530
|
and `--all` refuses `--file`, `--config` and `RAF_FILE`: each project reads its own plan. For a one-line-per-project overview, `cadence lead tour`.
|
|
527
531
|
|
|
528
532
|
`cadence session next` without a line refuses (exit 2) and leaves the notes of the
|
|
@@ -591,7 +595,7 @@ the exit code nor the verdict.
|
|
|
591
595
|
|
|
592
596
|
## lead tour
|
|
593
597
|
|
|
594
|
-
`cadence lead tour [folder] [--idle 3] [--json]` is the lead's morning table, with no model in
|
|
598
|
+
`cadence lead tour [folder] [--idle 3] [--depth n] [--json]` is the lead's morning table, with no model in
|
|
595
599
|
the loop. From a parent folder (default: the current one) it takes every direct sub-folder that
|
|
596
600
|
holds `docs/plan/raf.yaml`, or a `cadence.yaml` with a `plan:` key (a plan kept by another tool
|
|
597
601
|
included), and for each one reads the same facts as `cadence session start` — in-process, no
|
|
@@ -618,6 +622,10 @@ the lots done / in progress / to do (dropped and recurring lots left out) and th
|
|
|
618
622
|
[`cadence-hud`](plugins/cadence-hud/README.md) draws as one progress bar per project. Projects come in the order of the
|
|
619
623
|
`priority:` key of the folder's `cadence.yaml` (the one `orchestrate --continue` reads), the others after, alphabetically; an unreadable `cadence.yaml` or
|
|
620
624
|
a `priority:` that is not a list of names (`priority: ol`, `priority: []`) keeps the alphabetical order and adds a first row `cadence.yaml · ✗ erreur : <cause>` (`project: "cadence.yaml"` with `error` in `--json`).
|
|
625
|
+
Sub-projects are looked for one level down by default. `--depth n` goes `n` levels down (same meaning as in `cadence session start --all --depth n`:
|
|
626
|
+
a folder that is a project is not entered; an integer ≥ 1, otherwise refused), and the `depth:` key of the folder's `cadence.yaml`, next to `priority:`, sets it once for all
|
|
627
|
+
(`depth: 2`); `--depth` wins over the key, and a `depth:` that is not an integer ≥ 1 adds the same first row `cadence.yaml · ✗ erreur : …` and leaves one level read.
|
|
628
|
+
`cadence-hud` asks the tour from the folder of the session, so it follows the key with no change. A project is named by its folder's name; one found below the first level is named by its path from the folder (`groupe/gamma`), unique and ready for `cadence orchestrate groupe/gamma:L1` run from there, while `priority:` and the alphabetical order read the folder's own name.
|
|
621
629
|
"Created in the last 7 days" means today and the six days before. When the folder has no sub-project but is itself a project, the tour is that project's single line
|
|
622
630
|
(this is what `cadence-hud` asks from a session opened inside a project). The tour is read-only: it changes
|
|
623
631
|
no plan. It exits 0 even when a project is in error — that project's line reads
|
|
@@ -648,7 +656,7 @@ The first baseline is in [docs/mesures/corrections-2026-10-10.md](docs/mesures/c
|
|
|
648
656
|
|
|
649
657
|
## spec
|
|
650
658
|
|
|
651
|
-
`cadence spec check <fiche.yaml>` checks a **
|
|
659
|
+
`cadence spec check <fiche.yaml>` checks a **sheet** (`fiche.yaml`, the machine-readable output of the spec step): a **screen sheet** (a lot with `screen:`), a **back-end sheet** (a lot that changes a behaviour without a screen) or a **mixed sheet** with both parts. The screen part is designed in
|
|
652
660
|
[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
661
|
[`templates/fiche.yaml`](templates/fiche.yaml) (it passes the check as is), a worked example sits next to the design. It prints one
|
|
654
662
|
`✗ …` 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:
|
|
@@ -660,6 +668,20 @@ The first baseline is in [docs/mesures/corrections-2026-10-10.md](docs/mesures/c
|
|
|
660
668
|
- `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
669
|
- `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
670
|
|
|
671
|
+
**Back-end sheet** (L187; design: [docs/superpowers/specs/2026-10-11-etape-spec-back-design.md](docs/superpowers/specs/2026-10-11-etape-spec-back-design.md)). Start from [`templates/fiche-back.yaml`](templates/fiche-back.yaml) (it passes the check as is); a worked example, a real lot of ol-companion, sits next to the design. The sheet has `sujet` instead of `ecran` (no `etats`, `champs`, mockup), and the same `regles`. The back-end invariants, one `✗ …` line each:
|
|
672
|
+
|
|
673
|
+
- `sujet` has `id` (kebab-case, the folder name `docs/specs/<id>/`), `titre`, `lot`, and a `perimetre` with `modules`, `endpoints` and `jobs` (lists of texts, at least one entry in the three) and an optional `hors_perimetre`;
|
|
674
|
+
- `cas[]` are numbered `C1`, `C2`… with no gap, each with `titre`, `acteur`, `declencheur`, `preconditions`, `nominal` (a non-empty list of steps), `resultat`, and `alternatives` — a list of `{ si, alors, regles }`, each citing at least one existing rule — or `alternatives: []` with its reason in `sans_alternative`; every case is cited by at least one rule;
|
|
675
|
+
- a back-end rule has `cas` (at least one existing case id) instead of `etat`, plus the screen rule's `enonce`, `statut` (`sourcee` + `source`, or `hypothese` + `si_faux`) and tests named `Rn — …`; `message`, `champs` and `masque` only make sense on a rule attached to a state;
|
|
676
|
+
- `contrats[]` are numbered `A1`… with no gap, each with an `appel` (`VERB /path`, `job <name>` or `commande <name>`), `entree`, `sortie`, `erreurs` — a list of `{ code, message }` where `code` is `HTTP <n>` or `log debug|log|warn|warning|error|info|critical|fatal|verbose` and `message` the exact text — or `erreurs: []` with its reason in `sans_erreur`, and the `regles` it carries exist;
|
|
677
|
+
- `donnees[]` are numbered `D1`…, each with `objet`, `note`, a boolean `existant` and a `modification` (`aucune`, `ajout` or `changement`); an existing object that is modified carries the `decision` of the lead (the answer to the targeted question). The list may be empty (`[]`: the lot touches no data).
|
|
678
|
+
|
|
679
|
+
**Mixed sheet** (a lot with `screen:` and a back-end part): `sujet` **and** `ecran` side by side, with the same `id` (the folder name) and the same `lot`. A rule is attached to a state (`etat`, a screen rule) or to cases (`cas`), at least one of the two. The `A` ids are shared: the actions of the screen and the `contrats` are numbered `A1…An` with no gap over the whole, and an action that calls an API already listed in `contrats` points to it with `contrat: Ax` instead of repeating its `appel`. An action that has its own `appel` equal to the `appel` of a contract is reported (it must point to the contract). A sheet without `ecran` refuses `actions`, `etats` and `champs` (they only make sense with a screen part), and a rule with `etat` there gets that single report. A sheet that only has `ecran` stays valid as it is (no migration); `sujet` is required as soon as the lot is back-end or mixed.
|
|
680
|
+
|
|
681
|
+
`cadence spec check` prints the same summary line for each kind (`N cas, N règles (N hypothèses), N contrats, N données` for a back-end sheet) and keeps its exit codes: 0 valid, 1 violations, 2 usage.
|
|
682
|
+
|
|
683
|
+
`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 (unchanged) sheet, see [The accept step](#the-accept-step-red-acceptance-tests-and-their-lock).
|
|
684
|
+
|
|
663
685
|
`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
686
|
(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
687
|
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:
|
|
@@ -671,6 +693,8 @@ error output, nothing on the standard one, and exits 1. The derivation is built
|
|
|
671
693
|
- `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
694
|
Actions triggered by a field stay with the acceptance tests.
|
|
673
695
|
|
|
696
|
+
`spec qa` only derives the **screen** part: a back-end sheet, which has no `ecran`, is refused (exit 2, « la fiche n'a pas de partie écran »); on a mixed sheet it reads the actions' calls through their `contrat`.
|
|
697
|
+
|
|
674
698
|
|
|
675
699
|
## deliver
|
|
676
700
|
|
|
@@ -921,7 +945,7 @@ command warns `ne lit pas les demandes de contrôle` on the error output.
|
|
|
921
945
|
plan too); then, each time the lots in play are finished, the wave **draws the next ready lots of the plan** — up to the
|
|
922
946
|
session cap — and plays them in the same wave (same budget, same state folder, journal line `continue : tire …`). A lot
|
|
923
947
|
is drawn when it is `todo`, its `after` is lifted, it is not recurring, neither its title nor a note says « à décider »
|
|
924
|
-
(« à décider avec … », « (à décider) »: a lot waiting for a human decision), it is not already in the wave, and its own budget (derived from its estimate)
|
|
948
|
+
(« à décider avec … », « (à décider) »: a lot waiting for a human decision), it is not already in the wave, and its own budget (derived from its estimate; a lot with `screen:` is worth 1.3 M whatever its estimate, or its ordinary budget plus the 350 k spec-stage allocation if that is more, and a lot with `spec: true` gets that allocation on top of its ordinary budget)
|
|
925
949
|
fits in the budget left — otherwise the next one that fits is taken (a lot that does not fit in what is left of the current
|
|
926
950
|
round is not dropped: it is tried again at the next round, once the budget allows it). A round takes at most **one lot per
|
|
927
951
|
repository** while other repositories have ready lots — the pool plays the lots of one repository one after the other, so a
|
|
@@ -946,6 +970,20 @@ limit. Before each new wave it reads the context of its own session with `cadenc
|
|
|
946
970
|
time (`cadence session next`). Stays with the human: the first choice and the order, the questions a session raised, the UX
|
|
947
971
|
reservations; a lot that is not ready, a red delivery or a blocking QA finding is reported and not chained over.
|
|
948
972
|
|
|
973
|
+
**Who gives the UX verdict (L197)**: by default the human looks at the `ux-reviewer`'s captures and gives the verdict of a `visible`
|
|
974
|
+
lot (`raf ux`). A human who is not a UX judge can set, in the `cadence.yaml` of the folder the `lead` skill works from:
|
|
975
|
+
|
|
976
|
+
```yaml
|
|
977
|
+
lead:
|
|
978
|
+
ux: lead # lead | human — default human, nothing changes without the key
|
|
979
|
+
```
|
|
980
|
+
|
|
981
|
+
With `lead.ux: lead` the lead forms the verdict itself, from the reviewer's report and its own look at the captures, records
|
|
982
|
+
`raf ux` and goes on; the human is consulted only at the slightest doubt (a reservation it cannot settle, a capture it
|
|
983
|
+
cannot read, a matter of taste), and the chain goes on with the other lots meanwhile. `cadence lead tour` prints
|
|
984
|
+
`verdict UX : lead …` as a last line when the setting is on (not part of `--json`), and `cadence.yaml · ✗ erreur : lead.ux doit
|
|
985
|
+
être « lead » ou « human »` for any other value. The setting is read from the parent folder only: a project's own `cadence.yaml` ignores it.
|
|
986
|
+
|
|
949
987
|
**Lot ids containing `/` (L120)**: the first `:` separates the project from the lot, a final `@` the model, and the lot
|
|
950
988
|
keeps its `/` (`maritime-atlas:Q4/accueil-4-ux12@haiku`); this holds for `--dry-run`, `--status`, `--resume` and
|
|
951
989
|
`--answer` too. In `.cadence/runs/<wave>/` the `/` of the lot becomes `__` (`maritime-atlas--Q4__accueil-4-ux12.json`,
|
|
@@ -996,7 +1034,7 @@ without `--effort` (see below), so `effort.precheck` has no effect on it and the
|
|
|
996
1034
|
|
|
997
1035
|
```yaml
|
|
998
1036
|
orchestrate:
|
|
999
|
-
effort: { precheck: low, spec: medium, maquette: high, accept: medium, implement: medium, fix: medium, review: high, ux: high } # defaults
|
|
1037
|
+
effort: { precheck: low, spec: medium, maquette: high, fiche: medium, accept: medium, implement: medium, fix: medium, review: high, ux: high } # defaults
|
|
1000
1038
|
```
|
|
1001
1039
|
|
|
1002
1040
|
To measure what a level costs, run the same kind of wave before and after changing the key: each step of
|
|
@@ -1013,8 +1051,8 @@ lot that already has commits is never pre-checked (resuming it is legitimate). `
|
|
|
1013
1051
|
|
|
1014
1052
|
### The spec step of a lot with `screen:`
|
|
1015
1053
|
|
|
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
|
|
1054
|
+
A lot that declares `screen:` (`raf add … --visible --screen page|component|journey`, or `raf screen <id> page|component|journey` on a lot that already exists, see [raf](#raf)) gets one more session, `spec`, **after** the pre-check and **before**
|
|
1055
|
+
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:` or `spec: true` follows the usual path, unchanged (a lot with `spec: true` and no screen has its own chain, see [The spec step of a lot with `spec: true`](#the-spec-step-of-a-lot-with-spec-true)). `--dry-run` lists the step
|
|
1018
1056
|
(`spec (sonnet)`), its command line and its brief `templates/orchestrate/spec.md`.
|
|
1019
1057
|
|
|
1020
1058
|
- **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,
|
|
@@ -1034,6 +1072,28 @@ the first implementation: `precheck → spec → maquette → accept → impleme
|
|
|
1034
1072
|
- **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
1073
|
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
1074
|
|
|
1075
|
+
### The spec step of a lot with `spec: true`
|
|
1076
|
+
|
|
1077
|
+
A lot that changes a behaviour but has no screen (`raf add … --spec`, or `raf spec <id> on`, see [raf](#raf); L188, design: [docs/superpowers/specs/2026-10-11-etape-spec-back-design.md](docs/superpowers/specs/2026-10-11-etape-spec-back-design.md)) is specified **before** it is coded, on a sheet, like a screen:
|
|
1078
|
+
`precheck → spec → fiche → accept → implement → review` (`fiche` unless `orchestrate.fiche: false`; `accept` only when the project declares `orchestrate.accept`). A lot with neither `screen:` nor `spec: true` keeps its path. `--dry-run` lists
|
|
1079
|
+
`spec (sonnet)`, `fiche (sonnet)` and `accept (sonnet)` with their command lines and briefs `templates/orchestrate/spec-back.md`, `fiche.md` and `accept-back.md`; the lot's budget gets a 350 k allocation on top of its estimate-derived budget (the worst case measured on a screen lot's steps: the back chain has not been measured yet).
|
|
1080
|
+
|
|
1081
|
+
- **The spec session**: Sonnet, the `spec-writer` agent, no Playwright. It reads the lot, the project's CLAUDE.md and the code and tests of the modules the lot touches (a rule already coded is a source, cited `file:line`), then writes only
|
|
1082
|
+
`<orchestrate.spec.dir>/<sujet>/fiche.yaml` in the format of [`templates/fiche-back.yaml`](templates/fiche-back.yaml) (`sujet`, `cas`, `regles`, `contrats`, `donnees`; no mockup, no capture, no state) and commits it with a message that cites the lot.
|
|
1083
|
+
The same rules as for a screen: a rule is `sourcee` or `hypothese` with its `si_faux`, and a hypothesis that hides a costly choice is a question (a stored model, a published contract or route, an irreversible action, a contradiction with a sourced or coded rule — the program's keyword safety net applies as is).
|
|
1084
|
+
An optional field added to an existing response is not a break when a rule of the sheet proves the old response unchanged. A lot that changes no behaviour is reported under the threshold (`sousSeuil`, warning `étape spec : sous le seuil, aucune fiche — …`) and follows the usual path.
|
|
1085
|
+
- **What the program checks**: the sheet passes `cadence spec check`, has a `sujet` block, is the lot's (`sujet.lot`), sits in the folder named by `sujet.id`, and is committed with a clean tree. Anything missing goes back to **one second `spec` session**; still invalid, the lot is handed back (`spec non conforme après 2 passes : …`).
|
|
1086
|
+
On a resume the step is skipped when a sheet of the lot (`sujet.lot`) already passes these checks and has no costly hypothesis.
|
|
1087
|
+
- **The sheet review** (`fiche`): a fresh session of the `code-reviewer` agent in **sheet mode** (Sonnet, read-only, no Playwright; `effort.fiche`, default `medium`). It reads the sheet, then the code, tests and sources of the perimeter, and checks (1) every `sourcee` rule cites a source that exists (it opens the file:line) and no `hypothese` hides a costly choice,
|
|
1088
|
+
(2) no contradiction with a rule already coded or an existing contract, (3) every contract has its empty / absent / expired / oversized / duplicate inputs and the failures of its external sources covered by a rule or a motivated `sans_alternative` / `sans_erreur`, (4) every rule has a planned test whose name says what could fail.
|
|
1089
|
+
Findings are ranked blocking / major / minor, each with its measurement. A blocking or major one sends the sheet back for a **second `spec` session** (its brief carries the findings), then the sheet is reviewed again; still not conforming, the lot is handed back with what remains (`fiche non conforme après 2 revues : …`).
|
|
1090
|
+
The `spec` session has **one budget of two sessions**, shared by the program's check and the reviews: if the check already used the second one, a non-conforming review hands the lot back at once (`fiche non conforme et la spec a déjà joué 2 sessions`), with no second review. A question to the lead (the session's own, or a costly hypothesis) and its answer open a new budget.
|
|
1091
|
+
Minor findings become notes of the lot (`Revue de la fiche — mineur : …`, one per finding, committed with the plan; on a read-only plan they become `[note à poser]` proposals), not lines of the final table. This verdict is **not** `raf review`: the review of the code keeps that role. `orchestrate.fiche: false` skips the step.
|
|
1092
|
+
- **A lot with a screen and a behaviour**: it is a lot with `screen:` whose **sheet** has a back part (a `sujet` block next to `ecran`, same folder), never a `spec: true` beside `screen:` (`raf spec <id> on` has no effect on a lot with a screen). The program reads the sheet, not the plan: as soon as the sheet has a `sujet` block (the contracts), the `code-reviewer` also reviews it,
|
|
1093
|
+
the chain is `spec → fiche → maquette → accept`, and the findings of the two reviews go together to a single second `spec` session. The brief of the spec of a lot with a screen offers the back part (and joins its template) without making it compulsory; a lot whose sheet has no `sujet` keeps its chain, without `fiche`. `--dry-run` cannot list `fiche` for a lot with a screen (the sheet does not exist yet).
|
|
1094
|
+
- **Acceptance and code**: `accept` is the screen's step, with a back brief (`accept-back.md`: cases call the contracts of `contrats[]` as close as possible, external sources simulated from `entree`; no `data-testid`). `implement`, `fix` and `review` receive the sheet (cases, rules, contracts) as for a screen, without mockup; the review also checks that each contract is held (output, exact codes and messages of the errors).
|
|
1095
|
+
- **Hypotheses**: a lot without a screen has no News entry. Once the sheet is final — after its review and the second `spec` session if there was one, just before `accept` or `implement`, and also for a sheet already present on a resume — the program writes **one note of the lot per hypothesis** (`Hypothèses (fiche <sujet>) — R3 : … ; si faux : …`, not duplicated on a resume) and commits it with the plan; on a plan kept by another tool the lines become proposals (`[note à poser] …`). The end-of-wave table lists them under each lot (`hypothèse de la fiche : …`) for the lead to relay.
|
|
1096
|
+
|
|
1037
1097
|
### The mockup review: before any code
|
|
1038
1098
|
|
|
1039
1099
|
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`.
|
|
@@ -1044,27 +1104,39 @@ After a valid spec, a lot with a sheet gets a UX review of its mockup, `maquette
|
|
|
1044
1104
|
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
1105
|
`#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
1106
|
- **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`.
|
|
1107
|
+
still not conforming, the lot is handed back with what remains (`maquette non conforme après 2 revues : …`) and nothing is implemented. The same budget of two `spec` sessions applies as for the sheet review: if the program's check already used the second one, a non-conforming review hands the lot back at once (`maquette non conforme et la spec a déjà joué 2 sessions`); an answer to a question of the lead opens a new budget. 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
1108
|
- **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
1109
|
- **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
1110
|
- **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
1111
|
|
|
1052
1112
|
### The accept step: red acceptance tests and their lock
|
|
1053
1113
|
|
|
1054
|
-
After a valid spec, and only when `cadence.yaml` declares `orchestrate.accept` (the project's **dedicated command**, which
|
|
1114
|
+
After a valid spec, and only when `cadence.yaml` declares `orchestrate.accept` (the project's **dedicated command**, or a list of them, which run *only* the acceptance tests of one lot), a lot with a sheet gets one more
|
|
1055
1115
|
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
1116
|
`--dry-run` lists the step (`accept (sonnet)`) and its brief `templates/orchestrate/accept.md`.
|
|
1057
1117
|
|
|
1058
1118
|
- **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
1119
|
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
1120
|
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.
|
|
1121
|
+
- **One command or a list of runners** (L189). `orchestrate.accept` is a string or a **list** of commands, for a project with a front and a back runner (Vitest in `frontend/`, Jest in `backend/`):
|
|
1122
|
+
|
|
1123
|
+
```yaml
|
|
1124
|
+
orchestrate:
|
|
1125
|
+
accept:
|
|
1126
|
+
- cd frontend && npx vitest run -c vitest.acceptation.config.ts
|
|
1127
|
+
- cd backend && npx jest -c jest.acceptation.config.js
|
|
1128
|
+
```
|
|
1129
|
+
|
|
1130
|
+
The program runs **each** command from the repository root with `CADENCE_ACCEPTATION` (and `{acceptation}` substituted) and `CADENCE_ACCEPTATION_ROOT`, the command's **root**: the folder of its leading `cd <folder> &&`, else the repository (`.`). A command takes **only the files listed under its root**: `acceptationOnly()` of the runner template returns them relative to that root, where the runner starts. A command with **no listed file under its root is not run**; a listed file under **no root** is a deviation of the step (`fichiers listés … sous la racine d'aucune commande de orchestrate.accept`, one second pass, then `accept non conforme après 2 passes`). **Red check**: every command that is run must fail (the deviation names the one that passes); **green**: `vert: true` is set only when all of them pass, and a lot sent back to `fix` is told which commands are still red. A string keeps its behaviour: **it ignores its `cd` for the root** — the whole repository is its root and `CADENCE_ACCEPTATION_ROOT` is `.`, so `acceptationOnly()` returns paths relative to the repository; only a list derives a root from each command's leading `cd`. One lot per app wires its back runner (dedicated config, `exclude` in the ordinary one, a line in `cadence.yaml`): that is the app's plan, not cadence's.
|
|
1131
|
+
|
|
1132
|
+
**Moving from a string to a list.** The two forms are not interchangeable: a string keeps the repository as its root, a list (even of **one** element) derives each root from the command's leading `cd <folder> &&` and sets `CADENCE_ACCEPTATION_ROOT` to it. The brief of the step and the cycle decide by the same test (a YAML list or not), so they always agree. To switch: (1) write the entries as `cd <folder> && <runner>`; (2) make the runner's config resolve from its own root (its `include` and `rootDir` relative to `<folder>`, since the runner starts there and `acceptationOnly()` returns the paths relative to that root); (3) **copy the runner template again** into the project (`templates/acceptation-runner.mjs` reads `CADENCE_ACCEPTATION_ROOT`; an older copy lists the repository-relative paths and matches nothing from a folder). A project that has not migrated stays on its string, unchanged.
|
|
1061
1133
|
- **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
1134
|
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
1135
|
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
1136
|
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
1137
|
(paths hard-coded), the session must not commit red tests and puts the question in its report.
|
|
1066
1138
|
**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.
|
|
1139
|
+
`CADENCE_ACCEPTATION=<path of the acceptation file> <command>` (with a `{acceptation}` in the command, write the path there too). For a command of an `orchestrate.accept` **list**, also set its root, which `acceptationOnly()` uses to return the files relative to where the runner starts: `CADENCE_ACCEPTATION=<path of the acceptation file> CADENCE_ACCEPTATION_ROOT=<root of the command> <command>` (the folder of its leading `cd <folder> &&`; without the variable the root is the repository `.`, and the paths are relative to it, which no runner started in a folder will match). A single string needs no root. 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
1140
|
- **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
1141
|
**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
1142
|
(`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).
|
|
@@ -1073,6 +1145,7 @@ session, `accept` (L173): `precheck → spec → maquette → accept → impleme
|
|
|
1073
1145
|
- **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
1146
|
(`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
1147
|
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).
|
|
1148
|
+
- **A sealed test that contradicts the sheet: `cadence spec reseal` (L200).** The lock is total for the lot in progress (the delivered-lot exception above never covers it), so a test that is wrong against an unchanged sheet — e.g. the regex `/\d{1,2} /` of an acceptance test rejecting « T3 2027 annoncée », which the sheet allows — would leave the lot handed back with no way out. The way out is the lead's, outside any wave: correct the test in the working tree (**the sheet unchanged**), then `cadence spec reseal <lot> <test> --reason "why the test contradicts the sheet"`. The program checks that the lot is in progress (`doing`), that the test is listed in the lot's sealed `acceptation-<lot>.json`, that the sheet is unchanged since the red commit, that **no other listed test** changed (the lock keeps everything else) and that the test did change; it then redoes the fingerprint of that one test, appends `{ test, raison, date, avant, apres }` to the `resceaux` key of `acceptation.json`, commits the test and `acceptation.json` (`test(L35): acceptation rescellée, <test> : <reason>`, the new red commit) and the lot's note with the reason (`plan: …`). It is refused during an orchestrated wave (`CADENCE_ORCHESTRATED`, or the repository's wave lock while one of its lots still works, like `cadence deliver`), with no `--reason`, and on a lot that is not in progress. Then, depending on how the lot stands: a lot waiting on a `question` is continued by `--resume --answer` (the cycle moves its red-commit anchor to the resealed commit, a rewrite of `acceptation.json` without a `resceaux` entry still being a violation); a lot handed back with `verrou des tests d'acceptation` is finished for `--resume`, so it is replayed by a new wave `cadence orchestrate <project>:<lot>`, which starts again from the red commit. A session never does it, three guards: (1) `cadence spec reseal` is in the sessions' `--disallowedTools` (like `raf done`/`review`/`ux`); (2) a resealed commit is adopted as the new red commit only if it belongs to **no session of the wave** (commits listed in each `steps[].commits`, or in `headBefore..headAfter` of any session of any lot of the wave) — otherwise it stays a violation of the lock; (3) the lock is checked at the end of **every** work session, a session that ends with a question included, so a session that replaces the test, forges the fingerprint, commits and asks a question is handed back with `verrou des tests d'acceptation` without waiting for the lead's `--answer`. The reseal is atomic: if the commit fails (a `pre-commit` hook exiting 1, say) `acceptation.json` and the test are put back as they were before the command (the lead's correction in the working tree is kept, nothing staged) and a readable error says nothing was resealed. With a plan kept read-only by another tool, the reseal itself succeeds but the plan is not touched: the note of the lot is left to the lead (the reason stays in `acceptation.json` and in the commit message; the command only says a note is to be added). With a plan outside the repository or untracked, the note **is** written in the plan file but not committed (the command says `plan à commiter`); do not add it a second time. If the commit of the note is refused (a hook), the reseal stays done: the error gives its commit and says the note, already written, is to be committed by hand.
|
|
1076
1149
|
- **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
1150
|
`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
1151
|
- **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).
|
|
@@ -1164,6 +1237,25 @@ The sessions of the wave also get `.cadence/runs/<wave>/tool/bin` (the `raf` and
|
|
|
1164
1237
|
`PATH`**, ahead of the per-project Node below and of the usual `PATH`: the `raf` a reviewer runs (`raf commits`…) is the
|
|
1165
1238
|
snapshot's, not the installed one. A wave without a snapshot leaves the `PATH` as it is.
|
|
1166
1239
|
|
|
1240
|
+
**The code in service (L195)**: on cadence's own repository, `bin/raf.js` and `bin/cadence.js` load `dist/`, so the `raf` and `cadence` of your
|
|
1241
|
+
`PATH` used to be whatever the working repository last built. The snapshot protects the wave running, not that installed tool, and a wave's
|
|
1242
|
+
sessions run `npm run build`, `npm install`… The code in service now lives in a **separate copy**: a detached git worktree built there,
|
|
1243
|
+
`<root>/releases/<sha12>`, with `<root>/service` pointing at the current one (`<root>` is `~/.local/share/cadence`), and `~/.local/bin/raf` and
|
|
1244
|
+
`~/.local/bin/cadence` linked to `<root>/service/bin/`. Nothing in the working repository (`npm run build`, `prepare`, `npm install`, `npm ci`,
|
|
1245
|
+
an uncommitted `src/` file) touches it. `npm run build` only type-checks, which is what a session of a wave runs, with the tests, before its report.
|
|
1246
|
+
|
|
1247
|
+
The lead updates the copy after the review, once the lot is accepted (`raf done`):
|
|
1248
|
+
|
|
1249
|
+
```
|
|
1250
|
+
npm run service -- <sha> # [--root dir] [--bin-dir dir] [--repo dir]
|
|
1251
|
+
```
|
|
1252
|
+
|
|
1253
|
+
The script refuses a sha that is not an ancestor of HEAD, and a sha whose commits (since the one in service; only the sha itself the first time)
|
|
1254
|
+
cite a lot whose status is not `done` (`plan:` commits are ignored). It builds the new copy aside (`npm ci --ignore-scripts`, then `tsc`) and switches
|
|
1255
|
+
`service` and the two links only once the build succeeded (atomic renames): a failed install changes nothing. The previous copy is kept for a
|
|
1256
|
+
rollback, the older ones are removed only once they are more than 7 days old, counted from the day they left service (a wave's snapshot links its `node_modules` to the copy that launched it). The first run is also what installs the links in `~/.local/bin`. It prints the fingerprint of the copy
|
|
1257
|
+
(bin, dist, package.json).
|
|
1258
|
+
|
|
1167
1259
|
### A lot whose work is in a neighbouring repository
|
|
1168
1260
|
|
|
1169
1261
|
Some lots are done in another repository that is not a cadence project (B64 of `maritime-atlas` lives in
|
|
@@ -1250,8 +1342,8 @@ upstream ref and `git ls-remote` are compared with the "before", and a read-only
|
|
|
1250
1342
|
`CADENCE_ORCHESTRATED` is set.
|
|
1251
1343
|
|
|
1252
1344
|
**Budget**: the wave counts input + cache writes + output tokens (default 2 M); cache reads are kept and
|
|
1253
|
-
shown apart. Each lot also has its own budget
|
|
1254
|
-
`--dry-run`): it bounds the *writing* passes, never the reviews. A lot that spent it gets no further implementation or
|
|
1345
|
+
shown apart. Each lot also has its own budget, the 90th percentile of the *total* measured per lot on `.cadence/runs` (all the waves a lot went through, 250 lots) for its category (L194): an ordinary lot of up to 0.5 day gets 450 k (floor: a write pass, its review, one fix pass and the short review after it; measured p90 374 k), 0.5 to 1 day 750 k (p90 732 k), then 570 k per day of estimate, 750 k staying the floor until that exceeds it, i.e. up to 1.3 day (p90 1.14 M for 2 days); a lot with `screen:` gets 1.3 M whatever its estimate (p90 1.28 M: spec, mockup, accept, conformity UX and passes), or its ordinary budget plus 350 k beyond that; a lot with `spec: true` gets its ordinary budget plus 350 k (no such lot measured yet); shown by
|
|
1346
|
+
`--dry-run` with its basis): it bounds the *writing* passes, never the reviews. A lot that spent it gets no further implementation or
|
|
1255
1347
|
fix and is handed back to the lead, but its review (and UX review) is played first; a fix pass starts only if
|
|
1256
1348
|
the remaining budget can also pay the review that follows it (65 k tokens reserved: a fixed amount close to the 90th
|
|
1257
1349
|
percentile of the full reviews, 62.7 k over 187 reviews; the short review after the minors pass has a higher p90, 67.6 k
|
|
@@ -1317,9 +1409,10 @@ orchestrate:
|
|
|
1317
1409
|
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
|
|
1318
1410
|
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
1411
|
maquette: true # default: UX review of the mockup between spec and accept (see « The mockup review »); false skips it
|
|
1412
|
+
fiche: true # default: review of the back-end sheet of a lot with spec: true between spec and accept (see « The spec step of a lot with spec: true »); false skips it
|
|
1320
1413
|
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
1414
|
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
|
|
1415
|
+
effort: { review: xhigh } # effort level per pass (see « Effort level per pass »): precheck, spec, maquette, fiche, accept, implement, fix, review, ux
|
|
1323
1416
|
ux: http://localhost:4200 # a URL, a launch command, or { command, url, timeout? } — for the UX review (see below)
|
|
1324
1417
|
permissionMode: auto # default
|
|
1325
1418
|
addDirs: [/home/me/projects/tmp] # extra directories the sessions may use
|
|
@@ -1592,11 +1685,11 @@ From 1.0.0 cadence follows [semantic versioning](https://semver.org): what is li
|
|
|
1592
1685
|
**Guaranteed**
|
|
1593
1686
|
|
|
1594
1687
|
- **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`;
|
|
1688
|
+
`note`, `did`, `public`, `screen`, `spec`, `ux`, `review`, `commits`, `show`, `list`, `now`, `ignore`, `check`, `gantt`, `hook`;
|
|
1596
1689
|
`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);
|
|
1690
|
+
`skills`, `spec` (`cadence spec <lot> on|off` is `raf 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
1691
|
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`
|
|
1692
|
+
- **The keys of `cadence.yaml`**: `plan`, `news`, `hook`, `session`, `deliver`, `orchestrate`, `docs`, `qa`, `priority`, `depth`, `lead` (`lead.ux`)
|
|
1600
1693
|
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
1694
|
- **The plan file** (`docs/plan/raf.yaml`): `project`, `prefix`, `since`, `ignore`, `lots` (with their
|
|
1602
1695
|
fields, `tasks`, `notes`, `repos`) and `acknowledged`, and the plan formats `plan:` in `cadence.yaml` can read.
|
|
@@ -1613,7 +1706,7 @@ From 1.0.0 cadence follows [semantic versioning](https://semver.org): what is li
|
|
|
1613
1706
|
- The **`cadence-hud` band**: its segments, colours and layout; it is versioned on its own.
|
|
1614
1707
|
- The **wave journals** under `.cadence/runs` and the files `cadence orchestrate` keeps there.
|
|
1615
1708
|
- The wording of the briefs and of the instructions inside the skills and the agents.
|
|
1616
|
-
- The **format of the screen sheet
|
|
1709
|
+
- 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.
|
|
1617
1710
|
|
|
1618
1711
|
There is no schema version and no migration: a file written by an earlier release keeps working, and a key a
|
|
1619
1712
|
release adds is optional.
|
|
@@ -11,9 +11,11 @@ Follow the brief you are given. The method:
|
|
|
11
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
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
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.
|
|
14
|
+
4. **Red for the right reason.** Run the dedicated command (by hand, outside the cycle, with `CADENCE_ACCEPTATION=<path of the acceptation file>`; for a command of a list, also `CADENCE_ACCEPTATION_ROOT=<root of the command>`, the folder of its leading `cd <folder> &&`, else the repository `.`): 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
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
16
|
|
|
17
|
+
For a back sheet (`sujet`, `cas`, `contrats[]`, no mockup), the cases call the contracts of `contrats[]` as close as possible — the controller or the service for an HTTP call, the method of the job for a `job` — and simulate the external sources from `entree`; there are no `data-testid`.
|
|
18
|
+
|
|
17
19
|
- 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
20
|
- Never write `vert: true` or the fingerprints: the program seals the file and the cycle turns it green.
|
|
19
21
|
- Give the report in the structured output the brief asks for.
|
package/agents/code-reviewer.md
CHANGED
|
@@ -59,6 +59,12 @@ fact. If the path or the id is missing, or the lot has no commit to review, say
|
|
|
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
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.
|
|
62
|
+
- **Sheet mode** — when the brief says "sheet mode" (the orchestrator, before any code exists, for a lot with a back sheet `docs/specs/<sujet>/fiche.yaml`), the subject is not a diff but the sheet itself: `sujet`, `cas`, `regles`, `contrats`, `donnees`. There are no commits of the lot to read yet: skip steps 3–5 and read the sheet, then the code and the tests of the modules of `sujet.perimetre` and every source the sheet cites. Check, each finding with its measurement (the file:line you opened, the command you ran):
|
|
63
|
+
1. **Sourced or hypothesis.** Each `sourcee` rule cites a source that exists: open the file:line or the note and read what it says (a source that does not say so is a *major* finding). Each `hypothese` has a `si_faux` and hides none of the four expensive-to-undo categories (data model or storage; public or shared API contract or published route; destructive or irreversible action; contradiction with a sourced rule): such a hypothesis is a *major* finding, because it is a question for the lead.
|
|
64
|
+
2. **No contradiction.** With a rule already coded (search the modules of the perimeter, open the existing tests that assert the opposite) and with an existing API contract (field, error code, route).
|
|
65
|
+
3. **Errors and limits.** For each contract, the empty, absent, expired, oversized and duplicate inputs and each failure of an external source have a rule, or a motivated `sans_alternative` / `sans_erreur`.
|
|
66
|
+
4. **One test per rule.** Each rule has at least one planned test, whose name says what is checked and could fail (the program already checks that one is planned).
|
|
67
|
+
Rank *blocking* (the sheet would make the implementation wrong or irreversible), *major* (a rule unsourced, contradicted, or hiding a costly choice; an error case without a rule), *minor* (a vague test name, a wording). Never on taste. A blocking or major finding sends the sheet back to the spec writer; a minor one becomes a note. Leave `sousTaches` empty. This verdict is **not** `raf review`: the review of the code, after the implementation, keeps that role.
|
|
62
68
|
7. **Rank** each finding: *blocking* (wrong result, lost data, security hole, crash, a command that
|
|
63
69
|
fails), *major* (breaks in a plausible scenario, behaviour changed without a test, a written
|
|
64
70
|
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
|
package/agents/spec-writer.md
CHANGED
|
@@ -16,6 +16,8 @@ Follow the brief you are given. The method:
|
|
|
16
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
17
|
6. **Under the threshold, say so.** If the lot changes no screen, give the one-line reason in `sousSeuil` and write nothing.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
**A lot without a screen (`spec: true`) — back sheet.** The brief then names `<dir>/<sujet>/`, not a screen: there is no mockup, no capture and no state. You write only `fiche.yaml`, with `sujet` (id, titre, lot, perimetre), `cas` (use cases: trigger, preconditions, nominal steps, alternatives and error cases, each pointing to rules), `regles` (each attached to a case, sourced or a hypothesis, with planned tests named `Rn — …`), `contrats` (call, input, output, errors with the exact code and message) and `donnees`. Read the code and the tests of the modules the lot touches first: a rule already coded is a source (cite `file:line`), and a new rule must not contradict it. If the lot changes no behaviour (nothing a user, an API client or another service can observe), say so in `sousSeuil` and write nothing. The four costly categories are the same, instantiated for back: a stored model (key, column, table, file or cache format, migration), a published contract or route, an irreversible action (deletion, purge, sending, payment), a contradiction with a sourced or coded rule. An optional field added to an existing response is not a break when a rule of the sheet proves the old response unchanged: write it as a hypothesis with its `si_faux`. A lot with a screen that also changes a behaviour (the program reads the sheet: a `sujet` block next to `ecran`, never a `spec: true` beside `screen:`) has one sheet with both parts: the API calls of the screen are listed once in `contrats`, and the actions of the screen point to them with `contrat: Ax`.
|
|
20
|
+
|
|
21
|
+
- You edit only the spec folder (`<dir>/<écran>/` for a screen, `<dir>/<sujet>/` without one): never application code, tests or the plan. Do not push, deliver, run `raf start|done|note|review|ux`, or launch subagents.
|
|
20
22
|
- Commit with explicit paths and a message that cites the lot; leave the tree clean.
|
|
21
23
|
- Give the report in the structured output the brief asks for.
|
package/bin/cadence.js
CHANGED
|
@@ -47,9 +47,12 @@ if (tool === 'raf') {
|
|
|
47
47
|
la mesure des passes de correction des vagues (dossier/.cadence/runs) : lots à ≥1 et ≥2 corrections,
|
|
48
48
|
par projet, visibles ou non, passes par cause ; --classify les classe par Ollama (hors quota)
|
|
49
49
|
cadence spec check <fiche.yaml>
|
|
50
|
-
les invariants d'une fiche d'écran (étape spec
|
|
50
|
+
les invariants d'une fiche d'écran, back ou mixte (étape spec ; gabarits templates/fiche.yaml, fiche-back.yaml) ; code 1 si un écart, 2 si illisible
|
|
51
51
|
cadence spec qa <fiche.yaml>
|
|
52
52
|
la section de docs/qa/expectations.md dérivée de la fiche (shows, never, api), sur la sortie standard
|
|
53
|
+
cadence spec reseal <lot> <test> --reason "pourquoi"
|
|
54
|
+
le chemin du lead quand un test d'acceptation scellé du lot en cours contredit la fiche : le test corrigé dans l'arbre,
|
|
55
|
+
l'empreinte de ce seul test refaite, la raison dans acceptation.json et en note du lot ; hors vague orchestrée
|
|
53
56
|
cadence skills install [--dir .claude] [--force]
|
|
54
57
|
installe les skills Claude Code session-start, session-close, deliver et l'agent ux-reviewer`);
|
|
55
58
|
process.exitCode = !tool || ['help', '--help', '-h'].includes(tool) ? 0 : 2;
|