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