@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +45 -1734
- package/agents/acceptance-writer.md +1 -0
- package/dist/audit.js +4 -3
- package/dist/cli.js +4 -4
- package/dist/orchestrate/accept.js +8 -3
- package/dist/orchestrate/briefs.js +1 -1
- package/dist/orchestrate/command.js +3 -0
- package/dist/orchestrate/cycle.js +68 -6
- package/docs/cadence-hud.md +50 -0
- package/docs/corrections.md +24 -0
- package/docs/cycle-vague-dark.svg +42 -0
- package/docs/cycle-vague-light.svg +42 -0
- package/docs/deliver.md +204 -0
- package/docs/fonctionnement-lead-dark.svg +101 -0
- package/docs/fonctionnement-lead-light.svg +101 -0
- package/docs/fonctionnement-lot-dark.svg +38 -0
- package/docs/fonctionnement-lot-light.svg +38 -0
- package/docs/fonctionnement-service-dark.svg +23 -0
- package/docs/fonctionnement-service-light.svg +23 -0
- package/docs/fonctionnement-wave-dark.svg +66 -0
- package/docs/fonctionnement-wave-light.svg +66 -0
- package/docs/fonctionnement.md +106 -0
- package/docs/lead-workflow-dark.svg +200 -0
- package/docs/lead-workflow-light.svg +200 -0
- package/docs/lead.md +147 -0
- package/docs/news.md +245 -0
- package/docs/orchestrate.md +639 -0
- package/docs/overview.md +27 -0
- package/docs/raf.md +192 -0
- package/docs/releasing.md +59 -0
- package/docs/session.md +107 -0
- package/docs/skills.md +76 -0
- package/docs/spec.md +60 -0
- package/docs/stabilite.md +35 -0
- package/docs/whats-new.md +81 -0
- package/package.json +28 -1
- package/templates/acceptation-runner.mjs +1 -1
- package/templates/fiche-back.yaml +1 -1
- package/templates/fiche.yaml +1 -1
package/docs/overview.md
ADDED
|
@@ -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.
|
package/docs/session.md
ADDED
|
@@ -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.
|