@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
package/docs/ref.md
ADDED
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
[← cadence](../README.md)
|
|
2
|
+
|
|
3
|
+
# `cadence ref`: reference documents (specs, norms, mock-ups)
|
|
4
|
+
|
|
5
|
+
A spec delivered as a PDF often keeps part of its information in images: screen mock-ups,
|
|
6
|
+
tables drawn as pictures, message templates, figures of a norm (WMO, ICAO…). `cadence ref`
|
|
7
|
+
turns such a document into files a session can read without losing the pictures. The whole
|
|
8
|
+
design is in
|
|
9
|
+
[`docs/superpowers/specs/2026-10-23-ref-documents-de-reference-design.md`](superpowers/specs/2026-10-23-ref-documents-de-reference-design.md)
|
|
10
|
+
(issue #14); this page describes what is delivered so far: **`cadence ref add`** (lot 1 of 10), **`cadence ref measure`** (lot 2 of 10) **`cadence ref check`** with the inventory schema (lot 3 of 10), **`cadence ref eval`** (lot 4 of 10, with the synthetic corpus `cadence ref corpus`) **`cadence ref analyse`** (lot 5 of 10: the `reference-analyst` agent, one single reading) and **`cadence ref diff`** with the double reading (lot 6 of 10). **The series stops at lot 6**: the stopping point of the double reading (hypothesis H1) was not met, so lots 7 to 10 are dropped and the double reading stays an option, `--double` ([measurement and conclusion](mesures/ref-double-lecture-2026-10-25.md)).
|
|
11
|
+
|
|
12
|
+
## `cadence ref add <document.pdf> [--sections 3-5,9] [--slug name]`
|
|
13
|
+
|
|
14
|
+
Registers a PDF and builds, for it:
|
|
15
|
+
|
|
16
|
+
- **pages rendered at 200 dpi** (`pages/page-<n>.png`, `pdftoppm`);
|
|
17
|
+
- **positioned text** of every page (`pdftotext -bbox-layout`): each line with its box
|
|
18
|
+
`x, y, l, h` in pixels of the rendered page (200 dpi);
|
|
19
|
+
- **embedded images** (`pdfimages`, `images/p<page>-<n>.png`) with their region in the same
|
|
20
|
+
pixels (`pdftohtml -xml`);
|
|
21
|
+
- **the figure index**: one entry per caption at the start of a line (`Figure n`, `Fig. n`,
|
|
22
|
+
`Table n`, `Tableau n`, `Planche n`). After a separator (`—`, `–`, `:`, `.`, `-`) the line is a
|
|
23
|
+
caption whatever the case of the title (`Figure 1 — map of stations`); without one,
|
|
24
|
+
`Figure 3 shows…`, `Figure 5, which…` and `Figure 5 (page 4) and…` cite the figure. One exception:
|
|
25
|
+
a line made only of the number and one closed parenthesis (`Table IV.3 (in accordance with
|
|
26
|
+
4.3.11)`, WMO-No. 49 vol. II) is a caption when no other line looks like the caption of that
|
|
27
|
+
number; with another one, or open (`Table 11 (see Example…`), it cites. A separator
|
|
28
|
+
followed by nothing (`figure 24.` ending a sentence) is not a caption either. A
|
|
29
|
+
table-of-contents entry (dot leaders on its line or on the next one, or any line of a contents
|
|
30
|
+
page: one where at least two lines, and more than half, have dot leaders or end with a possible
|
|
31
|
+
page number) is neither a caption nor a citation, so a figure that only the contents list names
|
|
32
|
+
comes out as « nothing cites it ». A trailing number alone never makes an entry:
|
|
33
|
+
`Table 4.1. … presented in Chapter 4` among prose is a caption. When several lines look like the
|
|
34
|
+
caption of one figure, those with a title are kept (`Figure 5 Jet speed` rather than a bare `Figure 5`), if any; among them
|
|
35
|
+
the first on a page that holds an image wins, then the first with a separator, then the first. Each entry has its page, line, box, its images, and **the passages that cite it** (page,
|
|
36
|
+
line, exact line; `nommee` when the text names the figure, `designee` for « as shown
|
|
37
|
+
below » / « ci-dessous », attached to the nearest caption of the page). Plurals count one citation per figure
|
|
38
|
+
(`Figures 2 and 3`, `Tables 4 to 6`, `Figs. 2.1 et 2.2`), and ranges are expanded figure by figure (`Figures 2–4` with an en dash glued to its bounds — a dash set off by spaces or an em dash, `Figures 2 and 3 — 10 stations`, `Figures 2 and 3—10 stations`, is prose and not a range —, `Figures 01–03` keeping the leading zeros of its bounds, `Figures 2, 4 to 6`, `Figures 1.1 to 1.3`, `Figures 1.B.1 to 1.B.3`, `Figures 3-1 to 3-3`, `Tables A1 to A3`; a range of which the bounds do not share their prefix, that decreases or that spans 50 numbers or more keeps its two bounds, and a bare second bound after a prefixed one (`Tables 4.8–10`, `A3–1`) is not a figure of its own; the figures in the middle of a range are cited when they have a caption, and are never an unresolved link when they have none, so `figures 11–20` leaves only `Figure 11` and `Figure 20` to resolve, and an explicit `Figure 15` further on the same line stays cited or unresolved on its own); a number keeps the letters of an annex numbering (`Figure 1.B.1`, `Table 12.B.3`). A figure preceded by the word `code` or `indicator` (`code figure 3`, `code figures 2 and 3`, `indicator figures 1 to 6, 8 and 9` — a value of a WMO code —, including when the word ends the previous line, or the last line of the previous page before its footer and the header of the next page, and the reference opens the next one) is not a citation and not an unresolved link; neither is an en-dash range (`figures 20–49`) in a sentence that already has a `code figure` (`code figure 17 shall have precedence over figures 20–49`). A header or footer is a line that, digits apart, opens or ends three pages or more. `code table` is not affected. Listed under **`unresolved`**
|
|
39
|
+
(« lien non résolu »): a citation of a figure with no caption, a figure that nothing cites,
|
|
40
|
+
and an image on a page that has no caption (`image sans légende`).
|
|
41
|
+
|
|
42
|
+
- **thumbnails of every page** (`thumbs/page-<n>.png`, 40 dpi) and the **pages without text**:
|
|
43
|
+
a page with fewer than 20 characters of text is taken for scanned and reported
|
|
44
|
+
(`pages sans texte : 30 (1-4, 6-31)`), so a scanned norm does not look indexed while its index
|
|
45
|
+
is empty; the thumbnails tell which pages to render with `--sections`. (Both recipes come from
|
|
46
|
+
the `norme-etude` skill of maritime-atlas: `refdoc.py index`.)
|
|
47
|
+
|
|
48
|
+
Without `--sections`, a document of 30 pages or fewer is rendered whole; a larger one only gets
|
|
49
|
+
its index (text and figures), no page is rendered. With `--sections`, the pages asked for are
|
|
50
|
+
rendered **plus the pages of the figures they name**, wherever they are in the document. Running
|
|
51
|
+
`add` again on the same document (same sha256) keeps the pages rendered before and adds the new
|
|
52
|
+
ones; a slug taken by another document is refused (`--slug` picks another name).
|
|
53
|
+
|
|
54
|
+
A PDF that asks for a password, forbids copying, is damaged, is not a PDF or has no page is refused with the reason. Image
|
|
55
|
+
documents (PNG, JPG) are not read yet.
|
|
56
|
+
|
|
57
|
+
## `cadence ref measure <slug> <page> <zone> [--quoi couleurs|contraste|boites|texte] [--largeur 1440] [--json]`
|
|
58
|
+
|
|
59
|
+
Measures a zone of a **rendered** page of a document registered by `add` (a page `add` did not render
|
|
60
|
+
is refused with the command that renders it). The zone is `page` (the whole page), `x,y` (one
|
|
61
|
+
point) or `x,y,l,h` (a rectangle), in pixels of the rendered page (200 dpi: the unit of the boxes in
|
|
62
|
+
`document.json`). Every length in the answer is brought back to a **reference width** of 1440 px
|
|
63
|
+
(`--largeur`), the width of a screen, whatever the resolution of the page: the first line says the
|
|
64
|
+
factor. Without `--quoi`, the four measures; a point only has colours.
|
|
65
|
+
|
|
66
|
+
- **`couleurs`**: the exact colour of a point (`#c81e28`, `rgb(200, 30, 40)`); for a rectangle the
|
|
67
|
+
mean (rounded) and the **dominant colours** with their share of the zone (grouped by 8 levels per
|
|
68
|
+
channel, at most 5, none under 1 %).
|
|
69
|
+
- **`contraste`**: WCAG 2.2 contrast ratio between the zone's **background** (its dominant colour) and
|
|
70
|
+
its **text**: every colour carried by at least 10 % of the non-background pixels is a text colour
|
|
71
|
+
(an anti-aliased edge is spread over many shades and stays under that share), and the verdict is the
|
|
72
|
+
one of the **least contrasted** text colour, never a mean of several (a red and a blue text do not
|
|
73
|
+
make a purple that is not in the image). The one exception is a zone where no colour reaches that share (a gradient, text over a photo): the text is then the mean of the pixels furthest from the background, a colour that may not exist in the image, and the answer says so (`texte.moyenne: true` in JSON, a note on the `contraste` line). The three thresholds are read on the unrounded ratio: AA (4.5), AA large text and interface
|
|
74
|
+
components (3), AAA (7). `#767676` on white gives 4.54, `#777777` 4.48. A zone of one colour has no
|
|
75
|
+
contrast to measure.
|
|
76
|
+
- **`boites`**: the connected shapes that differ from the background (8 neighbours), the 20 largest first, and the
|
|
77
|
+
bounding box of all the content; coordinates are those of the page, not of the zone. A pixel belongs to a shape from a distance of 24 (RGB, Euclidean) to the background, the threshold under which a zone is flat: a pale card (`#eeeeee` on white) is a shape.
|
|
78
|
+
Shapes under 16 pixels are dust.
|
|
79
|
+
- **`texte`**: the words tesseract reads (English model, `--psm 6`) with their box and confidence, and the
|
|
80
|
+
**estimated font size**: the median height of the words that have no descender and a letter as tall
|
|
81
|
+
as a capital (`Hello`, `2026`, not `gap`) read with confidence ≥ 60, divided by 0.72 (the cap height
|
|
82
|
+
of Helvetica / Arial in em). The size is the one of the reference width.
|
|
83
|
+
|
|
84
|
+
**Declared tolerance** (last line, and `tolerance` in `--json`): colours ±1/255 per channel (mean
|
|
85
|
+
rounded), boxes ±1 pixel of the page, i.e. ±⌈factor⌉ px at the reference width, font size ±5 % (the cap
|
|
86
|
+
height of a face is 0.70 to 0.73 em) plus one pixel of cap height, given with the measure
|
|
87
|
+
(`police : ≈ 28.2 px (±10 %, 4 mot(s) …)`). The image is read as it is: an alpha channel is composed over white.
|
|
88
|
+
Only 8-bit, non-interlaced PNG (what `pdftoppm` writes) is read; another kind is refused with the reason.
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
$ cadence ref measure norme 2 page --quoi contraste
|
|
92
|
+
norme p.2 · zone 0,0,1700,2200 px de la page · ramené à 1440 px (×0.85)
|
|
93
|
+
contraste : 4.54:1 (texte #767676 sur fond #ffffff) · AA ✓ · AA grand texte et composants ✓ · AAA ✗
|
|
94
|
+
tolérance : couleurs ±1/255 par canal, boîtes ±1 px, police ±5 % plus un pixel de hauteur de capitale
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`--json` prints one object (`document`, `page`, `zone`, `echelle`, `tolerance`, then `couleurs`,
|
|
98
|
+
`contraste`, `boites`, `texte` as asked). Exit codes: 0 done, 2 refusal (tool, unknown document,
|
|
99
|
+
page absent or not rendered, invalid zone or option).
|
|
100
|
+
|
|
101
|
+
## `cadence ref check <inventaire.json | lecture.json>`
|
|
102
|
+
|
|
103
|
+
Validates an **inventory** (`genre: "inventaire"`) or a **reading** (`genre: "lecture"`): the JSON file in which the
|
|
104
|
+
reference analysis lists what the document shows. The model to copy is
|
|
105
|
+
[`templates/inventaire.json`](../templates/inventaire.json) (one element of each of the eleven types, slug `exemple`).
|
|
106
|
+
`check` validates the **form**, never the truth of a measure; it calls no system tool (it works with an empty `PATH`), does not read
|
|
107
|
+
`references.dir` and writes no file.
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
$ cadence ref check inventaire.json
|
|
111
|
+
✗ elements[3].libelle : champ du type texte manquant ou invalide
|
|
112
|
+
✗ elements[5].ecran : exemple#texte-1 ne désigne aucun élément de type ecran
|
|
113
|
+
2 écart(s)
|
|
114
|
+
$ cadence ref check templates/inventaire.json
|
|
115
|
+
inventaire valide : 11 éléments (ecran: 1, composant: 1, etat: 1, texte: 1, jeton: 1, table: 1, gabarit: 1, schema: 1, lien: 1, statut: 1, silence: 1)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Exit codes: **0** valid (summary on the standard output; « lecture valide » for a reading), **1** deviations (one
|
|
119
|
+
`✗ <path> : <reason>` line per deviation then `N écart(s)`, **on the standard output**), **2** wrong call (not exactly one
|
|
120
|
+
argument) or unreadable file (absent, a folder, empty, not JSON, UTF-8 BOM included): the reason goes to the error output. A
|
|
121
|
+
duplicated JSON key is not detected (the last one wins, as with `JSON.parse`). An unknown key, at the root or in an element, is ignored.
|
|
122
|
+
|
|
123
|
+
**Root**: `version` (1), `genre`, `document` `{ slug (kebab-case), sha256 (64 lowercase hex) }`, `elements` (non-empty array), and, in an
|
|
124
|
+
expected inventory, `pages` (the number of pages of the document, an integer ≥ 1; not checked here, read by `ref eval` for the tokens per page).
|
|
125
|
+
|
|
126
|
+
**Every element**: `type` (`ecran`, `composant`, `etat`, `texte`, `jeton`, `table`, `gabarit`, `schema`, `lien`, `statut`, `silence`);
|
|
127
|
+
`id` = `<slug of document>#<type>-<n>` (n ≥ 1, no leading zero; the slug is compared as it is, even invalid, and two elements never share an id);
|
|
128
|
+
`source` `{ page ≥ 1, zone { x, y, l, h } }` in pixels of the page rendered at 200 dpi (x, y ≥ 0, l, h ≥ 1; the zone is optional only for a `silence`);
|
|
129
|
+
`citations` (optional) `[{ page, ligne, extrait }]`; `confiance` (`mesure`, `lu`, `incertain`); `cause` (non-empty, **only** on an
|
|
130
|
+
`incertain` element); `ocr` (optional boolean; in a reading an `ocr: true` element is never `lu`).
|
|
131
|
+
|
|
132
|
+
| Type | Own keys |
|
|
133
|
+
|---|---|
|
|
134
|
+
| `ecran` | `largeur_reference` (integer > 0, 1440 in the model), `zones` (non-empty) `[{ nom, x, y, l, h, pct { x, y, l, h } }]`: pixels at that width, `pct` numbers from 0 to 100 |
|
|
135
|
+
| `composant` | `role` (from the list of roles below), `position { x, y }` (≥ 0), `taille { l, h }` (≥ 1), `contenu` (text, may be empty), `ecran` (id of an `ecran`) |
|
|
136
|
+
| `etat` | `nom` (non-empty, open list), `cible` (id of a `composant` or an `ecran`) |
|
|
137
|
+
| `texte` | `libelle` (non-empty, no leading or trailing blank), `role` (from the list of roles below) |
|
|
138
|
+
| `jeton` | `categorie` (`couleur`, `taille_police`, `espacement`, `rayon`, `opacite`), `valeur` (non-empty string or finite number), `point` (`{ x, y }` or a zone `{ x, y, l, h }`; required when `confiance` is `mesure`), `contraste` (optional) `{ texte, fond, ratio 1 to 21 }` |
|
|
139
|
+
| `table` | `colonnes` (non-empty array of texts), `lignes` (non-empty, each row has as many text cells as columns) |
|
|
140
|
+
| `gabarit` | `nom`, `champs` (non-empty, ordered) `[{ nom, obligatoire (boolean), format, min?, max? }]`, `min ≤ max` |
|
|
141
|
+
| `schema` | `noeuds` (non-empty) `[{ id, libelle }]` (unique ids), `flux` `[{ de, vers, libelle, direction }]` (`de`, `vers` = node ids; `direction` = `de_vers` or `bidirectionnel`) |
|
|
142
|
+
| `lien` | `figure`, `passage { page, ligne, extrait }`, `constat` (`confirme`, `precise`, `contredit`); `precise` adds `lecture_ambigue`, `interpretation`, `raison`; `contredit` adds `enonces` (exactly two texts) and carries no `interpretation` |
|
|
143
|
+
| `statut` | `libelle`, `couvre` (non-empty array of ids of any type, itself included) |
|
|
144
|
+
| `silence` | `question` (non-empty, ends with `?`) |
|
|
145
|
+
|
|
146
|
+
**Roles** (`role` of a `texte` and of a `composant`): a **closed list**, because the role takes part in the identity of a component and
|
|
147
|
+
in the verdict on a text in `ref eval`. A role outside the list is a deviation of the schema (`« label » n'est pas un rôle de la
|
|
148
|
+
liste : …`), never a reading error counted later. The list is in `ROLES` of `src/ref/check.ts` and in the `roles` key of
|
|
149
|
+
[`templates/inventaire.json`](../templates/inventaire.json) (one line of definition per role; a test keeps both identical):
|
|
150
|
+
|
|
151
|
+
| Role | Definition |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `titre` | title of a document, a page or a section |
|
|
154
|
+
| `titre-panneau` | title of a panel or a window of an interface |
|
|
155
|
+
| `paragraphe` | sentence or block of running text |
|
|
156
|
+
| `legende` | text that names a figure, a table or a colour scale (« Figure 1 — … ») |
|
|
157
|
+
| `etiquette-figure` | word or value written inside a figure (arrow, axis, curve, threshold) |
|
|
158
|
+
| `exigence` | statement of one requirement in a list of requirements |
|
|
159
|
+
| `ligne` | line of a record or a form, with no other function |
|
|
160
|
+
| `message_erreur` | message that reports an error or a refusal to the user |
|
|
161
|
+
| `unite` | unit attached to a value (kt, hPa, m) |
|
|
162
|
+
| `info_bulle` | short text shown on hover or focus of an element |
|
|
163
|
+
| `bouton` | control one acts on (`composant`), or its label (`texte`) |
|
|
164
|
+
| `champ` | area where a value is typed (`composant`), or its label (`texte`) |
|
|
165
|
+
| `case_a_cocher` | two-state control, ticked or not, independent of the others |
|
|
166
|
+
| `selecteur` | control that picks one value in a closed list (drop-down, radio buttons) |
|
|
167
|
+
| `onglet` | entry of a bar that switches between views of the same level |
|
|
168
|
+
| `menu` | list of actions or destinations that opens from a control |
|
|
169
|
+
| `liste` | sequence of items of the same kind shown one under the other |
|
|
170
|
+
| `panneau` | interface area that groups controls (`composant`) |
|
|
171
|
+
| `carte` | map or chart display area (`composant`) |
|
|
172
|
+
| `icone` | pictogram with no text that stands for an action or an object |
|
|
173
|
+
| `badge` | pill or mark that qualifies an element (status, counter) |
|
|
174
|
+
|
|
175
|
+
References (`ecran`, `cible`, `couvre`, flux nodes) are resolved on the whole list of ids, wherever the element is. Every slug and id
|
|
176
|
+
deviation (R6/R9) is listed, none masks another; elsewhere a deviation can hide others (a non-object element only reports its
|
|
177
|
+
`type`, an invalid `confiance` skips the `cause` check, an invalid `elements` validates no element). The key names of `ecran` and the values of `direction` are a format shared with the later lots
|
|
178
|
+
(they are hypotheses of the sheet `docs/specs/ref-inventaire-schema/fiche.yaml`).
|
|
179
|
+
|
|
180
|
+
### Where the files go
|
|
181
|
+
|
|
182
|
+
Outside the repository: `references.dir` of `cadence.yaml` (relative to that file), by default
|
|
183
|
+
`$XDG_DATA_HOME/cadence/references` (`~/.local/share/cadence/references`). A `references.dir`
|
|
184
|
+
inside a Git repository is refused: the documents may be private. One folder per document:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
<references.dir>/<slug>/document.json source, sha256, pages (lines, boxes), images, figures, unresolved
|
|
188
|
+
<references.dir>/<slug>/pages/ page-<n>.png, 200 dpi
|
|
189
|
+
<references.dir>/<slug>/images/ p<page>-<n>.png
|
|
190
|
+
<references.dir>/<slug>/thumbs/ page-<n>.png, 40 dpi, every page
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### System tools
|
|
194
|
+
|
|
195
|
+
`cadence ref` calls poppler (`pdftoppm`, `pdftotext`, `pdfimages`, `pdfinfo`, `pdftohtml`),
|
|
196
|
+
ImageMagick (`magick`, or `convert` for version 6) and tesseract. They are looked up in the
|
|
197
|
+
`PATH` before the document is read; each one missing is named with its install command and the
|
|
198
|
+
command exits **2**, writing nothing and installing nothing:
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
ref : outil absent du PATH, à installer (rien n'est installé d'office) :
|
|
202
|
+
magick ou convert : sudo apt install imagemagick
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
(`poppler-utils`, `imagemagick`, `tesseract-ocr`.) `add` does not call ImageMagick or tesseract, `measure` calls tesseract (and only for the text); both check all the tools at the first call, as the design asks.
|
|
206
|
+
ImageMagick is not called by either: `measure` decodes the rendered PNG pages itself. The rest of cadence depends on none of them.
|
|
207
|
+
|
|
208
|
+
A poppler tool that fails while `add` reads the document (`pdftotext`, `pdftoppm`, `pdfimages`, `pdftohtml`: non-zero exit, output too large, disk full)
|
|
209
|
+
is a refusal too, naming the tool, the document and the reason: `ref : pdftotext a échoué sur doc.pdf (disque plein)`. The folder of a new document is not left behind (an existing document keeps its `document.json`; `pdftohtml` is read before anything is written).
|
|
210
|
+
|
|
211
|
+
Exit codes: 0 done, 2 refusal (tool, file, option, slug, folder, tool failure).
|
|
212
|
+
|
|
213
|
+
## `cadence ref eval <attendu> <lecture> [--json]`
|
|
214
|
+
|
|
215
|
+
Scores a reading against the inventory that is known to be true (the evaluation of the design, §« Mesure »). `attendu` is an
|
|
216
|
+
inventory (`genre: "inventaire"`), `lecture` a reading or an inventory of the same document; both go through the checks of
|
|
217
|
+
`ref check` first. Two folders work too (a file against a folder, or the reverse, is refused with exit 2 and the accepted combinations: two files, or two folders): `attendu` holds `<cas>/attendu.json` (what `ref corpus` writes) and `lecture`
|
|
218
|
+
`<cas>/lecture.json`; a case without a reading counts as read with nothing (recall 0) and is named under `sans lecture`.
|
|
219
|
+
|
|
220
|
+
An element read is matched to an expected one **by type and identity**, never by id or zone (two independent readings number
|
|
221
|
+
their elements their own way; blanks inside a text do not count, and the case does not either, except for a `texte`, which is verbatim: `120 KT` is not `120 kt`): `texte` and `statut` by `libelle`, `composant` by
|
|
222
|
+
`role` and `contenu`, `etat` by `nom` and the identity of its target, `jeton` by `categorie` and `valeur` (a colour is compared as
|
|
223
|
+
written), `table` by `colonnes`, `gabarit` by `nom`, `schema` by the labels of its nodes, `lien` by `figure`, `silence` by
|
|
224
|
+
`question`, `ecran` (one per document). An expected element is matched once. The matched element is **juste** if it also says the
|
|
225
|
+
same thing: the `role` of a `texte`, the `lignes` of a `table`, the `champs` of a `gabarit` (name, mandatory, format, bounds, in
|
|
226
|
+
order), the `flux` of a `schema`, the `constat` of a `lien` (the interpretation of a `precise` is not compared), the elements
|
|
227
|
+
covered by a `statut`, the `largeur_reference` of an `ecran`.
|
|
228
|
+
|
|
229
|
+
- **rappel** = juste / expected, **précision** = juste / read, both by type and overall;
|
|
230
|
+
- **faux lu** = read elements marked `lu` or `mesure` (« sûrs ») that are not juste, over the sûrs: an invented element, a wrong
|
|
231
|
+
cell, a `lien` that confirms what the figure contradicts. An `incertain` element is never a faux lu (it lowers the precision);
|
|
232
|
+
- **pièges**: an expected element carries `piege: "<name>"`; a piège is found when all its elements are juste (`✓ nom : 1/1`);
|
|
233
|
+
- **tokens par page**: the `usage: { tokens }` of the reading divided by the `pages` of the expected inventory (a root key of the
|
|
234
|
+
expected file, see the model), for the cases that have both; without `usage`, « non mesurés » (`null` in `--json`), never a zero.
|
|
235
|
+
A case whose expected inventory has **no `pages`** is left out of the figure, tokens and pages alike, and the output says so:
|
|
236
|
+
`tokens par page : N cas sans `pages` exclus (names)` (`tokens.exclus` in `--json`).
|
|
237
|
+
|
|
238
|
+
The output is the totals, then one line per type present (in the order of the eleven types), then the pièges (`✓` all found, `✗`
|
|
239
|
+
some missing) and, last, the cases without a reading. This one is a reading of the corpus that confirms a link the figure makes
|
|
240
|
+
precise, misreads a table cell, an opacity and a state, drops one line of the scan and counts 4,200 tokens for the one case that
|
|
241
|
+
reports `usage`:
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
$ cadence ref eval tmp/corpus-ref lectures/
|
|
245
|
+
7 cas · 47 éléments attendus · 46 lus
|
|
246
|
+
rappel : 89.4 % (42/47) · précision : 91.3 % (42/46)
|
|
247
|
+
faux lu : 9.3 % (4/43 sûrs)
|
|
248
|
+
tokens par page : 4200 (4200 sur 1 pages)
|
|
249
|
+
par type :
|
|
250
|
+
ecran rappel 100 % (2/2) · précision 100 % (2/2) · faux lu 0/2
|
|
251
|
+
composant rappel 100 % (5/5) · précision 100 % (5/5) · faux lu 0/5
|
|
252
|
+
etat rappel 50 % (1/2) · précision 50 % (1/2) · faux lu 1/2
|
|
253
|
+
texte rappel 96.7 % (29/30) · précision 100 % (29/29) · faux lu 0/26
|
|
254
|
+
jeton rappel 50 % (1/2) · précision 50 % (1/2) · faux lu 1/2
|
|
255
|
+
table rappel 0 % (0/1) · précision 0 % (0/1) · faux lu 1/1
|
|
256
|
+
gabarit rappel 100 % (1/1) · précision 100 % (1/1) · faux lu 0/1
|
|
257
|
+
lien rappel 66.7 % (2/3) · précision 66.7 % (2/3) · faux lu 1/3
|
|
258
|
+
statut rappel 100 % (1/1) · précision 100 % (1/1) · faux lu 0/1
|
|
259
|
+
pièges :
|
|
260
|
+
✗ controle-translucide : 0/1
|
|
261
|
+
✓ figure-contredit-texte : 1/1
|
|
262
|
+
✓ gabarit-type-bufr : 1/1
|
|
263
|
+
✓ page-proposal : 1/1
|
|
264
|
+
✗ scan-bruite : 3/4
|
|
265
|
+
✗ table-en-image : 0/1
|
|
266
|
+
✗ texte-ambigu-leve-par-figure : 0/1
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Reading it: the `etat` line is the recall of the states (the threshold of the design is 95 % of the components **and** states);
|
|
270
|
+
in `faux lu 1/2` the second number is the number of sûrs read of that type (an `incertain` one, like the OCR texts of the scan,
|
|
271
|
+
is not in it). A misread affirmation (the table cell, the confirmed link) is an element found but not juste; a misread part of the identity (the opacity, the name of a state) is a missing element and an invented one; both cost recall and add a faux lu, while a dropped element (the scan line) costs recall only. The `✗` pièges name what a reader must work on: here the confirmed link, the cell and the
|
|
272
|
+
opacity are exactly the traps of those cases.
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
A reading whose `document.slug` or `document.sha256` differs from the expected one is refused (never a measure over two versions
|
|
276
|
+
mixed). Exit codes: **0** done, **2** refusal (wrong call, file absent or unreadable, invalid reading, other document, folder with
|
|
277
|
+
no `attendu.json`). `--json` prints one object: `total`, `types`, `pieges`, `tokens`, `cas`.
|
|
278
|
+
|
|
279
|
+
## `cadence ref diff <lecture-a.json> <lecture-b.json> [--out inventaire.json] [--seuil 30]`
|
|
280
|
+
|
|
281
|
+
Reconciles **two readings of the same document** (design §3, step 3), by program, without any session. Both files must pass `ref check`, be of genre `lecture`, and carry the same `slug` **and** `sha256` (a reconciliation over two
|
|
282
|
+
versions of a document is refused, exit 2). Elements are paired **by type, page, identity and zone overlap**; the identity is what designates an element whatever its id, zone and confidence (the same notion as `ref eval`: the
|
|
283
|
+
text of a `texte`, role and content of a `composant`, figure of a `lien`…), since two independent readings number their ids their own way:
|
|
284
|
+
|
|
285
|
+
| Paired as | When | Result |
|
|
286
|
+
|---|---|---|
|
|
287
|
+
| **concordant** | same identity and same affirmation (the role of a text, the verdict of a link, the cells of a table…) | one element, `mesure` if either reading measured it, else `lu`; a doubt of one reading (`incertain`) stays a doubt, with its cause |
|
|
288
|
+
| **divergent** | same identity but another affirmation, or another identity on the same zone (overlap ≥ 50 %, same type and page: `120 KT` read `120 kt`) | one `incertain` element whose cause holds both versions: `lectures divergentes — libelle : A « 120 KT » ≠ B « 120 kt »`; neither is chosen |
|
|
289
|
+
| **seul** | carried by one reading only | `incertain` (`lu dans la lecture B seulement, troisième regard non fait`) until the third look rules on it (see `ref analyse`) |
|
|
290
|
+
| **silence** | a question, in either reading | gathered (one question once), never sent to a third look and not counted below: a silence is not a reading that someone else contradicts |
|
|
291
|
+
|
|
292
|
+
More than **30 %** of the paired-or-single elements unpaired (silences left out, `--seuil` changes it, in percent) means the two readings do not describe the same document: no reconciliation, the question goes to the lead (exit 1, nothing written).
|
|
293
|
+
The ids of the result are renumbered `<slug>#<type>-<n>` (reading A in its order, then what B alone carries) and the references (`composant.ecran`, `etat.cible`, `statut.couvre`) follow; an element that referred to a discarded one is discarded with it, **except a paired element** (both readings carry it): it holds while one of its two versions points to a kept element, and is then `incertain` with the cause when only one version does; it is discarded only when both versions point to discarded elements (see `ref analyse`, « Reconciliation »).
|
|
294
|
+
|
|
295
|
+
```
|
|
296
|
+
$ cadence ref diff a.json b.json --out inventaire.json
|
|
297
|
+
concordants : 31 · divergents : 2 · seuls : 3 (A : 1, B : 2) · silences : 9
|
|
298
|
+
non appariés : 8.3 % (seuil 30 %)
|
|
299
|
+
divergent : texte p.2 : libelle : A « 120 KT » ≠ B « 120 kt »
|
|
300
|
+
seul (B) : composant p.1 : bouton|Layers
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
`--out` writes the reconciled inventory (genre `inventaire`, valid for `ref check`). Exit codes: **0** reconciled, **1** too many unpaired elements, **2** refusal (wrong call, unreadable or invalid file, not a reading, two documents, bad `--seuil`).
|
|
304
|
+
|
|
305
|
+
## `cadence ref analyse <document.pdf> [--sections 3-5,9] [--slug name] [--model sonnet|opus|haiku] [--model-b sonnet|opus|haiku] [--seuil 30] [--double]`
|
|
306
|
+
|
|
307
|
+
The chain: `add`, then **one reading** (one session of the [`reference-analyst`](../agents/reference-analyst.md) agent, `lectures/a.json`), checked by the program. `--double` adds the **double reading** of the design (§3): two independent readings, `ref diff` by program,
|
|
308
|
+
a **third look** at what only one reading carries, and the reconciled inventory.
|
|
309
|
+
|
|
310
|
+
**The double reading is an option, not the default, because its measurement did not show a gain.** On the synthetic corpus (7 cases, one draw per case) it gives the same recall as the single reading (83 %), a **higher** rate of false « read » (50.7 % against 37.7 % for reading A alone), the same
|
|
311
|
+
three misses and **2.8 times the tokens** (63 250 per page against 22 375), with errors that are correlated between the two readings (hypothesis H1 not met). The design is explicit: a version that raises the rate of false « read » or lowers the recall of the `precise` links does not ship as the default.
|
|
312
|
+
`--model-b` and `--seuil` are accepted with `--double` only (exit 2 otherwise). The figures and their limits: [`docs/mesures/ref-double-lecture-2026-10-25.md`](mesures/ref-double-lecture-2026-10-25.md) (« Lecture des chiffres », conclusion at the end).
|
|
313
|
+
|
|
314
|
+
**Single reading (default).** One fresh session of `reference-analyst`, on `--model` (default `sonnet`), writes `lectures/a.json`; the program reads the file itself (below). The `lectures/b.json` and `inventaire.json` of an earlier `--double` pass are removed first: they would not match the new `a.json`.
|
|
315
|
+
|
|
316
|
+
**Two readings (`--double`).** Two fresh sessions of the [`reference-analyst`](../agents/reference-analyst.md) agent (`claude -p`, the review effort and the permission mode of `orchestrate` in `cadence.yaml`, a working directory that is the
|
|
317
|
+
document folder) run together: reading **A** on `--model` (default `sonnet`), reading **B** on `--model-b` (default `opus`: another model decorrelates the errors, hypothesis H1). Each agent looks at every rendered page whole,
|
|
318
|
+
then every zone at full resolution, measures with `cadence ref measure`, copies every text verbatim, links every figure to the passages that cite it (`confirme`, `precise`, `contredit`), writes what the document does not show as a `silence`,
|
|
319
|
+
marks `incertain` (with its cause) what it cannot read for sure, and writes **`<references.dir>/<slug>/lectures/a.json`** (resp. `b.json`): a reading (`genre: "lecture"`) in the format of
|
|
320
|
+
[`templates/inventaire.json`](../templates/inventaire.json), validated by `cadence ref check` before it hands back. The two briefs are the same text, the file to write apart; neither names the other reading, an expected inventory or a corpus,
|
|
321
|
+
and the agent is told never to open another file of `lectures/`. The sessions need `claude` on the `PATH` (or `CADENCE_CLAUDE_BIN`) and the system tools of `ref add`.
|
|
322
|
+
|
|
323
|
+
**The program does not trust the reports.** For each reading it reads the file itself: it must exist (the ones of an earlier run, `a.json`, `b.json` and `inventaire.json`, are removed before the sessions start), pass `ref check`, be a `lecture`
|
|
324
|
+
and carry the `slug` and `sha256` of the document that was read, never another (a reading of two versions mixed is refused). It then writes **`usage`** into each reading, `{ tokens, modele, session }`, `tokens` being the input, cache-write
|
|
325
|
+
and output tokens of the session (the count of the orchestrate budget; cache reads are left out), which the agent never writes.
|
|
326
|
+
|
|
327
|
+
**Reconciliation.** [`ref diff`](#cadence-ref-diff-lecture-ajson-lecture-bjson---out-inventairejson---seuil-30) pairs the two readings. More than 30 % of unpaired elements (`--seuil`, in percent): no reconciliation, exit 1, the question to the lead
|
|
328
|
+
(the two readings stay in `lectures/`, `cadence ref diff` compares them again). Otherwise:
|
|
329
|
+
|
|
330
|
+
- **concordant** elements become one `lu` (or `mesure`) element; **divergent** ones are `incertain` with both versions in the cause, **never chosen**;
|
|
331
|
+
- the elements **only one reading carries** go to the **third look**: one session of the [`reference-verifier`](../agents/reference-verifier.md) agent (read-only: `Read` and `Bash` to measure; same model as reading A) that sees **only those elements**, each with the
|
|
332
|
+
rendered page and a **crop** of its zone (`crops/regard-<n>.png`, the zone and 24 px around it; no crop when the page is not rendered, the brief then says so), and answers `confirme` or `ecarte` with a reason. **Confirmed**: the element keeps its confidence
|
|
333
|
+
(`mesure` stays `mesure`, `lu` stays `lu`, a doubt stays a doubt); **discarded**: it disappears, with what only held through it (a state of a discarded component, a badge that covers nothing any more). A paired element (both readings carry it) holds as long as **one** of its two versions points to kept elements: when only one version pointed to a discarded element (a reading that cut a second screen wrongly and attached its components to it), the element stays, attached as the other version has it, and is `incertain` with the cause (`rattachement : la lecture A le rattachait à un élément écarté…`); it disappears only when both versions point to discarded elements. A verdict without a reason, an unknown verdict or a number that is not
|
|
334
|
+
in the list counts as **no answer**: the element stays `incertain` (`troisième regard sans réponse`), never a `lu` by default. No element carried by one reading only: no third look, no session;
|
|
335
|
+
- the **silences** of both readings are gathered, once per question, and never sent to a third look.
|
|
336
|
+
|
|
337
|
+
The result is **`<references.dir>/<slug>/inventaire.json`**: `genre: "inventaire"`, valid for `ref check`, ids renumbered, `usage` = `{ tokens, lectures: { a, b, regard } }` (the total of the three sessions and each one's tokens and model, what `ref eval` reads for the tokens per page)
|
|
338
|
+
and `reconciliation` = the counts, the unpaired ratio and, for each element the third look ruled on, `{ lecture, id (in its reading), verdict, raison }`.
|
|
339
|
+
|
|
340
|
+
A session cut by a signal with nothing written is started again once in a fresh session (like a review); cut twice, it is a failure (exit 2). Without `--double` the single reading is written to `lectures/a.json` and checked as above; `--model-b` and `--seuil` are refused then (exit 2).
|
|
341
|
+
|
|
342
|
+
**Declared ceiling: 20 pages per reading** (`LECTURE_PAGES_MAX`, design §5 « Taille »). With `--sections`, the pages read are those of `--sections` plus the pages of the figures they cite: the pages an
|
|
343
|
+
earlier `add` of the same document rendered stay on disk but are **not** read, so choosing fewer pages with `--sections` works under the same slug. Without `--sections`, every rendered page is read (the whole document when it
|
|
344
|
+
has 30 pages or fewer, else the pages an earlier `add` rendered). More than 20 pages to read is refused before any session (exit 2, the count and the command `cadence ref analyse <document> --slug <slug> --sections 3-12`), and so is a large document with no
|
|
345
|
+
`--sections` and no page rendered. Splitting into several pairs of readings is not done here.
|
|
346
|
+
|
|
347
|
+
A session cut by a signal and started again is counted in full: its tokens (read back from its Claude Code journal, as `orchestrate` does) are added to those of the fresh one, and the half-written reading of the cut session is removed before the fresh one starts.
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
$ cadence ref analyse norme.pdf --sections 4-9 --double
|
|
351
|
+
norme : norme.pdf
|
|
352
|
+
pages : 120
|
|
353
|
+
rendues : 8 (4, 5, 6, 7, 8, 9, 33, 34)
|
|
354
|
+
…
|
|
355
|
+
norme : double lecture (A sonnet, B opus) — 8 pages lues (plafond d'une lecture : 20)
|
|
356
|
+
lectures : ~/.local/share/cadence/references/norme/lectures/a.json, ~/.local/share/cadence/references/norme/lectures/b.json
|
|
357
|
+
réconciliation : concordants 31 · divergents 2 · seuls 3 · silences 9 — non appariés 8.3 % (seuil 30 %)
|
|
358
|
+
troisième regard (sonnet) : 2 confirmés, 1 écarté, 0 sans réponse
|
|
359
|
+
inventaire : ~/.local/share/cadence/references/norme/inventaire.json
|
|
360
|
+
éléments : 44 (mesure : 6, lu : 27, incertain : 11)
|
|
361
|
+
tokens : 520000 (65000 par page, 8 pages lues) — A : 190000, B : 250000, troisième regard : 80000
|
|
362
|
+
question : Que veut dire « Figure 1 » ?
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
The last lines are one `question :` per distinct question of the agents (a `contredit`, an `incertain`). Exit codes: **0** done, **1** a refused reading (no file, `ref check` deviations, wrong genre, wrong document: one
|
|
366
|
+
`✗ lecture A : <reason>` line per deviation then `N écart(s)` on the standard output, the file is left as written, no `usage` is added) or too many unpaired elements, or the third look discarding every element (all of them were carried by one reading only: nothing is left to write, no inventory, the readings stay, a question to the lead), **2** refusal (unknown `--model` or `--model-b`, no page or more than 20 to read, tool or file as for `add`, a session that
|
|
367
|
+
failed: `la session de lecture a échoué : <cause>`), **3** quota reached (message on the error output, no inventory; the readings already written stay; run it again later). The tokens per page of the output divide by the pages **read**; `ref eval` divides by the `pages` of the expected inventory,
|
|
368
|
+
the same number for a corpus case read whole. Without `--double` the output is the one of lot 5: `<slug> : lecture unique (<model>) — …`, `lecture : <file>`, `éléments : …`, `tokens : …`.
|
|
369
|
+
|
|
370
|
+
### Reference measure on the corpus
|
|
371
|
+
|
|
372
|
+
`docs/mesures/ref-lecture-unique-2026-10-24.md` states what the single reading is measured on and with which commands (recall, false « read », tokens per page against the corpus of `ref corpus`, the declared ceiling), and what was measured.
|
|
373
|
+
The double reading is measured the same way, `ref eval` on `inventaire.json` instead of `lectures/a.json`, and compared with that baseline: `docs/mesures/ref-double-lecture-2026-10-25.md` (hypothesis H1, the stopping point of lot 6: not met, which is why `--double` is an option).
|
|
374
|
+
|
|
375
|
+
## `cadence ref corpus <dossier> [--sans-rendu]`
|
|
376
|
+
|
|
377
|
+
Writes the **synthetic corpus with a known truth** that `ref eval` scores against (design §« Évaluation »): seven small documents,
|
|
378
|
+
one per trap taken from a real defect, each with the inventory that is true of what is drawn.
|
|
379
|
+
|
|
380
|
+
| Case (= trap) | What it draws | Expected `piege` element |
|
|
381
|
+
|---|---|---|
|
|
382
|
+
| `texte-ambigu-leve-par-figure` | « written beside the arrow » (head or tail?), the figure puts `120 KT` over the tail | `lien` `precise` |
|
|
383
|
+
| `figure-contredit-texte` | text says 80 kt, the figure draws the threshold at 100 kt | `lien` `contredit` |
|
|
384
|
+
| `table-en-image` | a code table rasterised at render time: its cells are not in the PDF text layer | `table` |
|
|
385
|
+
| `gabarit-type-bufr` | BUFR section 1: ordered fields, mandatory or optional, format, bounds | `gabarit` |
|
|
386
|
+
| `controle-translucide` | a white button at 25 % opacity on a striped gradient, next to an opaque one | `jeton` `opacite` |
|
|
387
|
+
| `page-proposal` | page 1 requirements, page 2 a panel mock-up carrying a « Proposal » badge; two rows of the panel are drawn selected and greyed (`etat` `selectionne`, `desactive`), and the caption confirms the requirement (`lien` `confirme`) | `statut` |
|
|
388
|
+
| `scan-bruite` | a station sheet rasterised, grainy and blurred: the PDF has no text layer, expected texts are `ocr` | `texte` (`ocr`) |
|
|
389
|
+
|
|
390
|
+
Each case folder holds `document.html` (one 8.5×11 in `section.page` per page, deterministic), `attendu.json` (an inventory that
|
|
391
|
+
passes `ref check`, slug `corpus-<case>`, `sha256` of the `document.pdf` once rendered (of the HTML with `--sans-rendu`, which writes no PDF), `pages`, zones in pixels at 200 dpi, `piege` on the trap elements), and,
|
|
392
|
+
unless `--sans-rendu`, `document.pdf` and `page-<n>.png` (1700×2200, 200 dpi) written by **Playwright** (Chromium). Texts of a table,
|
|
393
|
+
a template or a schema belong to it and are not listed as `texte`; labels of a figure are.
|
|
394
|
+
|
|
395
|
+
**One convention for the labels** (what a faithful reading must find, so that `ref eval` does not count it as a faux lu): every
|
|
396
|
+
visible text outside a table or a template is an expected `texte`, with its role, **including the label of a component**: the
|
|
397
|
+
button `Layers` is a `composant` (`bouton`, `contenu: "Layers"`) **and** a `texte` (`bouton`, `libelle: "Layers"`), the rows `Wind`
|
|
398
|
+
and `Waves` of the panel are `case_a_cocher` components and `case_a_cocher` texts, the `Proposal` badge is a `statut` and a `badge`
|
|
399
|
+
`texte`. The tests check it both ways: every label of the expected inventory is drawn, and every drawn text (the HTML, and the
|
|
400
|
+
words of `pdftotext` once rendered) has an expected `texte`. Playwright is not a dependency of cadence:
|
|
401
|
+
install it (`npm i -D playwright`, `npx playwright install chromium`) or point `CADENCE_PLAYWRIGHT` to the folder of the package;
|
|
402
|
+
without it, or when Chromium does not launch (`npx playwright install chromium` missing), the command exits **2** and writes nothing (`--sans-rendu` still writes HTML and expected files). An existing folder is
|
|
403
|
+
refused (exit 2). The corpus is written where you say, not in `evals/`, which `claude plugin eval` reads as case folders.
|
|
404
|
+
|
|
405
|
+
The tests of the real render (PDF and PNG sizes, page counts, hash, zones of the texts against `pdftotext -bbox`) run only when
|
|
406
|
+
`CADENCE_PLAYWRIGHT` points to the package; `.github/workflows/tests.yml` installs Playwright and Chromium and sets it. Locally:
|
|
407
|
+
`CADENCE_PLAYWRIGHT=<folder of the playwright package> npx vitest run test/ref-corpus.test.ts`.
|
|
408
|
+
|
|
409
|
+
The PDF changes at every render, so the expected `sha256` is the one of the PDF just written: register it with the slug of the
|
|
410
|
+
expected file (`cadence ref add tmp/corpus-ref/<case>/document.pdf --slug corpus-<case>`), or `ref eval` refuses the reading.
|
|
411
|
+
|
|
412
|
+
```
|
|
413
|
+
$ cadence ref corpus tmp/corpus-ref
|
|
414
|
+
$ cadence ref eval tmp/corpus-ref lectures/ # lectures/<case>/lecture.json
|
|
415
|
+
```
|
package/docs/releasing.md
CHANGED
|
@@ -7,11 +7,11 @@ A version exists in three places and is published in two; a release does all of
|
|
|
7
7
|
1. Bump `version` in `package.json` (then `npm install` to refresh `package-lock.json`),
|
|
8
8
|
`.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json`, and write the version's section of
|
|
9
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 «
|
|
11
|
-
|
|
10
|
+
only those files** (the version fields and the CHANGELOG, nothing else in the manifests, `docs/whats-new.md`: add the version to its « In two lines » list and its
|
|
11
|
+
long form (the README no longer carries a « What's new » section, L326)). Such a commit is
|
|
12
12
|
exempt from the code-review gate like a plan commit: it closes the lot after its review, and `raf check`
|
|
13
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
|
|
14
|
+
summary (`docs/whats-new.md`) is ordered by version, a number known only at the release and shared by several lots: write it
|
|
15
15
|
in that commit, not before the review. A commit that touches any other file
|
|
16
16
|
— or another field of a manifest, or a dependency in `package-lock.json` — is work like any other and has
|
|
17
17
|
to be reviewed.
|
package/docs/session.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# session
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
cadence session start # notes from the last close, lots in progress (silent ones flagged),
|
|
6
|
+
cadence session start # notes from the last close, lots in progress (commit count, `0 commit` included, and last activity; silent ones flagged),
|
|
7
7
|
# work done since yesterday by lot, drift, repo state, 3 proposals
|
|
8
8
|
cadence session start --since "3 days ago" --idle 2
|
|
9
9
|
cadence session close # commits by lot since the last `session start`,
|
|
@@ -35,7 +35,7 @@ ouverture`, then the lines as written, blank ones dropped), so `session-close` c
|
|
|
35
35
|
them without running `session start` again.
|
|
36
36
|
|
|
37
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
|
|
38
|
+
`.cadence/raf.yaml`, `docs/plan/raf.yaml`, or a `cadence.yaml` with `plan:` — and never enters a project
|
|
39
39
|
to look for another. `--since` and `--idle` go to every project; an error in one
|
|
40
40
|
project is printed in its section and the others still run. It replaces the shell
|
|
41
41
|
loop over the sub-folders. A project that is not the root of its own git repository gets a `✗` line
|
package/docs/skills.md
CHANGED
|
@@ -40,7 +40,7 @@ repository with `cadence skills install` (to `.claude/skills/cadence-*` and
|
|
|
40
40
|
one project at a time; a delivery that changes what a page shows or what it is
|
|
41
41
|
served is then checked in the running app by the `qa-reviewer` agent, whose
|
|
42
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
|
|
43
|
+
subagents as the session cap at most (2 by default, `CADENCE_MAX_SESSIONS`), the ones it starts by hand declared with `cadence lead hold`, never two in the same repository. The whole flow is drawn in
|
|
44
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
45
|
[docs/fonctionnement.md](fonctionnement.md).
|
|
46
46
|
- **ux-reviewer** (agent): captures at 1440 and 390 px, findings grounded in a
|
|
@@ -48,7 +48,7 @@ repository with `cadence skills install` (to `.claude/skills/cadence-*` and
|
|
|
48
48
|
`raf add --parent` sub-tasks, and a one-line verdict for `raf ux`. It never
|
|
49
49
|
edits code. Read-only for real: its `tools:` list is `Read, Grep, Glob, Bash` and the
|
|
50
50
|
Playwright tools (`mcp__playwright`, and `mcp__plugin_playwright_playwright` when the
|
|
51
|
-
browser comes from the Playwright plugin) — no `Edit`, no `Write`.
|
|
51
|
+
browser comes from the Playwright plugin) — no `Edit`, no `Write`. In a wave it gives its captures the absolute path of the capture directory its brief names (a bare name would land in the repository); outside a wave, a path under `.playwright-mcp/` (e.g. `.playwright-mcp/page-home.png`; the Playwright MCP resolves a bare file name against the repository, where it would land at the root); `qa-reviewer` follows it too.
|
|
52
52
|
- **code-reviewer** (agent): any stack; given a repository and a lot id, it reads
|
|
53
53
|
the diff itself from the commits that cite the lot — not the author's summary —
|
|
54
54
|
and the project's CLAUDE.md, when there is one, for its conventions; findings grounded in a
|
|
@@ -58,6 +58,25 @@ repository with `cadence skills install` (to `.claude/skills/cadence-*` and
|
|
|
58
58
|
verdict for `raf review`. It takes the lot's commits from `raf commits`, never
|
|
59
59
|
runs a build whose output is used live, and never edits code. A README or usage
|
|
60
60
|
documentation that does not follow the lot's change is a *major* finding.
|
|
61
|
+
- **doc-keeper** (agent, L306): any stack; given a repository and a lot id, it reads the diff of the lot and the
|
|
62
|
+
project's map of documents (`docs.sync` of `cadence.yaml`, README, `docs/`, CHANGELOG, news entries), says which
|
|
63
|
+
documents must change and where, then updates them in a writing session (explicit paths, `docs(<lot>): …`) or
|
|
64
|
+
only lists them in a read-only one. `cadence orchestrate` calls it before the review when `docs.sync` reports a
|
|
65
|
+
document behind the lot; the lead calls it by hand. A document outside the repository only when the project's
|
|
66
|
+
`cadence.yaml` names it (`docs.articles`): the agent then proposes a lot for that repository's plan and never writes it
|
|
67
|
+
([news](news.md#the-librarian-doc-keeper)).
|
|
68
|
+
- **reference-analyst** (agent, L265): given the folder of a document registered by `cadence ref add` and the file to
|
|
69
|
+
write, it looks at every rendered page whole, then every zone at full resolution, measures with `cadence ref measure`
|
|
70
|
+
(never by eye), copies every text verbatim, links each figure to the passages that cite it and writes one reading in
|
|
71
|
+
the format of `templates/inventaire.json`, validated by `cadence ref check`; what it cannot read for sure is
|
|
72
|
+
`incertain` with its cause, what the document does not show is a `silence`. Its tools are `Read`, `Write`, `Bash`,
|
|
73
|
+
`Grep`, `Glob`: it writes only its reading, never the tokens (the program counts them), never an expected inventory, and it never opens
|
|
74
|
+
another file of `lectures/` (L266: with `--double`, `cadence ref analyse` launches it twice, readings A and B, which must stay independent).
|
|
75
|
+
`cadence ref analyse` launches it ([ref](ref.md#cadence-ref-analyse-documentpdf---sections-3-59---slug-name---model-sonnetopushaiku---model-b-sonnetopushaiku---seuil-30---double)).
|
|
76
|
+
- **reference-verifier** (agent, L266): the third look of `cadence ref analyse`. It receives only the elements that one of the two readings wrote and the
|
|
77
|
+
other did not, each with the rendered page and a crop of its zone, and answers `confirme` or `ecarte` with a reason, measuring with
|
|
78
|
+
`cadence ref measure` rather than by eye and never guessing (what it cannot tell is `ecarte`). Its tools are `Read` and `Bash`: it writes nothing and never sees the readings
|
|
79
|
+
([ref](ref.md#cadence-ref-analyse-documentpdf---sections-3-59---slug-name---model-sonnetopushaiku---model-b-sonnetopushaiku---seuil-30---double)).
|
|
61
80
|
- **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
81
|
optionally a lot id, to walk only the pages it touched — those that call the
|
|
63
82
|
changed endpoints, those of the screens it changed, the pages that consume the services the lot changed,
|
package/docs/spec.md
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
`cadence spec check` prints the same summary line for each kind (`N cas, N règles (N hypothèses), N contrats, N données` for a back-end sheet) and keeps its exit codes: 0 valid, 1 violations, 2 usage.
|
|
28
28
|
|
|
29
|
-
`cadence spec reseal <lot> <test> --reason texte` is the lead's way to correct one sealed acceptance test of the lot in progress that contradicts its sheet (unchanged, or amended by commits of the lot, L217; of a delivered lot, also by commits of another delivered lot, L229) (of a delivered lot: add `--porteur <lot in progress>`), see [The accept step](orchestrate.md#the-accept-step-red-acceptance-tests-and-their-lock).
|
|
29
|
+
`cadence spec reseal <lot> <test> --reason texte` is the lead's way to correct one sealed acceptance test of the lot in progress that contradicts its sheet (unchanged, or amended by commits of the lot, L217; of a delivered lot, also by commits of another delivered lot, L229) (of a delivered lot: add `--porteur <lot in progress>`); refused while a wave of the repository is running, or a wave that is not `done` keeps open (question waiting, suspended, queued) any lot of this repository still `doing` in its plan, the resealed lot or another (L238: one error, also when a live wave holds the lock, names each wave (live ones to wait for), its launch folder and, for each stopped wave, the single `cd <folder> && cadence orchestrate --resume --wave <wave> --drop <project>:<lot> --drop …` that closes all its open lots of the repository, the queued ones that are not `doing` in the plan included (L239); a lot `done` or absent in the plan never refuses), see [The accept step](orchestrate.md#the-accept-step-red-acceptance-tests-and-their-lock).
|
|
30
30
|
|
|
31
31
|
`cadence spec qa <fiche.yaml>` derives from a valid sheet the section of `docs/qa/expectations.md` for its screen and prints it on the standard output
|
|
32
32
|
(it never writes the file: you paste the section, and the lead commits it like the rest of the plan files). A sheet with violations prints them on the
|
package/docs/stabilite.md
CHANGED
|
@@ -8,17 +8,17 @@ From 1.0.0 cadence follows [semantic versioning](https://semver.org): what is li
|
|
|
8
8
|
**Guaranteed**
|
|
9
9
|
|
|
10
10
|
- **Commands and options** of `raf` and `cadence` (`cadence raf …` is `raf …`): `init`, `add`, `start`, `done`, `drop`,
|
|
11
|
-
`note`, `did`, `public`, `screen`, `spec`, `ux`, `review`, `commits`, `show`, `list`, `now`, `ignore`, `check`, `gantt`, `hook`;
|
|
11
|
+
`note`, `did`, `public`, `screen`, `spec`, `visible`, `ux`, `review`, `commits`, `show`, `list`, `now`, `ignore`, `check`, `gantt`, `hook`;
|
|
12
12
|
`cadence news`, `session` (`start`, `close`, `next`, `context`), `lead tour`, `corrections`, `deliver`, `verify`, `orchestrate`,
|
|
13
13
|
`skills`, `spec` (`cadence spec <lot> on|off` is `raf spec`; `check`, `qa`: exit **0** when the sheet is valid and the section is printed, **1** with violations, **2** on a missing or unreadable file or a wrong usage);
|
|
14
14
|
their options and exit codes as the pages [raf](raf.md), [orchestrate](orchestrate.md), [deliver](deliver.md), [spec](spec.md), [news](news.md), [session](session.md), [lead](lead.md), [corrections](corrections.md) and [skills](skills.md) document them. A new command or option is a minor change.
|
|
15
15
|
- **The keys of `cadence.yaml`**: `plan`, `news`, `hook`, `session`, `deliver`, `orchestrate`, `docs`, `qa`, `priority`, `depth`, `lead` (`lead.ux`)
|
|
16
|
-
and the keys each of them takes. A key is not renamed nor removed, nor does its meaning change; a new key is a minor change.
|
|
17
|
-
- **The plan file** (`docs/plan/raf.yaml`): `project`, `prefix`, `since`, `ignore`, `lots` (with their
|
|
16
|
+
and the keys each of them takes (`docs`: `sync`, `since`, `articles`; `docs.articles` names both the article refreshed after a delivery and the outside documents the `doc-keeper` agent proposes lots for). A key is not renamed nor removed, nor does its meaning change; a new key is a minor change.
|
|
17
|
+
- **The plan file** (`.cadence/raf.yaml`, or the legacy `docs/plan/raf.yaml`): `project`, `prefix`, `since`, `ignore`, `lots` (with their
|
|
18
18
|
fields, `tasks`, `notes`, `repos`) and `acknowledged`, and the plan formats `plan:` in `cadence.yaml` can read.
|
|
19
19
|
The `version` key is kept in the file but ignored (`src/plan.ts` does not read it): it is not a schema version.
|
|
20
20
|
- **The names of the skills** (`session-start`, `session-close`, `deliver`, `lead`) **and of the agents**
|
|
21
|
-
(`ux-reviewer`, `code-reviewer`, `qa-reviewer`).
|
|
21
|
+
(`ux-reviewer`, `code-reviewer`, `qa-reviewer`, `doc-keeper`).
|
|
22
22
|
|
|
23
23
|
**Not guaranteed** (may change in any release)
|
|
24
24
|
|
package/docs/whats-new.md
CHANGED
|
@@ -2,7 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
# What's new, version by version
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## In two lines
|
|
6
|
+
|
|
7
|
+
- **1.10.0**: the worktree mode of `cadence orchestrate` needs only the `orchestrate.worktrees` key and is on for cadence itself; the gate plays `orchestrate.build` before the tests, and `lead tour` flags a missing `orchestrate.test`.
|
|
8
|
+
A lot waiting for a slot obeys `--drop` and `--stop-after-current`, the pre-check is back on Sonnet, `cadence perf` classes red deliveries, and the README is a short home page again.
|
|
9
|
+
- **1.9.0**: the plan lives at `.cadence/raf.yaml` (`raf migrate`); `cadence ref` reads reference documents; `doc-keeper` agent, `orchestrate.testGate`, `cadence lead hold` shown by `cadence-hud`.
|
|
10
|
+
- **1.8.0**: `cadence perf` shows the speed of the workflow next to its quality (cost in euros per delivered lot, red deliveries, blocking QA findings), and `cadence lead tour` opens with a perf header.
|
|
11
|
+
- **1.7.0**: `cadence orchestrate` no longer replays `accept` on a green sealed acceptation and refuses `--resume --dry-run`; `spec reseal --porteur` accepts a sheet amended by a delivered lot; the README becomes a short home page.
|
|
12
|
+
- **1.6.0**: the mockup review sweeps everything in its first report and runs up to `orchestrate.maquetteReviews` times (3 by default); the acceptance lock names the first offending commit.
|
|
13
|
+
- **1.5.1**: publishes 1.5.0 (tagged, never published): one UX review per lot, replay of a lot handed back for its budget, a self-check list in the briefs, a `tests.yml` workflow.
|
|
14
|
+
- **1.5.0**: `gate: { count: N, … }` makes a lot wait for N done lots of a kind; `raf todo <id>` puts a started lot without work commits back to `todo`.
|
|
15
|
+
- **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.
|
|
16
|
+
- **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.
|
|
17
|
+
- **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.
|
|
18
|
+
- **1.1.0**: the spec step of `cadence orchestrate`: screen sheet, reviewed mockup, red locked acceptance tests, and briefs that carry rule → test → green.
|
|
19
|
+
- **1.0.0**: the first major release, a stable contract that follows semantic versioning; the [stability page](stabilite.md) lists what is guaranteed.
|
|
20
|
+
|
|
21
|
+
<details>
|
|
22
|
+
<summary>Older versions (0.10.0 to 0.28.0)</summary>
|
|
23
|
+
|
|
24
|
+
Each is a paragraph in [docs/whats-new.md](whats-new.md) and a full section in [CHANGELOG.md](../CHANGELOG.md): `cadence-hud` (0.12.0 to 0.25.0), `cadence orchestrate --continue` and `--status --watch`, `cadence lead tour`, `hook.autostart`, `docs.sync` and `docs.articles`, neighbouring repositories, `raf ignore`.
|
|
25
|
+
|
|
26
|
+
</details>
|
|
27
|
+
|
|
28
|
+
## Version by version
|
|
29
|
+
|
|
30
|
+
The long form of « In two lines » above (the README no longer carries a « What's new » section since L326: it links here). The full history, with the date of each version, is in [CHANGELOG.md](../CHANGELOG.md).
|
|
31
|
+
|
|
32
|
+
**1.10.0**: the worktree mode of `cadence orchestrate` (one git worktree per lot, independent lots of one repository in parallel) is no longer behind `CADENCE_EXPERIMENTAL_WORKTREES=1`: the `orchestrate.worktrees` key alone is the switch, on start and on `--resume`, `--integrate`, `--replay` and `--continue`, and cadence's own `cadence.yaml` turns it on after the trials L310 and L316 (L320); a red at the integrated tip is played once more before the lot is handed back, and the refusal names the red tests (L328); a union of the `CHANGELOG.md` entries of parallel lots, which accepts that a lot rewrites its own entry (L314, L323), and a kept branch recovered without the pre-check (L311). The gate of the wave plays `orchestrate.build` before `orchestrate.test`, a red build handing the lot back as a « build » finding (L333); `cadence lead tour` and `cadence orchestrate --dry-run` flag a project without `orchestrate.test` and name the probable command (L327). The pre-check is back on Sonnet in cadence's own configuration after the local model failed on about one lot in three, skips a lot created after the last code commit of the repository, and `cadence perf` measures it per lot (L322, L328). A lot waiting for a session slot obeys `--drop` and `--stop-after-current` (L332); `--resume` without a wave resumes the only unfinished one and is refused when several are (L309). `cadence perf` classes the red deliveries written before the class from their text (L331) and names the step that carries a rise of the tokens per lot (L312). `npm run service` purges the old copies put in service (L330), `cadence deliver` keeps a Ctrl-C (L325, L329), and `raf docs-ok` acknowledges a `docs.sync` gap (L317); `raf check` no longer reports two false drifts (L321). `cadence ref analyse` reads a reference document, `cadence ref diff` reconciles two readings and `--double` reads twice, an option (L265, L266); `cadence ref add` cites a range of figures and no longer reads « code figure n » as a citation (L274, L313); a failing PDF tool is a refusal, not a stack trace (L275). The README is a short home page again, the detail having moved to `docs/overview.md` (L326). Details: [CHANGELOG.md](../CHANGELOG.md).
|
|
33
|
+
|
|
34
|
+
**1.9.0**: the default plan is `.cadence/raf.yaml`, a hidden folder git versions and `docs/` never publishes (L246), and `raf migrate [--dry-run]` moves a legacy plan and the readers of the old path (L284, L305); `raf title`, `raf visible`, `uses:` resources shown by `lead tour` and the lot `goal:` (L244, L273, L251–L253, L258). `cadence ref add|measure|check|corpus|eval` registers reference documents outside the repository, measures a rendered zone, validates the inventory schema and scores a reading against a known truth (L261–L264). In `cadence orchestrate`: the `doc-keeper` agent and `docs.articles` (L306, L308), the mechanical `orchestrate.testGate` before the review (L287), `precheck: local` on every lot with no commit (L296), a write-step time limit proportioned to the lot (L298), sessions that no longer hold their slot after their report (L285), the real weekly-limit message recognised (L286), and an experimental worktree mode with `--resume --integrate|--replay` and `--remove-worktree` (L279, L299–L304). `cadence lead hold|release` counts the lead's hand-started sessions, an expired one is flagged by `lead tour`, `--status` and the `cadence-hud` band (0.5.0; L255, L276, L278). `cadence deliver --sha` is accepted while a wave runs (L277), `CADENCE_DEPLOYED_FILE` names the deployed sha (L277, L281) and `deliveries-failed.log` keeps the class and last lines of a red delivery, secrets masked (L282, L289, L294). `cadence perf` breaks red deliveries down and counts the `review-small` UX (L282, L283). Details: [CHANGELOG.md](../CHANGELOG.md).
|
|
6
35
|
|
|
7
36
|
**1.8.0**: `cadence perf [folder] [--since date] [--json]` is the permanent dashboard of the workflow, without a model: the last 7 days against the 7 before, read in `.cadence/runs`, with a `⚠` on a trend or a bottleneck (L225); `perf.prices` prices the lots in euros (L226); `cadence deliver` writes `deliveries-failed.log` and `cadence lead tour` opens with a perf header (L227). The measure of the back-end spec step on 10 lots is in `docs/mesures` (L190). The release was blocked by a test that required an entry under `[Unreleased]` (L235). Details: [docs/perf.md](perf.md).
|
|
8
37
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sylad/cadence",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "A small, repo-native working method: a versioned plan linked to your commits, a changelog with screenshots, session rituals and deliveries proven by their effect.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Sylvain Ladoire",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"docs/deliver.md",
|
|
23
23
|
"docs/spec.md",
|
|
24
24
|
"docs/lead.md",
|
|
25
|
+
"docs/ref.md",
|
|
25
26
|
"docs/stabilite.md",
|
|
26
27
|
"docs/news.md",
|
|
27
28
|
"docs/session.md",
|