@sylad/cadence 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +47 -1734
- package/agents/acceptance-writer.md +1 -0
- package/bin/cadence.js +4 -1
- package/dist/audit.js +4 -3
- package/dist/cli.js +68 -7
- package/dist/config.js +46 -0
- package/dist/corrections.js +57 -22
- package/dist/deliver.js +8 -1
- package/dist/orchestrate/accept.js +8 -3
- package/dist/orchestrate/briefs.js +1 -1
- package/dist/orchestrate/command.js +3 -0
- package/dist/orchestrate/cycle.js +68 -6
- package/dist/perf.js +559 -0
- package/dist/state.js +29 -0
- package/docs/cadence-hud.md +50 -0
- package/docs/corrections.md +24 -0
- package/docs/cycle-vague-dark.svg +42 -0
- package/docs/cycle-vague-light.svg +42 -0
- package/docs/deliver.md +204 -0
- package/docs/fonctionnement-lead-dark.svg +101 -0
- package/docs/fonctionnement-lead-light.svg +101 -0
- package/docs/fonctionnement-lot-dark.svg +38 -0
- package/docs/fonctionnement-lot-light.svg +38 -0
- package/docs/fonctionnement-service-dark.svg +23 -0
- package/docs/fonctionnement-service-light.svg +23 -0
- package/docs/fonctionnement-wave-dark.svg +66 -0
- package/docs/fonctionnement-wave-light.svg +66 -0
- package/docs/fonctionnement.md +106 -0
- package/docs/lead-workflow-dark.svg +200 -0
- package/docs/lead-workflow-light.svg +200 -0
- package/docs/lead.md +149 -0
- package/docs/news.md +245 -0
- package/docs/orchestrate.md +639 -0
- package/docs/overview.md +27 -0
- package/docs/perf.md +84 -0
- package/docs/raf.md +192 -0
- package/docs/releasing.md +59 -0
- package/docs/session.md +107 -0
- package/docs/skills.md +76 -0
- package/docs/spec.md +60 -0
- package/docs/stabilite.md +35 -0
- package/docs/whats-new.md +83 -0
- package/package.json +29 -1
- package/skills/lead/SKILL.md +7 -0
- package/templates/acceptation-runner.mjs +1 -1
- package/templates/fiche-back.yaml +1 -1
- package/templates/fiche.yaml +1 -1
package/docs/news.md
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
[← cadence](../README.md)
|
|
2
|
+
|
|
3
|
+
# news
|
|
4
|
+
|
|
5
|
+
What changed *for the user*, one entry per visible lot, each with a screenshot.
|
|
6
|
+
|
|
7
|
+
- Mark a lot as user-facing with `raf add … --visible` (or `visible: true` in
|
|
8
|
+
the YAML). `raf done` and the post-commit hook remind you to write its entry;
|
|
9
|
+
`raf check` fails while a visible lot is done without one.
|
|
10
|
+
- An entry is a Markdown file in `docs/nouveautes/`, with a YAML header.
|
|
11
|
+
Screenshots are files you take yourself, stored next to the entries.
|
|
12
|
+
- `cadence news build` writes `nouveautes.json` for your app to display, a
|
|
13
|
+
self-contained `index.html`, and copies the screenshots.
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
raf add "Amounts like 3.000 read as three thousand" --visible # → L8
|
|
17
|
+
raf start L8 && git commit -m "fix(L8): thousands separator" && raf done L8
|
|
18
|
+
cadence news new L8 # docs/nouveautes/2026-09-29-amounts-like-3-000-….md (title: the lot's public title if any)
|
|
19
|
+
# add docs/nouveautes/captures/l8.png, list it under `captures:`, write the text
|
|
20
|
+
cadence news check # exit 1 on drift (also part of raf check)
|
|
21
|
+
cadence news build -o frontend/public/nouveautes
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```markdown
|
|
25
|
+
---
|
|
26
|
+
title: Amounts like 3.000 read as three thousand
|
|
27
|
+
date: 2026-09-29
|
|
28
|
+
created: 2026-09-29T14:32+02:00
|
|
29
|
+
lots: [L8]
|
|
30
|
+
captures: [captures/l8.png]
|
|
31
|
+
# nocapture: reason, when a screenshot makes no sense
|
|
32
|
+
---
|
|
33
|
+
Imported statements now read **3.000** as three thousand, not three.
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
A screenshot can say what it shows: write it as `{ file, alt }` instead of a
|
|
37
|
+
bare path, one text per screenshot.
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
captures:
|
|
41
|
+
- { file: captures/l8-before.png, alt: "Statement total read as 3 instead of 3,000" }
|
|
42
|
+
- captures/l8-after.png # a bare path still works: no alternative text
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
| Command | Effect |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `cadence news new <lot…> [--title t]` | entry skeleton, dated and timed now (`date`, `created`), titled after the lot's public title (`public`), else its title; `--title` wins |
|
|
48
|
+
| `cadence news list` | entries, newest first (see *Order* below) |
|
|
49
|
+
| `cadence news check` | visible lots done without entry, unknown lots, missing or undeclared screenshots, entries without creation time, bad headers, a lot whose screen sheet has hypotheses and whose entry lacks the `## Hypothèses` section (or a line for one of them) |
|
|
50
|
+
| `cadence news stamp` | migration: writes `created:` into entries without one (or with an empty one), from the author date of the commit that added the file under its current name (now if not committed yet) |
|
|
51
|
+
| `cadence news build [-o dir]` | `nouveautes.json` + `index.html` + screenshots (default `docs/nouveautes/site`) |
|
|
52
|
+
|
|
53
|
+
`--dir` changes the entries folder (default `docs/nouveautes` at the git root).
|
|
54
|
+
The Markdown is deliberately small: headings (`#` to `######`, rendered one level lower, `<h2>` to `<h6>`; a heading takes its own line and cuts the paragraph or list around it), paragraphs, `-` lists (a bullet may continue on the next lines, indented), `**bold**`,
|
|
55
|
+
`` `code` ``, `[links](../url)`; everything else is escaped text. The JSON holds
|
|
56
|
+
`{ project, generated, entries: [{ slug, title, date, lots, captures, html }] }`,
|
|
57
|
+
with screenshot paths relative to the JSON file. `captures` is always a list of
|
|
58
|
+
paths; an entry that gives at least one alternative text also carries `alts`,
|
|
59
|
+
the texts in the same order (`""` for a screenshot without one) — an entry
|
|
60
|
+
without any keeps exactly the shape above. The built page puts the text in the
|
|
61
|
+
image's `alt`, and falls back to "Capture : <title>".
|
|
62
|
+
|
|
63
|
+
**Order.** Everywhere (`list`, `build`, the JSON), entries are strictly newest
|
|
64
|
+
first: by `date`, then, on the same day, by creation time. Every entry carries
|
|
65
|
+
it to the minute in its `created` header, which `cadence news new` writes as
|
|
66
|
+
local time with an explicit offset (`2026-09-29T14:32+02:00`, or `Z`). The
|
|
67
|
+
offset is required, so the order does not depend on the machine's time zone:
|
|
68
|
+
`news check` (and `raf check`) flags a value without it, an impossible one, an
|
|
69
|
+
empty `created:`, and an entry without `created`. `cadence news stamp` fills
|
|
70
|
+
it in older entries (or replaces an empty one) from the author date of the
|
|
71
|
+
commit that added the file under its current name; until then, that date is
|
|
72
|
+
used for sorting (an entry not committed yet counts as the newest). Renames
|
|
73
|
+
are not followed: a renamed entry counts as added on the day of the rename,
|
|
74
|
+
so stamp it before renaming it. The file name only breaks the remaining ties,
|
|
75
|
+
since it follows the title, not the chronology. The page and the JSON still
|
|
76
|
+
show the day only.
|
|
77
|
+
|
|
78
|
+
## UX review
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
raf ux enable # from today, a --visible lot needs a UX review before done
|
|
82
|
+
raf ux L4 "compliant after 2 fixes" # record the verdict (from the ux-reviewer agent)
|
|
83
|
+
raf ux L8 "no screen: calculation fix"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
With the rule on, `raf done` refuses a visible lot without a review (`--force`
|
|
87
|
+
to override) and `raf check` reports visible lots finished after the `uxSince`
|
|
88
|
+
day without one. An empty verdict is refused, and one left empty or blank by hand
|
|
89
|
+
in the YAML counts as no review. Plans without `uxSince` are not affected.
|
|
90
|
+
|
|
91
|
+
## Code review
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
raf review enable # from today, a lot with commits needs a code review before done
|
|
95
|
+
raf commits L4 # what there is to review: the commits the gate counts for the lot
|
|
96
|
+
raf review L4 "compliant after 2 fixes" # record the verdict (from the code-reviewer agent)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The counterpart of the UX review, off by default. With the rule on, `raf done`
|
|
100
|
+
refuses a lot that has at least one commit citing it and no recorded verdict
|
|
101
|
+
(`--force` to override), and `raf check` reports such lots finished after the
|
|
102
|
+
`reviewSince` day. A lot with no commit has nothing to review; neither does a
|
|
103
|
+
lot whose only commits touch plan files alone (the plan, a file listed under
|
|
104
|
+
`plan.files`, or the QA expectations file), are version commits (see [Releasing](releasing.md#releasing)), predate the plan's `since` or match an `ignore:` pattern — `raf commits <id>` prints exactly the counted set.
|
|
105
|
+
|
|
106
|
+
The verdict is tied to what was reviewed: `raf review` stores it on the lot with
|
|
107
|
+
the sha of the lot's latest counted commit (`review: { date, verdict, commit }`,
|
|
108
|
+
`commit: null` when the lot had none). A counted commit made after that one
|
|
109
|
+
makes the review stale: `raf done` refuses (`--force` to override), and
|
|
110
|
+
`raf check` reports a finished lot, until the lot is reviewed again and
|
|
111
|
+
`raf review` is rerun. A verdict
|
|
112
|
+
written by hand without a `commit` field is not checked for staleness. An empty
|
|
113
|
+
verdict is refused, and one left empty or blank by hand in the YAML counts as no
|
|
114
|
+
review. Plans without `reviewSince` are not affected.
|
|
115
|
+
|
|
116
|
+
A lot that works in neighbouring repositories (`repos:`, see [orchestrate](orchestrate.md#a-lot-whose-work-is-in-a-neighbouring-repository))
|
|
117
|
+
has its verdict tied to each of them: `raf review` also stores, under `repos`, the sha of the latest counted commit of the
|
|
118
|
+
lot in each neighbour (the one `raf commits` lists last: it cites the lot, falls within the lot's period and contains the `cite:` string if any) (`review: { date, verdict, commit, repos: { ../aetherwx-gitops: <sha> } }`, `null` when a
|
|
119
|
+
neighbour has none), and refuses to record when a listed repository cannot be read. `raf check` does not audit the
|
|
120
|
+
neighbours: their staleness is not checked, only the project's own commits are.
|
|
121
|
+
|
|
122
|
+
## Documentation that follows the code
|
|
123
|
+
|
|
124
|
+
A stale README misleads. `cadence.yaml` can declare which documents must follow which code:
|
|
125
|
+
|
|
126
|
+
```yaml
|
|
127
|
+
docs:
|
|
128
|
+
sync:
|
|
129
|
+
- paths: [src/**, bin/*.js] # what changes…
|
|
130
|
+
docs: [README.md, docs/usage.md] # …must change one of these, in the same lot
|
|
131
|
+
- paths: [templates/]
|
|
132
|
+
docs: [CLAUDE.md]
|
|
133
|
+
- paths: [frontend/src/**, '!**/*.test.tsx'] # a pattern starting with ! leaves files out
|
|
134
|
+
docs: [README.md]
|
|
135
|
+
since: 2026-10-09 # optional: also audit lots finished on or after this day
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
A pattern is an exact path, with `*` (inside a folder), `**` (across folders), `?`, or a trailing `/` for
|
|
139
|
+
a whole folder. `raf check` takes the **work commits** of every lot in progress (plan-only commits and
|
|
140
|
+
version commits do not count — so a "What's new" line written in the version commit is not documentation; a lot finished on or after `docs.since` is audited too) and, for each pair, reports the lot when
|
|
141
|
+
those commits touch `paths` without any of them touching a file of `docs`:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
✗ L7 : documentation en retard — src/a.ts, src/b.ts sans toucher README.md ou docs/usage.md (docs.sync)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
It counts as drift: exit code 1, shown in the `dérive` column of `cadence lead tour`, and the review
|
|
148
|
+
brief of `cadence orchestrate` (`review` and `review-small`) carries the list the program computed,
|
|
149
|
+
to be reported as one **major** finding per line — a stale document is not left to the reviewer's
|
|
150
|
+
memory of a sentence. Touching a document is what the program checks; whether its text is true is
|
|
151
|
+
still the review's reading. The commits of neighbouring repositories (`repos:`) are not audited.
|
|
152
|
+
|
|
153
|
+
### An article elsewhere that follows the delivery
|
|
154
|
+
|
|
155
|
+
A case study that lives in a neighbouring repository (the project's article on a showcase site) goes stale
|
|
156
|
+
the same way. `docs.articles` names it:
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
docs:
|
|
160
|
+
articles:
|
|
161
|
+
- repo: ../claude-code-codex # neighbouring repository, relative to the project
|
|
162
|
+
file: src/pages/cas/demo.md # the article in it
|
|
163
|
+
name: demo # optional: the name in the lot title (default: the plan's project)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
After a **green** `cadence deliver`, for the lots it lists as delivered **that have a public title** (`public:`, or
|
|
167
|
+
the title of their Nouveautés entry), cadence opens in this repository's plan the lot
|
|
168
|
+
`Article demo à rafraîchir` (todo, estimate 0.5, `repos: [{ path: ../claude-code-codex, cite: demo }]`), with a note
|
|
169
|
+
that quotes the delivery, the public titles delivered, the article and the **sections to read again**: the headings
|
|
170
|
+
(`#` lines, or `<h1>`…`<h6>` of an Astro page) that share a word of five letters or more with a delivered title,
|
|
171
|
+
else all the `##` headings. The lot is then played like any other, in an ordinary wave (`cadence orchestrate`: an
|
|
172
|
+
implementer rewrites the article in the neighbouring repository, the review checks it against the note). If a lot
|
|
173
|
+
of that title is still open, it receives a note instead of a duplicate. Two entries with the same name (the same
|
|
174
|
+
project told in two neighbouring repositories) share one lot, which declares both repositories in `repos:`. Internal lots (no public title) open nothing;
|
|
175
|
+
a red delivery opens nothing; `cadence deliver --dry-run` announces the articles. The plan is written but **not
|
|
176
|
+
committed** (`deliver` never commits): the line `article à rafraîchir : L9 …` says so. With a plan kept by another
|
|
177
|
+
tool (read-only), the same line carries the instruction to open the lot with that tool. This replaces the manual
|
|
178
|
+
`sync-site-docs` skill.
|
|
179
|
+
|
|
180
|
+
## QA review
|
|
181
|
+
|
|
182
|
+
No gate and no command here: the QA review comes **after** a delivery, and
|
|
183
|
+
`raf done` does not wait for it. It follows any delivery that changes what a
|
|
184
|
+
page shows or what it is served (screen, API, data source, configuration of
|
|
185
|
+
either) — in practice every delivery except docs-, plan- or tests-only ones: a
|
|
186
|
+
backend-only lot can empty a page without touching a screen, and the agent then
|
|
187
|
+
walks the pages that call the changed endpoints. It also walks the pages that consume the services the lot changed; when the diff changes no route and no screen, or cannot be linked to pages, it walks every page and says so. The `qa-reviewer` agent
|
|
188
|
+
opens each page of the running app in a real browser and judges it from the
|
|
189
|
+
user's side. A page can be empty while everything else is green — no code
|
|
190
|
+
changed, a data source went down upstream, the unit tests replace the network,
|
|
191
|
+
`/api/health` answers ok, and the "nothing found" on screen is the message the
|
|
192
|
+
code was written to show.
|
|
193
|
+
|
|
194
|
+
The agent cannot tell such an empty state from a normal one by itself: the
|
|
195
|
+
project says what each page must show, in `docs/qa/expectations.md` — one
|
|
196
|
+
`## <route>` section per page, three kinds of lines:
|
|
197
|
+
|
|
198
|
+
```markdown
|
|
199
|
+
# QA expectations
|
|
200
|
+
|
|
201
|
+
## *
|
|
202
|
+
- shows: the header and the navigation links
|
|
203
|
+
- never: "Loading failed", "Too Many Requests"
|
|
204
|
+
- api: /api/live/current — may be empty when no match is within 24 hours
|
|
205
|
+
|
|
206
|
+
## /players
|
|
207
|
+
- shows: the squad of the last match — at least 11 players
|
|
208
|
+
- shows: the season statistics table, 8 columns — 1440 only
|
|
209
|
+
- never: "No recent line-up found"
|
|
210
|
+
- api: /api/squad/last — a non-empty list
|
|
211
|
+
|
|
212
|
+
## /fixtures/:id (the first match linked from /fixtures)
|
|
213
|
+
- shows: both team names, the date, the score once the match is played
|
|
214
|
+
- never: "Unknown match"
|
|
215
|
+
- api: /api/fixtures/:id
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
- `shows:` — content that must be present and non-empty, with a count where one exists;
|
|
219
|
+
- `never:` — texts that must not appear: error messages, and empty-state messages that mean
|
|
220
|
+
missing data;
|
|
221
|
+
- `api:` — the calls the page depends on: each must answer 2xx with a non-empty body (a 200 with
|
|
222
|
+
`[]`, `{}` or `null` is a failure, unless its line says `may be empty when …`).
|
|
223
|
+
|
|
224
|
+
An optional `## *` section holds what every page must show, never show and call. A line may end
|
|
225
|
+
with a condition in plain words, which the agent honours: `may be empty when …`, `1440 only`,
|
|
226
|
+
`390 only` (a line without a width holds at both). Content hidden on the phone by design is not a
|
|
227
|
+
defect unless a `shows:` line requires it at 390; content pushed outside the visible area (it
|
|
228
|
+
needs a sideways scroll) is reported as suspect and handed to `ux-reviewer` in one line.
|
|
229
|
+
|
|
230
|
+
The rest is free text, written for a reader: a line can be repeated, and a route with a parameter
|
|
231
|
+
names a real value to visit or says where to find one. The file can live elsewhere:
|
|
232
|
+
|
|
233
|
+
```yaml
|
|
234
|
+
# cadence.yaml
|
|
235
|
+
qa:
|
|
236
|
+
expectations: docs/quality/pages.md
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The agent reads that key, and so does `raf check`: a commit touching only that file is plan upkeep (no lot to cite, see above). Without an expectations file the agent walks
|
|
240
|
+
the routes it discovers and still runs its universal checks: an error shown, a failed API call
|
|
241
|
+
whose content is missing on screen, a broken or missing content image are defects with or without a
|
|
242
|
+
file; an empty 2xx body, like whatever else would need an expectation to judge, is suspect at most
|
|
243
|
+
(it may be a normal absence). For a route with a
|
|
244
|
+
parameter, it finds a real value in the app's links or its API responses and says how it built the
|
|
245
|
+
URL. The agent then returns a draft for you to correct — it never writes the file itself.
|