@sylad/cadence 1.3.0 → 1.5.1

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.
@@ -12,6 +12,8 @@ export const WORK_SCHEMA = {
12
12
  nonVerifie: strings,
13
13
  questions: strings,
14
14
  choix: strings,
15
+ echecsDeBase: strings,
16
+ nouveauxEchecs: strings,
15
17
  resume: str,
16
18
  },
17
19
  required: ['commits', 'tests', 'build', 'nonVerifie', 'questions', 'resume'],
@@ -89,6 +89,20 @@ export function waveReadsControl(waveDir) {
89
89
  return false;
90
90
  }
91
91
  }
92
+ /**
93
+ * L'instantané de la vague connaît-il `--budget projet:lot=+N` (L223) ? Un instantané plus ancien relit l'argument avec son `parseBudget` et le refuse
94
+ * comme budget invalide. Sans instantané : rien à relire, on suppose que oui.
95
+ */
96
+ export function waveReadsLotBudget(waveDir) {
97
+ if (!snapshotExists(waveDir))
98
+ return true;
99
+ try {
100
+ return readFileSync(join(toolDirOf(waveDir), 'dist', 'orchestrate', 'command.js'), 'utf8').includes('lotBudgets');
101
+ }
102
+ catch {
103
+ return false;
104
+ }
105
+ }
92
106
  /** Relance réelle : un processus node sur la copie, signaux transmis, code de sortie rendu. */
