@sylad/cadence 1.6.0 → 1.7.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.
Files changed (41) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +45 -1734
  4. package/agents/acceptance-writer.md +1 -0
  5. package/dist/audit.js +4 -3
  6. package/dist/cli.js +4 -4
  7. package/dist/orchestrate/accept.js +8 -3
  8. package/dist/orchestrate/briefs.js +1 -1
  9. package/dist/orchestrate/command.js +3 -0
  10. package/dist/orchestrate/cycle.js +68 -6
  11. package/docs/cadence-hud.md +50 -0
  12. package/docs/corrections.md +24 -0
  13. package/docs/cycle-vague-dark.svg +42 -0
  14. package/docs/cycle-vague-light.svg +42 -0
  15. package/docs/deliver.md +204 -0
  16. package/docs/fonctionnement-lead-dark.svg +101 -0
  17. package/docs/fonctionnement-lead-light.svg +101 -0
  18. package/docs/fonctionnement-lot-dark.svg +38 -0
  19. package/docs/fonctionnement-lot-light.svg +38 -0
  20. package/docs/fonctionnement-service-dark.svg +23 -0
  21. package/docs/fonctionnement-service-light.svg +23 -0
  22. package/docs/fonctionnement-wave-dark.svg +66 -0
  23. package/docs/fonctionnement-wave-light.svg +66 -0
  24. package/docs/fonctionnement.md +106 -0
  25. package/docs/lead-workflow-dark.svg +200 -0
  26. package/docs/lead-workflow-light.svg +200 -0
  27. package/docs/lead.md +147 -0
  28. package/docs/news.md +245 -0
  29. package/docs/orchestrate.md +639 -0
  30. package/docs/overview.md +27 -0
  31. package/docs/raf.md +192 -0
  32. package/docs/releasing.md +59 -0
  33. package/docs/session.md +107 -0
  34. package/docs/skills.md +76 -0
  35. package/docs/spec.md +60 -0
  36. package/docs/stabilite.md +35 -0
  37. package/docs/whats-new.md +81 -0
  38. package/package.json +28 -1
  39. package/templates/acceptation-runner.mjs +1 -1
  40. package/templates/fiche-back.yaml +1 -1
  41. package/templates/fiche.yaml +1 -1
