@sylad/cadence 1.8.0 → 1.10.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 +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +27 -54
- package/agents/code-reviewer.md +2 -2
- package/agents/doc-keeper.md +19 -0
- package/agents/precheck-reader.md +1 -1
- package/agents/qa-reviewer.md +2 -2
- package/agents/reference-analyst.md +25 -0
- package/agents/reference-verifier.md +19 -0
- package/agents/spec-writer.md +1 -1
- package/agents/ux-reviewer.md +1 -1
- package/bin/cadence.js +9 -1
- package/dist/audit.js +16 -4
- package/dist/check.js +24 -2
- package/dist/cli.js +258 -30
- package/dist/config.js +101 -5
- package/dist/corrections.js +24 -2
- package/dist/deliver.js +125 -37
- package/dist/docsync.js +19 -3
- package/dist/git.js +16 -3
- package/dist/lead.js +45 -12
- package/dist/migrate.js +166 -0
- package/dist/orchestrate/briefs.js +46 -6
- package/dist/orchestrate/changelog-merge.js +94 -0
- package/dist/orchestrate/command.js +358 -41
- package/dist/orchestrate/cycle.js +922 -285
- package/dist/orchestrate/guard.js +2 -2
- package/dist/orchestrate/integrate.js +129 -0
- package/dist/orchestrate/launch.js +48 -6
- package/dist/orchestrate/mutex.js +30 -0
- package/dist/orchestrate/no-test.js +41 -0
- package/dist/orchestrate/pool.js +74 -36
- package/dist/orchestrate/registry.js +146 -14
- package/dist/orchestrate/result.js +1 -1
- package/dist/orchestrate/snapshot.js +54 -1
- package/dist/orchestrate/spec.js +89 -5
- package/dist/orchestrate/state.js +56 -15
- package/dist/orchestrate/table.js +74 -3
- package/dist/orchestrate/timeouts.js +40 -0
- package/dist/orchestrate/worktree.js +368 -0
- package/dist/perf.js +188 -25
- package/dist/plan.js +112 -7
- package/dist/proc.js +6 -0
- package/dist/ready-free.js +109 -0
- package/dist/ref/add.js +129 -0
- package/dist/ref/analyse.js +220 -0
- package/dist/ref/check.js +338 -0
- package/dist/ref/command.js +92 -0
- package/dist/ref/corpus-render.js +83 -0
- package/dist/ref/corpus.js +201 -0
- package/dist/ref/diff.js +262 -0
- package/dist/ref/evaluate.js +241 -0
- package/dist/ref/figures.js +252 -0
- package/dist/ref/measure.js +330 -0
- package/dist/ref/pdf.js +116 -0
- package/dist/ref/png.js +125 -0
- package/dist/ref/regard.js +102 -0
- package/dist/ref/session.js +34 -0
- package/dist/ref/store.js +40 -0
- package/dist/ref/tools.js +51 -0
- package/dist/resources.js +51 -0
- package/dist/session.js +5 -2
- package/dist/state.js +75 -7
- package/dist/testgate.js +15 -0
- package/docs/cadence-hud.md +12 -0
- package/docs/cycle-vague-dark.svg +1 -1
- package/docs/cycle-vague-light.svg +1 -1
- package/docs/deliver.md +76 -5
- package/docs/fonctionnement-wave-dark.svg +1 -1
- package/docs/fonctionnement-wave-light.svg +1 -1
- package/docs/fonctionnement.md +6 -6
- package/docs/lead.md +40 -13
- package/docs/news.md +30 -1
- package/docs/orchestrate.md +275 -33
- package/docs/overview.md +65 -1
- package/docs/perf.md +14 -8
- package/docs/raf.md +90 -11
- package/docs/ref.md +415 -0
- package/docs/releasing.md +3 -3
- package/docs/session.md +2 -2
- package/docs/skills.md +21 -2
- package/docs/spec.md +1 -1
- package/docs/stabilite.md +4 -4
- package/docs/whats-new.md +30 -1
- package/package.json +2 -1
- package/skills/deliver/SKILL.md +6 -1
- package/skills/lead/SKILL.md +28 -10
- package/skills/session-close/SKILL.md +1 -1
- package/skills/session-start/SKILL.md +2 -2
- package/templates/inventaire.json +96 -0
- package/templates/orchestrate/accept-back.md +1 -0
- package/templates/orchestrate/accept.md +1 -0
- package/templates/orchestrate/fiche.md +1 -0
- package/templates/orchestrate/fix-docs.md +18 -0
- package/templates/orchestrate/fix-minors.md +2 -1
- package/templates/orchestrate/fix.md +5 -2
- package/templates/orchestrate/implement.md +7 -4
- package/templates/orchestrate/maquette.md +2 -1
- package/templates/orchestrate/precheck.md +2 -1
- package/templates/orchestrate/review-recheck.md +2 -0
- package/templates/orchestrate/review-small.md +5 -1
- package/templates/orchestrate/review.md +2 -0
- package/templates/orchestrate/spec-back.md +2 -1
- package/templates/orchestrate/spec.md +4 -3
- package/templates/orchestrate/ux.md +3 -1
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
{
|
|
9
9
|
"name": "cadence",
|
|
10
10
|
"description": "Session start and close rituals driven by a versioned plan (raf), and deliveries proven by their effect. Needs the cadence CLI (npm i -g @sylad/cadence).",
|
|
11
|
-
"version": "1.
|
|
11
|
+
"version": "1.10.0",
|
|
12
12
|
"source": "./",
|
|
13
13
|
"author": {
|
|
14
14
|
"name": "Sylvain Ladoire"
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
{
|
|
18
18
|
"name": "cadence-hud",
|
|
19
19
|
"description": "A status band above the Claude Code prompt: context, 5 h / 7 d quota windows, cost per model, agents of the session and the running cadence orchestrate waves. Works without the cadence CLI, except the per-project plan progress, which needs `cadence` on the PATH.",
|
|
20
|
-
"version": "0.
|
|
20
|
+
"version": "0.5.0",
|
|
21
21
|
"source": "./plugins/cadence-hud",
|
|
22
22
|
"author": {
|
|
23
23
|
"name": "Sylvain Ladoire"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cadence",
|
|
3
3
|
"description": "A repo-native working method: session start and close rituals driven by a versioned plan (raf), deliveries proven by their effect, and three reviewer agents (UX, code, QA).",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.10.0",
|
|
5
5
|
"author": { "name": "Sylvain Ladoire" },
|
|
6
6
|
"homepage": "https://github.com/Sylad/cadence",
|
|
7
7
|
"repository": "https://github.com/Sylad/cadence",
|
package/README.md
CHANGED
|
@@ -1,73 +1,46 @@
|
|
|
1
1
|
# cadence
|
|
2
2
|
|
|
3
|
-
A small working method that lives in your repository: a versioned plan linked to your commits,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Four [Claude Code](https://claude.com/claude-code) skills, three reviewer agents and a status-band plugin (`cadence-hud`) turn it into rituals.
|
|
8
|
-
|
|
9
|
-
<picture>
|
|
10
|
-
<source media="(prefers-color-scheme: dark)" srcset="docs/cycle-vague-dark.svg">
|
|
11
|
-
<img alt="A lot goes through spec, mockup, accept, implement, review, ux and deliver; the lead picks the lots, answers the questions, re-verifies and delivers" src="docs/cycle-vague-light.svg">
|
|
12
|
-
</picture>
|
|
3
|
+
A small working method that lives in your repository: a versioned plan linked to your commits,
|
|
4
|
+
waves of fresh AI sessions driven by a program, and deliveries proved by their effect.
|
|
5
|
+
It is for solo developers and AI-assisted sessions who lose track of *what is left to do* and *what each commit was for*:
|
|
6
|
+
cadence keeps both in plain files next to the code, and [Claude Code](https://claude.com/claude-code) skills turn it into rituals.
|
|
13
7
|
|
|
14
8
|
## Start
|
|
15
9
|
|
|
16
10
|
```sh
|
|
17
|
-
npm install -g @sylad/cadence
|
|
18
|
-
raf init
|
|
11
|
+
npm install -g @sylad/cadence
|
|
12
|
+
raf init
|
|
19
13
|
raf add "My first lot" --estimate 1
|
|
20
14
|
```
|
|
21
15
|
|
|
22
16
|
Then `raf start L1`, commit with `feat(L1): …`, `raf now` to see where you are, `raf done L1` when it is finished.
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
| [docs/raf.md](docs/raf.md) | the plan: commands, plan file, foreign plan formats, Gantt |
|
|
29
|
-
| [docs/orchestrate.md](docs/orchestrate.md) | waves of sessions: budgets, spec, accept and review steps, neighbouring repositories |
|
|
30
|
-
| [docs/deliver.md](docs/deliver.md) | delivery: wait for CI, deploy, verify the effect |
|
|
31
|
-
| [docs/spec.md](docs/spec.md) | the screen and back-end sheets, `cadence spec check\|qa\|reseal` |
|
|
32
|
-
| [docs/lead.md](docs/lead.md) | the lead workflow and `cadence lead tour` |
|
|
33
|
-
| [docs/stabilite.md](docs/stabilite.md) | what is guaranteed from 1.0.0 and what is not |
|
|
34
|
-
|
|
35
|
-
Also: [news](docs/news.md) (changelog, UX, code and QA reviews, documentation that follows the code), [session](docs/session.md), [corrections](docs/corrections.md), [perf](docs/perf.md), [skills and agents](docs/skills.md), [cadence-hud](docs/cadence-hud.md), [releasing](docs/releasing.md), [overview](docs/overview.md), [how it all works](docs/fonctionnement.md) (four figures).
|
|
36
|
-
|
|
37
|
-
<details>
|
|
38
|
-
<summary>The four tools in short</summary>
|
|
39
|
-
|
|
40
|
-
- **raf** (French *reste à faire*, "what is left to do"): the plan, linked to your commits by the lot id in the message, computed from `git log` and never stored.
|
|
41
|
-
- **news**: a user-facing changelog with screenshots, tied to the plan; a lot is not done until its entry is written.
|
|
42
|
-
- **session**: `session start` and `session close` gather the facts of a work session.
|
|
43
|
-
- **deliver**: wait for the CI of the pushed commit, run the deploy commands, then **verify the effect**; a delivery is done only when its checks pass. A failed delivery is logged as a *red delivery*.
|
|
44
|
-
- **perf**: `cadence perf` is the dashboard of the workflow (speed next to quality, `⚠` on a trend), including the red deliveries and the blocking QA findings; `cadence lead tour` opens with its *perf header*, one line per `⚠`, nothing when stable ([docs/perf.md](docs/perf.md)).
|
|
45
|
-
|
|
46
|
-
Reviews are opt-in gates: `ux-reviewer` (no user-facing change is done before its usability review), `code-reviewer` (no lot with commits is done before its code review) and `qa-reviewer`, which walks the delivered app in a real browser.
|
|
47
|
-
|
|
48
|
-
</details>
|
|
49
|
-
|
|
50
|
-
## What's new
|
|
18
|
+
<picture>
|
|
19
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/cycle-vague-dark.svg">
|
|
20
|
+
<img alt="A lot goes through spec, mockup, accept, implement, review, ux and deliver; the lead picks the lots, answers the questions, re-verifies and delivers" src="docs/cycle-vague-light.svg">
|
|
21
|
+
</picture>
|
|
51
22
|
|
|
52
|
-
|
|
23
|
+
## Install as a Claude Code plugin
|
|
53
24
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
- **1.4.0**: `cadence spec reseal` accepts a sheet amended by the lot's commits; wave budgets recalibrated; a `git checkout` in a session no longer stops the wave.
|
|
60
|
-
- **1.3.0**: the spec step narrows to `screen: page`; `cadence spec reseal … --porteur` re-seals an unstable test; `cadence orchestrate --waits`; a third correction pass when the review converges.
|
|
61
|
-
- **1.2.0**: the spec step reaches lots without a screen (`spec: true`), `orchestrate.accept` may be a list of runners, `lead.ux: lead`, and the code in service is a separate worktree.
|
|
62
|
-
- **1.1.0**: the spec step of `cadence orchestrate`: screen sheet, reviewed mockup, red locked acceptance tests, and briefs that carry rule → test → green.
|
|
63
|
-
- **1.0.0**: the first major release, a stable contract that follows semantic versioning; the [stability page](docs/stabilite.md) lists what is guaranteed.
|
|
25
|
+
```
|
|
26
|
+
/plugin marketplace add Sylad/cadence
|
|
27
|
+
/plugin install cadence@cadence # skills and reviewer agents; needs @sylad/cadence above
|
|
28
|
+
/plugin install cadence-hud@cadence # the status band, works without the CLI
|
|
29
|
+
```
|
|
64
30
|
|
|
65
|
-
|
|
66
|
-
<summary>Older versions (0.10.0 to 0.28.0)</summary>
|
|
31
|
+
Details: [docs/skills.md](docs/skills.md) and [docs/cadence-hud.md](docs/cadence-hud.md).
|
|
67
32
|
|
|
68
|
-
|
|
33
|
+
## Where to read more
|
|
69
34
|
|
|
70
|
-
|
|
35
|
+
- [docs/raf.md](docs/raf.md): the plan, its commands and its file.
|
|
36
|
+
- [docs/orchestrate.md](docs/orchestrate.md): waves of sessions and their budgets.
|
|
37
|
+
- [docs/deliver.md](docs/deliver.md): wait for the CI, deploy, verify the effect.
|
|
38
|
+
- [docs/spec.md](docs/spec.md): screen and back-end sheets.
|
|
39
|
+
- [docs/lead.md](docs/lead.md): the lead workflow.
|
|
40
|
+
- [docs/overview.md](docs/overview.md): the longer introduction and the map of every page.
|
|
41
|
+
- [docs/fonctionnement.md](docs/fonctionnement.md): how it all works, in four figures.
|
|
42
|
+
- [docs/stabilite.md](docs/stabilite.md): what is guaranteed from 1.0.0.
|
|
43
|
+
- [docs/whats-new.md](docs/whats-new.md) and [CHANGELOG.md](CHANGELOG.md): what changed.
|
|
71
44
|
|
|
72
45
|
## License
|
|
73
46
|
|
package/agents/code-reviewer.md
CHANGED
|
@@ -21,8 +21,8 @@ fact. If the path or the id is missing, or the lot has no commit to review, say
|
|
|
21
21
|
folder's CLAUDE.md does not count unless it names this project. Then find the commands that
|
|
22
22
|
test, type-check, lint and build: in the README, then in the manifest (`package.json` scripts,
|
|
23
23
|
Makefile, `pyproject.toml`…).
|
|
24
|
-
2. **Read the lot**: its title, notes and sub-tasks in the plan (`docs/plan/raf.yaml`, or the file
|
|
25
|
-
named by `plan:` in `cadence.yaml`). That is the goal the commits are measured against. When the
|
|
24
|
+
2. **Read the lot**: its title, notes and sub-tasks in the plan (`.cadence/raf.yaml`, the legacy `docs/plan/raf.yaml`, or the file
|
|
25
|
+
named by `plan:` in `cadence.yaml`). That is the goal the commits are measured against. When the brief gives a "Goal of the lot", that goal of the lot given in the brief takes precedence over the title in the plan (a title can be stale; the goal was given on purpose): measure the commits against it, not against the title. When the
|
|
26
26
|
lot has only a title, also read the bodies of its commits and any spec the lot cites.
|
|
27
27
|
3. **Get the commits from the tool**: `raf commits <id>` prints exactly the set the gate counts —
|
|
28
28
|
`<sha> <subject>` per line, oldest first, the commits that only touch the plan left out. Only
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doc-keeper
|
|
3
|
+
description: Generic librarian. For one repository and one lot, reads the diff of the lot and the project's map of documents (docs.sync of cadence.yaml, README, docs/, CHANGELOG, Nouveautés), says which documents must change, then updates them (writing session) or only lists them (read-only session). A document outside the repository only when the configuration names it (docs.articles), and then it proposes a lot for that repository's plan and never writes it. Called by orchestrate when docs.sync reports a document behind the lot, or by the lead by hand.
|
|
4
|
+
tools: Read, Write, Edit, Grep, Glob, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You keep the documentation of one repository true to the work of one lot. You write documents; you never write the code of the lot.
|
|
8
|
+
|
|
9
|
+
Follow the brief you are given. The method:
|
|
10
|
+
|
|
11
|
+
1. **Read the diff of the lot.** The commits that cite the lot (`git log`, then `git show <sha>` for each; never a `git diff` range, which would take in the commits of other lots). Note what the change makes true or false for a reader: a behaviour, a command, a key, a default, a name, a file.
|
|
12
|
+
2. **Draw the map of the documents.** The `docs.sync` rules of the project's `cadence.yaml` (the code paths and the documents they call for), then what the project keeps besides: the README, the pages of `docs/`, the CHANGELOG, the Nouveautés / What's new entries, the architecture document. Read the project's CLAUDE.md first for its own rules on documentation. Nothing about a folder or a machine comes from you: only this project's files.
|
|
13
|
+
3. **Say which documents must change, and why.** A lot that changes how the tool works (a behaviour, a command, a key, a default) is written in the pages of `docs/`, in full; the README is a short home page and receives only a link to that page, never the detail (an option, a key, a path, a flag). A README that grows by a paragraph is a finding, not a document brought up to date. For each: the file, the passage, the sentence that the diff makes false or leaves out. A document the diff does not touch the truth of is not listed.
|
|
14
|
+
4. **Act according to the session.**
|
|
15
|
+
- Writing session: update each document (the detail in `docs/`, a link in the README), in the language and the style it already has. Test the project's documentation checks if it has any (links, doc tests). Commit as soon as a document is right, with explicit paths (never `git add -A` or `commit -a`) and a message that cites the lot (`docs(<lot>): …`). A CHANGELOG or Nouveautés entry only if the project keeps one for this kind of change.
|
|
16
|
+
- Read-only session (no write tool, or a brief that says read-only): change nothing; list the documents of step 3 with the passage to write, ready to be applied by someone else.
|
|
17
|
+
5. **A document outside the repository** is yours only when the configuration says so: the brief then lists the entries of `docs.articles` (the cadence.yaml of the project: « this project is also described by this file of that repository », with the absolute path of the repository, open to you for reading). Never guess such a file, never go looking for one. Do not edit it, and never write to the plan of that repository (no `raf add`, no edit of its plan file): write a proposed lot instead — a title and a body that name the repository, the file, the passage and the sentence to change — and put it in the `resume` of your report, starting with « lot proposé ». The lead decides whether it enters that repository's plan.
|
|
18
|
+
|
|
19
|
+
Never push, deliver, or run `raf done|start|note|review|ux`. Never run `git checkout` or `git switch` to another commit or branch in this repository. Do not launch subagents. Do not stop to ask: an interpretation you settle yourself goes under "choix" with the alternative you did not take. A document you could not check against the code goes under "nonVerifie". Give the report in the structured output the brief asks for.
|
|
@@ -6,7 +6,7 @@ tools: Read, Grep, Glob, Bash
|
|
|
6
6
|
|
|
7
7
|
You check, quickly, whether the deliverable of one lot of a plan is already in the repository. You report; you never edit code.
|
|
8
8
|
|
|
9
|
-
Follow the brief you are given:
|
|
9
|
+
Follow the brief you are given: the brief tells you how to get the lot (it carries it, or tells you where to read it in the plan), then look for each part of its deliverable in the code, the tests and `git log`. A lot with no commit of its own is the normal case here — do not stop for that, it is the reason for the check.
|
|
10
10
|
|
|
11
11
|
- Do not run the test suite, the type-check, the linter or the build: this is a quick look.
|
|
12
12
|
- Do not modify, commit, push, or run `raf start|done|note|review|ux`. Do not launch subagents.
|
package/agents/qa-reviewer.md
CHANGED
|
@@ -107,7 +107,7 @@ a delivery rarely changes them all:
|
|
|
107
107
|
- the pages that call the changed endpoints (`raf commits <id>` and the diff tell which routes
|
|
108
108
|
changed; the `api:` lines of the expectations, and the calls you see a page make, tell which
|
|
109
109
|
pages use them);
|
|
110
|
-
- the pages of the screens the lot changed (
|
|
110
|
+
- the pages of the screens the lot changed (the goal of the lot given in the brief takes precedence over the title in the plan; then its notes in the plan, and
|
|
111
111
|
the components in its commits, name them);
|
|
112
112
|
- the home page.
|
|
113
113
|
|
|
@@ -165,7 +165,7 @@ A short report:
|
|
|
165
165
|
(/players shows no player)", "no expectations file: 13 pages walked, 1 defect, 8 suspects, draft
|
|
166
166
|
returned". It is the last line of the report.
|
|
167
167
|
|
|
168
|
-
Give screenshots and snapshots a
|
|
168
|
+
Give screenshots and snapshots the absolute path of the capture directory your brief names when it names one (a wave's Playwright server resolves a bare name against the repository, not its output directory); with no such directory in the brief, 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 and dirty the working tree) and no other path inside the repository (list them in the report if git does not ignore that folder). Other temporary files go in a temporary directory outside the repository, or in the one
|
|
169
169
|
the caller names; remove them, or list their paths in the report — except the QA browser profile, which is kept for the next pass. The working tree is left as you
|
|
170
170
|
found it.
|
|
171
171
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reference-analyst
|
|
3
|
+
description: Reference document analyst. Reads the pages that `cadence ref add` rendered for one document (a screen mock-up PDF, a spec with figures, a norm), page by page and then zone by zone at full resolution, and writes one reading — an inventory of what the document shows (screens, components, states, verbatim texts, design tokens, tables, message templates, schemas, text-figure links, status badges, silences) — in the JSON format of `templates/inventaire.json`. Everything measurable goes through `cadence ref measure`; what cannot be read for sure is marked incertain with its cause. Writes only its reading, validates it with `cadence ref check`. Used by `cadence ref analyse` and by the orchestrator, not by hand.
|
|
4
|
+
tools: Read, Write, Bash, Grep, Glob
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You read one reference document and write down what it shows. You write one file, your reading; you never write code, specs or the plan, and you never decide what the project should do with what you read.
|
|
8
|
+
|
|
9
|
+
Follow the brief you are given. It names the document folder, the pages that were rendered (`pages/page-<n>.png`, 200 dpi), the file to write, the model to copy and the exact commands to measure and to validate. The folder also holds `document.json`: the positioned text of every page (each line with its box `x, y, l, h` in pixels of the rendered page), the images, the figure index with the passages that cite each figure, and the unresolved links. The method:
|
|
10
|
+
|
|
11
|
+
1. **Look at every page whole first.** Open each rendered page with the Read tool and say to yourself what it is: a mock-up, a requirements page, a figure, a table, a scan. A page you did not open is a page you did not read.
|
|
12
|
+
2. **Then every zone at full resolution.** A whole page is too small to read a label, a threshold or a table cell. Crop the zone (`cadence ref measure` gives the boxes of the shapes of a zone: `--quoi boites`) and look at the crop, or at the embedded image under `images/`, before writing anything about it.
|
|
13
|
+
3. **Measure whatever is measurable, never estimate it by eye.** A colour, a contrast, a size, a box, a font size: `cadence ref measure <slug> <page> <zone> --quoi couleurs|contraste|boites|texte`, with the commands of the brief. An element whose numbers come from that command is `confiance: mesure` and its `point` or zone says where it was sampled. Text read by tesseract on a whole page is `ocr: true` and never `lu`.
|
|
14
|
+
4. **Copy every visible text verbatim**: same characters, same case, same units (`120 KT` is not `120 kt`). One convention for labels: every visible text outside a table or a message template is a `texte` with its role from the closed list of `templates/inventaire.json`, including the label of a component (the button `Layers` is a `composant` and a `texte`). The text of a table or a template belongs to it, not to a `texte`.
|
|
15
|
+
5. **Link every figure to the passages that cite it.** For each figure of `document.json`, read the passages that cite it, then the figure, and write a `lien`: `confirme` when the figure says what the text says, `precise` when the figure settles an ambiguity of the text (say the ambiguous reading, the one you keep and why, from what the figure draws), `contredit` when the two disagree (give the two statements, never pick one). A figure with no caption, or a citation with no figure: say so, or declare it not found.
|
|
16
|
+
6. **What the document does not show is a `silence`**, written as a question that ends with `?`: a state, a message, a rule a developer will have to decide. Do not answer it.
|
|
17
|
+
7. **Never guess.** An element you cannot read for sure (blurred, cut, too small, two readings possible) is `confiance: incertain` with its `cause`, never `lu`. Never invent an element to complete a list, never leave one out because it looks like another. A text that is too small to measure (under about 8 px at the render) is `incertain` with that cause.
|
|
18
|
+
8. **Write the reading** to the file of the brief, in the format of `templates/inventaire.json` but with `genre: "lecture"`, the `document` `slug` and `sha256` of `document.json` (copy them, never retype them), and no `pages` key. Every id is `<slug>#<type>-<n>`. Then run `cadence ref check` on it, with the command of the brief, until it passes: a reading that does not pass is not a result.
|
|
19
|
+
|
|
20
|
+
- Never write `usage`, tokens or costs in the reading: the program that launched you counts them. Never write the `sha256` of another file than `document.json`.
|
|
21
|
+
- Never open another file of `lectures/` than the one you write: another reader may have written its own reading of the same document, and a reading made with the other in hand is not independent, so it measures nothing.
|
|
22
|
+
- Read only the document folder named in the brief and the model. Never look for, open or use an expected inventory, an answer key or a test corpus: the reading is yours alone, and a reading made with the answer in hand measures nothing.
|
|
23
|
+
- You write only the reading file: no other file, no commit, no change in the repository. Do not push, deliver, run `raf start|done|note|review|ux`, or launch subagents.
|
|
24
|
+
- A question a human must settle (a figure that contradicts its text, an element you cannot read) goes in `questions` of your report, as well as in the reading (`contredit`, `incertain`, `silence`).
|
|
25
|
+
- Give the report in the structured output the brief asks for.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reference-verifier
|
|
3
|
+
description: Third look at a reference document. Receives only the elements that ONE of two independent readings carried and the other did not (each with the rendered page and a crop of its zone), looks at the crop and says for each one whether the document really shows it (confirme) or not (ecarte), with the reason. Writes nothing. Used by `cadence ref analyse` after `cadence ref diff`, not by hand.
|
|
4
|
+
tools: Read, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are the third look on a reference document. Two readers read the same pages separately; they agree on most elements, and disagree on a few. The brief lists only the elements that **one** reader wrote and the other did not, each with a number, what was written, the rendered page and a **crop** of the zone it names. You never see the readings themselves, nor which reader wrote what, and you do not read the rest of the document: only the elements of the brief and their crops.
|
|
8
|
+
|
|
9
|
+
For each numbered element:
|
|
10
|
+
|
|
11
|
+
1. **Open the crop** with the Read tool, and say to yourself what is drawn there. If the brief says there is no crop (the page was not rendered, or the zone is outside it), open the whole page, and say so in the reason.
|
|
12
|
+
2. **Compare what was written with what is drawn**, character by character for a text (same characters, same case, same units: `120 KT` is not `120 kt`), value by value for a colour, a size or a cell. A number or a colour that can be measured is measured, never estimated by eye: `cadence ref measure` with the command of the brief.
|
|
13
|
+
3. **Rule**: `confirme` when the crop shows exactly what was written, `ecarte` when it does not show it, or shows something else, or the element is a duplicate of another written differently. Never guess: if you cannot tell (blurred, cut, too small), the answer is `ecarte` with that reason, never `confirme`. Never rewrite an element, never correct it, never add one.
|
|
14
|
+
|
|
15
|
+
Every verdict carries a `raison`: one sentence that says what the crop shows. A verdict without a reason, or with a verdict other than `confirme` or `ecarte`, is counted as no answer.
|
|
16
|
+
|
|
17
|
+
- You write no file, you make no commit, you change nothing in the repository. Do not push, deliver, run `raf start|done|note|review|ux`, or launch subagents.
|
|
18
|
+
- Never look for, open or use an expected inventory, an answer key or a test corpus, nor any file of `lectures/`.
|
|
19
|
+
- Give the report in the structured output the brief asks for: `decisions` (one object per numbered element: `numero`, `verdict`, `raison`) and `questions` (what a human must settle).
|
package/agents/spec-writer.md
CHANGED
|
@@ -10,7 +10,7 @@ Follow the brief you are given. The method:
|
|
|
10
10
|
|
|
11
11
|
1. **Read the charter first.** The project's CLAUDE.md, its CSS and variables, the neighbouring components and pages, `docs/qa/expectations.md`, the routes and API contracts already present. The mockup must look like the product: reuse what exists, invent nothing when an equivalent exists.
|
|
12
12
|
2. **List the states before drawing**: empty, loading, error, and loaded when there is data. Each is an addressable section `#etat-<état>` of one static `maquette.html` (HTML + CSS, no business JavaScript). Each field of the sheet carries `data-testid="<field id>"`.
|
|
13
|
-
3. **Render and look.** Capture each state at **1440 px** and **390 px** wide with the browser tool (Playwright),
|
|
13
|
+
3. **Render and look.** Capture each state at **1440 px** and **390 px** wide with the browser tool (Playwright), named `maquette-<état>-<largeur>.png`, with the absolute capture-directory path your brief gives in front of the name (a bare name lands in the repository), and look at every capture before keeping it: a mockup you did not look at is not checked. Copy the kept captures into the spec folder.
|
|
14
14
|
Before keeping a state, check its sample data: compute the weekday of every date shown (`date -d`), never write it from memory.
|
|
15
15
|
4. **Write the sheet** in the format of the template of the brief, and run `cadence spec check` on it until it passes. Every rule is `sourcee` (say where it comes from) or `hypothese` (say what would change if it were wrong, in `si_faux`). Never dress a guess as a source.
|
|
16
16
|
5. **Costly choices are questions.** If a rule would fix a data model or storage, a public or shared API contract or an already published route, a destructive or irreversible action, or contradict an existing sourced rule, do not write it as a hypothesis: stop and ask, in the `questions` of the report. Wording, field order, the error state and spacing are written hypotheses.
|
package/agents/ux-reviewer.md
CHANGED
|
@@ -38,7 +38,7 @@ When the brief says "conformity" (the orchestrator, after the code, for a lot th
|
|
|
38
38
|
|
|
39
39
|
1. **Look before judging.** Capture the screen with the browser tool available (Playwright or
|
|
40
40
|
equivalent) at **1440 px** and **390 px** wide, in its main states: empty, loaded, error, loading,
|
|
41
|
-
and the key interaction. Look at every capture. Give screenshots and snapshots a
|
|
41
|
+
and the key interaction. Look at every capture. Give screenshots and snapshots the absolute path of the capture directory your brief names when it names one (a wave's Playwright server resolves a bare name against the repository, not its output directory); with no such directory in the brief, 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 and dirty the working tree) and no other path inside the repository (list them in the report if git does not ignore that folder). Anything else you create goes in a temporary directory outside the repository, removed afterwards.
|
|
42
42
|
2. **Walk the main task** a real user comes for (find, read, compare, act, undo) and count the steps.
|
|
43
43
|
3. **Check, and measure where a number exists:**
|
|
44
44
|
- Nielsen's 10 heuristics — especially visibility of system status, match with the user's words,
|
package/bin/cadence.js
CHANGED
|
@@ -13,7 +13,7 @@ const io = {
|
|
|
13
13
|
|
|
14
14
|
if (tool === 'raf') {
|
|
15
15
|
process.exitCode = await run(args, io);
|
|
16
|
-
} else if (['news', 'session', 'deliver', 'verify', 'skills', 'orchestrate', 'lead', 'corrections', 'perf', 'spec'].includes(tool)) {
|
|
16
|
+
} else if (['news', 'session', 'deliver', 'verify', 'skills', 'orchestrate', 'lead', 'corrections', 'perf', 'spec', 'ref'].includes(tool)) {
|
|
17
17
|
process.exitCode = await run([tool, ...args], io);
|
|
18
18
|
} else if (tool === '--version' || tool === '-v') {
|
|
19
19
|
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
@@ -33,6 +33,12 @@ if (tool === 'raf') {
|
|
|
33
33
|
cadence deliver [--dry-run] [--sha rév] [--config cadence.yaml] [-- arguments du script du projet]
|
|
34
34
|
CI du sha poussé → déploiement → vérifications de l'effet ;
|
|
35
35
|
ou le script de livraison du projet (deliver.script), sous verrou et journal
|
|
36
|
+
cadence ref add <document.pdf> [--sections 3-5,9] [--slug nom]
|
|
37
|
+
enregistre un document de référence hors du dépôt : pages rendues, texte positionné, images, index des figures
|
|
38
|
+
et des passages qui les citent ; exige poppler, ImageMagick et tesseract (outil absent nommé avec sa commande, code 2)
|
|
39
|
+
cadence ref measure <slug> <page> <page | x,y | x,y,l,h> [--quoi couleurs|contraste|boites|texte] [--largeur 1440] [--json]
|
|
40
|
+
mesure une zone d'une page rendue : couleurs, contraste WCAG 2.2, boîtes, mots OCR et taille de police estimée,
|
|
41
|
+
ramenés à 1440 px de large, tolérance déclarée
|
|
36
42
|
cadence verify [--retry secondes] [--sha rév]
|
|
37
43
|
rejoue les vérifications d'effet (deliver.verify) hors livraison, une passe, en parallèle ;
|
|
38
44
|
code 0 tout vert, 1 un effet rouge, 2 rien à vérifier ; « session start » la lance aussi
|
|
@@ -41,6 +47,8 @@ if (tool === 'raf') {
|
|
|
41
47
|
--max-sessions : sessions simultanées, toutes vagues confondues (CADENCE_MAX_SESSIONS)
|
|
42
48
|
--continue [--until HH:MM] [--priority a,b] : tire seul les lots prêts du plan, jusqu'à une borne
|
|
43
49
|
--waits [--since AAAA-MM-JJ] : l'attente de créneau de session par jour et par vague, lue dans les journaux
|
|
50
|
+
cadence lead hold <étiquette> [--ttl minutes] | lead release <étiquette>
|
|
51
|
+
déclare, puis rend, une session lancée à la main par le lead : soustraite des créneaux libres
|
|
44
52
|
cadence lead tour [dossier] [--idle 3] [--json]
|
|
45
53
|
le tableau du lead, sans modèle : une ligne par sous-dossier qui a un plan, ou la ligne du dossier courant
|
|
46
54
|
s'il est lui-même un projet ; une première ligne « cadence.yaml · ✗ erreur » si priority: est illisible
|
package/dist/audit.js
CHANGED
|
@@ -4,19 +4,29 @@ import { check } from './check.js';
|
|
|
4
4
|
import { parse } from 'yaml';
|
|
5
5
|
import { changedFiles, fileAt, readCommits } from './git.js';
|
|
6
6
|
import { citedRefs, linkCommits, scopeOf } from './link.js';
|
|
7
|
-
import { readDocsConfig, readNewsConfig, readOrchestrateConfig } from './config.js';
|
|
7
|
+
import { PLAN_DEFAULT, PLAN_LEGACY, readDocsConfig, readNewsConfig, readOrchestrateConfig } from './config.js';
|
|
8
8
|
import { ficheHypotheses } from './spec.js';
|
|
9
9
|
import { docSyncGaps, filesOf, gapMessage } from './docsync.js';
|
|
10
10
|
import { loadEntries, newsIssues, PUBLIC_TITLE_DEFAULT, publicTitleTooLong, reusedNewsTitle } from './news.js';
|
|
11
11
|
import { isRecurring } from './recurring.js';
|
|
12
|
+
import { resourceIssues } from './resources.js';
|
|
12
13
|
import { escapeRe, isOpen } from './plan.js';
|
|
13
14
|
/** Chemin de la configuration lue, relatif à la racine : celui de --config, sinon cadence.yaml. */
|
|
14
15
|
function configRel(plan, root) {
|
|
15
16
|
return plan.configFile ? relative(root, plan.configFile) : 'cadence.yaml';
|
|
16
17
|
}
|
|
17
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Le plan, sa page Gantt, la configuration lue (cadence.yaml) et les fichiers tenus avec lui (plan.files). Le plan par défaut
|
|
20
|
+
* (.cadence/raf.yaml) compte aussi son emplacement hérité docs/plan/ : après le `git mv` proposé par raf, les anciens commits du
|
|
21
|
+
* plan et le commit du déplacement (qui liste la suppression et l'ajout) restent des commits de plan seul (L246, fiche plan-dossier-cache R12).
|
|
22
|
+
*/
|
|
18
23
|
export function ownFiles(plan, root) {
|
|
19
|
-
|
|
24
|
+
const own = new Set([relative(root, plan.path), relative(root, join(dirname(plan.path), 'gantt.html')), configRel(plan, root), ...plan.maintained]);
|
|
25
|
+
if (relative(root, plan.path) === PLAN_DEFAULT) {
|
|
26
|
+
own.add(PLAN_LEGACY);
|
|
27
|
+
own.add(join(dirname(PLAN_LEGACY), 'gantt.html'));
|
|
28
|
+
}
|
|
29
|
+
return own;
|
|
20
30
|
}
|
|
21
31
|
function withoutPlanKey(text) {
|
|
22
32
|
if (text === null)
|
|
@@ -160,7 +170,7 @@ export function audit(plan, root, newsDir, today, opts = {}) {
|
|
|
160
170
|
const m = l.public ? publicTitleTooLong(l.public, max) : reused ? publicTitleTooLong(reused, max) : null;
|
|
161
171
|
return m ? [{ message: `${l.id} : ${reused && !l.public ? m.replace('titre public', 'titre public repris de la Nouveauté') : m}` }] : [];
|
|
162
172
|
});
|
|
163
|
-
const issues = [...check(lots, { ...linked, byLot: all.byLot }, today, opts.idle ?? 7), ...newsIssues(lots, entries, newsDir, hypothesesOf(root, plan.configFile ?? join(root, 'cadence.yaml'))), ...titles, ...gates, ...docSyncIssues(plan, root, all.byLot), ...(plan.hasPublicField ? missingPublicTitles(lots, entries) : []),
|
|
173
|
+
const issues = [...check(lots, { ...linked, byLot: all.byLot }, today, opts.idle ?? 7, { readonly: plan.readonly, hasVisibleField: plan.hasVisibleField }), ...newsIssues(lots, entries, newsDir, hypothesesOf(root, plan.configFile ?? join(root, 'cadence.yaml'))), ...titles, ...gates, ...docSyncIssues(plan, root, all.byLot), ...resourceIssues(lots, root), ...(plan.hasPublicField ? missingPublicTitles(lots, entries) : []),
|
|
164
174
|
...plan.ignore.invalid.map((src) => ({ message: `ignore : motif invalide « ${src} »` }))];
|
|
165
175
|
// Un plan en lecture seule se corrige avec l'outil du projet : ne pas conseiller une commande raf qui refuserait.
|
|
166
176
|
return plan.readonly ? issues.map((i) => ({ ...i, message: i.message.replace(/ — raf (start|public) .*$/, '') })) : issues;
|
|
@@ -179,6 +189,7 @@ export function hypothesesOf(root, configFile) {
|
|
|
179
189
|
/**
|
|
180
190
|
* Documentation en retard (L143, clé `docs.sync`) : un lot en cours — ou terminé à partir de `docs.since` — dont les commits de
|
|
181
191
|
* travail touchent des chemins sans toucher le document que la règle désigne. Les commits de plan ne comptent pas.
|
|
192
|
+
* Un lot dont l'écart est acquitté et motivé (`raf docs-ok`, L317) n'est pas compté.
|
|
182
193
|
*/
|
|
183
194
|
export function docSyncIssues(plan, root, byLot) {
|
|
184
195
|
const { sync, since } = readDocsConfig(plan.configFile ?? join(root, 'cadence.yaml'));
|
|
@@ -186,6 +197,7 @@ export function docSyncIssues(plan, root, byLot) {
|
|
|
186
197
|
return [];
|
|
187
198
|
return plan
|
|
188
199
|
.lots()
|
|
200
|
+
.filter((l) => !l.docsOk)
|
|
189
201
|
.filter((l) => l.status === 'doing' || (l.status === 'done' && !!since && !!l.finished && l.finished >= since))
|
|
190
202
|
.flatMap((l) => docSyncGaps(sync, filesOf(root, workCommits(plan, root, byLot.get(l.id) ?? []))).map((g) => ({ message: gapMessage(l.id, g) })));
|
|
191
203
|
}
|
package/dist/check.js
CHANGED
|
@@ -3,7 +3,18 @@ import { isOpen } from './plan.js';
|
|
|
3
3
|
import { isRecurring } from './recurring.js';
|
|
4
4
|
/** Un commit sur une ligne : sha abrégé et sujet. */
|
|
5
5
|
export const short = (c) => `${c.sha.slice(0, 7)} ${c.subject}`;
|
|
6
|
-
|
|
6
|
+
/** Titre d'un lot de revue UX planifiée : « Revue UX — <écran> ». */
|
|
7
|
+
const UX_REVIEW_TITLE = /^revue ux\s+—/i;
|
|
8
|
+
/** Message de l'écart d'une revue UX sans `visible:` ; la correction dépend de qui tient le plan (L321). */
|
|
9
|
+
function uxReviewMessage(lot, plan) {
|
|
10
|
+
const head = `${lot.id} est une revue UX (« ${lot.title.slice(0, 60)} ») sans visible: — l'étape UX n'aurait pas lieu`;
|
|
11
|
+
if (!plan.readonly)
|
|
12
|
+
return `${head} : poser visible: true dans le plan (raf visible ${lot.id} on, ou raf add --visible pour un nouveau lot)`;
|
|
13
|
+
if (plan.hasVisibleField === false)
|
|
14
|
+
return `${head} : ce plan ne porte pas visible : mapper le champ dans cadence.yaml (plan.fields.visible) si l'outil du projet l'écrit ; sans ce champ, la revue d'ergonomie de cet écran se fait hors orchestrate`;
|
|
15
|
+
return `${head} : poser visible: true dans le plan avec l'outil du projet (plan en lecture seule)`;
|
|
16
|
+
}
|
|
17
|
+
export function check(lots, linked, today, idleDays = 7, plan = {}) {
|
|
7
18
|
const issues = [];
|
|
8
19
|
const ids = new Set(lots.map((l) => l.id));
|
|
9
20
|
for (const c of linked.orphans)
|
|
@@ -19,7 +30,14 @@ export function check(lots, linked, today, idleDays = 7) {
|
|
|
19
30
|
issues.push({ kind: 'todo-with-commits', message: `${lot.id} a ${commits.length} commit(s) mais est encore todo — raf start ${lot.id}` });
|
|
20
31
|
}
|
|
21
32
|
if (lot.status === 'doing' && !recurring) {
|
|
22
|
-
|
|
33
|
+
// Un lot parent travaille par ses sous-lots (champ parent:, L321) : leur dernier commit, ou leur démarrage s'ils sont en cours, compte comme le sien.
|
|
34
|
+
const own = [commits[0]?.day ?? lot.started];
|
|
35
|
+
for (const sub of lots) {
|
|
36
|
+
if (sub.parent !== lot.id)
|
|
37
|
+
continue;
|
|
38
|
+
own.push(linked.byLot.get(sub.id)?.[0]?.day ?? (sub.status === 'doing' ? sub.started : undefined));
|
|
39
|
+
}
|
|
40
|
+
const last = own.filter((d) => !!d).sort().at(-1);
|
|
23
41
|
if (last && diffDays(last, today) > idleDays) {
|
|
24
42
|
issues.push({ kind: 'idle', message: `${lot.id} en cours sans commit depuis ${diffDays(last, today)} j (${lot.title})` });
|
|
25
43
|
}
|
|
@@ -30,6 +48,10 @@ export function check(lots, linked, today, idleDays = 7) {
|
|
|
30
48
|
issues.push({ kind: 'done-open-tasks', message: `${lot.id} terminé avec sous-tâche(s) ouverte(s) : ${open.map((t) => t.id).join(', ')}` });
|
|
31
49
|
}
|
|
32
50
|
}
|
|
51
|
+
// L271 : sans visible:, le lot ne passe par aucune étape UX d'orchestrate (precheck → implement → review) et la revue de l'écran n'a pas lieu.
|
|
52
|
+
if (isOpen(lot.status) && UX_REVIEW_TITLE.test(lot.title) && !lot.visible) {
|
|
53
|
+
issues.push({ kind: 'ux-review-not-visible', message: uxReviewMessage(lot, plan) });
|
|
54
|
+
}
|
|
33
55
|
for (const p of lot.problems)
|
|
34
56
|
issues.push({ kind: 'bad-field', message: `${lot.id} : ${p}` });
|
|
35
57
|
for (const d of lot.after) {
|