93
107
  export function spawnReexec(toolDir, argv, env, sink) {
94
108
  return new Promise((resolve, reject) => {
@@ -93,6 +93,8 @@ function deliverable(lots, ancestor, fromGit) {
93
93
  }
94
94
  return out;
95
95
  }
96
+ /** Tests déjà rouges au départ listés un par un dans le tableau ; au-delà, un compte. */
97
+ const BASELINE_LISTED = 30;
96
98
  /** Le tableau de fin de vague (ou de `--status`), une ligne par lot puis le total et les questions. */
97
99
  export function renderTable(wave, lots, deps = {}) {
98
100
  const rows = lots.map((l) => [`${l.project}:${l.lot}`, LABEL[l.status], String(l.pass), review(l), ux(l), String(commits(l)), k(counted(l)), `${minutes(l)} min`]);
@@ -121,6 +123,15 @@ export function renderTable(wave, lots, deps = {}) {
121
123
  out.push(`${l.project}:${l.lot} — captures Playwright : ${l.uxCaptures}`);
122
124
  for (const w of l.warnings)
123
125
  out.push(`${l.project}:${l.lot} — ⚠ ${w}`);
126
+ // Ligne de base des tests (L213) : les échecs déjà présents au sha de départ, à part de ceux du lot.
127
+ const base = l.baseline;
128
+ if (base?.failures.length) {
129
+ const where = `${base.sha ? ` (${base.sha.slice(0, 7)}${base.verified ? '' : ', annoncé par la session, non vérifié'})` : ''}`;
130
+ for (const t of base.failures.slice(0, BASELINE_LISTED))
131
+ out.push(`${l.project}:${l.lot} — déjà rouge au départ${where} : ${t}`);
132
+ if (base.failures.length > BASELINE_LISTED)
133
+ out.push(`${l.project}:${l.lot} — déjà rouge au départ${where} : … et ${base.failures.length - BASELINE_LISTED} autre(s)`);
134
+ }
124
135
  for (const x of l.choix ?? [])
125
136
  out.push(`${l.project}:${l.lot} — choix fait : ${x}`);
126
137
  for (const h of l.hypotheses ?? [])
package/dist/plan.js CHANGED
@@ -3,9 +3,10 @@ import { dirname } from 'node:path';
3
3
  import { isMap, isSeq, parseDocument } from 'yaml';
4
4
  import { isDay, toDay } from './dates.js';
5
5
  export const STATUSES = ['todo', 'doing', 'done', 'dropped'];
6
+ export const GATE_INVALID = 'gate invalide : count: entier ≥ 1 et un critère spec: true ou screen: page attendus';
6
7
  export class RafError extends Error {
7
8
  }
8
- export const FIELDS = ['id', 'title', 'status', 'estimate', 'quickwin', 'visible', 'screen', 'spec', 'public', 'every', 'last', 'after', 'created', 'started', 'finished', 'notes', 'repos', 'parent'];
9
+ export const FIELDS = ['id', 'title', 'status', 'estimate', 'quickwin', 'visible', 'screen', 'spec', 'public', 'every', 'last', 'after', 'created', 'started', 'finished', 'notes', 'repos', 'parent', 'gate'];
9
10
  /** Nature de l'écran d'un lot visible : nouvelle page, nouveau composant, parcours modifié. */
10
11
  export const SCREENS = ['page', 'component', 'journey'];
11
12
  export function isOpen(status) {
@@ -398,6 +399,28 @@ export class Plan {
398
399
  if (status === 'done' || status === 'dropped')
399
400
  node.set('finished', today);
400
401
  }
402
+ /**
403
+ * Remet en attente un lot démarré (doing → todo, `started` retiré, note datée) — `raf todo` (L220). Les refus passent dans
404
+ * l'ordre : plan modifiable, lot et non sous-tâche, lot connu, lot doing ; `commits` n'est lu qu'ensuite (il lit git) et un lot
405
+ * qui a du travail est refusé. Les sous-tâches et les autres clés du lot ne bougent pas.
406
+ */
407
+ putBack(ref, today, reason, commits) {
408
+ this.writable();
409
+ if (ref.includes('/'))
410
+ throw new RafError(`raf todo se pose sur un lot, pas une sous-tâche : ${ref}`);
411
+ const lot = this.lot(ref);
412
+ if (lot.status === 'todo')
413
+ throw new RafError(`${ref} est déjà todo`);
414
+ if (lot.status !== 'doing')
415
+ throw new RafError(`${ref} est ${lot.status} ; le rouvrir à la main dans le YAML si c'est voulu`);
416
+ const n = commits();
417
+ if (n > 0)
418
+ throw new RafError(`${ref} a ${n} commit(s) qui le citent : le remettre en attente perdrait leur lien — raf drop ou le laisser doing`);
419
+ const node = this.lotNode(ref);
420
+ node.set('status', 'todo');
421
+ node.delete('started');
422
+ this.note(ref, reason.trim() ? `remis en attente : ${reason.trim()}` : 'remis en attente', today);
423
+ }
401
424
  /** Pose, remplace (texte) ou efface (null) le titre public d'un lot ; la clé suit `title`. */
402
425
  setPublic(ref, text) {
403
426
  this.writable();
@@ -541,6 +564,7 @@ function foreignLots(raw, format) {
541
564
  finished: day('finished'),
542
565
  notes: typeof notes === 'string' ? [{ text: notes }] : notes,
543
566
  repos: pick('repos'),
567
+ gate: pick('gate'),
544
568
  }, problems);
545
569
  const parent = pick('parent');
546
570
  return { lot, parent: parent == null ? undefined : String(parent) };
@@ -559,6 +583,25 @@ function foreignLots(raw, format) {
559
583
  }
560
584
  return lots;
561
585
  }
586
+ /** Lit `gate: { count: N, spec: true }` ou `{ count: N, screen: page }` ; toute autre forme est un problème du lot et une condition jamais remplie. */
587
+ function readGate(raw, problems) {
588
+ if (raw == null)
589
+ return undefined;
590
+ const invalid = () => {
591
+ problems.push(GATE_INVALID);
592
+ return { invalid: true };
593
+ };
594
+ if (typeof raw !== 'object' || Array.isArray(raw))
595
+ return invalid();
596
+ const g = raw;
597
+ if (!Number.isInteger(g.count) || g.count < 1)
598
+ return invalid();
599
+ const criteria = [...(g.spec === true ? ['spec'] : []), ...(g.screen === 'page' ? ['screen'] : [])];
600
+ const others = Object.keys(g).filter((k) => k !== 'count' && k !== 'spec' && k !== 'screen');
601
+ if (criteria.length !== 1 || others.length || ('spec' in g && g.spec !== true) || ('screen' in g && g.screen !== 'page'))
602
+ return invalid();
603
+ return { count: g.count, criterion: criteria[0] };
604
+ }
562
605
  /** Un titre public vide ne dirait rien au public : refusé plutôt qu'écrit. */
563
606
  function cleanPublic(text) {
564
607
  const t = text.trim();
@@ -595,6 +638,7 @@ function normalizeLot(raw, problems = []) {
595
638
  else if (raw.spec !== false)
596
639
  problems.push(`spec : true ou false attendu (reçu « ${String(raw.spec)} »)`);
597
640
  }
641
+ const gate = readGate(raw.gate, problems);
598
642
  return {
599
643
  id: String(raw.id),
600
644
  title: String(raw.title ?? ''),
@@ -604,6 +648,7 @@ function normalizeLot(raw, problems = []) {
604
648
  visible: raw.visible === true,
605
649
  ...(screen ? { screen } : {}),
606
650
  ...(spec ? { spec } : {}),
651
+ ...(gate ? { gate } : {}),
607
652
  ...(typeof raw.public === 'string' && raw.public.trim() !== '' ? { public: raw.public.trim() } : {}),
608
653
  ...(Number.isInteger(raw.every) && raw.every > 0 ? { every: raw.every } : {}),
609
654
  ...(last ? { last } : {}),
package/dist/session.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import { CLEAN_DAYS, scanStale } from './clean.js';
3
3
  import { dueLine, isRecurring, recurringByDue } from './recurring.js';
4
- import { audit, exemptPlanOnly, nextUp, planCommits } from './audit.js';
4
+ import { audit, exemptPlanOnly, gateWaiting, nextUp, planCommits } from './audit.js';
5
5
  import { diffDays, maxDay } from './dates.js';
6
6
  import { repoStatus } from './git.js';
7
7
  import { linkCommits } from './link.js';
@@ -109,7 +109,7 @@ export function sessionStart(ctx, opts) {
109
109
  const lock = lockStatus(ctx.shared);
110
110
  if (lock)
111
111
  out(`\n${lock.line}`);
112
- const { doing, ready } = nextUp(lots);
112
+ const { doing, ready, blocked } = nextUp(lots);
113
113
  out('\nEn cours');
114
114
  if (doing.length === 0)
115
115
  out(' (rien)');
@@ -119,6 +119,7 @@ export function sessionStart(ctx, opts) {
119
119
  const state = last ? `dernière activité ${last}${idle > opts.idle ? `, silencieux depuis ${idle} j` : ''}` : 'aucune activité';
120
120
  out(` ${l.id} ${l.title} (${state})`);
121
121
  }
122
+ section(out, 'En attente', gateWaiting(lots, blocked).map(({ lot, text }) => `${lot.id} ${lot.title} (${text})`));
122
123
  const recent = period(ctx, opts.since);
123
124
  const done = byLotLines(recent);
124
125
  if (recent.orphans.length)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sylad/cadence",
3
- "version": "1.3.0",
3
+ "version": "1.5.1",
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",
@@ -90,12 +90,11 @@ ends `interrupted`, and `--resume` takes it up again. To take a lot out of a wav
90
90
  `--resume --drop <project>:<lot>` (the lot is handed back instead of being replayed). Neither kills a session.
91
91
 
92
92
  `cadence orchestrate --dry-run …` first when a precondition is in doubt. The program, not the lead, runs
93
- for each lot a fresh short session per step — implementation (Sonnet), UX review if the lot is `visible`
94
- and the project declares how to see its app (`orchestrate.ux` in `cadence.yaml`), code review last
93
+ for each lot a fresh short session per step — implementation (Sonnet), code review
95
94
  (Opus, the `code-reviewer` agent; Sonnet, with no pass on the minor findings, for a lot whose estimate is
96
95
  ≤ 0.25 d — `orchestrate.review` in `cadence.yaml`; a blocker or major finding still brings a correction and an
97
96
  Opus review), a correction in a new session if the review is not compliant (two
98
- passes at most, a third when the review converges: blocking + major findings down from one review to the next and only one left) — and records `raf review` itself when the code review is compliant. A lot with `spec: true` (no screen) goes `spec → fiche → accept` before the code: the `code-reviewer` reviews its back-end sheet, and the hypotheses of the final sheet come back in the table as « hypothèse de la fiche » lines, which the lead relays to the human. The state is in
97
+ passes at most, a third when the review converges: blocking + major findings down from one review to the next and only one left), then, once, a UX review if the lot is `visible` and the project declares how to see its app (`orchestrate.ux` in `cadence.yaml`) — and records `raf review` itself when the code review is compliant and the UX review too. A lot with `spec: true` (no screen) goes `spec → fiche → accept` before the code: the `code-reviewer` reviews its back-end sheet, and the hypotheses of the final sheet come back in the table as « hypothèse de la fiche » lines, which the lead relays to the human. The state is in
99
98
  `.cadence/runs/<wave>/`, not in this conversation. `@haiku` only when the human writes it, for a
100
99
  mechanical lot. Exit code: 0 all ready · 1 some lots handed back · 2 refused before acting · 3 wave
101
100
  suspended (budget or usage limit; `--resume --budget …` continues).
@@ -103,7 +102,7 @@ suspended (budget or usage limit; `--resume --budget …` continues).
103
102
  What the orchestrator does **not** do, and stays with the lead: choose the lots (with the human), bring the
104
103
  questions back (`--resume --answer <project>:<lot> "…"`), look at the UX reviewer's captures and record
105
104
  `raf ux` (the orchestrator reports its verdict, it never records it; who decides it is the `lead.ux` setting, section 2c), re-verify (section 3, point 2),
106
- `raf done`, push and deliver. **A locked acceptance test that contradicts the sheet** (the lot is handed back with `verrou des tests d'acceptation`, or the session's question says its own test is wrong, e.g. a regex that rejects a sentence the sheet allows) has a path, and it is the lead's, never a session's: correct the test in the working tree, **the sheet unchanged**, then `cadence spec reseal <lot> <test> --reason "why it contradicts the sheet"` (outside any wave): the program redoes the fingerprint of that one test, writes the reason in `acceptation.json` (`resceaux`) and as a note of the lot, commits both, and the lock keeps everything else. For a **delivered** lot (`vert: true`) whose contract does not change but whose test is unstable, add `--porteur <the lot in progress that carries the fix>`: the commit and the note cite that lot, `vert` stays true (L212). It refuses a lot that is neither in progress nor delivered, a changed sheet and any other listed test touched, and during a wave of that repository. It is atomic (a refused commit restores `acceptation.json` and the test), with a plan kept read-only by another tool it leaves the plan untouched and says a note is to be added by hand, with an untracked plan or one outside the repository it writes the note but does not commit it (`plan à commiter`: do not add it again), and if the commit of the note is refused the reseal stays done and the error says to commit the plan by hand. Do it **between two sessions**, never inside one: a resealed commit that belongs to a session of the wave is not adopted (still a lock violation), and sessions are forbidden the command. Then continue the lot: `--resume --answer` when it waits on a `question`; a new wave `cadence orchestrate <project>:<lot>` when it was handed back (`--resume` skips finished lots). Minor findings and proposed sub-tasks come back in the table: adding them to
105
+ `raf done`, push and deliver. **A locked acceptance test that contradicts the sheet** (the lot is handed back with `verrou des tests d'acceptation`, or the session's question says its own test is wrong, e.g. a regex that rejects a sentence the sheet allows) has a path, and it is the lead's, never a session's: correct the test in the working tree (the sheet is left as it is; if it was amended, **commit it first, citing the lot**: an amended sheet whose every commit cites the lot is accepted, L217, never put it back to the red state), then `cadence spec reseal <lot> <test> --reason "why it contradicts the sheet"` (outside any wave): the program redoes the fingerprint of that one test, writes the reason in `acceptation.json` (`resceaux`) and as a note of the lot, commits both, and the lock keeps everything else. For a **delivered** lot (`vert: true`) whose contract does not change but whose test is unstable, add `--porteur <the lot in progress that carries the fix>`: the commit and the note cite that lot, `vert` stays true (L212). It refuses a lot that is neither in progress nor delivered, a sheet with uncommitted changes or touched by a commit that does not cite the lot, and any other listed test touched, and during a wave of that repository. It is atomic (a refused commit restores `acceptation.json` and the test), with a plan kept read-only by another tool it leaves the plan untouched and says a note is to be added by hand, with an untracked plan or one outside the repository it writes the note but does not commit it (`plan à commiter`: do not add it again), and if the commit of the note is refused the reseal stays done and the error says to commit the plan by hand. Do it **between two sessions**, never inside one: a resealed commit that belongs to a session of the wave is not adopted (still a lock violation), and sessions are forbidden the command. Then continue the lot: `--resume --answer` when it waits on a `question`; a new wave `cadence orchestrate <project>:<lot>` when it was handed back (`--resume` skips finished lots). Minor findings and proposed sub-tasks come back in the table: adding them to
107
106
  the plan is the lead's decision. A minor finding becomes a lot of its own only if it describes an observable bug (a wrong output, a crash, a measured regression); otherwise it stays a note of the originating lot, so that a review never feeds the next one. If an orchestrated wave is running in a repository, do not commit there
108
107
  and do not deliver it (`cadence deliver` refuses).
109
108
 
@@ -7,6 +7,7 @@ Rules:
7
7
  - Every test must FAIL for now, because the feature is missing (not because of a typo or a broken setup): the program runs the dedicated command and refuses tests that pass.
8
8
  - Do not touch the sheet, the plan or any application code. Do not push, deliver, run `raf done`, `raf ux` or `raf review`.
9
9
  - Commit with explicit paths (never `git add -A` or `commit -a`), ONE commit citing the lot (`test({{lot}}): acceptation R1–Rn (rouge)`) with the test files, the acceptation file and the runner configuration, and leave the working tree clean. The program seals the acceptation file afterwards (it adds the fingerprint of each test file): never write `empreintes` or `vert: true` yourself.
10
+ Never run `git checkout` or `git switch` to another commit or branch in this repository: the orchestrator watches it and a moved HEAD breaks the other sessions of the wave. To look at another sha, use a throwaway `git worktree add --detach <tmp> <sha>`, removed afterwards.
10
11
  Decide minor interpretation questions yourself and list each one under "choix" with the alternative you did not take. Leave "questions" empty rather than writing a placeholder such as "no question".
11
12
  {{commits}}
12
13
  {{reponse}}
@@ -7,6 +7,7 @@ Rules:
7
7
  - Every test must FAIL for now, because the feature is missing (not because of a typo or a broken setup): the program runs the dedicated command and refuses tests that pass.
8
8
  - Do not touch the sheet, the mockup, the plan or any application code. Do not push, deliver, run `raf done`, `raf ux` or `raf review`.
9
9
  - Commit with explicit paths (never `git add -A` or `commit -a`), ONE commit citing the lot (`test({{lot}}): acceptation R1–Rn (rouge)`) with the test files, the acceptation file and the runner configuration, and leave the working tree clean. The program seals the acceptation file afterwards (it adds the fingerprint of each test file): never write `empreintes` or `vert: true` yourself.
10
+ Never run `git checkout` or `git switch` to another commit or branch in this repository: the orchestrator watches it and a moved HEAD breaks the other sessions of the wave. To look at another sha, use a throwaway `git worktree add --detach <tmp> <sha>`, removed afterwards.
10
11
  Decide minor interpretation questions yourself and list each one under "choix" with the alternative you did not take. Leave "questions" empty rather than writing a placeholder such as "no question".
11
12
  {{commits}}
12
13
  {{reponse}}
@@ -12,6 +12,7 @@ Fix each minor finding that is right, and nothing else. Rules: test first; commi
12
12
  its tests pass, with explicit paths (never `git add -A` or `commit -a`), and a message that cites the
13
13
  lot (`fix({{lot}}): …`); run the project's full test suite and build before reporting; do not push,
14
14
  deliver, run `raf done`, `raf ux` or `raf review`. Read the project's CLAUDE.md first.
15
+ Never run `git checkout` or `git switch` to another commit or branch in this repository: the orchestrator watches it and a moved HEAD breaks the other sessions of the wave. To look at another sha, use a throwaway `git worktree add --detach <tmp> <sha>`, removed afterwards.
15
16
  Do not stop to ask. A finding that is wrong, or not worth its change, is not fixed: list it under
16
17
  "choix" in your report with the reason — the reviewer re-reads it and the lead sees it. Leave
17
18
  "questions" empty. Making no commit at all is a valid outcome when every finding is rejected.
@@ -12,6 +12,15 @@ Rules: test first; commit each fix as soon as its tests pass, with explicit path
12
12
  `git add -A` or `commit -a`), and a message that cites the lot (`fix({{lot}}): …`); run the project's
13
13
  full test suite and build before reporting; do not push, deliver, run `raf done`, `raf ux` or
14
14
  `raf review`. Read the project's CLAUDE.md first.
15
+ Never run `git checkout` or `git switch` to another commit or branch in this repository: the orchestrator watches it and a moved HEAD breaks the other sessions of the wave. To look at another sha, use a throwaway `git worktree add --detach <tmp> <sha>`, removed afterwards.
16
+ Self-check before handing back (the recurring findings of the reviews), covering only what you changed: go through this list point by point on your own fix commits before you report, and touch nothing else:
17
+ - documentation: the README and the architecture documentation describe the behaviour, updated in the same commits as the behaviour (and the CHANGELOG);
18
+ - tests: one test per rule of the fiche, named « Rn — … »; with no fiche, one test per business rule of the lot, named after it;
19
+ - no dead code, and no test that cannot fail: a test whose assertion is always true, or that does not exercise the rule it names;
20
+ - screens: for a modified screen, the capture due of each state, at 1440 and 390 px, with a relative file name; a lot with no modified screen owes none, and says so;
21
+ - no false comment: a comment, a docstring or a message never describes a behaviour the code no longer has or does not have.
22
+ A point you cannot hold is written under "choix" or "nonVerifie" of your report, not left unsaid.
23
+
15
24
  If a finding is wrong, say so under "choix" with the reason. Ask (under "questions") only when a fix needs a decision that passes the rule below.
16
25
  A question is legitimate only if it names what it would change: the scope of the lot, the architecture, or a costly rollback (data, production, public API);
17
26
  otherwise it is a choice: decide, write the alternative you did not take, go on. Minor choices to settle yourself:
@@ -19,6 +28,7 @@ a spacing, colour or label value when a measurement or a rule justifies it; the
19
28
  a News entry: only if a finding asks for it; a written rule of the project's CLAUDE.md (apply it); who launches the review or UX pass (never the session: the program and the lead do).
20
29
  "not my job to touch the plan" is not a question: say it in the report.
21
30
  Never stop to ask about how to organise your own work (split or squash a commit, order of the sub-parts, whether to continue, "I have no question"): decide, list it under "choix", go on. Leave "questions" empty rather than writing a placeholder such as "no question".
31
+ Tests already red before the lot: if the suite is red, check whether the same tests are red at the sha the lot started from (the parent of the oldest work commit that cites {{lot}}, plan-only commits left out, or the `HEAD` before this session if the lot has none: a throwaway `git worktree add --detach <tmp> <sha>`, removed afterwards). Failures already there are not a defect of this lot: do not try to fix them and do not report your tests as red for them; list their names under "echecsDeBase" in your report (one test per entry, as the runner prints it), list under "nouveauxEchecs" the tests that are red now and were NOT red at that sha (an empty list when there are none: with `vert: false`, a non-empty "echecsDeBase" and an empty "nouveauxEchecs" the lot goes to review without a correction pass; any entry in "nouveauxEchecs" with `vert: false` triggers one), and say under "nonVerifie" if you could not check. The program replays the suite itself and compares to the same baseline.
22
32
  A finding you contest (it describes a state older than the code, or you think it wrong) is not a question and not a reason to stop: do not ask the lead to arbitrate. Write it under "choix" with the evidence (the command, the line, the commit), fix what is right, go on; the next fresh review re-reads it.
23
33
  You are one short session of an orchestrated wave: do not launch subagents (the Agent tool is disabled).
24
34
  Give your final report as the structured output (commits, tests, build, what you could not verify, choices, questions).
@@ -7,7 +7,16 @@ Rules: test first; commit each sub-part as soon as its tests pass, with explicit
7
7
  `git add -A` or `commit -a`), and a message that cites the lot (`feat({{lot}}): …`); run the project's
8
8
  full test suite and build before reporting; do not push, deliver, run `raf done`, `raf ux` or
9
9
  `raf review`.
10
+ Never run `git checkout` or `git switch` to another commit or branch in this repository: the orchestrator watches it and a moved HEAD breaks the other sessions of the wave. To look at another sha, use a throwaway `git worktree add --detach <tmp> <sha>`, removed afterwards.
10
11
  Documentation: the project's README (and its usage documentation) describes the behaviour you deliver, updated in the same commits, like the CHANGELOG — a README that does not follow your change is a major finding of the review.
12
+ Self-check before handing back (the recurring findings of the reviews). Go through this list point by point on your own commits before you report, and fix what is missing:
13
+ - documentation: the README and the architecture documentation describe the behaviour, updated in the same commits as the behaviour (and the CHANGELOG);
14
+ - tests: one test per rule of the fiche, named « Rn — … »; with no fiche, one test per business rule of the lot, named after it;
15
+ - no dead code, and no test that cannot fail: a test whose assertion is always true, or that does not exercise the rule it names;
16
+ - screens: for a modified screen, the capture due of each state, at 1440 and 390 px, with a relative file name; a lot with no modified screen owes none, and says so;
17
+ - no false comment: a comment, a docstring or a message never describes a behaviour the code no longer has or does not have.
18
+ A point you cannot hold is written under "choix" or "nonVerifie" of your report, not left unsaid.
19
+
11
20
  Decide minor interpretation questions yourself (the wording of a message, a name, a default, the
12
21
  reading of an ambiguous line of the lot) and list each one under "choix" in your report, with the
13
22
  alternative you did not take — the reviewer re-reads them. Stop and ask (under "questions") only on a real blocker.
@@ -19,6 +28,7 @@ a written rule of the project's CLAUDE.md (apply it); who launches the review or
19
28
  Never stop to ask about how to organise your own work (split or squash a commit, order of the sub-parts, whether to continue, "I have no question"): decide, list it under "choix", go on. Leave "questions" empty rather than writing a placeholder such as "no question".
20
29
  If the lot's commits already cover its open sub-tasks, do not ask whether to continue: make no commit and say so
21
30
  in your report (the review that follows re-reads those commits). If they do not cover them all, implement the rest.
31
+ Tests already red before the lot: if the suite is red, check whether the same tests are red at the sha the lot started from (the parent of the oldest work commit that cites {{lot}}, plan-only commits left out, or the `HEAD` before this session if the lot has none: a throwaway `git worktree add --detach <tmp> <sha>`, removed afterwards). Failures already there are not a defect of this lot: do not try to fix them and do not report your tests as red for them; list their names under "echecsDeBase" in your report (one test per entry, as the runner prints it), list under "nouveauxEchecs" the tests that are red now and were NOT red at that sha (an empty list when there are none: with `vert: false`, a non-empty "echecsDeBase" and an empty "nouveauxEchecs" the lot goes to review without a correction pass; any entry in "nouveauxEchecs" with `vert: false` triggers one), and say under "nonVerifie" if you could not check. The program replays the suite itself and compares to the same baseline.
22
32
  Report: commits (sha + subject), tests and build results with their numbers, what you could not
23
33
  verify, choices made, open questions.
24
34
 
@@ -16,6 +16,7 @@ Sheet rules:
16
16
  - If, after reading the lot and the code, you find that the lot changes NO behaviour (nothing a user, an API client or another service can observe: a lint, a rename, a move, a doc, a CI or cache setting without observable effect), write one line with the reason in `sousSeuil`, create no sheet, and finish: the lot then follows the usual path.
17
17
 
18
18
  Commit the sheet with explicit paths (never `git add -A` or `commit -a`), a message that cites the lot (`spec({{lot}}): …`), and leave the working tree clean. Do not implement the behaviour, do not write application code or tests, do not push, deliver, run `raf done`, `raf ux` or `raf review`.
19
+ Never run `git checkout` or `git switch` to another commit or branch in this repository: the orchestrator watches it and a moved HEAD breaks the other sessions of the wave. To look at another sha, use a throwaway `git worktree add --detach <tmp> <sha>`, removed afterwards.
19
20
  Decide minor interpretation questions yourself and list each one under "choix" with the alternative you did not take. Leave "questions" empty rather than writing a placeholder such as "no question".
20
21
  {{commits}}
21
22
  {{reponse}}
@@ -17,6 +17,7 @@ Sheet rules:
17
17
  - If, after reading the lot and the code, you find that the lot changes NO screen (no new page), write one line with the reason in `sousSeuil`, create no mockup and no sheet, and finish: the lot then follows the usual path.
18
18
 
19
19
  Commit the spec with explicit paths (never `git add -A` or `commit -a`), a message that cites the lot (`spec({{lot}}): …`), the sheet, the mockup and the captures together, and leave the working tree clean. Do not implement the screen, do not write application code or tests, do not push, deliver, run `raf done`, `raf ux` or `raf review`.
20
+ Never run `git checkout` or `git switch` to another commit or branch in this repository: the orchestrator watches it and a moved HEAD breaks the other sessions of the wave. To look at another sha, use a throwaway `git worktree add --detach <tmp> <sha>`, removed afterwards.
20
21
  Decide minor interpretation questions yourself and list each one under "choix" with the alternative you did not take. Leave "questions" empty rather than writing a placeholder such as "no question".
21
22
  {{commits}}
22
23
  {{reponse}}