@@ -0,0 +1,27 @@
1
+ [← cadence](../README.md)
2
+
3
+ # Overview: the tools and the skills
4
+
5
+ The longer introduction the README used to open with.
6
+
7
+ A small working method that lives in your repository. Solo developers and
8
+ AI-assisted sessions lose track of *what is left to do* and *what each commit
9
+ was for*; cadence keeps both in plain files next to the code.
10
+
11
+ Four tools:
12
+
13
+ - **raf** (French *reste à faire*, "what is left to do"): the plan, linked to your commits;
14
+ - **news**: a user-facing changelog with screenshots, tied to the plan;
15
+ - **session**: the facts to start and to close a work session;
16
+ - **deliver**: wait for the CI of the pushed commit, deploy, then **verify the effect**.
17
+
18
+ And four [Claude Code](https://claude.com/claude-code) skills that turn them
19
+ into rituals — `session-start`, `session-close`, `deliver`, and `lead` to pilot
20
+ several projects through subagents — plus three reviewer agents: `ux-reviewer`
21
+ (no user-facing change is done before its usability review) and `code-reviewer`
22
+ (no lot with commits is done before its code review), each behind an opt-in
23
+ gate, and `qa-reviewer`, which walks the delivered app in a real browser and
24
+ reports a page left empty or in error.
25
+
26
+ And a second plugin, [`cadence-hud`](cadence-hud.md): a status band above the Claude
27
+ Code prompt that shows the session's context, quota, cost and the orchestrate waves running.
package/docs/raf.md ADDED
@@ -0,0 +1,192 @@
1
+ [← cadence](../README.md)
2
+
3
+ # raf
4
+
5
+ - The plan is a YAML file in the repo (`docs/plan/raf.yaml`), edited by the CLI.
6
+ Your comments and hand edits are preserved.
7
+ - A commit belongs to a lot when its message cites the id: `feat(L3): …`,
8
+ `fix: L3/t1 …`. The link is **computed from `git log`**, never stored, so
9
+ committing never dirties the plan. The id is read as a whole word: `XL3`,
10
+ `L3x` and `L3.4` do not cite `L3`, while `L3.` at the end of a sentence does.
11
+ When the subject has a scope that cites lots (`feat(L3): …`,
12
+ `chore(L31,L32): …`), **the scope alone decides**: a passing mention
13
+ (`page équipe (L27)`), a range (`L28–L31`, `L45 à L48`) or the body does not
14
+ count. Without a scope citing a lot, the whole message is read as before.
15
+ - `raf check` audits drift between the plan and the history.
16
+ - Plan upkeep needs no lot. A commit is plan upkeep when **every file it
17
+ touches is a plan file**: the plan itself, its Gantt page (only at its default place, `gantt.html` next to the plan — written elsewhere with `raf gantt -o`, declare it under `plan.files`), the `plan:` key of the config file in use (`cadence.yaml`, or
18
+ the `--config` file; a change to `deliver:`/`session:` is work), or a file the
19
+ project lists under `plan.files` in `cadence.yaml` (a page it generates from
20
+ the plan, a journal), or the QA expectations file (`docs/qa/expectations.md`,
21
+ or the file named by `qa.expectations`; the lead commits the `qa-reviewer`'s draft of it). Such a commit is never a "commit without a lot", and it
22
+ does not count as work on the lots it cites: it is absent from `raf commits`,
23
+ does not start a `todo` lot, does not make a code review stale, and
24
+ `cadence deliver` does not announce the lots it cites as delivered. The files
25
+ decide, never the subject: a `chore(plan): …` commit that touches a source
26
+ file is a commit like any other.
27
+ - `raf gantt` writes a single self-contained HTML page (no server, no CDN).
28
+
29
+ ```sh
30
+ npm install -g @sylad/cadence # or: npx -p @sylad/cadence raf …
31
+
32
+ raf init # docs/plan/raf.yaml + post-commit hook + .playwright-mcp/ in .gitignore
33
+ raf add "Monthly dedup on merge" --estimate 2
34
+ raf add "Typo in footer" --quickwin
35
+ raf add "Loan cache" --after L1
36
+ raf add "write the migration" --parent L1 # → L1/t1
37
+ raf start L1
38
+ git commit -m "feat(L1): dedup by calendar month"
39
+ raf now # in progress, next up (quickwins first), recently done
40
+ raf done L1/t1 && raf done L1
41
+ raf check # exit 1 on drift
42
+ raf gantt # docs/plan/gantt.html
43
+ ```
44
+
45
+ ## Commands
46
+
47
+ | Command | Effect |
48
+ |---|---|
49
+ | `raf init [--project name] [--prefix L] [--no-hook]` | create the plan, install the hook, add `.playwright-mcp/` to `.gitignore` |
50
+ | `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. Only `page` triggers the spec step of `orchestrate` (L209), 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) |
51
+ | `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`) |
52
+ | `raf screen <id> page\|component\|journey\|none` | set, replace or remove `screen:` on an existing lot, to adopt the [spec step](orchestrate.md#the-spec-step-of-a-lot-with-screen) on a plan already written (only `page` adopts the [spec step](orchestrate.md#the-spec-step-of-a-lot-with-screen); `component` and `journey` do not); refused on a lot without `visible:` (like `raf add --screen`) and on a sub-task; `none` removes the key and leaves `visible:` alone |
53
+ | `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`) |
54
+ | `raf public <id> "title"` · `raf public <id> --clear` | set, replace or remove the public title of a lot |
55
+ | `raf start <id>` · `raf done <id> [--force]` · `raf drop <id> [--reason text]` | dated transitions (`done` refuses open sub-tasks unless `--force`) |
56
+ | `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 |
57
+ | `raf note <id> "text"` | dated note — keep decisions next to the work |
58
+ | `raf show <id> [--notes]` | one lot: status, dates, `after`, public title, dated notes in order, then the counted commits (as `raf commits`, neighbouring repositories included); `--notes` prints the notes alone |
59
+ | `raf commits <id>` | the commits counted for a lot (the set the code review gate uses), one `<sha> <subject>` per line, oldest first; a lot that declares `repos:` ([neighbouring repositories](orchestrate.md#a-lot-whose-work-is-in-a-neighbouring-repository)) gets, after them, one `dépôt <path> :` section per neighbour with the commits there that cite the lot and fall within the lot's period (`started` to `finished`) and, when the lot declares a `cite:` for that neighbour, contain that string (`aucun commit du lot`, or `introuvable` for a path that is not there) |
60
+ | `raf now` | what to do next |
61
+ | `raf list [--status s]` | flat list |
62
+ | `raf ignore <sha> \| "exact subject" [--reason text]` | acknowledge a commit without a lot (tooling chore, a plan commit citing an unknown id) without rewriting history: a dated, reasoned line in the plan's `acknowledged:` section; a sha is exact, a subject covers every commit carrying it |
63
+ | `raf check --ignored` | list the acknowledged commits with their date and reason |
64
+ | `raf check [--since date] [--idle 7]` | since the plan's adoption date by default (a visible lot without a public title is only a `⚠` warning: it never changes the exit code): commits without a lot (commits touching only plan files, or only version fields, `CHANGELOG.md`, the README's « What's new » section and `docs/whats-new.md` are exempt), unknown ids, `todo` lots that already have commits, idle lots, `done` lots with open sub-tasks, bad or circular dependencies |
65
+ | `raf gantt [-o file]` | standalone Gantt page |
66
+ | `raf hook install` | add the post-commit hook (read-only, never blocks) and the pre-commit hook (does nothing unless `hook.autostart` says so, see below) |
67
+
68
+ ### A commit on a lot that is still `todo`
69
+
70
+ By default the post-commit hook only warns (`L1 est encore todo — raf start L1`). The `hook.autostart`
71
+ key of `cadence.yaml` changes what the **pre-commit** hook does when the message cites a `todo` lot
72
+ (a recurring lot, a lot already `doing`, a commit without a lot and a plan-upkeep commit are never concerned):
73
+
74
+ ```yaml
75
+ hook:
76
+ autostart: refuse # warn (default) | refuse | start
77
+ ```
78
+
79
+ - `warn`: today's behaviour, the commit goes through, the post-commit hook warns.
80
+ - `refuse`: the commit fails, loudly, with `raf start <id>` in the message (`--no-verify` still bypasses it).
81
+ - `start`: the hook runs `raf start <id>` and stages the plan, so the plan change is **in the same commit** —
82
+ no amend afterwards, no dirty plan left behind. Only when `docs/plan/raf.yaml` is identical to `HEAD` (no
83
+ uncommitted change to the plan, staged or not): otherwise nothing is started, the hook says why
84
+ (`plan modifié non commité : démarrage automatique sauté, raf start <id> à la main`) and behaves like `warn`.
85
+
86
+ The pre-commit hook reads the message from the command line of the `git commit` that runs it (`-m`, `-am`,
87
+ `--message`, `-F`; Linux, through `/proc`) or from `CADENCE_COMMIT_MESSAGE`. When the message is not known yet
88
+ (editor, `--amend`) it does nothing and the post-commit warning stays. Run `raf hook install` again to add the
89
+ pre-commit block to an existing repository. A read-only plan is never started by the hook. Only a refusal (exit code 3 of `raf hook pre-commit`) stops a commit: an older or broken `raf` lets it through.
90
+
91
+ Global options: `--file path` or `RAF_FILE`; `RAF_TODAY=YYYY-MM-DD` to freeze
92
+ the date. `cadence raf …` is the same as `raf …`.
93
+
94
+ ## Plan file
95
+
96
+ ```yaml
97
+ version: 1
98
+ project: my-app
99
+ prefix: L
100
+ since: 2026-09-28 # commits before this date are not audited
101
+ ignore: ['^chore\(batch\):'] # optional: subjects of automated commits, neither audited nor counted for a lot
102
+ lots:
103
+ - id: L1
104
+ title: Monthly dedup on merge
105
+ status: doing # todo | doing | done | dropped
106
+ estimate: 2 # working days
107
+ quickwin: false
108
+ visible: true # user-facing: a news entry is expected when done
109
+ after: [L0]
110
+ gate: { count: 8, spec: true } # optional: not before 8 lots with `spec: true` are done (or `screen: page`)
111
+ created: 2026-09-28
112
+ started: 2026-09-29
113
+ notes:
114
+ - { date: 2026-09-29, text: "keep the bank line when both sources exist" }
115
+ tasks:
116
+ - { id: t1, title: write the migration, status: done }
117
+ ```
118
+
119
+ ## A plan elsewhere, or in another format
120
+
121
+ `cadence.yaml`, at the repository root, can say where the plan is. The short form keeps raf's own
122
+ format, and the plan stays writable:
123
+
124
+ ```yaml
125
+ plan: planning/todo.yaml
126
+ ```
127
+
128
+ A project that publishes its plan (a JSON generated from it and committed with it)
129
+ declares that file, so a commit touching only the plan and its published copy is
130
+ plan upkeep; the plan keeps raf's format and stays writable:
131
+
132
+ ```yaml
133
+ plan:
134
+ files: [frontend/public/plan-data/plan.json]
135
+ ```
136
+
137
+ Until the file is declared, such a commit is reported as a "commit without a
138
+ lot" when it cites none, and counts as work on the lots it cites.
139
+
140
+ A project that already keeps its plan with its own tool is read **without migrating it**: describe
141
+ the file, and `raf now`, `raf list`, `raf commits`, `raf check`, `raf gantt` and
142
+ `cadence session start|close` work on it. Such a plan is **read-only** —
143
+ `raf add|start|done|note|ux|review` refuse and leave the file to the project's tool, and the two
144
+ review gates do not apply to it (a `uxSince` or `reviewSince` written in it is ignored).
145
+
146
+ ```yaml
147
+ plan:
148
+ path: docs/plan/taches.yaml
149
+ project: my-app # what the file does not say itself: project, since, ignore
150
+ since: 2026-10-02
151
+ ignore: ['^plan: ']
152
+ files: [docs/plan/journal.ndjson] # kept with the plan: a commit touching only these is a plan commit
153
+ lots: taches # root key holding the list (default: lots)
154
+ fields: # raf field: key in the file (a list = first one present)
155
+ title: titre
156
+ public: titre_public # the lot's title for the public; read when it is text, else ignored
157
+ screen: ecran # page, component or journey; only on a visible lot (only `page` enters the spec step)
158
+ spec: fiche # true or false: the lot changes a behaviour
159
+ status: etat
160
+ estimate: effort
161
+ created: cree_le
162
+ started: demarre_le
163
+ finished: [livre_le, ferme_le]
164
+ notes: note
165
+ repos: depots # the lot's neighbouring repositories (a list of paths and/or { path, cite }, or one of them)
166
+ parent: parent
167
+ statuses: # raf status: their states
168
+ todo: [prevu, specifie]
169
+ doing: [en_cours, teste]
170
+ done: [deploye, valide]
171
+ dropped: caduc
172
+ estimates: { S: 0.5, M: 1, L: 3 } # their effort labels, in working days
173
+ ```
174
+
175
+ - Fields: `id`, `title`, `status`, `estimate`, `quickwin`, `visible`, `screen`, `spec`, `public`, `every`, `last`, `after`, `created`, `started`,
176
+ `finished`, `notes`, `repos`, `parent`, `gate`; one left out is read under its own name. A timestamp counts for
177
+ its day; a note written as plain text is one note.
178
+ - `gate` (L219) is a drawing condition added to `after`: `gate: { count: N, spec: true }` or `gate: { count: N, screen: page }` (N an integer ≥ 1, one criterion). It is written by hand in the plan (no `raf add` option). The count is the number of `done` lots of the same plan that carry the criterion (`todo`, `doing`, `dropped` lots and sub-tasks do not count; recurring lots do). Until the count reaches N, a `todo` lot is *waiting*, never *ready*: `raf now` lists it on a line `en attente de condition de tirage : L190 (2/8 lots spec: true faits)` (the existing `en attente de dépendances : …` line stays for lots waiting on `after`), `cadence session start` adds an `En attente` section (nothing when no lot is gated) and leaves the lot out of `À suivre` and of the proposals, `cadence lead tour` skips it for `prochain` and adds `attend L190` to the project's line (and `waiting` to `--json`, only when a lot waits), `cadence orchestrate` refuses it before any action (`a:L190 : condition de tirage non remplie : 2/8 lots spec: true faits`) and `--continue` never draws it, and `raf show` prints `gate : 8 lots spec: true faits`. Once the count is reached the lot is ready like any other (the field stays in the plan); a lot already `doing` is not refused for its condition. A malformed `gate` is reported by `raf check` (`gate invalide : …`) and the lot is never drawable. A plan without `gate` behaves exactly as before; `after` read by the Gantt scheduling is unchanged.
179
+ - `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). Consequence for a `gate: { count: N, spec: true }` in a read-only plan: it counts only lots whose `spec` is mapped by `plan.fields.spec`; without that mapping the count stays 0 and the lot waits for good, with no `raf check` problem. `gate: { count: N, screen: page }` has no such condition.
180
+ - `parent`: an entry `B33/t1-fusion` whose parent is `B33` becomes the sub-task `t1-fusion` of `B33`.
181
+ - Ids need no prefix: a commit belongs to a lot when its message cites one of the plan's ids as a
182
+ whole word (`E-A2`, `NC2.4`, `B33/t1-fusion`).
183
+ An id that is not in the plan cannot be told from ordinary text: such a commit counts as
184
+ "without a lot", never as an unknown reference.
185
+ - A state missing from `statuses`, or an effort label missing from `estimates`, is reported by
186
+ `raf check`.
187
+
188
+ ## Gantt scheduling
189
+
190
+ One lane of work. Finished lots use their real dates (or their commits' dates);
191
+ lots in progress run until `max(start + estimate, today)`; lots to do follow in
192
+ file order, after their dependencies, on working days.
@@ -0,0 +1,59 @@
1
+ [← cadence](../README.md)
2
+
3
+ # Releasing
4
+
5
+ A version exists in three places and is published in two; a release does all of it, in this order:
6
+
7
+ 1. Bump `version` in `package.json` (then `npm install` to refresh `package-lock.json`),
8
+ `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json`, and write the version's section of
9
+ `CHANGELOG.md` (`## [x.y.z] - date`, what changes for the user, lots cited), in **one commit that holds
10
+ only those files** (the version fields and the CHANGELOG, nothing else in the manifests, the « What's new »
11
+ section of the README, the one place of it a release rewrites, and `docs/whats-new.md`, its long form: add the version there too). Such a commit is
12
+ exempt from the code-review gate like a plan commit: it closes the lot after its review, and `raf check`
13
+ does not ask for a new one (nor does it count it as a commit without a lot). The « What's new »
14
+ summary is ordered by version, a number known only at the release and shared by several lots: write it
15
+ in that commit, not before the review. A commit that touches any other file
16
+ — or another field of a manifest, or a dependency in `package-lock.json` — is work like any other and has
17
+ to be reviewed.
18
+ 2. Run the plugin evaluation, `npm run eval:plugin` (billed, see [Evaluating the plugin](#evaluating-the-plugin-before-a-release)),
19
+ on that version commit; a case below the threshold stops the release until you have read it in the report.
20
+ 3. `git tag v<version> && git push origin main v<version>` — the tag starts `.github/workflows/publish.yml`,
21
+ which publishes to npm through Trusted Publishing (OIDC, no token stored anywhere): it checks the tag
22
+ matches `package.json`, `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json` and that `CHANGELOG.md` has a `## [x.y.z]` section for it (no section, no publication), then `npm publish --provenance`, where `prepublishOnly` runs the type-check and the
23
+ tests and `prepare` builds `dist/`; a red suite stops the publication; then it creates the GitHub release with that CHANGELOG section as its text. The trusted publisher is declared
24
+ once on npmjs.com (package settings → Trusted Publisher → GitHub Actions, `Sylad/cadence`, `publish.yml`).
25
+ 4. Watch the run: `gh run watch` (or `gh run list --workflow publish.yml`).
26
+ 5. Check the effect: `npm view @sylad/cadence version` answers the new version.
27
+ A run is safe to re-run, and two runs for one tag queue instead of racing (`concurrency` per ref, never cancelling the one that publishes):
28
+ a version already on npm skips `npm publish`, and a GitHub release that is missing is created (`--verify-tag`)
29
+ while an existing one is left alone. If the package is on npm but the release is still missing, re-run the job;
30
+ the by-hand fallback is `gh release create v<version> --title v<version> --notes-file <the section of CHANGELOG.md> --verify-tag`.
31
+
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
+
34
+ The Claude Code plugin is read from the repository, so pushing `main` is what updates it; npm is what
35
+ `npx @sylad/cadence` and a global install read, and only the tag publishes there. A missing tag, or a red
36
+ publish run, leaves npm behind without any other error — 0.3.0 and 0.4.0 were never published — hence
37
+ step 5.
38
+
39
+ ## Evaluating the plugin (before a release)
40
+
41
+ `evals/` holds an evaluation suite for the plugin itself, run by `claude plugin eval` (Claude Code 2.1.263 and later). Each case is
42
+ a folder with a `prompt.md` and `graders/*.md`, and replays a trap found by hand: `raf-done-sans-revue` (`raf done` refused on a lot whose
43
+ commits have no code review, with no `--force` to get round it), `deliver-sha` (`git push origin <sha>:main` then
44
+ `cadence deliver --sha <sha>` for a pushed commit that is not `HEAD`), `orchestrate-id-avec-slash` (`maritime-atlas:Q4/accueil-4-ux12@haiku`
45
+ keeps its `/`) and `livrer-sh-sans-bloc` (a `./livrer.sh` without a `deliver:` block in `cadence.yaml` is not
46
+ run by `cadence deliver`). Every case also runs a **baseline without the plugin**, so the report gives the score of each arm and the
47
+ difference: a trap the baseline already avoids proves nothing about the plugin. The cases are read-only questions (tools `Read`, `Glob`, `Grep`,
48
+ `Skill`, no scaffold script), each graded by a regular expression and by a model-judged criterion.
49
+
50
+ ```sh
51
+ npm run eval:plugin # claude plugin eval . --max-cost-usd 5 --no-publish; 4 cases × 3 runs × 2 arms = 24 runs
52
+ claude plugin eval . --case deliver-sha --runs 1 --trust-plugin --no-publish --max-cost-usd 1 # one case, one run (the first run asks to trust the plugin)
53
+ ```
54
+
55
+ **Every run is billed** (a full `claude` session on your own credential, plus the judge): the suite is run at the release, once the
56
+ version commit is ready, never in `npm test`, in `prepublishOnly` or in CI, and `--max-cost-usd 5` aborts a runaway. A case below
57
+ the threshold (1.0 by default, `--threshold`) makes the command exit 1: read the case in the report before deciding it is the plugin
58
+ and not the wording of the case. `npm test` only checks that the
59
+ files are well formed (`test/plugin-evals.test.ts`); `evals/` is not part of the npm package.
@@ -0,0 +1,107 @@
1
+ [← cadence](../README.md)
2
+
3
+ # session
4
+
5
+ ```sh
6
+ cadence session start # notes from the last close, lots in progress (silent ones flagged),
7
+ # work done since yesterday by lot, drift, repo state, 3 proposals
8
+ cadence session start --since "3 days ago" --idle 2
9
+ cadence session close # commits by lot since the last `session start`,
10
+ # commits without a lot, lots in progress with no commit in that window,
11
+ # drift, uncommitted / unpushed work; exit 1 while something is still open
12
+ cadence session close --since "2 days ago" # --since overrides the window
13
+ cadence session start --all # from a folder that is not a repository: one "## project" section per
14
+ cadence session close --all --depth 2 # sub-folder holding a plan (--depth n: n levels down, 1 by default);
15
+ # exit = the worst code of the projects (2 error, 1 open, 0 closed)
16
+ cadence session next "finish L3" "review L4" # shown by the next session start; replaces the previous notes
17
+ cadence session next --clear # erase those notes, on purpose
18
+ cadence session context # `ctx 42 % (84000/200000)`: the context of YOUR session, as the cadence-hud band publishes
19
+ # it: the one named by $CLAUDE_CODE_SESSION_ID (set in Claude Code's Bash); --session <id>
20
+ # overrides it; with no variable, the folder decides only if a single session publishes for it
21
+ # (two sessions in one folder = exit 2, "pass --session"); exit 2 too when no fresh figure
22
+ # (band not loaded) = treat as at the threshold
23
+ ```
24
+
25
+ `session start` records its time in the worktree's state (`session.json`, under the git dir); the next
26
+ `session close` takes it as its window and names it in the section title: `Commits de la période (depuis
27
+ l'ouverture de 09:12)` (with the date when it is not today). A close never moves the boundary, refused
28
+ or not: run again without a `session start` in between (the `session-close` skill does, after fixing a
29
+ point), it still reports since that opening instead of an empty period. With no recorded opening, or an
30
+ unreadable file, the window is the current day, said as such (`depuis 2026-09-28 00:00`); `--since` is
31
+ quoted as given. (A `session.json` written by 0.18.0 after a close, `depuis la clôture de …`, is still read.)
32
+
33
+ On success `cadence session next` prints what it recorded (`2 lignes enregistrées pour la prochaine
34
+ ouverture`, then the lines as written, blank ones dropped), so `session-close` can report
35
+ them without running `session start` again.
36
+
37
+ `--all` runs the same command inside each project found under the current folder —
38
+ `docs/plan/raf.yaml`, or a `cadence.yaml` with `plan:` — and never enters a project
39
+ to look for another. `--since` and `--idle` go to every project; an error in one
40
+ project is printed in its section and the others still run. It replaces the shell
41
+ loop over the sub-folders. A project that is not the root of its own git repository gets a `✗` line
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
+ 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
+
45
+ `cadence session next` without a line refuses (exit 2) and leaves the notes of the
46
+ last close as they are — it used to erase them silently; erasing is `--clear`.
47
+
48
+ Proposals come from the plan only: lots in progress, then ready lots (dependencies
49
+ done), quick wins first. Local state lives in the git directory, never committed:
50
+ the close notes per worktree, the delivery lock and log in `.git/cadence/`, shared
51
+ by all the worktrees of a clone.
52
+
53
+ A project that already has its own morning and evening scripts keeps them: name
54
+ them in `cadence.yaml` and their output is added to the report, under "Faits
55
+ propres au projet", before the proposals (start) or the verdict (close).
56
+
57
+ ```yaml
58
+ session:
59
+ start: ./scripts/morning.sh "$CADENCE_SINCE" # sh, at the repo root, 120 s at most
60
+ close: ./scripts/evening.sh "$CADENCE_SINCE"
61
+ ```
62
+
63
+ ```yaml
64
+ session:
65
+ clean: [ "~/projects/tmp/*", "tmp/*", "test-output-*" ] # working files to propose for removal at close
66
+ cleanDays: 7 # older than this many days (default 7)
67
+ ```
68
+
69
+ `cadence session close` then lists, under "Nettoyage proposé", the entries matching these
70
+ patterns (`*` stands for part of a name and never crosses a `/`; `~` is the home folder, a
71
+ relative pattern starts at the repo root) that were not modified for more than `cleanDays`
72
+ days, oldest first — a folder's age is that of the most recent entry it contains, at any depth,
73
+ and an entry's age runs from the later of its modification time and its status-change time (ctime):
74
+ what `tar xf`, `cp -a` or `rsync -a` just brought in with an old modification time is not old.
75
+
76
+ An entry is proposed only if it could be measured entirely. Never proposed:
77
+
78
+ - a git repository, a folder that contains one at any depth, and anything under a `.git` folder;
79
+ - a git directory without a `.git` entry — a bare repository (`git init --bare`, `git clone
80
+ --mirror`, `backup.git/`), a `--separate-git-dir`, a worktree's admin folder —, recognised by
81
+ its content as git does (`HEAD` with `objects` and `refs`, or `HEAD` with `commondir`): neither
82
+ it, nor anything inside it, nor a folder that contains one;
83
+ - anything `git` tracks, in any repository that has a `.git` entry above it. One limit, stated
84
+ plainly: a bare repository driven with an external work tree (`git --git-dir=~/.dotfiles
85
+ --work-tree=~`) leaves no `.git` beside the files, so its tracked files cannot be recognised and
86
+ can be proposed — never point a pattern at such a work tree;
87
+ - a name starting with `.` unless the pattern itself starts that name with `.` (as in the
88
+ shell, `tmp/*` does not match `tmp/.env`; `tmp/.cache-*` does);
89
+ - anything reached through a symbolic link matched by a `*` segment: unlike the shell, the walk
90
+ never descends into such a link (`tmp/*/*` lists nothing behind `tmp/link → ../outside`), and a
91
+ folder's age never looks behind a link; the link itself can be proposed, as a link — removing it
92
+ leaves its target alone. Only segments written in full *before* the first `*` follow a link, as
93
+ `cd` would (`~/shared/*` with `~/shared` a link lists the target's entries); once a `*` has been
94
+ crossed no link is followed any more, even on a segment written in full (`tmp/*/out/*` with
95
+ `tmp/run1/out → /elsewhere` lists nothing behind `out`);
96
+ - anything that could not be read entirely: a folder that cannot be listed — nor anything
97
+ inside it, even named in full —, an entry that cannot be examined or vanished during the
98
+ walk, an entry under a `.git` that `git` could not answer for. These are listed apart,
99
+ under "Nettoyage : N élément(s) illisible(s), jamais proposé(s)";
100
+ - the repository itself, or a folder that contains it.
101
+
102
+ The command deletes nothing, never fails on the cleanup and does not change the exit code: the
103
+ `session-close` skill shows the list and removes the entries only after the human agrees.
104
+
105
+ The commands get `CADENCE_SINCE` and `CADENCE_TODAY`. `CADENCE_SINCE` is the `--since` as given; on `session close` without `--since` it is the instant of the last `session start` as an ISO 8601 UTC string (`2026-09-28T07:12:00.000Z`), or `<today> 00:00` when no mark exists.
106
+ The commands add facts and decide nothing: a failing command is reported and changes neither
107
+ the exit code nor the verdict.
package/docs/skills.md ADDED
@@ -0,0 +1,76 @@
1
+ [← cadence](../README.md)
2
+
3
+ # Claude Code skills
4
+
5
+ As a plugin:
6
+
7
+ ```
8
+ /plugin marketplace add Sylad/cadence
9
+ /plugin install cadence@cadence
10
+ ```
11
+
12
+ gives `/cadence:session-start`, `/cadence:session-close`, `/cadence:deliver`,
13
+ `/cadence:lead` and the `ux-reviewer`, `code-reviewer` and `qa-reviewer` agents. Or copy them into the
14
+ repository with `cadence skills install` (to `.claude/skills/cadence-*` and
15
+ `.claude/agents/cadence-*.md`; `--dir` for another `.claude` folder,
16
+ `--force` to overwrite local edits).
17
+
18
+ - **session-start**: reports the facts briefly, proposes three lots from the
19
+ plan, then waits for your priority — nothing starts before your answer.
20
+ - **session-close**: plan hygiene, clean repository, a cleanup proposal for stale
21
+ working files (`session.clean` patterns, older than `session.cleanDays`; never
22
+ anything git tracks, a git repository or a folder holding one, anything under
23
+ `.git`, a bare repository or separate git directory or anything inside one,
24
+ anything behind a symbolic link a `*` matched (only the link itself), a hidden `.xxx` name a `*` would not match, nor anything it could not
25
+ read entirely — it asks before deleting), memory limited to what the
26
+ repository does not say, new skills or agents proposed but never created, three
27
+ lines for next time.
28
+ - A project with its own tooling keeps it: its plan is read where it is (`plan:`),
29
+ its delivery script is called by `cadence deliver` (`deliver.script`), its
30
+ morning and evening scripts feed the session report (`session:`), and its own
31
+ skills can become one-line aliases of `session-start` / `session-close`.
32
+ - **deliver**: dry run, delivery, and on failure the cause fixed rather than a
33
+ blind retry; after a green delivery that changes what a page shows or what it
34
+ is served, the `qa-reviewer` agent walks the delivered app.
35
+ - **lead**: from a folder holding several projects, `cadence lead tour` (a program,
36
+ no model: see [lead tour](lead.md#lead-tour)) prints one line of facts per project, you choose the priorities, the lots are delegated with
37
+ `cadence orchestrate` (fresh short sessions with a standard brief — test first,
38
+ README and usage documentation updated with the change, commits citing the lot, no push — reviewed by the `code-reviewer` agent, see
39
+ [orchestrate](orchestrate.md#orchestrate); a lot with `screen: page` first goes through the [spec, mockup review and accept steps](orchestrate.md#the-spec-step-of-a-lot-with-screen)), re-verified by the lead, then delivered
40
+ one project at a time; a delivery that changes what a page shows or what it is
41
+ served is then checked in the running app by the `qa-reviewer` agent, whose
42
+ blocking findings come back to you. As many
43
+ subagents as the session cap at most (2 by default, `CADENCE_MAX_SESSIONS`), never two in the same repository. The whole flow is drawn in
44
+ [docs/lead.md](lead.md); how a lot, a wave, the lead and the service of cadence itself fit together, in four figures, is in
45
+ [docs/fonctionnement.md](fonctionnement.md).
46
+ - **ux-reviewer** (agent): captures at 1440 and 390 px, findings grounded in a
47
+ named rule (Nielsen, WCAG 2.2 AA) or a measurement, ranked, turned into
48
+ `raf add --parent` sub-tasks, and a one-line verdict for `raf ux`. It never
49
+ edits code. Read-only for real: its `tools:` list is `Read, Grep, Glob, Bash` and the
50
+ Playwright tools (`mcp__playwright`, and `mcp__plugin_playwright_playwright` when the
51
+ browser comes from the Playwright plugin) — no `Edit`, no `Write`. Outside a wave it gives its captures a relative file name only, which the Playwright MCP writes under `.playwright-mcp/` (the same rule as the wave's briefs); `qa-reviewer` follows it too.
52
+ - **code-reviewer** (agent): any stack; given a repository and a lot id, it reads
53
+ the diff itself from the commits that cite the lot — not the author's summary —
54
+ and the project's CLAUDE.md, when there is one, for its conventions; findings grounded in a
55
+ measurement (a failing command, changed code without a test, a duplicated
56
+ block, dead code) or a named rule, each with `file:line` and a concrete
57
+ scenario; real defects only, ranked, what it could not verify, and a one-line
58
+ verdict for `raf review`. It takes the lot's commits from `raf commits`, never
59
+ runs a build whose output is used live, and never edits code. A README or usage
60
+ documentation that does not follow the lot's change is a *major* finding.
61
+ - **qa-reviewer** (agent): any web app (read-only like `ux-reviewer`: same tool list, no `Edit`, no `Write`); given a repository and a base URL (and
62
+ optionally a lot id, to walk only the pages it touched — those that call the
63
+ changed endpoints, those of the screens it changed, the pages that consume the services the lot changed,
64
+ and the home page; a backend-only lot stays in scope, and when the lot changes no route
65
+ and no screen, or the endpoints cannot be mapped to pages, every page is walked; the others are named « Not walked »), it opens each page of
66
+ the project's expectations file in a real browser at 1440 and 390 px and
67
+ measures: expected content present and non-empty, no error or missing-data
68
+ message, every API call answered 2xx with a non-empty body, no console error,
69
+ no broken content image. It reads the page as text first and takes a capture only for a gap. Findings are defects (a line of the expectations
70
+ broken, or a universal check failing with a visible effect, with or without an
71
+ expectations file), suspects (it looks like missing or wrong data and no
72
+ expectation settles it) or noise (a console error or a failed request with no
73
+ visible effect, ranked minor) or already planned (an open lot covers it: returned in one line, the lot id and its title), ranked, each with
74
+ the route, what was expected, what was measured and the evidence; pages checked
75
+ N/N, follow-ups as `raf add` lines, what it could not verify, a one-line
76
+ verdict. Read-only: GET only, no login, nothing submitted; it stops at a PIN.
package/docs/spec.md ADDED
@@ -0,0 +1,60 @@
1
+ [← cadence](../README.md)
2
+
3
+ # spec
4
+
5
+ `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
6
+ [docs/superpowers/specs/2026-10-10-etape-spec-design.md](superpowers/specs/2026-10-10-etape-spec-design.md)). Start from the template
7
+ [`templates/fiche.yaml`](../templates/fiche.yaml) (it passes the check as is), a worked example sits next to the design. It prints one
8
+ `✗ …` 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:
9
+
10
+ - `ecran` has `id`, `titre`, `route` (starts with `/`), `lot`, `maquette`, and `largeurs: [1440, 390]`; `etats` holds at least `vide`, `chargement`, `erreur`, none twice;
11
+ - `champs[]`: a unique kebab-case `id` (it is also the mockup's `data-testid`), `libelle`, `type`, `source`, and a boolean `obligatoire`;
12
+ - `regles[]` are numbered `R1`, `R2`… in order with no gap; each has an `etat` that is one of `etats`, an `enonce`, a `message` (the exact text on screen, or `null`),
13
+ a `statut` — `sourcee` with the `source` it comes from, or `hypothese` with the `si_faux` that says what would change — and at least one planned test, named `Rn — …`;
14
+ - `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`;
15
+ - `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.
16
+
17
+ **Back-end sheet** (L187; design: [docs/superpowers/specs/2026-10-11-etape-spec-back-design.md](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:
18
+
19
+ - `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`;
20
+ - `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;
21
+ - 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;
22
+ - `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;
23
+ - `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).
24
+
25
+ **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.
26
+
27
+ `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.
28
+
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>`), see [The accept step](orchestrate.md#the-accept-step-red-acceptance-tests-and-their-lock).
30
+
31
+ `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
+ (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
+ 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:
34
+
35
+ - `## <route>` is the screen's route;
36
+ - `shows:` — one line per mandatory field (its `libelle`), **except** the fields that belong to a state (listed in `champs` of a rule of state `vide` or `erreur`, like the empty-state message);
37
+ the line of a field listed in the `masque` of a `sourcee` rule of state `vide` ends with `— unless <the rule's statement>`; the other fields (a static title) never get one;
38
+ - `never:` — the messages of the rules of state `erreur`, on one line; the message of a rule of state `vide` is a planned display and never goes there;
39
+ - `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.
40
+ Actions triggered by a field stay with the acceptance tests.
41
+
42
+ `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`.
43
+
44
+
45
+
46
+ ## Spec step (design, first steps delivered)
47
+
48
+ For a visible lot that adds a page (`screen: page`; a component or a journey follows the ordinary path since L209), `orchestrate` gets a step
49
+ before the code: a static HTML mockup in the project's own style (1440 and 390 px; empty, loading and
50
+ error states) and a machine-readable screen sheet (fields, numbered rules `R1…` each marked *sourced*
51
+ or *hypothesis*, actions → API calls). The `ux-reviewer` agent reads the mockup before any code; the
52
+ acceptance tests are written from the sheet, red, by a session other than the implementer's; the
53
+ implementation gets the sheet, the code review checks rule → test → green, the hypotheses go into the
54
+ lot's news entry, and a human is asked only about a choice that is costly to undo. The design is in
55
+ `docs/superpowers/specs/2026-10-10-etape-spec-design.md` (with an example sheet and the plan of the
56
+ 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`
57
+ (the sheet's invariants) and `cadence spec qa` (the screen's `docs/qa/expectations.md` section, derived
58
+ from the sheet), see [spec](#spec) below, and the `spec` step of `orchestrate` itself (the `spec-writer` agent, the
59
+ render at 1440 and 390 px, the commit of the spec), see [The spec step](orchestrate.md#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](orchestrate.md#the-accept-step-red-acceptance-tests-and-their-lock); the UX review of
60
+ the mockup (the `ux-reviewer` agent in mockup mode), see [The mockup review](orchestrate.md#the-mockup-review-before-any-code); and the downstream briefs (the sheet given to `implement`, rule → test → green in the code review, a light UX conformity pass, the `## Hypothèses` section of the news entry), see [The downstream briefs](orchestrate.md#the-downstream-briefs-sheet-rule--test--green-conformity-hypothèses).
@@ -0,0 +1,35 @@
1
+ [← cadence](../README.md)
2
+
3
+ # Stability
4
+
5
+ From 1.0.0 cadence follows [semantic versioning](https://semver.org): what is listed under
6
+ *Guaranteed* only changes incompatibly in a major version; a minor or a patch never breaks it.
7
+
8
+ **Guaranteed**
9
+
10
+ - **Commands and options** of `raf` and `cadence` (`cadence raf …` is `raf …`): `init`, `add`, `start`, `done`, `drop`,
11
+ `note`, `did`, `public`, `screen`, `spec`, `ux`, `review`, `commits`, `show`, `list`, `now`, `ignore`, `check`, `gantt`, `hook`;
12
+ `cadence news`, `session` (`start`, `close`, `next`, `context`), `lead tour`, `corrections`, `deliver`, `verify`, `orchestrate`,
13
+ `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);
14
+ their options and exit codes as the pages [raf](raf.md), [orchestrate](orchestrate.md), [deliver](deliver.md), [spec](spec.md), [news](news.md), [session](session.md), [lead](lead.md), [corrections](corrections.md) and [skills](skills.md) document them. A new command or option is a minor change.
15
+ - **The keys of `cadence.yaml`**: `plan`, `news`, `hook`, `session`, `deliver`, `orchestrate`, `docs`, `qa`, `priority`, `depth`, `lead` (`lead.ux`)
16
+ 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.
17
+ - **The plan file** (`docs/plan/raf.yaml`): `project`, `prefix`, `since`, `ignore`, `lots` (with their
18
+ fields, `tasks`, `notes`, `repos`) and `acknowledged`, and the plan formats `plan:` in `cadence.yaml` can read.
19
+ The `version` key is kept in the file but ignored (`src/plan.ts` does not read it): it is not a schema version.
20
+ - **The names of the skills** (`session-start`, `session-close`, `deliver`, `lead`) **and of the agents**
21
+ (`ux-reviewer`, `code-reviewer`, `qa-reviewer`).
22
+
23
+ **Not guaranteed** (may change in any release)
24
+
25
+ - The **text of the outputs**: wording, layout, order of the lines and columns of every report, table and message
26
+ (the `--json` outputs and the exit codes are part of the commands above). In a `--json` output a new field is a
27
+ minor change, so consumers must tolerate unknown fields; removing or renaming a field is a major change.
28
+ - The **`precheck-reader`**, **`spec-writer`** and **`acceptance-writer`** agents, and the mockup and conformity modes of **`ux-reviewer`**: internal to `cadence orchestrate`, not meant to be called by hand.
29
+ - The **`cadence-hud` band**: its segments, colours and layout; it is versioned on its own.
30
+ - The **wave journals** under `.cadence/runs` and the files `cadence orchestrate` keeps there.
31
+ - The wording of the briefs and of the instructions inside the skills and the agents.
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
+
34
+ There is no schema version and no migration: a file written by an earlier release keeps working, and a key a
35
+ release adds is optional.