@sylad/cadence 1.26.0 → 1.28.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/agents/doc-keeper.md +17 -0
- package/agents/spec-writer.md +1 -0
- package/agents/ux-reviewer.md +48 -1
- package/dist/cli.js +90 -15
- package/dist/config-set.js +2 -1
- package/dist/config.js +16 -1
- package/dist/corrections.js +164 -1
- package/dist/lead.js +24 -7
- package/dist/orchestrate/cycle.js +29 -2
- package/dist/perf.js +18 -4
- package/dist/priority.js +77 -0
- package/dist/verify-gate.js +3 -2
- package/docs/cadence-hud.md +2 -0
- package/docs/corrections.md +11 -1
- package/docs/deliver.md +2 -0
- package/docs/fonctionnement-lead-dark.svg +2 -2
- package/docs/fonctionnement-lead-light.svg +2 -2
- package/docs/lead-workflow-dark.svg +2 -2
- package/docs/lead-workflow-light.svg +2 -2
- package/docs/lead.md +12 -4
- package/docs/orchestrate.md +7 -2
- package/docs/perf.md +1 -1
- package/docs/raf.md +1 -0
- package/docs/session.md +7 -0
- package/docs/skills.md +4 -0
- package/docs/whats-new.md +6 -0
- package/package.json +1 -1
- package/skills/lead/SKILL.md +8 -5
- package/templates/orchestrate/implement.md +1 -1
- package/templates/orchestrate/maquette.md +1 -1
- package/templates/orchestrate/spec.md +2 -0
package/docs/lead.md
CHANGED
|
@@ -74,10 +74,14 @@ picture, not its source.
|
|
|
74
74
|
The lead asks both reviewers (`code-reviewer`, `qa-reviewer`) for a short reply with a `Report file: <path>` line in
|
|
75
75
|
the brief (L440): the full report goes to that file, outside the repository, and the agent answers in 5 lines at most
|
|
76
76
|
(`Verdict:`, `Blocking:`, `Follow-ups:`, `Report:`). The lead reads the file only when it needs the detail; twenty
|
|
77
|
-
reports of 3 to 5k each had swollen its context on 29-10.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
reports of 3 to 5k each had swollen its context on 29-10. The same line goes to the `ux-reviewer` and the `doc-keeper` (L452), which answer in 15 lines at most
|
|
78
|
+
(`Verdict:`, `Findings:` with the rule or measure of each, `Not verified:`, `Sub-tasks:`, `Report:`): about 25 reports of 2 to 4k had taken
|
|
79
|
+
the lead's context from 80k to 466k tokens on 30-10.
|
|
80
|
+
7. **Threshold and chaining.** Before every new wave the lead reads `cadence session context`. While the context is under
|
|
81
|
+
the threshold it chains: `cadence orchestrate --continue` draws the next ready lot of the plan, in the
|
|
82
|
+
declared priority, without asking the human « next? ». The threshold is in tokens, not in %: `lead.contextThreshold` in the `cadence.yaml` of the folder where the lead runs
|
|
83
|
+
(an integer ≥ 1, `150000` by default, because 60 % of a 1M window is 600k), and `session context` prints its verdict on a
|
|
84
|
+
second line (`seuil 150000 tokens : sous le seuil` or `atteint`). When it is reached, or when the figure cannot
|
|
81
85
|
be read (exit code 2: the band is not loaded, or its figure is stale), it starts nothing. A lot
|
|
82
86
|
that was not handed back ready is reported, not chained over; a question or a UX reservation
|
|
83
87
|
pending on a lot never stops the chain on the other lots.
|
|
@@ -119,6 +123,10 @@ The mechanics around it (the life of a lot in the plan, a lot inside a wave, put
|
|
|
119
123
|
[fonctionnement.md](fonctionnement.md). See also the [lead tour](lead.md#lead-tour) section below and the [orchestrate](orchestrate.md#orchestrate)
|
|
120
124
|
page.
|
|
121
125
|
|
|
126
|
+
## lead priority
|
|
127
|
+
|
|
128
|
+
`cadence lead priority <project> --before|--after <project> [folder] [--depth n]` (L449) puts a project right before or after another one in the order of the projects of the folder: it rewrites the `priority:` list of the folder's `cadence.yaml` (created when missing), the list `lead tour`, `cadence orchestrate --continue` and the [lots panel](cadence-hud.md#the-lots-panel-hud-lots-l401) all read. The projects are named as `lead tour` names them (the folder name, or the path from the folder at `depth:` 2 and more). The list written names **every** project of the folder, in the displayed order: a name that covered several projects by prefix (`shop` for `shop-web`) becomes explicit (the comment on its line moves to the first project it covered), a name that matches no project stays at the end of the list. The rest of the file is kept as it is, comments included (the list stays in the style it had, block or `[a, b]`). Nothing is written, and the answer says so (`… est déjà avant … : rien à changer`), when the project is already at that place. A `cadence.yaml` that cannot be read, a `priority:` that is not a list of names, an unknown project, the same project on both sides or two projects with the same folder name are refused; a move the list cannot express is refused too: when a project's name begins another's (`shop` and `shop-web`, matched by prefix as `priority:` always does), `shop-web` cannot be put after a project that follows `shop`, so the move is refused naming the clash instead of announcing a placement that does not happen. In every refusal the file is left untouched. The command never commits: the `cadence.yaml` change is yours to commit.
|
|
129
|
+
|
|
122
130
|
## lead hold and release
|
|
123
131
|
|
|
124
132
|
`cadence lead hold <label> [--ttl minutes]` and `cadence lead release <label>` (L255) declare the sessions the lead starts by hand — a fix subagent, a review, a QA pass launched outside an orchestrated wave. No wave carries such a session, so the slot registry could not see it: on 2026-10-23 the lead ran 4 sessions under a cap of 3 while `créneaux libres` said one slot was free. Orchestrated waves read the holds too (L424): a wave takes no session slot while the held sessions and the running ones already reach the cap, so a hold can no longer be overtaken by a wave starting a session on the « free » slot. `hold` registers the session under its label for `--ttl` minutes (an integer ≥ 1, 60 by default; holding the same label again renews it instead of counting twice); `release` hands it back (releasing a label that is not held answers `aucune session « <label> » inscrite` and exits 0). After the release (L416), `release` prints what it leaves: the slots line, the `prêts, ressources libres` line when a ready lot is free, and `⚠ N créneau(x) libre(s) sur M : lancer un lot prêt ou une session, un créneau vide ne sert à rien` while at least one slot is free (on 2026-10-29 a cap of 3 was taken for 2 and a slot stayed empty for more than an hour); `hold` prints neither. A hold whose time has run out stops counting, but is not forgotten: nothing stops the session (L278), so `cadence lead tour` and `cadence orchestrate --status` print `⚠ session du lead échue : <label> (inscrite depuis 5 h 10 min, échue depuis 2 h 10 min) — la reprendre (cadence lead hold <label> --ttl <minutes>) ou l'arrêter (cadence lead release <label>)` after the slots line, and the `cadence-hud` band shows the same ⚠ row, until the lead renews the hold or releases it (an expired hold nobody touched is dropped 24 h after its expiry). The `--ttl` is therefore the maximum duration declared for the session; the `lead` skill says to renew or stop it at each ⚠. The line is not part of `--json`.
|
package/docs/orchestrate.md
CHANGED
|
@@ -133,8 +133,8 @@ Both keys are optional; no `continue:` key keeps the old behaviour. A lot whose
|
|
|
133
133
|
**Chaining without the human (L148)**: the `lead` skill, once the human has chosen the first lots and the order, does not ask « next? »
|
|
134
134
|
after a lot that comes back ready: it re-verifies it, records `raf done`, pushes, delivers, has the `qa-reviewer` check the
|
|
135
135
|
delivered app, then starts the next wave with `--continue`, in the declared priority — one project at a time, within the two-session
|
|
136
|
-
limit. Before each new wave it reads the context of its own session with `cadence session context` (the figure of the `ctx` segment of the `cadence-hud` band, which publishes the context of each session to `~/.cadence/orchestrate/hud-context/<session id>.json`; the command picks the file named by `$CLAUDE_CODE_SESSION_ID`, set in the environment of the session's Bash, never "the latest file of the folder" — two sessions of one folder alternate; without the band loaded in that session the command exits with code 2, and a missing or stale figure counts as at the threshold);
|
|
137
|
-
|
|
136
|
+
limit. Before each new wave it reads the context of its own session with `cadence session context` (the figure of the `ctx` segment of the `cadence-hud` band, which publishes the context of each session to `~/.cadence/orchestrate/hud-context/<session id>.json`; the command picks the file named by `$CLAUDE_CODE_SESSION_ID`, set in the environment of the session's Bash, never "the latest file of the folder" — two sessions of one folder alternate; without the band loaded in that session the command exits with code 2, and a missing or stale figure counts as at the threshold); once it has reached
|
|
137
|
+
**`lead.contextThreshold`** (tokens, `150000` by default, see [session](session.md)) it starts nothing: it runs `session-close` in each project touched, writes its memory and records three lines for next
|
|
138
138
|
time (`cadence session next`). Stays with the human: the first choice and the order, the questions a session raised, the UX
|
|
139
139
|
reservations; a lot that is not ready, a red delivery or a blocking QA finding is reported and not chained over.
|
|
140
140
|
|
|
@@ -183,6 +183,8 @@ usability (code only when the lot is not `visible`). Failing tests (reported red
|
|
|
183
183
|
|
|
184
184
|
**One UX review per lot (L221)**: the UX review of a `visible` lot used to run before the code review and again after every correction (finance L75 on 2026-10-15: three Opus UX sessions for one useful verdict). It now runs once, as the last step, on the code the review found compliant: after the single pass on minor findings and its short review when there is one. Without `orchestrate.ux`, or when the app does not start (port taken, silent app), no UX session is played: the lot concludes on the compliant code review and keeps its note (« UX à faire par le lead », « UX non vérifiée : … »). The lot budget bounds writing, never this review; an exhausted wave budget suspends it like any session. Every write step (implementation, correction) clears the lot's UX state (`ux`, `uxVerdict`, UX findings), so a stale UX verdict never sends a compliant code review back to a correction. A resumed wave whose state says `next = ux` (written before this change) replays the code review first unless the last compliant one read the current `HEAD`. The recorded `raf review` verdict and sha are the code review's; a commit made by someone else since that review hands the lot back, as before. A small lot and a lot with no screen keep their single review. The measure before/after is in [`docs/mesures/ux-une-fois-2026-10-15.md`](mesures/ux-une-fois-2026-10-15.md).
|
|
185
185
|
|
|
186
|
+
**A lot made visible by its own session (L454)**: `visible` is read from the plan when the wave starts, and a session may add it (warhammer L37 and L43 on 2026-10-30: the lot left « ready » with « — » in the UX column and no UX step). After every writing session (`implement`, `fix`), before the first review, the orchestrator re-reads `visible` in the plan of the lot's worktree: a lot that became visible follows the path of a visible lot — the UX review after the compliant code review (or the single `review-small` pass of a small lot) — and the table shows its UX column. Without `orchestrate.ux`, no UX session can be played: the lot concludes and carries the note « visible ajouté en cours de vague, étape UX à jouer », under the table, for the lead. An unreadable plan, or a `visible` removed during the wave, leaves the lot as it was; a `screen:` added during the wave does not reopen the spec stage.
|
|
187
|
+
|
|
186
188
|
**A project without `orchestrate.test` is flagged (L327)**: without the key the wave never runs the suite itself — only the review does, if it decides to (it ran 12 test files of a project on 2026-10-25 and a red test reached « ready »). `cadence orchestrate --dry-run` writes one line per repository, under the first lot of that repository: `<repo> · porte de tests absente : orchestrate.test n'est pas déclaré, la vague ne lancera pas la suite (seule la revue le fera si elle le décide) · commande probable : npm test (à déclarer en orchestrate.test)`, and [`cadence lead tour`](lead.md#lead-tour) writes the same line for every project of the folder. The probable command is read from the repository, never run: `npm test` when `package.json` has a `scripts.test` (the `npm init` placeholder « no test specified » does not count), `pytest` when `pyproject.toml` names pytest, `mvn test` when there is a `pom.xml`; with none of them the line carries no command. A `cadence.yaml` that cannot be read gives no such line (it has its own error). Declaring `test:` (and `build:`) in the project's `cadence.yaml`, once the command is known to be green, removes the line.
|
|
187
189
|
|
|
188
190
|
**Tests already red at the start (L213)**: a lot is no longer handed back « tests rouges » for failures that were there before it. When `orchestrate.test` fails (or the session reports red tests), the program reads the failing tests from the runner's output (vitest/jest `FAIL`/`●`, pytest `FAILED`, go `--- FAIL:`, TAP `not ok`), replays the same command at the sha the lot started from (the parent of the lot's oldest work commit, plan-only commits left out, else the `HEAD` before its first session) in a throwaway `git worktree` outside the repository, and compares: if every failing test was already red, it is not a defect of the lot — no correction pass, the code review takes place, the reviewer is told, and the final table lists them apart (`déjà rouge au départ (<sha>) : <test>`, 30 at most then a count). The worktree gets links to the repository's ignored folders at any depth, such as `.venv` and, in a monorepo, `packages/*/node_modules`, when their parent exists at that sha; build outputs such as `dist` or `coverage` are left out. Each `node_modules` is rebuilt entry by entry, every entry linked to the live one except the workspace links of npm, pnpm and yarn (`node_modules/@x/shared -> ../../packages/shared`, a link to code of the repository outside any `node_modules`), which are remade towards the worktree's own copy so that the start sha is tested against its own sources, not the lot's (a workspace package that does not exist at the start sha gets no link). Known limit: only `node_modules` links are remade; whatever points into the live repository by an absolute path, such as an editable Python install (`.venv` with a `.pth` file naming the live `src`, `pip install -e`) or an absolute symlink in another ignored folder, still runs the lot's code in the baseline. Likewise, a workspace package consumed through its build output (`main: dist/...`) cannot load in the baseline worktree: output dirs are not linked, so such a monorepo keeps the pre-L213 « tests rouges » outcome unless `orchestrate.build` is declared (the build is then played first in the baseline worktree, see below). A lot resumed in a later wave keeps the same baseline: the sha is the parent of its oldest work commit, not the `HEAD` of the new wave, so a failure the lot itself introduced in an earlier wave is never excused. A test red now and not at the start stays a blocking finding, and only that one is given to the correction (the others are counted as « already red »). When the output names no test, or the baseline cannot be run, the tests stay red as before (no comparison is guessed). A failure the output does not tie to a test (unhandled error, a spec file that fails to load such as jest « Test suite failed to run » or vitest `FAIL a.test.ts [ a.test.ts ]`, coverage threshold) keeps the tests red. Without `orchestrate.test` the program cannot replay anything: a session that reports green tests and lists under `echecsDeBase` the failures it saw at the start sha gets them listed apart, marked « non vérifié » in the table, and the review takes place; a session that reports the tests red stays red, the brief asking it not to report red for base failures alone — unless (L215) the report says so in a structured way: with `vert: false`, a non-empty `echecsDeBase` and an empty `nouveauxEchecs` (the list of tests red now that were not red at the start sha), `vert: false` is not a reason to correct, the lot carries a « non vérifié » warning, the reviewer is told that the baseline is unverified and the review takes place. A non-empty `nouveauxEchecs` with `vert: false` triggers a correction pass (the new failures are in the finding); an absent `nouveauxEchecs`, or an empty `echecsDeBase`, keeps the correction. With `orchestrate.test` declared (L361), the same structured report is honoured when the program's own gate is green (`orchestrate.test` exits 0): `vert: false` with a non-empty `echecsDeBase` and an empty `nouveauxEchecs` goes straight to the review, with a warning, without a correction pass and without the « tests rouges » escalation; without those two fields the claim of red tests still triggers the correction. The program never guesses from the text of the result (« 24 failed »). The `implement` and `fix` briefs ask for `echecsDeBase` and `nouveauxEchecs`.
|
|
@@ -335,6 +337,7 @@ After a valid spec, a lot with a sheet gets a UX review of its mockup, `maquette
|
|
|
335
337
|
that it checks the **consistency mockup ↔ sheet**: every field of the sheet in the mockup with its `data-testid`, every rule message visible, word for word, in the state its `etat` names, every state with its
|
|
336
338
|
`#etat-<état>` section, the `masque` of an empty-state rule really hiding the fields it names. `effort.maquette` (default `high`) sets its effort level. Its verdict is **not** `raf ux`: the conformity pass after the code keeps that role.
|
|
337
339
|
- **A full sweep from the first review** (L230). The brief and the agent ask for a checklist in the text of the report, one line per item: every state of the sheet at 1440 and 390 px, every rule of the sheet, contrast, the real envelope of the app (usable width, side bar, header), gutters, empty or stretched panels, holes in the layout. What cannot be verified goes in `nonVerifie`; the program does not check the list. The first report must hold ALL the blocking and major findings, none kept for a later review.
|
|
340
|
+
- **Design criteria in the mockup review** (L448). In mockup mode only, the agent also checks four families of criteria absent from its method, each tied to a named rule or a count: **visual hierarchy** (one primary element per state, Nielsen 8), **consistency with the product tokens** (count of colour, size and spacing values that do not come from the product's CSS variables, Nielsen 4), **quality of the texts** (error message = what, why, how to fix, Nielsen 9; empty or loading state = what it is, why it is empty, how to start, Nielsen 1; action label = a verb that names the result, Nielsen 2 and 4; destructive confirmation naming the object and the consequence, Nielsen 5; one word per notion, count of distinct labels) and **complementary accessibility** (focus order 2.4.3, name, role, value and field label 4.1.2 / 3.3.2 / 1.3.1, error identified by text 3.3.1, text at 200 % 1.4.4). The checklist of the report gets one line per family and per state; what a static mockup cannot show (a real screen reader) goes in `nonVerifie`. Severity keeps its scale: an accessibility gap stays blocking or major, a text, hierarchy or token defect is major only if it misleads or slows the task, otherwise minor. The spec writer applies the drawing-time ones (the texts, one primary element per state, one label per field, the product's variables) before the review; the measures (contrast, zoom, focus order) stay with the reviewer. No new review, no new session: the budget of `maquetteReviews` and the report schema are unchanged. Measure: `cadence perf`, « sessions ux par lot visible » (1.6 on the window of 30-10, target 1.2).
|
|
338
341
|
- **The loop, `orchestrate.maquetteReviews` reviews at most** (integer ≥ 1, default 3; any other value is a configuration error). A blocking or major finding sends the mockup back to the spec writer: a fresh `spec` session whose brief carries the findings, then the mockup is reviewed again (the brief of review n says « review n of N », and « the last review » for the last). If the last review is
|
|
339
342
|
still not conforming, the lot is handed back with what remains (`maquette non conforme après 3 revues : …`, `après 1 revue` when the key is 1) and nothing is implemented. A lot with a screen and `orchestrate.maquette` not `false` has a budget of `maquetteReviews` `spec` sessions, shared with the sheet review of a mixed lot (which keeps its two reviews); any other lot keeps two. If the program's check or the reviews already used the budget, a non-conforming review hands the lot back at once (`maquette non conforme et la spec a déjà joué 3 sessions`); an answer to a question of the lead opens a new budget.
|
|
340
343
|
- **Review defects in the journal.** From review 2, the agent marks `inchange: true` on each blocking or major finding about a point the spec writer did not change and the previous review had not raised (optional boolean of a finding; anything but `true` counts as false). For each one the program writes `<project>:<lot> · défaut de revue : maquette, revue <n>, majeur sur un point inchangé absent de la revue <n-1> : <text>` in the wave journal. Nothing else changes: verdict, loop and state of the lot are the same. A conforming review goes on to `accept` (or `implement`). On a resume, a **sealed** `acceptation.json` (its `empreintes` set by the program), still red or already green (`vert: true`), proves the review was done and is not replayed; an unsealed one proves nothing, a `vert: true` one included (only the cycle sets `vert`, after the seal). **A green and sealed acceptation never goes back to `accept` (L233)**, nor to the sheet and mockup reviews, even when its seal no longer holds (a test resealed by `cadence spec reseal`, a sheet amended since): the lot goes to `implement` or the review, the step would rewrite a green oracle and demand red tests. The `accept` brief and the `acceptance-writer` agent say the same: given a `vert: true` file whose `empreintes` hold one entry per listed test file, never rewrite it nor touch `resceaux`, `empreintes` or `vert`, write nothing and hand the lot back; given a `vert: true` file without `empreintes`, or whose `empreintes` lack one of the listed files (never sealed, it proves nothing), write the oracle as usual with `vert: false` (the program itself never starts an `accept` session on a green and sealed acceptation, even for a lot waiting on an answer with `next` = `accept`, so nothing relies on the prompt alone). A lot waiting on an answer is compared with the file as it was before its first `accept` session: if that session rewrote the green file and committed it before asking its question (`vert: false`, `resceaux` erased), the lot is handed back (`verrou des tests d'acceptation : … acceptation verte réécrite …`) instead of adopting the rewrite as its red commit; only a `cadence spec reseal` by the lead (journal `resceaux` longer, commit outside any session) is accepted. A `maquette` step with no sheet warns (`revue de la maquette ignorée : aucune fiche …`) and goes to `implement`.
|
|
@@ -399,6 +402,7 @@ Once the sheet exists, the steps after it all read it (L174, `src/orchestrate/av
|
|
|
399
402
|
- **A self-check list before handing back (L222).** Both `implement.md` and `fix.md` carry the same fixed list (plain text, no marker, no new variable), taken from the recurring findings of the reviews of 2026-10-15: the usage documentation (README and architecture documentation) updated in the same commits as the behaviour; one test named `Rn — …` per rule of the sheet (one per business rule of the lot when there is no sheet); no dead code and no test that cannot fail (an assertion always true, or a test that does not exercise its rule); for a modified screen, the capture due of each state at 1440 and 390 px with a file name (where it goes is the Playwright paragraph's rule) (a lot with no modified screen owes none and says so); no false comment, docstring or message. The session goes through it point by point on its own commits before it reports, and a point it cannot hold is written under `choix` or `nonVerifie` of its report: the report schema has no new field. In `fix` the list covers only what the session changed, and "fix them, and nothing else" stays. The other briefs (`fix-minors`, `spec`, `spec-back`, `accept`, `review-small`…) are unchanged. The before/after measure — correction passes per lot, replayed with `cadence corrections` (`--until <bound>` for the "before", `--since <bound>` for the "after", the bound being the time of the `npm run service` that puts the list in service) — is in [docs/mesures/autocontrole-avant-revue-2026-10-15.md](mesures/autocontrole-avant-revue-2026-10-15.md).
|
|
400
403
|
- **Auto-verification once the tests are green (L236).** After the self-check list, `implement.md` and `fix.md` carry a second fixed block: when the full suite and the build pass, the session re-reads the complete diff of its lot (of its fix commits, in `fix`) against the grid of the `code-reviewer` agent — code bug, architecture drift, `docs/architecture.md` (or the project's architecture documentation) up to date, edge cases, one test per changed behaviour — fixes what it finds at once (test first, a `fix(<lot>): …` commit, suite and build replayed), then starts `resume` with an « auto-vérification » paragraph: what it re-read, found and fixed, could not hold. No new report field. The cost bound is written in the brief: one reading of the diff, not a second review (no subagent, no files the diff does not touch). Measure before the block (`cadence corrections --classify`, 10 to 17-10): 356 passes, 53 % code bug, 19 % architecture drift, 14 % unclear spec; `cadence perf` of 17-10: 37 % right the first time. Target: above 50 % on the next window with tokens per lot stable (`cadence perf`).
|
|
401
404
|
- **Limits and rules before the walkthrough (L428).** `implement.md` (not `fix.md`) carries a third fixed block between the self-check list and the real walkthrough, aimed at the first cause of correction passes: a code bug the review finds in the diff (100 of the 143 classified passes of the 23–29-10 window, `cadence perf`). The session re-reads its diff against the fiche and the lot and, **per rule** (`Rn`), names the test that fails if the code breaks it and the line that holds it; **per function, parser, pattern, threshold or command it adds or changes**, lists the inputs at the edge (empty, absent, twice, wrong order, wrong type, refused, the real shape of the data, the other callers) and gives each a test that fails without its code, except a case the fiche does not cover: with a fiche, the session does not code a rule the fiche does not state, so that case goes under `"nonVerifie"` or `"choix"`, neither coded nor tested (a lot without a fiche has no such exception: every listed case is due a test, and one left untested goes under `"nonVerifie"`); **per figure, « all », « never » or « always »** written in README, docs, comments or tests, checks it against the code or by running it. A listed case left untested goes under `"nonVerifie"`. The reading of the 23–29-10 passes that led to it, and the way to measure its effect on two windows, are in [mesures/bug-code-2026-10-29.md](mesures/bug-code-2026-10-29.md). Test: `test/limites-et-regles-l428.test.ts`.
|
|
405
|
+
- **The edge-cases point, sharpened (L447).** `cadence corrections` now sub-classifies the `bug-code` passes ([corrections](corrections.md)); on the 24→30-10 window the dominant link is the `implement` brief (99 of 136 passes; 96 of them, 71 %, are edge cases). The « edge cases » bullet of the L428 block therefore carries, marked `[L447]`, two more demands: the list of edge inputs is written before the first line of code, and before reporting each listed input is played once on the real path (a real file or call, not only the fixture). It is the same block, not a second one; no other brief changes. Table, protocol and the two windows to measure (L428 and L447 together, from 2026-10-30): [docs/mesures/bug-code-2026-10-30.md](mesures/bug-code-2026-10-30.md).
|
|
402
406
|
- **Real walkthrough before the auto-verification (L344).** Reading a diff did not show three major review findings of 26-10 (a command impossible in its own documented path, a « champs exclus » read against a decision of 22-10, a failure banner out of view). `implement.md` therefore asks, once the tests are green, to play what was delivered as a user would: a command in a throwaway repository (`git init` in a fresh temporary folder), following the documentation the lot wrote, command by command; a screen in each of its states, failure included and shown where the action takes place, with a capture of each. What breaks is fixed in the same session (test first) and played again; the report says it in a paragraph of `"resume"` that starts with « parcours réel » (no new field; a lot with nothing to play says so). `fix.md` does not carry it: a correction pass fixes the findings it is given.
|
|
403
407
|
- **Decisions to respect (L344).** The program (not the pre-check session, which many lots skip) reads the notes of the lot and of its parent lot (`parent:`) and keeps those that name who decided (Sylvain, the human, the lead, the user) and say that they decided, validated, asked or refused (`src/orchestrate/decisions.ts`). The notes the program writes itself are never taken for one, whatever they quote: a hypothesis of a fiche (« Hypothèses (fiche …) — », a choice nobody validated), a minor of a review (« Revue de … — mineur : »), a replaced title (« titre remplacé : », the stale one), « remis en attente » and « abandonné : ». Each is given with its date and its text as written (cut at 1500 characters) under « Decisions to respect » in the `implement` and `fix` briefs (and in the `--dry-run` briefs), with the rule: an interpretation that departs from one of them is a question under `"questions"`, never a choice under `"choix"`. Nothing is written when no note qualifies. The effect is measured by the share right the first time of `cadence perf` over two windows.
|
|
404
408
|
- **The code review (`review`, `review-small`) checks rule → test → green** (`règle → test → vert`). For each `Rn` of the sheet the reviewer checks that its test exists (named after the rule), that it is green, and that the behaviour is in the diff; when an acceptance file is named, that each listed test is unchanged since the red commit (`git diff <red commit> -- <file>` empty; the brief gives the red commit). A rule without a test, an acceptance test modified since the red commit, a rule coded that is not in the sheet, and a test that is green without exercising its rule are **major** findings. The reviewer no longer rebuilds the cases from the code.
|
|
@@ -868,6 +872,7 @@ orchestrate:
|
|
|
868
872
|
testReplay: npx vitest run --minWorkers=1 --maxWorkers=$CADENCE_TEST_WORKERS {files} # replay alone of a red test before it counts (L354, see « A red test is replayed alone »; `cadence verify --gate` applies it too, L387, `docs/deliver.md`); `{files}` required; absent: no replay, nothing held for unstable (optional)
|
|
869
873
|
build: npm run build # run BEFORE the tests (L333); both results go to the reviewer, who does not redo them (optional)
|
|
870
874
|
worktreeDeps: [node_modules, .venv] # untracked dependencies that `cadence verify --gate` copies into its throwaway worktree (L348, L389; the gate runs in the main tree instead when it is clean at the sha, `verify.inPlace`, `docs/deliver.md`); absent: the `node_modules` of every level and the `.venv` are copied (never data or `.env`, L392), the other ignored folders are linked as in the worktrees of a wave (optional)
|
|
875
|
+
gate: { readsPlan: true } # a test of the gate reads the plan (`.cadence/raf.yaml`): `cadence verify --gate` no longer takes over a wave's verdict under commits that change only the plan (L444), it replays; `true` or the list of the paths of the tests that read it; absent or `false`: those commits are crossed (L450, `docs/deliver.md`) (optional)
|
|
871
876
|
precheck: true # default: before the first implementation of a lot with no commit whose title cites a finding or an earlier lot, and whose title or `goal:` cites a finding (`constat`, `revue`, `review`, `audit`) or a plan id (an earlier `L<number>`, also followed by a hyphen as in `L12-L15` or `L12-bis`; any other id such as `Q-CAN5`; `project:L<number>`), a read-only Sonnet session checks whether the deliverable is already in the repository (see below); false skips it, local runs it on claude-local (Ollama) with Sonnet as fallback, for every lot with no commit whatever its title (L296); a lot created after the last code commit of the repository is not pre-checked, local or Sonnet, unless it cites a lot that already has commits (L322)
|
|
872
877
|
accept: npx vitest run -c vitest.acceptation.config.ts # accept step (see « The accept step »): the dedicated command that runs ONLY the acceptance tests of the lot (optional; without it the step is skipped with a warning)
|
|
873
878
|
maquette: true # default: UX review of the mockup between spec and accept (see « The mockup review »); false skips it
|
package/docs/perf.md
CHANGED
|
@@ -14,7 +14,7 @@ one (the 7 days before). Every speed indicator is printed on the same line as it
|
|
|
14
14
|
|---|---|---|---|
|
|
15
15
|
| Throughput | lots ready, lots handed back per day, lots delivered (plan `done` with `finished` in the window), share of handed-back lots within their token budget | escaped defects | is the flow dropping? look for the bottleneck before adding lots; are the budgets right? |
|
|
16
16
|
| Corrections | median of `fix` passes per lot, share of lots with 2 passes or more | share of lots right the first time (no `fix` pass) | is the first write good enough? harden the sheet or the brief |
|
|
17
|
-
| Corrections | dominant causes (top 3 of the classified passes, the unclassified share apart) | — | which link to fix |
|
|
17
|
+
| Corrections | dominant causes (top 3 of the classified passes, the unclassified share apart); under it, the sub-causes of the `bug-code` passes and the dominant link (L447, [corrections](corrections.md)) | — | which link to fix |
|
|
18
18
|
| Lead interventions | lots handed back by a wave then finished outside it, sessions that see the application per visible lot (`ux` steps, plus the `review-small` of a small visible lot), share of visible lots reviewed by a dedicated `ux` step | escaped defects (sessions per lot only) | does the wave stop too early? does the ergonomics review cost more than one round? |
|
|
19
19
|
|
|
20
20
|
A line starts with `⚠` and ends with the decision it informs when its value is **worse than the previous window by more than 25 %**
|
package/docs/raf.md
CHANGED
|
@@ -66,6 +66,7 @@ raf gantt # .cadence/gantt.html (next to the plan)
|
|
|
66
66
|
| `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`), or on a sub-task; sub-tasks and other keys are left as they are. **Reopening** (L396): on a `done` or `dropped` lot, `raf todo` is THE command — never the YAML — that reopens it (`→ todo`, `finished:` removed, `started:` kept so its commits stay its own, dated note « rouvert (était done) : reason »); `raf start`/`raf done`/`raf drop` on a closed lot say so (`L3 est done ; le rouvrir si c'est voulu : raf todo L3`). An archived lot reopened this way comes back into the plan file at that write |
|
|
67
67
|
| `raf migrate [--dry-run]` | move `docs/plan/raf.yaml` to `.cadence/raf.yaml` and rewrite the readers of the old path in the repository, see [Moving the plan: `raf migrate`](#moving-the-plan-raf-migrate) |
|
|
68
68
|
| `raf note <id> "text"` | dated note — keep decisions next to the work |
|
|
69
|
+
| `--verbose` on `raf done`, `ux`, `review`, `note`, `move`, `public` · `raf hook post-commit --verbose` (L453) | those commands print no title of the lot they touch (nothing in the lead's context but `L12 → done` and the `plan non commité` command, which is unchanged); `--verbose` adds one line `L12 doing <full title>` (nothing for a sub-task). The post-commit hook warning `raf: L12 (doing) <title>` cuts the title at 60 characters (59 and `…` beyond; a title of 60 stays whole), `--verbose` on the hook gives it whole. `raf show`, `raf list`, `raf now` and the session tables are not concerned |
|
|
69
70
|
| `raf title <id> "new title"` | replace the title of a lot of any status (`done` included) and add a dated note « titre remplacé : « old title » »; `raf now`, `raf show`, `raf list`, `session start` and the proposals read the new one. Refused on an empty or identical title, an unknown lot or a sub-task |
|
|
70
71
|
| `raf archive [--before date] [--dry-run]` | move the `done` and `dropped` lots (those finished strictly before `--before`, when given; a lot with no `finished:` date stays then) out of the FILE `.cadence/raf.yaml` into `.cadence/archive/<year>.yaml`, the year of their end (L396). **The archive is a storage detail, invisible to every reader**: the loaded plan presents all the lots, active and archived, **in the order they had before the archiving** — each archived lot takes its place by number among the lots of the plan file (just before the first active lot with a greater number), the order of the plan file itself never moves — so `raf show`, `raf list`, `raf commits`, `raf check`, `raf now`, `raf gantt`, `cadence news`, `cadence perf`, `session start`, `lead tour`, `cadence ref coverage`, `cadence deliver`, the post-commit hook and `cadence orchestrate` print exactly what they printed before the archiving — nothing has to « also look in the archive », a lot id is never reused, and a commit or a News entry citing an archived lot is not « inconnu ». What changes is the file: the plan the sessions open stays short (the cadence plan weighed 559 KB, ≈ 150 k tokens) and the briefs of the implementation, the sheets, the code review and the pre-check tell the sessions never to open `.cadence/archive/`. **Writing**: every lot goes back to the file it came from — `raf note`, `raf review`, `raf ux`, `raf title`… on an archived lot rewrite its year file, the plan file is untouched; a lot reopened (`raf todo <id>`, or `status: doing` set by hand in a year file) comes back to the end of the plan file at the next write, so the archive only ever holds `done` and `dropped` lots. **Lossless, whatever fails**: the year files are written before the plan file (should the plan then fail to write, a moved lot is at worst duplicated — which the next load refuses by name — never lost), and any exception during the write (`EACCES` on a read-only file, a full disk, a `plan.onWrite` command that fails) puts the plan, the year files and the declared files back as they were — a year file born of that write disappears — and the error says so (`écriture du plan refusée (EACCES, …) — plan et archive inchangés`). **Guards**: a closed lot with an open gap (what `raf check` signals — code review, UX review, docs.sync, News entry…) stays in the plan with the gap as its printed reason (`L1 reste dans le plan : écart ouvert — L1 est visible et terminé sans entrée Nouveautés …`); a lot named in `after:` by another, or counted by a `gate:`, is archived like any other — the readers see the archive, so the dependency and the count read the same. A same id found in two files (plan and archive, or two years) is a named error that stops every command (`identifiant en double : L1 est dans .cadence/archive/2025.yaml et dans .cadence/raf.yaml`) until one copy is removed by hand — never a silent choice of one copy. `--dry-run` lists without writing; `--before` takes `YYYY-MM-DD`; refused on a read-only plan (its tool keeps its own history) and while the plan is still at the legacy `docs/plan/raf.yaml` (the archive would land under `docs/`, published, and `raf migrate` would not move it: `raf migrate` first, the refusal says so). For `cadence orchestrate`, the year files are plan files like `.cadence/raf.yaml`: a session that commits one has « touché le plan ». Like every plan write, it is not committed: the command to commit the plan and the archive files together, at explicit paths, is printed (`plan.commit` template, action `N lot(s) archivé(s)`); replaying moves nothing twice. The archive files are kept with the plan: touching them is not working on a lot. **The published plan**: a generator run by `plan.onWrite` (below) that reads only the file `.cadence/raf.yaml` publishes a plan without the archived lots; `raf archive` says so on stderr when `plan.onWrite` is declared, the generator must also read `.cadence/archive/*.yaml` (key `lots`, same lot format as the plan) |
|
|
71
72
|
| `raf show <id> [--notes]` | one lot: status, dates, `goal : …` right after the title when the lot has a `goal:` (native key or `plan.fields.goal`, L272: the objective that replaces the title in the `orchestrate` briefs), `after`, public title, then for a visible lot two stable lines — `visible : oui` (followed by `screen : …` when the lot has one) and `ux : <verdict>` or `ux : absent` (the `raf ux` verdict, L439: what the `livreur` agent reads before closing a visible lot; a lot that is not visible prints neither line), `spec`, `uses : banc, passerelle` when the lot has `uses:`, dated notes in order, then the counted commits (as `raf commits`, neighbouring repositories included); `--notes` prints the notes alone |
|
package/docs/session.md
CHANGED
|
@@ -20,8 +20,15 @@ cadence session context # `ctx 42 % (84000/200000)`: the context of Y
|
|
|
20
20
|
# overrides it; with no variable, the folder decides only if a single session publishes for it
|
|
21
21
|
# (two sessions in one folder = exit 2, "pass --session"); exit 2 too when no fresh figure
|
|
22
22
|
# (band not loaded) = treat as at the threshold
|
|
23
|
+
# a second line gives the verdict against `lead.contextThreshold` (tokens, 150000 by default):
|
|
24
|
+
# `seuil 150000 tokens : sous le seuil` or `… : atteint` (tokens ≥ threshold)
|
|
23
25
|
```
|
|
24
26
|
|
|
27
|
+
`lead.contextThreshold` is read in the `cadence.yaml` of the folder where `session context` runs (the lead's folder): an integer ≥ 1,
|
|
28
|
+
in tokens, because a percentage moves with the window (60 % is 120k on 200k, 600k on 1M). A zero, a negative, a decimal or
|
|
29
|
+
a non-number is refused with the key's name (exit 2, read as at the threshold). It is not scaled to the window: on a window
|
|
30
|
+
smaller than the threshold the verdict never reads `atteint`, so set a lower one there.
|
|
31
|
+
|
|
25
32
|
`session start` records its time in the worktree's state (`session.json`, under the git dir); the next
|
|
26
33
|
`session close` takes it as its window and names it in the section title: `Commits de la période (depuis
|
|
27
34
|
l'ouverture de 09:12)` (with the date when it is not today). A close never moves the boundary, refused
|
package/docs/skills.md
CHANGED
|
@@ -50,6 +50,8 @@ repository with `cadence skills install` (to `.claude/skills/cadence-*` and
|
|
|
50
50
|
edits code. Read-only for real: its `tools:` list is `Read, Grep, Glob, Bash` and the
|
|
51
51
|
Playwright tools (`mcp__playwright`, and `mcp__plugin_playwright_playwright` when the
|
|
52
52
|
browser comes from the Playwright plugin) — no `Edit`, no `Write`. In a wave it gives its captures the absolute path of the capture directory its brief names (a bare name would land in the repository); outside a wave, a path under `.playwright-mcp/` (e.g. `.playwright-mcp/page-home.png`; the Playwright MCP resolves a bare file name against the repository, where it would land at the root); `qa-reviewer` follows it too.
|
|
53
|
+
**Short reply (L452):** with a `Report file: <absolute path>` line in the brief it answers in 15 lines at most (`Verdict:`, `Findings:` with
|
|
54
|
+
the rule or measure of each, `Not verified:`, `Sub-tasks:`, `Report:`, `Captures:`) and writes the full report to that file (outside the repository, verdict last).
|
|
53
55
|
- **code-reviewer** (agent): any stack; given a repository and a lot id, it reads
|
|
54
56
|
the diff itself from the commits that cite the lot — not the author's summary —
|
|
55
57
|
and the project's CLAUDE.md, when there is one, for its conventions; findings grounded in a
|
|
@@ -69,6 +71,8 @@ repository with `cadence skills install` (to `.claude/skills/cadence-*` and
|
|
|
69
71
|
document behind the lot; the lead calls it by hand. A document outside the repository only when the project's
|
|
70
72
|
`cadence.yaml` names it (`docs.articles`): the agent then proposes a lot for that repository's plan and never writes it
|
|
71
73
|
([news](news.md#the-librarian-doc-keeper)).
|
|
74
|
+
**Short reply (L452):** with a `Report file: <absolute path>` line in the brief it answers in 15 lines at most (`Verdict:`, `Findings:` with
|
|
75
|
+
the rule or measure of each, `Not verified:`, `Sub-tasks:`, `Report:`) and writes the full report to that file (outside the repository, verdict last).
|
|
72
76
|
- **reference-analyst** (agent, L265): given the folder of a document registered by `cadence ref add` and the file to
|
|
73
77
|
write, it looks at every rendered page whole, then every zone at full resolution, measures with `cadence ref measure`
|
|
74
78
|
(never by eye), copies every text verbatim, links each figure to the passages that cite it and writes one reading in
|
package/docs/whats-new.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
## In two lines
|
|
6
6
|
|
|
7
|
+
- **1.28.0**: projects are reordered from the lots panel or `cadence lead priority`; the lead's context threshold is in tokens; reviewers answer the lead in a few lines; the gate replays under plan commits when tests read the plan.
|
|
8
|
+
- **1.27.0**: `cadence corrections --classify` names the sub-cause of each code-bug pass and the dominant link of the chain, `cadence perf` shows it; the mockup review checks hierarchy, tokens, texts and extra accessibility.
|
|
7
9
|
- **1.26.0**: a new `livreur` agent delivers a ready lot for the lead (gate, UX verdict, `raf done`, push, deliver) and hands back one line; `raf show` prints `visible` and `ux` for a visible lot.
|
|
8
10
|
- **1.25.1**: publishes 1.25.0 (tagged, never published); tests now pass in a fresh clone and `cadence release` replays them in one; the panel of lots shows each project's last delivery.
|
|
9
11
|
- **1.25.0**: the panel of lots shows pending decisions, each lot's cycle and its budget and time overrun; `orchestrate --status` is compact; reviewers answer in 5 lines; `--resume --integrate` waits for a live wave.
|
|
@@ -53,6 +55,10 @@ Each is a paragraph in [docs/whats-new.md](whats-new.md) and a full section in [
|
|
|
53
55
|
|
|
54
56
|
The long form of « In two lines » above (the README no longer carries a « What's new » section since L326: it links here). The full history, with the date of each version, is in [CHANGELOG.md](../CHANGELOG.md).
|
|
55
57
|
|
|
58
|
+
**1.28.0**: the lead spends less of its context, and the projects are ordered where they are read. `cadence lead priority <project> --before|--after <project>` rewrites the `priority:` list of the folder's `cadence.yaml`, comments kept, and the lots panel does the same by drag and drop or Alt+↑/↓ in a region « ordre des projets » above the tree (L449, `docs/lead.md`, `docs/cadence-hud.md`); a move it cannot write back faithfully (a name that prefixes another) is refused with its reason. The lead's context threshold is a number of tokens, `lead.contextThreshold` (150000 by default), read by `cadence session context` (L437). `ux-reviewer`, `doc-keeper` and the reviewers answer the lead in a few lines and keep the full report in the file named by `Report file:` (L452), and `raf` cuts the titles it echoes to 60 characters (L453). `orchestrate.gate.readsPlan` lets a project whose tests read the plan say so: `cadence verify --gate` then replays the suite under plan-only commits instead of taking over the wave's verdict (L450). A lot made `visible` by its own session during a wave now goes through the UX step instead of coming out ready without it (L454).
|
|
59
|
+
|
|
60
|
+
**1.27.0**: the code-bug bottleneck is named, and the mockup review looks at more. `cadence corrections` sub-classifies the « bug de code » passes (L447, `docs/corrections.md`): one of seven sub-causes (edge case, broken test, misread contract, forgotten caller, false statement, empty test, other) per pass, asked of the local model with `--classify` and cached in `.cadence/corrections-sous-causes.json` (`--cache-sous-causes`); the report gains the section « Bug de code par sous-cause » and the dominant link of the chain (at least 10 passes sub-classified and 40 % of them), `--json` the key `bugCode`, and `cadence perf` prints the same count under « causes dominantes », read-only; nothing changes for a window with no `bug-code` pass. On the 24→30-10 window the dominant link is the `implement` brief (`docs/mesures/bug-code-2026-10-30.md`): 96 of the 136 `bug-code` passes are edge cases, so the « edge cases » bullet of the L428 block of `implement.md` now asks for the list before the first line of code and for each listed input to be played once on the real path before reporting (marked `[L447]`); the next measure counts L428 and L447 together, from 2026-10-30. The mockup review (L448, `docs/orchestrate.md`) checks four more families of design criteria, each tied to a named rule or a count: visual hierarchy (one primary element per state), consistency with the product tokens (values that do not come from the product's CSS variables), quality of the texts (error, empty and loading states, action labels, destructive confirmations, one word per notion) and complementary accessibility (focus order, name, role and label, error as text, text at 200 %). It applies in mockup mode only, with no new review or session and the same severity scale and report; the spec writer and its brief apply the drawing-time criteria before the review. Measure: « sessions ux par lot visible » of `cadence perf` (1.6 on the window of 30-10, target 1.2).
|
|
61
|
+
|
|
56
62
|
**1.26.0**: the lead hands the delivery of a ready lot to a subagent. The `livreur` agent (L439, installed by `cadence skills install` like the others) takes one ready lot and one sha given by the lead, and runs `cadence verify --gate --sha`, the UX verdict according to `lead.ux`, `raf done` and the plan commit it prints, `git push origin <sha>:main` and `cadence deliver`, then hands back one line (`L84 livré 3d6edf4, QA à lancer <url>`) or one `Question : …`. It first checks that the sha is an ancestor of HEAD, has no lot that is not done below it and is not already in `origin/main` and in the delivery log; it launches no agent, never the `qa-reviewer` (the lead does, after the line), and the lead launches one `livreur` at a time (`docs/lead.md`). A relaunch on a lot already done weighs both proofs (`origin/main` and `deliveries.log`), so « pushed, never delivered » is no longer masked by « déjà clos ». It reads `git diff --name-only origin/main..<sha>` right after `git fetch origin main`, before the gate and the push, to decide whether a QA pass is due and refuses a brief without the base URL before any action. `raf show <lot>` prints two new stable lines for a visible lot, `visible : oui` (then `screen : …` when the lot has one) and `ux : <verdict>` or `ux : absent` (`docs/raf.md`): that is how the `livreur` knows whether the lot is visible and whether the human's UX verdict is recorded (`lead.ux: human`).
|
|
57
63
|
|
|
58
64
|
**1.25.1**: publishes 1.25.0 and closes the hole that kept it from reaching npm. The `v1.25.0` tag was pushed but its `publish` workflow failed in `test/hud-cycle`, `test/hud-deliveries` and `test/hud-depense-l414`: vitest read `plugins/cadence-hud/tsconfig.json`, which extends `.claude-plugin/types/tsconfig.json`, a file Claude Code writes when it loads the mod and git does not track, so no local tree could see it fail (L445); the tag is not rewritten, everything 1.25.0 brings (see below) ships in this version. The test suite now passes in a fresh `git clone` (the mod's own typecheck still extends that file). `cadence release` prints, right after the gate replay, a step that replays the version commit in a fresh `git clone --no-hardlinks` (`npm ci`, `npm run typecheck`, `npm test`, the clone removed afterwards), and `.github/workflows/tests.yml` also runs on every push to `main` (L446, `docs/releasing.md`). The panel of lots (`/hud lots`, `docs/cadence-hud.md`) shows, under the lots in progress, the last delivery of each project: its short sha, its age in days, green or red (read from the journal `cadence deliver` writes), and the lots closed since the last green delivery that were not delivered; `cadence lead tour --json` gains `closed`, the closed lots of a project with their closing day (L415).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sylad/cadence",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.0",
|
|
4
4
|
"description": "A small, repo-native working method: a versioned plan linked to your commits, a changelog with screenshots, session rituals and deliveries proven by their effect.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Sylvain Ladoire",
|
package/skills/lead/SKILL.md
CHANGED
|
@@ -80,7 +80,7 @@ like (the human's words) and keeps the rest verbatim. **A stale title is no reas
|
|
|
80
80
|
|
|
81
81
|
A lot that adds or changes a screen is `visible`: after the implementation, have the
|
|
82
82
|
`ux-reviewer` agent review it (give it the URL or the way to run the app) and bring its verdict and
|
|
83
|
-
proposed sub-tasks back to the human — or, where the folder's `cadence.yaml` says `lead.ux: lead`, form the UX verdict yourself (see « The UX verdict » in section 2c).
|
|
83
|
+
proposed sub-tasks back to the human (add a line `Report file: <absolute path>` outside the repository, and the folder of the captures: it answers in 15 lines at most — verdict, findings with their rule or measure, not verified, sub-tasks, the paths — and keeps the measurements in that file, L452) — or, where the folder's `cadence.yaml` says `lead.ux: lead`, form the UX verdict yourself (see « The UX verdict » in section 2c).
|
|
84
84
|
|
|
85
85
|
### 2b. A wave through `cadence orchestrate`
|
|
86
86
|
|
|
@@ -157,12 +157,15 @@ one named by `$CLAUDE_CODE_SESSION_ID` (Claude Code sets it in the environment o
|
|
|
157
157
|
whatever the folder; `--session <id>` overrides it). Without the variable it falls back to the folder only if a single
|
|
158
158
|
session publishes for it; two sessions in one folder make it exit 2 ("pass --session"), never guess the latest. It prints
|
|
159
159
|
`ctx 42 % (84000/200000)`, the figure the `ctx` segment of the band shows, which the band publishes to
|
|
160
|
-
a file because it is only a rendering the model cannot see
|
|
160
|
+
a file because it is only a rendering the model cannot see, then a second line, `seuil 150000 tokens : sous le seuil` or
|
|
161
|
+
`… : atteint`: the threshold is in **tokens**, not in %, because a percentage moves with the window (60 % is 120k on 200k and
|
|
162
|
+
600k on 1M). It is `lead.contextThreshold` in the `cadence.yaml` of the folder where the lead runs (150000 by default); read the
|
|
163
|
+
second line, do not recompute it. If the command fails (exit code 2: the band is not loaded in
|
|
161
164
|
this session, several sessions share the folder without the variable, or the figure is older than two minutes), treat it as
|
|
162
165
|
**at the threshold**: you cannot prove you are under it, and without the band loaded the lead does not chain.
|
|
163
|
-
|
|
166
|
+
When the second line says `atteint` (the context has reached the threshold), start nothing: at the threshold the lead runs `session-close` in each project touched, writes its
|
|
164
167
|
memory (filtered, as `session-close` says), and records three lines for next time with `cadence session next` — the wave
|
|
165
|
-
that was about to start comes first among them.
|
|
168
|
+
that was about to start comes first among them. While it says `sous le seuil`, chain. The lead says in one sentence which side of the threshold
|
|
166
169
|
it is on each time it chains or stops; it never waits for the figure to move (never a polling loop).
|
|
167
170
|
|
|
168
171
|
**What stays with the human**: the first choice and the order; the questions a session raised (the lead brings them
|
|
@@ -193,7 +196,7 @@ is recorded by the lead's own `raf ux` or, for a lot it hands over, by the `livr
|
|
|
193
196
|
|
|
194
197
|
0. After an orchestrated wave the review is already done, by a fresh session: read the table, then go to
|
|
195
198
|
point 2. For a lot delegated by hand:
|
|
196
|
-
0b. For a lot delegated by hand, `raf check` or the `dérive` column reporting `documentation en retard` is handled **before** the review: hand the lot to the `doc-keeper` agent (a fresh subagent; the absolute path of the project and the lot id; it updates the documents, or only lists them if you say read-only). Read the `docs.articles` key of the project's `cadence.yaml` yourself and put its entries (`repo`, `file`, and the absolute path of that repository, `repo` being relative to the project) in the brief, with read access to that repository for the subagent: the agent examines a document outside the repository only if the brief names it, and with no entry (the key is absent by default) you name none. A proposed lot it returns for a document outside the repository (`docs.articles`) is yours to decide: it never writes to that plan.
|
|
199
|
+
0b. For a lot delegated by hand, `raf check` or the `dérive` column reporting `documentation en retard` is handled **before** the review: hand the lot to the `doc-keeper` agent (a fresh subagent; the absolute path of the project and the lot id; it updates the documents, or only lists them if you say read-only). Read the `docs.articles` key of the project's `cadence.yaml` yourself and put its entries (`repo`, `file`, and the absolute path of that repository, `repo` being relative to the project) in the brief, with read access to that repository for the subagent: the agent examines a document outside the repository only if the brief names it, and with no entry (the key is absent by default) you name none. A proposed lot it returns for a document outside the repository (`docs.articles`) is yours to decide: it never writes to that plan. Add a line `Report file: <absolute path>` (outside the repository) to the brief: it answers in 15 lines at most and writes its full report there (L452); read the file only to apply a document it only listed.
|
|
197
200
|
1. The `code-reviewer` agent, as a fresh subagent (most capable model), reviews the lot. Give it
|
|
198
201
|
the absolute path of the project and the lot id, **not** the author's report: it reads the diff
|
|
199
202
|
itself from the commits that cite the lot, runs the checks, and returns real defects only,
|
|
@@ -21,7 +21,7 @@ A point you cannot hold is written under "choix" or "nonVerifie" of your report,
|
|
|
21
21
|
|
|
22
22
|
Limits and rules, before the walkthrough (a code bug found by the review is the first cause of correction passes: 100 of the 143 classified passes of the 23–29-10 window). Re-read your diff against the fiche (if there is one) and the lot, then:
|
|
23
23
|
- rules: for each rule of the fiche (`Rn`), or of the lot when it has no fiche, name the test that fails if the code breaks it and the line of code that holds it; a rule with no such pair is not done;
|
|
24
|
-
- edge cases:
|
|
24
|
+
- edge cases [L447] (the first sub-cause of the code bugs: 96 of the 136 `bug-code` passes of the 24–30-10 window, 71 %): write the list BEFORE the first line of code, and before reporting play each listed input once on the real path (a real file or a real call, never only your fixture) and compare what comes out with what the rule says. For every function, parser, pattern, threshold or command you add or change, list the inputs at its edge — empty, absent, twice, wrong order, wrong type, refused, the real shape of the data (not the one of your fixture), the other callers of what you changed — and give each one a test that fails without your code, before handing back, except a case the fiche does not cover: with a fiche, you do not code a rule it does not state, so that case is written under "nonVerifie" or "choix", neither coded nor tested; a case you listed and did not test goes under "nonVerifie";
|
|
25
25
|
- claims: each figure, « all », « never » or « always » that your README, docs, comments or tests state is checked against the code or by running it, not from memory.
|
|
26
26
|
|
|
27
27
|
Real walkthrough once the tests are green, before the auto-verification below: play what you delivered as a user would, not by re-reading the diff. A command: run it in a throwaway repository (`git init` in a fresh folder of the session's temporary folder, never inside the repository), following step by step the documentation the lot wrote (README, `docs/`), every command exactly as written there; a command the documentation cannot run, or whose documented path is impossible from the state the previous steps leave, is broken. A screen: open it in each of its states, failure included, the failure shown where the action takes place (in view from the control the user just used, not above or below the fold), and take a capture of each. What breaks, fix in this same session (test first, a `fix({{lot}}): …` commit) and play it again. Then write in "resume" a paragraph that starts with « parcours réel »: what you played, what broke and was fixed, what you could not play (also under "nonVerifie"); a lot with nothing to play (no command, no screen) says so in that paragraph.
|
|
@@ -5,7 +5,7 @@ Goal of the lot: {{objectif}}
|
|
|
5
5
|
|
|
6
6
|
You review the mockup BEFORE any code is written: the later steps (acceptance tests, implementation) will take the sheet and the mockup as their reference. Read the project's CLAUDE.md and its charter (existing CSS and variables, neighbouring components) first: the product's identity is a constraint.
|
|
7
7
|
Besides the usability and accessibility checks of your instructions, check the consistency between the mockup and the sheet: every field of `champs` is in the mockup with its `data-testid`, every rule message (`regles[].message`) is visible, word for word, in the state named by the `etat` of the rule, every state of `etats` has its section `#etat-<état>`, the `masque` of an empty-state rule really hides the fields it names.
|
|
8
|
-
Sweep the whole mockup in this review, whatever its rank, and render it as a checklist in the text of your report (one line per item, checked or not): every state of the sheet at 1440 px and at 390 px; every rule of the sheet; contrast (WCAG 2.2 AA, measured); the real envelope of the app (usable width, side bar, header: measure it in the neighbouring pages instead of assuming it); gutters; empty or stretched panels; holes in the layout; what you cannot verify goes in `nonVerifie`, not ticked.
|
|
8
|
+
Sweep the whole mockup in this review, whatever its rank, and render it as a checklist in the text of your report (one line per item, checked or not): every state of the sheet at 1440 px and at 390 px; every rule of the sheet; one line per family of the added criteria of your instructions (visual hierarchy, consistency with the product tokens, quality of the texts, complementary accessibility), per state at 1440 px and 390 px; contrast (WCAG 2.2 AA, measured); the real envelope of the app (usable width, side bar, header: measure it in the neighbouring pages instead of assuming it); gutters; empty or stretched panels; holes in the layout; what you cannot verify goes in `nonVerifie`, not ticked.
|
|
9
9
|
A later review that finds a major on a point nobody changed is counted as a review defect in the wave journal.
|
|
10
10
|
Check the sample data of the mockup: recompute the weekday of every date shown (do not trust the one written). A wrong sample datum (weekday, date, figure that does not add up) is a minor finding, not a major one: it changes no rule, no field and no state of the sheet, and is fixed in a line.
|
|
11
11
|
Ground every finding in a named rule (Nielsen heuristic, WCAG 2.2 AA criterion) or a measurement, or in a mismatch between the mockup and the sheet. Rank them blocking / major / minor: a blocking or major finding sends the mockup back to the spec writer, a minor one becomes a note of the lot.
|
|
@@ -9,6 +9,8 @@ What you produce, in `<dir>/<écran>/`:
|
|
|
9
9
|
2. The captures described above, one per state and per width, copied from the Playwright output directory of this wave into the folder (give a capture the absolute path of that directory, as the Playwright paragraph says, then copy it).
|
|
10
10
|
3. `fiche.yaml`, in the format of the template below. Check it with `cadence spec check <fiche>` until it is valid, and derive the QA expectations with `cadence spec qa <fiche>` only if the lot asks for it.
|
|
11
11
|
|
|
12
|
+
Write the texts before the review, with the structure the UX reviewer will check: an error message says what, why, how to fix; an empty or loading state says what it is, why it is empty, how to start; an action label is a verb that names the result, never "OK" or "Validate" alone; the confirmation of a destructive action names the object and the consequence; one word per notion, in the sheet and in the mockup. A word or a message already in the product is kept as it is.
|
|
13
|
+
|
|
12
14
|
Sheet rules:
|
|
13
15
|
- Every rule is `sourcee` (it says where it comes from: a line of the lot, a note, `expectations.md`, a rule already coded, an API contract) or `hypothese` (you chose it for lack of a source; `si_faux` says what would change if it were wrong). Never present a guess as sourced.
|
|
14
16
|
- Check every date in the sample data of the mockup before keeping it: compute its weekday (a command such as `date -d 2026-09-03 +%A`, or a script), never write it from memory — a « Wed 03/09 » that is a Thursday sends the mockup back for nothing. The same goes for any figure that must add up (a score and its result, a total and its parts).
|