@sylad/cadence 0.9.0 → 0.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 +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +27 -2
- package/dist/cli.js +8 -8
- package/dist/git.js +29 -0
- package/dist/orchestrate/cycle.js +4 -3
- package/dist/verify.js +30 -3
- package/package.json +1 -1
- package/templates/orchestrate/fix-minors.md +4 -0
- package/templates/orchestrate/fix.md +7 -2
- package/templates/orchestrate/implement.md +8 -3
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
{
|
|
7
7
|
"name": "cadence",
|
|
8
8
|
"description": "Session start and close rituals driven by a versioned plan (raf), and deliveries proven by their effect. Needs the cadence CLI (npm i -g @sylad/cadence).",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.10.0",
|
|
10
10
|
"source": "./",
|
|
11
11
|
"author": { "name": "Sylvain Ladoire" }
|
|
12
12
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cadence",
|
|
3
3
|
"description": "A repo-native working method: session start and close rituals driven by a versioned plan (raf), deliveries proven by their effect, and three reviewer agents (UX, code, QA).",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.10.0",
|
|
5
5
|
"author": { "name": "Sylvain Ladoire" },
|
|
6
6
|
"homepage": "https://github.com/Sylad/cadence",
|
|
7
7
|
"repository": "https://github.com/Sylad/cadence",
|
package/README.md
CHANGED
|
@@ -558,7 +558,7 @@ no journal entry, nothing written.
|
|
|
558
558
|
```sh
|
|
559
559
|
cadence verify # one pass, one line per check, then a one-line summary
|
|
560
560
|
cadence verify --retry 60 # retry each failing check for up to 60 s (deliver's 300 s is not applied)
|
|
561
|
-
cadence verify --sha 6b0d9aa # the sha that replaces ${SHA} / ${SHORT} (default:
|
|
561
|
+
cadence verify --sha 6b0d9aa # the sha that replaces ${SHA} / ${SHORT} (default: see below)
|
|
562
562
|
```
|
|
563
563
|
|
|
564
564
|
```
|
|
@@ -570,6 +570,22 @@ verify : 1 effet rouge sur 2 vérifications
|
|
|
570
570
|
Exit code: **0** every check green · **1** at least one red effect · **2** nothing
|
|
571
571
|
to verify or invalid configuration.
|
|
572
572
|
|
|
573
|
+
**Which sha is expected.** By default `${SHA}` / `${SHORT}` is the last recorded
|
|
574
|
+
delivery (else `HEAD`). One case differs: a project with `ci: none` (the default) and
|
|
575
|
+
**neither** deploy commands (`deliver.deploy`) nor a delivery script — a host that
|
|
576
|
+
builds every push, like Cloudflare Pages — delivers by pushing, and every push counts,
|
|
577
|
+
plan-maintenance commits included. The expected sha is then the head of the tracked
|
|
578
|
+
upstream branch (`origin/<branch>`, as last fetched — `verify` does no network git),
|
|
579
|
+
**provided that upstream is the remote's production branch**: read without network from
|
|
580
|
+
`refs/remotes/origin/HEAD` (set by `git clone` or `git remote set-head origin <branch>`);
|
|
581
|
+
when that reference does not exist locally (repository created with `git init` + push),
|
|
582
|
+
`main` then `master` are taken as the production branch. A work branch pushed with `-u`
|
|
583
|
+
is not published by such a host, so it keeps the default rule. A project with `ci: github`
|
|
584
|
+
or a `ci.command` and no deploy also keeps the last delivery. When local `HEAD` is ahead
|
|
585
|
+
of the upstream, the report says so first — `2 commit(s) non poussé(s) — l'effet vérifié
|
|
586
|
+
est celui de origin/main` — so a red there reads "waiting for a push", not "broken
|
|
587
|
+
effect". `session start` uses the same rule; `--sha` always wins.
|
|
588
|
+
|
|
573
589
|
Time limits differ from deliver's. `verify` runs all the checks **in parallel**,
|
|
574
590
|
each try with the whole 120 s limit (a `url` request gives up after 20 s; a slow
|
|
575
591
|
check is killed at its limit, "délai dépassé", and takes nothing from the others); results are printed in the order
|
|
@@ -635,6 +651,15 @@ you with the findings. A small lot (`estimate` ≤ 0.5 or `quickwin`) gets one s
|
|
|
635
651
|
usability (code only when the lot is not `visible`). Failing tests (reported red, or red when
|
|
636
652
|
`orchestrate.test` is run) go straight to a correction.
|
|
637
653
|
|
|
654
|
+
**A lot that already has commits** (a spec commit, an interrupted wave, a lot committed by hand, a lot sent back after a
|
|
655
|
+
review) still starts with the implementation session: its brief tells it to read the lot, its notes and its open
|
|
656
|
+
sub-tasks, which carry the findings of any earlier review. If that session ends without a new commit on a lot that
|
|
657
|
+
already has commits, the wave goes on to the review (warning `implement sans nouveau commit`) instead of handing the
|
|
658
|
+
lot back; with no commit on the lot at all it is handed back as `implement sans commit`. The same goes for a
|
|
659
|
+
correction pass: a `fix` session that adds no commit to a lot that already has work commits goes on to a fresh review
|
|
660
|
+
(warning `fix sans nouveau commit : revue lancée sur les commits du lot`), the pass still counted — the cap of two
|
|
661
|
+
correction passes stays the guard against a loop; with no commit on the lot it is handed back as `fix sans commit`.
|
|
662
|
+
|
|
638
663
|
**Compliant with minor findings**: the minors are not left for a follow-up lot. One **minors pass** runs
|
|
639
664
|
before concluding: a new Sonnet session with its own brief (`fix-minors.md`) fixes the minors that are right
|
|
640
665
|
and lists in `choix`, with the reason, the ones it rejects (it never stops to ask); it does not count among the
|
|
@@ -646,7 +671,7 @@ committed, a short re-review of that commit runs instead): `ready`, verdict reco
|
|
|
646
671
|
the untreated minors returned as proposals. Same when the budget is exhausted right after a compliant
|
|
647
672
|
review with minors: it concludes on that review instead of staying suspended.
|
|
648
673
|
|
|
649
|
-
**Choices, not questions**: the author brief tells the session to decide minor interpretation questions itself and to list them under `choix` in its report; the reviewer receives that list to re-read, and the final table prints each one (`choix fait : …`). A session stops with a question only on a real blocker
|
|
674
|
+
**Choices, not questions**: the author brief tells the session to decide minor interpretation questions itself and to list them under `choix` in its report; the reviewer receives that list to re-read, and the final table prints each one (`choix fait : …`). A session stops with a question only on a real blocker: a decision that changes the scope or the architecture or is costly to undo, AND that the plan, its notes and CLAUDE.md do not settle; everything else is a choice.
|
|
650
675
|
|
|
651
676
|
**What stays with you**: choosing the lots, the questions raised (`--resume --answer`), re-verifying
|
|
652
677
|
after the wave (`git log`, tests, `raf check`), `raf done`, **`raf ux`** (the orchestrator reports the UX
|
package/dist/cli.js
CHANGED
|
@@ -6,9 +6,9 @@ import { audit, exemptPlanOnly, isPlanOnly, lotWork, nextUp, planCommits, unrevi
|
|
|
6
6
|
import { short } from './check.js';
|
|
7
7
|
import { isDay, toDay } from './dates.js';
|
|
8
8
|
import { deliver, parseDeliverConfig, realDeps } from './deliver.js';
|
|
9
|
-
import { effectLines, realCheckDeps, verifyCommand } from './verify.js';
|
|
9
|
+
import { defaultTarget, effectLines, realCheckDeps, verifyCommand } from './verify.js';
|
|
10
10
|
import { ganttData, renderGantt } from './gantt.js';
|
|
11
|
-
import { gitRoot,
|
|
11
|
+
import { gitRoot, readCommits, resolveCommit } from './git.js';
|
|
12
12
|
import { installHook } from './hook.js';
|
|
13
13
|
import { citedRefs, linkCommits } from './link.js';
|
|
14
14
|
import { buildNews, loadEntries, newEntry, newsData, newsIssues, stampEntries } from './news.js';
|
|
@@ -19,7 +19,7 @@ import { AGENTS_DIR, installAgents, installSkills, SKILLS_DIR } from './skills.j
|
|
|
19
19
|
import { orchestrate, realOrchestrateDeps } from './orchestrate/command.js';
|
|
20
20
|
import { activeLock, REPO_LOCK } from './orchestrate/lock.js';
|
|
21
21
|
import { sessionClose, sessionStart } from './session.js';
|
|
22
|
-
import { clearNext,
|
|
22
|
+
import { clearNext, readNext, sharedStateDir, stateDir, writeNext } from './state.js';
|
|
23
23
|
const HELP = `raf — plan « reste à faire » versionné dans le dépôt, relié aux commits
|
|
24
24
|
|
|
25
25
|
raf init [--project nom] [--prefix L] [--no-hook]
|
|
@@ -310,10 +310,10 @@ function dispatch(argv, io) {
|
|
|
310
310
|
if (!Number.isFinite(retry) || retry < 0)
|
|
311
311
|
throw new RafError(`--retry invalide : ${values.retry} (secondes, 0 ou plus)`);
|
|
312
312
|
const config = parseDeliverConfig(readFileSync(configPath, 'utf8'), configPath);
|
|
313
|
-
const
|
|
314
|
-
if (values.sha && !sha)
|
|
313
|
+
const target = values.sha ? { sha: resolveCommit(root, values.sha) ?? '', note: null } : defaultTarget(root, config);
|
|
314
|
+
if (values.sha && !target.sha)
|
|
315
315
|
throw new RafError(`--sha ${values.sha} : commit introuvable`);
|
|
316
|
-
return verifyCommand({ config, sha, retry, out: io.out }, realCheckDeps(root));
|
|
316
|
+
return verifyCommand({ config, sha: target.sha, note: target.note, retry, out: io.out }, realCheckDeps(root));
|
|
317
317
|
}
|
|
318
318
|
case 'skills': {
|
|
319
319
|
if (rest[0] !== 'install')
|
|
@@ -516,8 +516,8 @@ function morningEffects(configPath, root) {
|
|
|
516
516
|
const config = parseDeliverConfig(text, configPath);
|
|
517
517
|
if (config.verify.length === 0)
|
|
518
518
|
return null;
|
|
519
|
-
const
|
|
520
|
-
return effectLines(config, sha, realCheckDeps(root, { quiet: true }));
|
|
519
|
+
const target = defaultTarget(root, config);
|
|
520
|
+
return effectLines(config, target.sha, realCheckDeps(root, { quiet: true }), target.note);
|
|
521
521
|
}
|
|
522
522
|
catch (e) {
|
|
523
523
|
return [`✗ ${e.message}`];
|
package/dist/git.js
CHANGED
|
@@ -88,6 +88,35 @@ export function repoStatus(cwd) {
|
|
|
88
88
|
ahead,
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
|
+
/** Branche amont suivie (« origin/main ») et son sha tel que connu localement (sans réseau), null sans amont. */
|
|
92
|
+
export function upstreamHead(cwd) {
|
|
93
|
+
const ref = tryGit(cwd, ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}']);
|
|
94
|
+
const sha = ref ? tryGit(cwd, ['rev-parse', '--verify', '-q', '@{u}']) : null;
|
|
95
|
+
return ref && sha ? { ref, sha } : null;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* L'amont suivi est-il la branche de production du dépôt distant ? Lu sans réseau : `refs/remotes/<remote>/HEAD`
|
|
99
|
+
* (origin/HEAD, posé par clone ou `git remote set-head`). Absent (dépôt créé par init + push) : repli sur les
|
|
100
|
+
* noms usuels, main puis master.
|
|
101
|
+
*/
|
|
102
|
+
export function upstreamIsDefaultBranch(cwd, upstreamRef) {
|
|
103
|
+
// Le remote vient de la config de la branche, pas d'une coupe de `@{u}` au premier « / » : un remote peut contenir un
|
|
104
|
+
// « / » (gh/origin) et un amont local (branche locale suivie) a pour remote « . » — jamais la branche de production.
|
|
105
|
+
const branch = tryGit(cwd, ['symbolic-ref', '-q', '--short', 'HEAD']);
|
|
106
|
+
if (!branch)
|
|
107
|
+
return false;
|
|
108
|
+
const remote = tryGit(cwd, ['config', '--get', `branch.${branch}.remote`]);
|
|
109
|
+
const merge = tryGit(cwd, ['config', '--get', `branch.${branch}.merge`]);
|
|
110
|
+
if (!remote || remote === '.' || !merge)
|
|
111
|
+
return false;
|
|
112
|
+
const upstreamBranch = merge.replace(/^refs\/heads\//, '');
|
|
113
|
+
if (upstreamRef !== `${remote}/${upstreamBranch}`)
|
|
114
|
+
return false;
|
|
115
|
+
const head = tryGit(cwd, ['symbolic-ref', '-q', '--short', `refs/remotes/${remote}/HEAD`]);
|
|
116
|
+
if (head)
|
|
117
|
+
return head === upstreamRef;
|
|
118
|
+
return upstreamBranch === 'main' || upstreamBranch === 'master';
|
|
119
|
+
}
|
|
91
120
|
/** Le commit est-il contenu dans une branche distante connue localement ? */
|
|
92
121
|
export function onRemote(cwd, sha) {
|
|
93
122
|
return (tryGit(cwd, ['branch', '-r', '--contains', sha]) ?? '').length > 0;
|
|
@@ -454,8 +454,9 @@ async function work(c, kind) {
|
|
|
454
454
|
stop(c, 'handed-back', 'passe des mineurs sans commit, mais aucune revue conforme gardée');
|
|
455
455
|
return;
|
|
456
456
|
}
|
|
457
|
-
//
|
|
458
|
-
|
|
457
|
+
// La session peut n'avoir plus rien à commiter (réponse du lead, lot commité avant la vague) : le travail du lot est déjà dans git.
|
|
458
|
+
// Même règle côté fix (L56) : la passe n'avait rien à ajouter, le lot a déjà ses commits de travail → revue neuve ; la passe reste consommée, MAX_PASSES borne la boucle.
|
|
459
|
+
const alreadyDone = (kind === 'implement' || kind === 'fix') && lotWork(plan, l.repo, l.lot).length > 0;
|
|
459
460
|
if (commits.length === 0 && !alreadyDone && !headMoved) {
|
|
460
461
|
stop(c, 'handed-back', `${kind} sans commit`);
|
|
461
462
|
return;
|
|
@@ -463,7 +464,7 @@ async function work(c, kind) {
|
|
|
463
464
|
if (headMoved)
|
|
464
465
|
l.warnings.push(`${minorsPass ? 'passe des mineurs' : 'correction'} reprise sans nouveau commit : un commit d'une session précédente est relu par la revue`);
|
|
465
466
|
else if (commits.length === 0)
|
|
466
|
-
l.warnings.push(`${kind} sans nouveau commit : revue lancée sur les commits déjà faits du lot`);
|
|
467
|
+
l.warnings.push(kind === 'fix' ? 'fix sans nouveau commit : revue lancée sur les commits du lot' : `${kind} sans nouveau commit : revue lancée sur les commits déjà faits du lot`);
|
|
467
468
|
const red = [];
|
|
468
469
|
if (!rep.tests.vert)
|
|
469
470
|
red.push({ source: 'tests', gravite: 'bloquant', texte: `tests annoncés rouges par la session : ${rep.tests.commande} — ${rep.tests.resultat}` });
|
package/dist/verify.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { constants } from 'node:os';
|
|
3
|
+
import { headSha, repoStatus, upstreamHead, upstreamIsDefaultBranch } from './git.js';
|
|
4
|
+
import { lastDelivery, sharedStateDir } from './state.js';
|
|
3
5
|
import { onTermination } from './proc.js';
|
|
4
6
|
import { describeCheck, realDeps, retryCheck, TIMED_OUT } from './deliver.js';
|
|
5
7
|
function killGroup(pgid, sig) {
|
|
@@ -73,6 +75,28 @@ export function summaryLine(results) {
|
|
|
73
75
|
export function verifyEnv(sha) {
|
|
74
76
|
return { CADENCE_SHA: sha, CADENCE_SHORT: sha.slice(0, 7), CADENCE_BRANCH: '' };
|
|
75
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Sha attendu par les vérifications (${SHA} / ${SHORT}) et note éventuelle pour le compte rendu.
|
|
80
|
+
* - Par défaut : la dernière livraison, à défaut la tête (inchangé).
|
|
81
|
+
* - `ci: none` SANS commande ni script de livraison : la livraison EST le push (Cloudflare Pages construit chaque
|
|
82
|
+
* push, plan compris), donc la tête de la branche amont suivie (état local de la référence, aucun réseau) —
|
|
83
|
+
* mais seulement si cet amont est la branche de production du dépôt distant : une branche de travail poussée
|
|
84
|
+
* avec -u n'est pas publiée, elle garde la règle par défaut. Des commits locaux non poussés ne changent pas
|
|
85
|
+
* ce sha mais sont dits dans la note.
|
|
86
|
+
* - Sans amont : règle par défaut.
|
|
87
|
+
*/
|
|
88
|
+
export function expectedTarget(root, config, last) {
|
|
89
|
+
const fallback = last ?? headSha(root) ?? '';
|
|
90
|
+
if (config.script !== undefined || config.deploy.length > 0 || config.ci !== 'none')
|
|
91
|
+
return { sha: fallback, note: null };
|
|
92
|
+
const up = upstreamHead(root);
|
|
93
|
+
if (!up || !upstreamIsDefaultBranch(root, up.ref))
|
|
94
|
+
return { sha: fallback, note: null };
|
|
95
|
+
const ahead = repoStatus(root).ahead;
|
|
96
|
+
return { sha: up.sha, note: ahead > 0 ? `${ahead} commit(s) non poussé(s) — l'effet vérifié est celui de ${up.ref}` : null };
|
|
97
|
+
}
|
|
98
|
+
/** Sha attendu de la reprise et de `cadence verify` sans --sha. */
|
|
99
|
+
export const defaultTarget = (root, config) => expectedTarget(root, config, lastDelivery(sharedStateDir(root)));
|
|
76
100
|
/** Délai de chaque essai d'une vérification de `cadence verify`. */
|
|
77
101
|
export const VERIFY_ATTEMPT_MS = 120_000;
|
|
78
102
|
/** `cadence verify` : 0 tout vert, 1 un effet rouge, 2 rien à vérifier. */
|
|
@@ -85,6 +109,8 @@ export async function verifyCommand(ctx, deps) {
|
|
|
85
109
|
: 'verify : aucune vérification déclarée (deliver.verify)');
|
|
86
110
|
return 2;
|
|
87
111
|
}
|
|
112
|
+
if (ctx.note)
|
|
113
|
+
out(ctx.note);
|
|
88
114
|
const results = await replayChecks(config.verify, deps, ctx.sha, verifyEnv(ctx.sha), { retryMs: ctx.retry * 1000, attemptMs: VERIFY_ATTEMPT_MS });
|
|
89
115
|
for (const r of results)
|
|
90
116
|
out(resultLine(r));
|
|
@@ -100,15 +126,16 @@ export const MORNING_BUDGET_MS = 10_000;
|
|
|
100
126
|
* Lignes « Effets en production » du rapport de reprise : un seul essai par vérification, borné. Rien à dire
|
|
101
127
|
* (liste vide) pour un projet sans verify ; ne lève jamais — c'est un fait de plus, pas une condition.
|
|
102
128
|
*/
|
|
103
|
-
export async function effectLines(config, sha, deps) {
|
|
129
|
+
export async function effectLines(config, sha, deps, note = null) {
|
|
104
130
|
if (config.verify.length === 0)
|
|
105
131
|
return [];
|
|
132
|
+
const head = note ? [note] : [];
|
|
106
133
|
try {
|
|
107
134
|
const results = await replayChecks(config.verify, deps, sha, verifyEnv(sha), { retryMs: 0, attemptMs: MORNING_BUDGET_MS });
|
|
108
135
|
const shown = results.filter((r) => r.reason !== null);
|
|
109
|
-
return shown.length === 0 ? [`✓ ${summaryLine(results)}`] : [...shown.map(resultLine), summaryLine(results)];
|
|
136
|
+
return shown.length === 0 ? [...head, `✓ ${summaryLine(results)}`] : [...head, ...shown.map(resultLine), summaryLine(results)];
|
|
110
137
|
}
|
|
111
138
|
catch (e) {
|
|
112
|
-
return [`✗ verify : ${e.message}`];
|
|
139
|
+
return [...head, `✗ verify : ${e.message}`];
|
|
113
140
|
}
|
|
114
141
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sylad/cadence",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.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",
|
|
@@ -13,6 +13,10 @@ deliver, run `raf done`, `raf ux` or `raf review`. Read the project's CLAUDE.md
|
|
|
13
13
|
Do not stop to ask. A finding that is wrong, or not worth its change, is not fixed: list it under
|
|
14
14
|
"choix" in your report with the reason — the reviewer re-reads it and the lead sees it. Leave
|
|
15
15
|
"questions" empty. Making no commit at all is a valid outcome when every finding is rejected.
|
|
16
|
+
Minor choices to settle yourself, writing the alternative you did not take:
|
|
17
|
+
a spacing, colour or label value when a measurement or a rule justifies it; the URL of a link (the most general official page if a precise one is not certain);
|
|
18
|
+
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).
|
|
19
|
+
"not my job to touch the plan" is not a question: say it in the report.
|
|
16
20
|
You are one short session of an orchestrated wave: do not launch subagents (the Agent tool is disabled).
|
|
17
21
|
Give your final report as the structured output (commits, tests, build, what you could not verify, choices).
|
|
18
22
|
{{reponse}}
|
|
@@ -10,7 +10,12 @@ Rules: test first; commit each fix as soon as its tests pass, with explicit path
|
|
|
10
10
|
`git add -A` or `commit -a`), and a message that cites the lot (`fix({{lot}}): …`); run the project's
|
|
11
11
|
full test suite and build before reporting; do not push, deliver, run `raf done`, `raf ux` or
|
|
12
12
|
`raf review`. Read the project's CLAUDE.md first.
|
|
13
|
-
If a finding is wrong,
|
|
13
|
+
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.
|
|
14
|
+
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);
|
|
15
|
+
otherwise it is a choice: decide, write the alternative you did not take, go on. Minor choices to settle yourself:
|
|
16
|
+
a spacing, colour or label value when a measurement or a rule justifies it; the URL of a link (the most general official page if a precise one is not certain);
|
|
17
|
+
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).
|
|
18
|
+
"not my job to touch the plan" is not a question: say it in the report.
|
|
14
19
|
You are one short session of an orchestrated wave: do not launch subagents (the Agent tool is disabled).
|
|
15
|
-
Give your final report as the structured output (commits, tests, build, what you could not verify, questions).
|
|
20
|
+
Give your final report as the structured output (commits, tests, build, what you could not verify, choices, questions).
|
|
16
21
|
{{reponse}}
|
|
@@ -7,9 +7,14 @@ full test suite and build before reporting; do not push, deliver, run `raf done`
|
|
|
7
7
|
`raf review`.
|
|
8
8
|
Decide minor interpretation questions yourself (the wording of a message, a name, a default, the
|
|
9
9
|
reading of an ambiguous line of the lot) and list each one under "choix" in your report, with the
|
|
10
|
-
alternative you did not take — the reviewer re-reads them. Stop and ask (under "questions") only on a real blocker
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
alternative you did not take — the reviewer re-reads them. Stop and ask (under "questions") only on a real blocker.
|
|
11
|
+
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), AND the plan, its notes and the project's CLAUDE.md do not settle it;
|
|
12
|
+
otherwise it is a choice: decide, write the alternative you did not take, go on. Minor choices to settle yourself:
|
|
13
|
+
a spacing, colour or label value when a measurement or a rule justifies it; the URL of a link (the most general official page if a precise one is not certain);
|
|
14
|
+
a News entry for a visible lot (yes, always); 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).
|
|
15
|
+
"not my job to touch the plan" is not a question: say it in the report.
|
|
16
|
+
If the lot's commits already cover its open sub-tasks, do not ask whether to continue: make no commit and say so
|
|
17
|
+
in your report (the review that follows re-reads those commits). If they do not cover them all, implement the rest.
|
|
13
18
|
Report: commits (sha + subject), tests and build results with their numbers, what you could not
|
|
14
19
|
verify, choices made, open questions.
|
|
15
20
|
|