canon-ai 3.15.0 → 3.16.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/CHANGELOG.md +8 -0
- package/README.md +1 -1
- package/dist/cli/index.js +6 -6
- package/dist/orchestrator/run-task.js +4 -4
- package/package.json +1 -1
- package/templates/.claude/skills/canon-spec/SKILL.md +6 -5
- package/templates/.claude/skills/canon-spec-review/SKILL.md +1 -1
- package/templates/docs/pipeline-orchestrator.md +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [3.16.0] — 2026-10-28
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **Codex spec review for small tasks runs at `high` effort instead of `medium`.** Small (`S`) tasks now get the same spec-review effort as medium and large ones. In a replay of past specs, `high` caught more spec gaps that later forced a reroute and did not block more clean specs; a review takes about 20 seconds longer. Effort has no environment override, so restoring `medium` means installing the previous release.
|
|
12
|
+
- **Spec authoring and `/canon-spec-review` look for sibling implementations, not just callers.** The spec prompts and `/canon-spec` tell the author to search for every other place that implements the behavior being changed (a second listener or entry path, a parallel component, or a test or doc asserting the current behavior) before settling Affected Files. The `/canon-spec-review` factual lens now searches for them too and flags an unnamed one the change must reach as blocking.
|
|
13
|
+
- **`/canon-spec` now strongly recommends `/canon-spec-review` after every spec with logic to vet, before you approve it.** It was optional and pitched mainly at larger tasks. In full-send mode, `/canon-spec` now runs `/canon-spec-review` itself before launching: it applies every blocking finding, applies other findings at its own judgment, and stops to ask only when a fix would change the approved scope. The pipeline guide and README say the same.
|
|
14
|
+
|
|
7
15
|
## [3.15.0] — 2026-10-27
|
|
8
16
|
|
|
9
17
|
### Changed
|
package/README.md
CHANGED
|
@@ -161,7 +161,7 @@ The other installed skills (auto-trigger on natural-language phrases — see eac
|
|
|
161
161
|
| Skill | When it fires |
|
|
162
162
|
|---|---|
|
|
163
163
|
| `/canon-spec` | Authoring a new task — "let's add X", "start a task for…" |
|
|
164
|
-
| `/canon-spec-review` | Pre-flighting a spec before invoking the pipeline |
|
|
164
|
+
| `/canon-spec-review` | Pre-flighting a spec before invoking the pipeline; strongly recommended after authoring any spec with logic to vet |
|
|
165
165
|
| `/canon-inline-review` | Independent cross-review of inline or below-pipeline changes before commit or PR |
|
|
166
166
|
| `/canon-sweep` | Triaging `docs/lessons-learned.md` — promote, keep, or prune, human-approved |
|
|
167
167
|
| `/canon-pipeline` | Driving an existing task forward (`canon run`, `--pr`, `--ship`, recovery) |
|
package/dist/cli/index.js
CHANGED
|
@@ -1694,7 +1694,7 @@ function checkTemplates(cwd) {
|
|
|
1694
1694
|
}
|
|
1695
1695
|
function checkCanonVersion(cwd) {
|
|
1696
1696
|
const versionPath = join(cwd, ".canon", "version");
|
|
1697
|
-
const installedVersion = "3.
|
|
1697
|
+
const installedVersion = "3.16.0";
|
|
1698
1698
|
if (!existsSync(versionPath)) {
|
|
1699
1699
|
return { label: ".canon/version", status: "warn", detail: "missing \u2014 run `canon upgrade`" };
|
|
1700
1700
|
}
|
|
@@ -2223,7 +2223,7 @@ function initCmd(args2) {
|
|
|
2223
2223
|
}
|
|
2224
2224
|
function writeCanonVersion(cwd) {
|
|
2225
2225
|
const versionPath = join2(cwd, ".canon", "version");
|
|
2226
|
-
const version = "3.
|
|
2226
|
+
const version = "3.16.0";
|
|
2227
2227
|
mkdirSync(dirname2(versionPath), { recursive: true });
|
|
2228
2228
|
writeFileSync(versionPath, version + "\n");
|
|
2229
2229
|
}
|
|
@@ -3303,7 +3303,7 @@ function isInstalledSourcePath(sourcePath) {
|
|
|
3303
3303
|
return sourcePath.includes("/node_modules/") || sourcePath.includes("\\node_modules\\") || sourcePath.includes("/_npx/") || sourcePath.includes("\\_npx\\");
|
|
3304
3304
|
}
|
|
3305
3305
|
function resolveCanonVersion(explicit) {
|
|
3306
|
-
return explicit ?? "3.
|
|
3306
|
+
return explicit ?? "3.16.0" ?? "dev";
|
|
3307
3307
|
}
|
|
3308
3308
|
function resolveOrchestratorCommit(repoRoot, upstreamCommit, runGitAt) {
|
|
3309
3309
|
const ownToplevel = captureGitOutput(repoRoot, ["rev-parse", "--show-toplevel"], runGitAt);
|
|
@@ -5548,7 +5548,7 @@ function currentPinFromManifest(manifest) {
|
|
|
5548
5548
|
return "unknown";
|
|
5549
5549
|
}
|
|
5550
5550
|
function bakedVersion() {
|
|
5551
|
-
return "3.
|
|
5551
|
+
return "3.16.0";
|
|
5552
5552
|
}
|
|
5553
5553
|
function ownPackageName(pkgDir) {
|
|
5554
5554
|
try {
|
|
@@ -6035,7 +6035,7 @@ function runUpgrade(cwd, pkgDir, options = {}) {
|
|
|
6035
6035
|
cutoverWarnings.push(docsRefsCheckRel);
|
|
6036
6036
|
}
|
|
6037
6037
|
const versionPath = join5(cwd, ".canon", "version");
|
|
6038
|
-
const newVersion = "3.
|
|
6038
|
+
const newVersion = "3.16.0";
|
|
6039
6039
|
const currentVersion = existsSync5(versionPath) ? readFileSync4(versionPath, "utf8").trim() : null;
|
|
6040
6040
|
if (currentVersion !== newVersion) {
|
|
6041
6041
|
pending.push({ rel: ".canon/version", projectPath: versionPath, content: newVersion + "\n" });
|
|
@@ -6651,7 +6651,7 @@ Global:
|
|
|
6651
6651
|
Run 'canon <command> --help' for details.`);
|
|
6652
6652
|
}
|
|
6653
6653
|
function printVersion() {
|
|
6654
|
-
console.log("3.
|
|
6654
|
+
console.log("3.16.0");
|
|
6655
6655
|
}
|
|
6656
6656
|
switch (command) {
|
|
6657
6657
|
case "doctor":
|
|
@@ -2172,7 +2172,7 @@ function codexMatrix(config3) {
|
|
|
2172
2172
|
return {
|
|
2173
2173
|
spec_review: {
|
|
2174
2174
|
XS: { model: config3.codexModelMini, effort: "medium" },
|
|
2175
|
-
S: { model: config3.codexModelMini, effort: "
|
|
2175
|
+
S: { model: config3.codexModelMini, effort: "high" },
|
|
2176
2176
|
M: { model: config3.codexModelMini, effort: "high" },
|
|
2177
2177
|
L: { model: config3.codexModelMini, effort: "high" },
|
|
2178
2178
|
XL: { model: config3.codexModelFull, effort: "high" }
|
|
@@ -5355,10 +5355,10 @@ var plan_default = "You are writing implementation plans for {{taskScope}} for {
|
|
|
5355
5355
|
var qa_default = 'You are writing QA summaries for {{taskScope}} for {{projectName}}.\n\n{{{startup}}}\n\nTasks:\n{{{taskLines}}}\n\nFor each task:\n1. **Use the Write tool** to create tasks/<id>/done.md \u2014 plain-English summary for the human. Include: what changed, files changed, how to test, test results, human verification required, decisions made, open questions.\n \u26A0\uFE0F CRITICAL: Use the `Write` tool \u2014 do NOT simply output the done.md content as text in your response. Content in your chat reply does not get saved to disk. The pipeline validates that done.md contains real content (not the template) before advancing. Write the file.\n2. Read the latest `## Validation Outcomes` table in `tasks/<id>/handoff.md`, including any later iteration `### Re-run validation` tables. If any check\'s latest result is `human_pending`, include a **Human Verification Required** section in done.md that lists each pending check and its Notes. If none remain, write `None.` in that section. Do not hide `human_pending` checks inside the generic Test Results table.\n - If the human chooses to waive or defer a pending check later, the waiver line in done.md must begin with `Acknowledged:`. The `human_review` gate only treats that explicit prefix as a waiver.\n - Preserve `deferred_by_spec` rows in Test Results with the spec citation from Notes; do not translate them to `Pass`.\n3. Include a **Proposed Changelog** section in done.md \u2014 the changelog **entry text only**. Do **NOT** include a version number, a "Proposed version" line, or a bump tier (Patch/Minor/Major): the version is decided at the release step (`/canon-changelog` + human), never by QA.\n - **Canon release rules (non-negotiable)**: (1) Agents do not bump versions or land changelog edits without explicit scope authorization. (2) The QA step proposes a draft changelog entry text only \u2014 not the version number. (3) Changelog + version bump are committed separately from code changes (when a project versions its releases). (4) No major versioning surprises: if a task introduces a breaking change the spec didn\'t flag, raise it before shipping.\n - Read `docs/decisions.md` \xA7"Versioning and release policy" for this project\'s changelog **scope** (which changes warrant an entry). The bump tier / SemVer interpretation is the release step\'s call, not QA\'s \u2014 do not propose one.\n - If CHANGELOG.md exists, read the top of it (the most recent version section) to calibrate on scope and voice.\n - Apply the "would a user notice" test to every candidate bullet (or the project\'s equivalent scope test): if a candidate falls outside the project\'s defined changelog scope, omit it. If a task is entirely out of scope, say so explicitly ("no user-facing change \u2014 omit from changelog") rather than inventing a bullet.\n - Implementation mechanics belong in the "What Changed" section above \u2014 not in the proposed changelog.\n The human finalizes the changelog entry.\n4. **For single tasks only \u2014 use the Write tool** to create `tasks/<id>/pr-body.md` \u2014 the outward-facing PR body draft for `--pr`. Write it as if a human wrote it after doing the work.\n {{#prTemplate}}\n The repo has this PR template. Fill every section with specifics from what shipped. Keep the headings; replace every placeholder:\n\n {{{prTemplate}}}\n {{/prTemplate}}\n\n {{^prTemplate}}\n No PR template found. Use this structure:\n\n ## Summary\n 1\u20133 bullets: what changed and why.\n\n ## Changes\n Key files or areas touched, described for a reviewer.\n\n ## How to Test\n Steps a reviewer can follow to verify the change.\n\n ## Notes for Reviewer\n Any context, caveats, or follow-up items.\n {{/prTemplate}}\n \u26A0\uFE0F Write as the human engineer who did the work \u2014 not as the AI or tool that produced it (Claude, Codex, canon, an LLM). \u2705 e.g. "Fix the pagination off-by-one that dropped the last row." \u274C e.g. "\u{1F916} Generated with Claude Code."\n Skip this step entirely for bundle tasks \u2014 per-task bodies are not combined for bundle PRs.\n\n**Citing files in task artifacts:** cite every repository file by its full path from the repository root, including any workspace or package prefix \u2014 never a path relative to a package or to the current directory. For a file that does not exist \u2014 one this task deleted, or one only planned \u2014 use the markdown-link form `[path](path)` instead of backticks, because `docs-refs-check` reports a backticked path to a missing file as a broken reference.\n\nAfter writing all done.md files:\n- Read tasks/<id>/notes.md for each task. For each insight, ask: "would this have changed how a *different* task was approached?" If yes, **append** one new entry for *this* task to its own lessons fragment, using the entry format in docs/lessons-learned.md. The fragment holds only `###` entries: create it if it doesn\'t exist, and give it no title or other `#`/`##` heading. Do not edit docs/lessons-learned.md; `--ship` folds the fragments into it. If no, the detail stays in notes.md only. Append-only: never edit, prune, promote, reorganize, or delete existing entries \u2014 not this task\'s earlier entries, and never another task\'s. Promoting entries into permanent docs (patterns.md / decisions.md) and pruning the buffer is a **human-initiated, human-approved** action \u2014 never perform it during QA, and no entry count ever triggers it. (See docs/lessons-learned.md \u2192 "How to use this doc".)\n\n{{{lessonsFragments}}}\n\n- Add a `## Quality Log` section to done.md with the five judgment cells the pipeline cannot derive from status.json. Do **not** edit docs/task-quality-log.md directly \u2014 the qa \u2192 done transition writes or upserts that row automatically into each task\'s quality-log.md fragment from status.json plus this section. `--ship` folds it into the shared log.\n\n ```markdown\n ## Quality Log\n - Spec verdict: <the FIRST spec_review verdict this task ever received \u2014 approved / approved_with_nits / changes_requested; leave blank only if truly unknown>\n - Human reroute?: <Yes/No \u2014 did the human reroute this task at any phase, forcing rework? Do not infer this from any reroute counter; if this is a fresh QA pass with no human reroute yet, answer No>\n - Dropped ACs: <count of ACs the implementation missed, caught in code review>\n - Validation gaps: <count of validation checks that should have run but did not>\n - Notes: <one-line summary of anything notable \u2014 single line, no embedded line breaks>\n ```\n\n On a re-upsert after a reroute, only fill in cells that changed or that you are correcting \u2014 an omitted cell keeps its previously recorded value. In particular, do not overwrite an already-recorded `Spec verdict` with the current status.json verdict; that column means the first spec_review verdict, and status.json only retains the latest.\n\n**Handoff Validation pre-merge checklist** (include in `done.md` Human Verification section if any item cannot be confirmed):\n- [ ] Version correct (per project policy; skip if unversioned)\n- [ ] Changelog updated if needed (per project policy; skip if unversioned)\n- [ ] PR body current\n- [ ] Final CI/CD checks green\n- [ ] Final diff matches spec intent\n\n**Output Format for Human** \u2014 `done.md` must contain:\n1. One-paragraph plain-English summary\n2. Files changed\n3. How to test (product-level steps, not code)\n4. Test results table\n5. Decisions made during implementation\n6. Open questions needing human input\n\n**Code is Canonical; Docs Reference Symbols**: Code is the source of truth for anything derivable from code: numbers, thresholds, file locations, function signatures, type shapes, observable behavior. Docs that restate these facts inline rot silently \u2014 reference the symbol or path; do not restate the value.\n\n**Commit Ownership** \u2014 three change categories:\n- Code changes \u2192 task branch, committed by the orchestrator after Codex static validation.\n- Pre-implement scaffold \u2192 base branch, committed by the orchestrator before first implement.\n- Changelog + version bump (if versioned) \u2192 separate commit, human + Claude, after human_review.\n\n- **Docs freshness \u2014 Two-checkpoint**: {{#docsEditable}}scan these docs ({{{docsEditable}}}) for references that {{docsScope}} *contradicts* \u2014 a renamed symbol, a moved file, a behavior this task changed \u2014 and correct those stale references. That is the only edit QA makes to permanent docs.{{/docsEditable}}{{^docsEditable}}no docs are configured for correction in this project, so QA makes no edits to permanent docs under this step.{{/docsEditable}} Do not add new lessons, pitfalls, or decisions here, and do not promote buffer entries \u2014 promotion is the human sweep, not Docs freshness.\n{{#docsFlagged}}\n- **Docs drift (flag only)**: also check {{{docsFlagged}}} for statements {{docsScope}} makes stale. Do **not** edit these docs. Report each stale statement in a `## Docs drift` section of done.md (doc, the stale statement, and what is now true). Omit the section if nothing is stale.\n{{/docsFlagged}}\n- **Buffer signal** (not an action): after appending, if docs/lessons-learned.md plus this task\'s lessons fragment now hold more than ~15 entries, add one line to this task\'s done.md \u2014 `Maintenance: lessons-learned.md plus this task\u2019s fragment have N entries; a human lessons sweep is due (see docs/lessons-learned.md \u2192 "How to use this doc").` Do not perform the sweep yourself.\n\nWhen done, run (use the Bash tool \u2014 do not just output the command as text):\n{{{phaseCommands}}}\n';
|
|
5356
5356
|
|
|
5357
5357
|
// src/orchestrator/prompts/templates/spec.md
|
|
5358
|
-
var spec_default = '{{{header}}}\n\n{{{startup}}}\n\n{{{instructions}}}\n{{{bundleNote}}}\n{{#doneNote}}\nNote: {{{doneNote}}}{{/doneNote}}\n\n{{#docsMapBlock}}\n{{{docsMapBlock}}}\n\n{{/docsMapBlock}}\n**Spec-writing rules of thumb** \u2014 apply when writing each spec:\n\n- **Name effects to DELETE** \u2014 frame supersession as replacement, not add-plus-remove. State: "replace `oldFn` with `newFn`; `oldFn` must not exist after" \u2014 not separate "Add" and "Remove" bullets.\n- **Prefer positive or structural assertions** over prose negations for load-bearing constraints. Back a "must not" with a grep AC or positive reframe; bare prose negation is fragile.\n- **Symbols named in ACs must exist** \u2014 grep for every function or symbol an AC names; verify its return shape matches the spec\'s assumed data contract before marking spec done.\n- **Enumerate every caller and classify its execution context before asserting how a mechanism works** \u2014 "counter X only increments on event Y" or "this writer can only be invoked from surface Z" is a control-flow claim, and control-flow claims need every caller traced. A helper named for one trigger routinely serves several, and whether a call site runs inside an agent\'s own session or in the orchestrator\'s process is invisible from the function body. Grep every caller of the function or counter \u2014 including skills and docs, not just source \u2014 and classify each site as in-agent-session or orchestrator-context before the spec asserts anything about it.\n- **Behavioral contracts, not mechanics** \u2014 ACs describe observable behavior; defer implementation mechanics (signatures, constant names, precise algorithms) to plan/implement. If review rounds start re-litigating literal regexes, exact file layouts, or verbatim command strings, the spec has dropped to code altitude and each round\'s "underspecified" finding just adds more reviewable surface: move the mechanics into a clearly-labeled non-binding *Implementation Notes* subsection owned by plan/implement, rather than wording the same mechanism more precisely.\n- **Bug and flake-fix specs need a confirmed mechanism and red-first test** \u2014 For a bug or flake fix, the spec author must state, in *Problem*, both the confirmed mechanism and how it was confirmed \u2014 not merely a plausible cause. Evidence must match the mechanism class: a deterministic mechanism (fixed inputs hit the same wrong branch every run) may cite a trace with the verified trigger values; a runtime-dependent mechanism (race, timing, environment/config interaction) needs executed confirmation \u2014 a throwaway prototype-fix spike that makes the symptom vanish, or a deterministic forced repro. The author must satisfy that checkpoint before the spec is marked done; on fast-tier (XS, non-delicate) tasks the `spec_review` checkpoint is skipped, so no reviewer will catch an unverified mechanism. The *Acceptance Criteria* must include a red-first regression-test AC: a test that fails on the pre-fix code for the stated reason and passes after the fix. If the mechanism is environment-bound and a faithful repro is impractical, *Problem* must say so and name a deterministic alternative (integration fixture or documented manual repro) instead of skipping verification silently.\n- **At \u22653 spec_review iterations, read the rounds\' content, not the count** \u2014 label each round *edge-fine-tune* (it narrows an already-identified case \u2014 converging, safe to finish once the remaining findings are addressed) or *scope-expansion* (it names a **new** structural case the spec hadn\'t covered \u2014 a real design gap). Round count alone is not the signal; a 6-round run of successive fine-tunes is convergence, not churn. On genuine scope-expansion, don\'t refine again: check whether the last two rejections share one structural root, and whether an existing layer already owns the concern. Dropping the whole mechanism class \u2014 or deleting the mechanism in favor of the layer that already owns it \u2014 is usually cheaper than another round of hardening.\n- **Refactor specs need structural caps** \u2014 provide hard size caps, explicit deletion expectations per symbol, and an allow-list grep AC for any symbol that must disappear.\n- **Refactor specs need a correctness audit** \u2014 For each behavior a refactor declares preserved, record in Problem whether it is correct today, and state one outcome: correct as-is, fixed deliberately (with its own AC), split into a separate task, or kept as a named quirk. A behavior confirmed correct needs only a one-line record. N/A for features and bug fixes.\n- **UI spatial / gesture tasks** \u2014 flag "visual positioning \u2014 expect human iteration" or "runtime debugging required" in *Known Risks*.\n- **Sensitive-surface escalation** \u2014 flag these categories as `delicate: true` in `status.json` and call them out in *Known Risks*: auth, billing / payments, privacy / data handling, destructive operations, schema / data-model migrations, analytics-event changes. The human spec gate is where such tasks stop for review.\n\n{{{selfCheck}}}\n\nWhen done, run (one per task):\n{{{phaseCommands}}}\n';
|
|
5358
|
+
var spec_default = '{{{header}}}\n\n{{{startup}}}\n\n{{{instructions}}}\n{{{bundleNote}}}\n{{#doneNote}}\nNote: {{{doneNote}}}{{/doneNote}}\n\n{{#docsMapBlock}}\n{{{docsMapBlock}}}\n\n{{/docsMapBlock}}\n**Spec-writing rules of thumb** \u2014 apply when writing each spec:\n\n- **Name effects to DELETE** \u2014 frame supersession as replacement, not add-plus-remove. State: "replace `oldFn` with `newFn`; `oldFn` must not exist after" \u2014 not separate "Add" and "Remove" bullets.\n- **Prefer positive or structural assertions** over prose negations for load-bearing constraints. Back a "must not" with a grep AC or positive reframe; bare prose negation is fragile.\n- **Symbols named in ACs must exist** \u2014 grep for every function or symbol an AC names; verify its return shape matches the spec\'s assumed data contract before marking spec done.\n- **Enumerate every caller and classify its execution context before asserting how a mechanism works** \u2014 "counter X only increments on event Y" or "this writer can only be invoked from surface Z" is a control-flow claim, and control-flow claims need every caller traced. A helper named for one trigger routinely serves several, and whether a call site runs inside an agent\'s own session or in the orchestrator\'s process is invisible from the function body. Grep every caller of the function or counter \u2014 including skills and docs, not just source \u2014 and classify each site as in-agent-session or orchestrator-context before the spec asserts anything about it.\n- **Find sibling implementations, not just callers** \u2014 before settling Affected Files, search for every other place that implements the behavior the spec changes: a second listener or entry path, a parallel component, or a test or doc that asserts the current behavior. A change that reaches one of two implementations ships half-done, and the gap usually surfaces only at code review.\n- **Behavioral contracts, not mechanics** \u2014 ACs describe observable behavior; defer implementation mechanics (signatures, constant names, precise algorithms) to plan/implement. If review rounds start re-litigating literal regexes, exact file layouts, or verbatim command strings, the spec has dropped to code altitude and each round\'s "underspecified" finding just adds more reviewable surface: move the mechanics into a clearly-labeled non-binding *Implementation Notes* subsection owned by plan/implement, rather than wording the same mechanism more precisely.\n- **Bug and flake-fix specs need a confirmed mechanism and red-first test** \u2014 For a bug or flake fix, the spec author must state, in *Problem*, both the confirmed mechanism and how it was confirmed \u2014 not merely a plausible cause. Evidence must match the mechanism class: a deterministic mechanism (fixed inputs hit the same wrong branch every run) may cite a trace with the verified trigger values; a runtime-dependent mechanism (race, timing, environment/config interaction) needs executed confirmation \u2014 a throwaway prototype-fix spike that makes the symptom vanish, or a deterministic forced repro. The author must satisfy that checkpoint before the spec is marked done; on fast-tier (XS, non-delicate) tasks the `spec_review` checkpoint is skipped, so no reviewer will catch an unverified mechanism. The *Acceptance Criteria* must include a red-first regression-test AC: a test that fails on the pre-fix code for the stated reason and passes after the fix. If the mechanism is environment-bound and a faithful repro is impractical, *Problem* must say so and name a deterministic alternative (integration fixture or documented manual repro) instead of skipping verification silently.\n- **At \u22653 spec_review iterations, read the rounds\' content, not the count** \u2014 label each round *edge-fine-tune* (it narrows an already-identified case \u2014 converging, safe to finish once the remaining findings are addressed) or *scope-expansion* (it names a **new** structural case the spec hadn\'t covered \u2014 a real design gap). Round count alone is not the signal; a 6-round run of successive fine-tunes is convergence, not churn. On genuine scope-expansion, don\'t refine again: check whether the last two rejections share one structural root, and whether an existing layer already owns the concern. Dropping the whole mechanism class \u2014 or deleting the mechanism in favor of the layer that already owns it \u2014 is usually cheaper than another round of hardening.\n- **Refactor specs need structural caps** \u2014 provide hard size caps, explicit deletion expectations per symbol, and an allow-list grep AC for any symbol that must disappear.\n- **Refactor specs need a correctness audit** \u2014 For each behavior a refactor declares preserved, record in Problem whether it is correct today, and state one outcome: correct as-is, fixed deliberately (with its own AC), split into a separate task, or kept as a named quirk. A behavior confirmed correct needs only a one-line record. N/A for features and bug fixes.\n- **UI spatial / gesture tasks** \u2014 flag "visual positioning \u2014 expect human iteration" or "runtime debugging required" in *Known Risks*.\n- **Sensitive-surface escalation** \u2014 flag these categories as `delicate: true` in `status.json` and call them out in *Known Risks*: auth, billing / payments, privacy / data handling, destructive operations, schema / data-model migrations, analytics-event changes. The human spec gate is where such tasks stop for review.\n\n{{{selfCheck}}}\n\nWhen done, run (one per task):\n{{{phaseCommands}}}\n';
|
|
5359
5359
|
|
|
5360
5360
|
// src/orchestrator/prompts/templates/spec-revision.md
|
|
5361
|
-
var spec_revision_default = 'You are revising specs for {{taskScope}} for {{projectName}}.\n\n{{{startup}}}\n\nTasks with review feedback:\n{{{reviewLines}}}\n\nAddress every `changes_requested` finding in each spec.md.{{#combined}}\nAlso update plan.md if spec changes affect the implementation approach.{{/combined}}\n\n{{#docsMapBlock}}\n{{{docsMapBlock}}}\n\n{{/docsMapBlock}}\n**Spec-writing rules of thumb** \u2014 apply when revising each spec:\n\n- **Name effects to DELETE** \u2014 frame supersession as replacement, not add-plus-remove. State: "replace `oldFn` with `newFn`; `oldFn` must not exist after" \u2014 not separate "Add" and "Remove" bullets.\n- **Prefer positive or structural assertions** over prose negations for load-bearing constraints. Back a "must not" with a grep AC or positive reframe; bare prose negation is fragile.\n- **Symbols named in ACs must exist** \u2014 grep for every function or symbol an AC names; verify its return shape matches the spec\'s assumed data contract before marking spec done.\n- **Enumerate every caller and classify its execution context before asserting how a mechanism works** \u2014 "counter X only increments on event Y" or "this writer can only be invoked from surface Z" is a control-flow claim, and control-flow claims need every caller traced. A helper named for one trigger routinely serves several, and whether a call site runs inside an agent\'s own session or in the orchestrator\'s process is invisible from the function body. Grep every caller of the function or counter \u2014 including skills and docs, not just source \u2014 and classify each site as in-agent-session or orchestrator-context before the spec asserts anything about it.\n- **Behavioral contracts, not mechanics** \u2014 ACs describe observable behavior; defer implementation mechanics (signatures, constant names, precise algorithms) to plan/implement. If review rounds start re-litigating literal regexes, exact file layouts, or verbatim command strings, the spec has dropped to code altitude and each round\'s "underspecified" finding just adds more reviewable surface: move the mechanics into a clearly-labeled non-binding *Implementation Notes* subsection owned by plan/implement, rather than wording the same mechanism more precisely.\n- **Bug and flake-fix specs need a confirmed mechanism and red-first test** \u2014 For a bug or flake fix, the spec author must state, in *Problem*, both the confirmed mechanism and how it was confirmed \u2014 not merely a plausible cause. Evidence must match the mechanism class: a deterministic mechanism (fixed inputs hit the same wrong branch every run) may cite a trace with the verified trigger values; a runtime-dependent mechanism (race, timing, environment/config interaction) needs executed confirmation \u2014 a throwaway prototype-fix spike that makes the symptom vanish, or a deterministic forced repro. The author must satisfy that checkpoint before the spec is marked done; on fast-tier (XS, non-delicate) tasks the `spec_review` checkpoint is skipped, so no reviewer will catch an unverified mechanism. The *Acceptance Criteria* must include a red-first regression-test AC: a test that fails on the pre-fix code for the stated reason and passes after the fix. If the mechanism is environment-bound and a faithful repro is impractical, *Problem* must say so and name a deterministic alternative (integration fixture or documented manual repro) instead of skipping verification silently.\n- **At \u22653 spec_review iterations, read the rounds\' content, not the count** \u2014 label each round *edge-fine-tune* (it narrows an already-identified case \u2014 converging, safe to finish once the remaining findings are addressed) or *scope-expansion* (it names a **new** structural case the spec hadn\'t covered \u2014 a real design gap). Round count alone is not the signal; a 6-round run of successive fine-tunes is convergence, not churn. On genuine scope-expansion, don\'t refine again: check whether the last two rejections share one structural root, and whether an existing layer already owns the concern. Dropping the whole mechanism class \u2014 or deleting the mechanism in favor of the layer that already owns it \u2014 is usually cheaper than another round of hardening.\n- **Refactor specs need structural caps** \u2014 provide hard size caps, explicit deletion expectations per symbol, and an allow-list grep AC for any symbol that must disappear.\n- **Refactor specs need a correctness audit** \u2014 For each behavior a refactor declares preserved, record in Problem whether it is correct today, and state one outcome: correct as-is, fixed deliberately (with its own AC), split into a separate task, or kept as a named quirk. A behavior confirmed correct needs only a one-line record. N/A for features and bug fixes.\n- **UI spatial / gesture tasks** \u2014 flag "visual positioning \u2014 expect human iteration" or "runtime debugging required" in *Known Risks*.\n- **Sensitive-surface escalation** \u2014 flag these categories as `delicate: true` in `status.json` and call them out in *Known Risks*: auth, billing / payments, privacy / data handling, destructive operations, schema / data-model migrations, analytics-event changes. The human spec gate is where such tasks stop for review.\n\nWhen done, run:\n{{{phaseCommands}}}\n';
|
|
5361
|
+
var spec_revision_default = 'You are revising specs for {{taskScope}} for {{projectName}}.\n\n{{{startup}}}\n\nTasks with review feedback:\n{{{reviewLines}}}\n\nAddress every `changes_requested` finding in each spec.md.{{#combined}}\nAlso update plan.md if spec changes affect the implementation approach.{{/combined}}\n\n{{#docsMapBlock}}\n{{{docsMapBlock}}}\n\n{{/docsMapBlock}}\n**Spec-writing rules of thumb** \u2014 apply when revising each spec:\n\n- **Name effects to DELETE** \u2014 frame supersession as replacement, not add-plus-remove. State: "replace `oldFn` with `newFn`; `oldFn` must not exist after" \u2014 not separate "Add" and "Remove" bullets.\n- **Prefer positive or structural assertions** over prose negations for load-bearing constraints. Back a "must not" with a grep AC or positive reframe; bare prose negation is fragile.\n- **Symbols named in ACs must exist** \u2014 grep for every function or symbol an AC names; verify its return shape matches the spec\'s assumed data contract before marking spec done.\n- **Enumerate every caller and classify its execution context before asserting how a mechanism works** \u2014 "counter X only increments on event Y" or "this writer can only be invoked from surface Z" is a control-flow claim, and control-flow claims need every caller traced. A helper named for one trigger routinely serves several, and whether a call site runs inside an agent\'s own session or in the orchestrator\'s process is invisible from the function body. Grep every caller of the function or counter \u2014 including skills and docs, not just source \u2014 and classify each site as in-agent-session or orchestrator-context before the spec asserts anything about it.\n- **Find sibling implementations, not just callers** \u2014 before settling Affected Files, search for every other place that implements the behavior the spec changes: a second listener or entry path, a parallel component, or a test or doc that asserts the current behavior. A change that reaches one of two implementations ships half-done, and the gap usually surfaces only at code review.\n- **Behavioral contracts, not mechanics** \u2014 ACs describe observable behavior; defer implementation mechanics (signatures, constant names, precise algorithms) to plan/implement. If review rounds start re-litigating literal regexes, exact file layouts, or verbatim command strings, the spec has dropped to code altitude and each round\'s "underspecified" finding just adds more reviewable surface: move the mechanics into a clearly-labeled non-binding *Implementation Notes* subsection owned by plan/implement, rather than wording the same mechanism more precisely.\n- **Bug and flake-fix specs need a confirmed mechanism and red-first test** \u2014 For a bug or flake fix, the spec author must state, in *Problem*, both the confirmed mechanism and how it was confirmed \u2014 not merely a plausible cause. Evidence must match the mechanism class: a deterministic mechanism (fixed inputs hit the same wrong branch every run) may cite a trace with the verified trigger values; a runtime-dependent mechanism (race, timing, environment/config interaction) needs executed confirmation \u2014 a throwaway prototype-fix spike that makes the symptom vanish, or a deterministic forced repro. The author must satisfy that checkpoint before the spec is marked done; on fast-tier (XS, non-delicate) tasks the `spec_review` checkpoint is skipped, so no reviewer will catch an unverified mechanism. The *Acceptance Criteria* must include a red-first regression-test AC: a test that fails on the pre-fix code for the stated reason and passes after the fix. If the mechanism is environment-bound and a faithful repro is impractical, *Problem* must say so and name a deterministic alternative (integration fixture or documented manual repro) instead of skipping verification silently.\n- **At \u22653 spec_review iterations, read the rounds\' content, not the count** \u2014 label each round *edge-fine-tune* (it narrows an already-identified case \u2014 converging, safe to finish once the remaining findings are addressed) or *scope-expansion* (it names a **new** structural case the spec hadn\'t covered \u2014 a real design gap). Round count alone is not the signal; a 6-round run of successive fine-tunes is convergence, not churn. On genuine scope-expansion, don\'t refine again: check whether the last two rejections share one structural root, and whether an existing layer already owns the concern. Dropping the whole mechanism class \u2014 or deleting the mechanism in favor of the layer that already owns it \u2014 is usually cheaper than another round of hardening.\n- **Refactor specs need structural caps** \u2014 provide hard size caps, explicit deletion expectations per symbol, and an allow-list grep AC for any symbol that must disappear.\n- **Refactor specs need a correctness audit** \u2014 For each behavior a refactor declares preserved, record in Problem whether it is correct today, and state one outcome: correct as-is, fixed deliberately (with its own AC), split into a separate task, or kept as a named quirk. A behavior confirmed correct needs only a one-line record. N/A for features and bug fixes.\n- **UI spatial / gesture tasks** \u2014 flag "visual positioning \u2014 expect human iteration" or "runtime debugging required" in *Known Risks*.\n- **Sensitive-surface escalation** \u2014 flag these categories as `delicate: true` in `status.json` and call them out in *Known Risks*: auth, billing / payments, privacy / data handling, destructive operations, schema / data-model migrations, analytics-event changes. The human spec gate is where such tasks stop for review.\n\nWhen done, run:\n{{{phaseCommands}}}\n';
|
|
5362
5362
|
|
|
5363
5363
|
// src/orchestrator/prompts/templates/spec-review-reroute.md
|
|
5364
5364
|
var spec_review_reroute_default = "You are reviewing {{taskScope}} for {{projectName}}.\n\n{{{startup}}}\n\nA human amended the spec and rerouted this task after implementation began. The original spec was already reviewed and approved. Your job is to review **the amendment and its integration** with the already-approved spec, not to re-litigate settled findings.\n\n{{{roundBanner}}}Tasks with amendments to review:\n{{{taskLines}}}\n\n**Amendment review scope** (for each task \u2014 EXCEPT tasks whose line above marks them EXEMPT: those have no amendment and require no review work this round; do not request changes for a missing Amendment heading on them):\n1. Read `tasks/<id>/spec.md` from your current directory. Locate the exact amendment heading named above: `## Amendment` for round 1, or `## Amendment Round N` for round 2+.\n2. Read `tasks/<id>/spec-review.md` so you know what was already reviewed and do not re-raise settled findings.\n3. Review the amendment itself: is it implementable as written, are ACs verifiable, and are edge cases handled?\n4. Review integration with approved ACs: does the amendment contradict, weaken, duplicate, or leave gaps against previously approved requirements?\n5. Review overall shape: with the amendment included, is the spec still coherent and in scope?\n6. Do **not** read or audit `handoff.md`, `review.md`, or `done.md`. This phase stays in the spec domain.\n\nGrounding rule: if a finding depends on a symbol or file, re-open it before claiming it exists.\n\n**Cross-review rule**: No agent reviews its own output. Claude writes specs \u2192 Codex reviews specs. Codex writes code \u2192 Claude reviews code.\n\n**Diagnose before you fix \u2014 3-role checkpoint**: For any amendment addressing a bug or flake fix, each role owns a checkpoint: the spec author states the confirmed mechanism and its evidence in *Problem* (a deterministic mechanism \u2014 fixed inputs hit the same wrong branch every run \u2014 may cite a trace with the verified trigger values; a runtime-dependent mechanism \u2014 race, timing, environment/config interaction \u2014 needs executed confirmation: a throwaway prototype-fix spike that makes the symptom vanish, or a deterministic forced repro); the reviewer challenges whether that evidence establishes the root cause; the implementer runs the spec's red-first test against the pre-fix code (or, under the environment-bound-and-impractical escape, its named deterministic alternative) and reports the result in the handoff. A mechanism with no confirmation evidence, or evidence below its class's required rung, is a blocking Shape Check concern \u2014 as is a bug/flake amendment carrying neither a red-first regression-test AC nor the explicit environment-bound-and-impractical escape with a named deterministic alternative.\n\n**Verdict rules** (same as normal spec review):\n- `changes_requested` \u2014 one or more blocking findings. The human must revise the amendment and re-run.\n- `approved_with_nits` \u2014 no blockers; non-blocking observations only. Loop exits immediately.\n- `approved` \u2014 no findings.\n\nFor each task, append a new amendment-review section to `tasks/<id>/spec-review.md`; do not overwrite the prior review. Use this exact heading for the section (the orchestrator's evidence gate requires it before advancing):\n - Round 1: `## Amendment Review`\n - Round N >= 2: `## Amendment Review Round N`\nRecord your verdict **inside that section** as a checked box \u2014 the evidence gate reads the verdict from this section, not from the original review above it. Check exactly one of:\n`- [x] **Approved**` / `- [x] **Approved with nits**` / `- [x] **Changes requested**`.\n\nWhen done, run (one per task with actual verdict):\n{{{phaseCommands}}}\n\n<!-- per-round append shape (round 1 omits the round suffix):\n## Amendment Review (round 1)\n## Amendment Review Round N (round N >= 2)\n- [x] **Approved** (check exactly one verdict box)\n> Findings: ...\n-->\n";
|
|
@@ -5847,7 +5847,7 @@ function isInstalledSourcePath(sourcePath) {
|
|
|
5847
5847
|
return sourcePath.includes("/node_modules/") || sourcePath.includes("\\node_modules\\") || sourcePath.includes("/_npx/") || sourcePath.includes("\\_npx\\");
|
|
5848
5848
|
}
|
|
5849
5849
|
function resolveCanonVersion(explicit) {
|
|
5850
|
-
return explicit ?? "3.
|
|
5850
|
+
return explicit ?? "3.16.0" ?? "dev";
|
|
5851
5851
|
}
|
|
5852
5852
|
function resolveOrchestratorCommit(repoRoot, upstreamCommit, runGitAt) {
|
|
5853
5853
|
const ownToplevel = captureGitOutput(repoRoot, ["rev-parse", "--show-toplevel"], runGitAt);
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: canon-spec
|
|
3
3
|
description: Use when the human describes a new feature, bug fix, or refactor that doesn't yet have a canon task — phrases like "let's add X", "I want to fix Y", "we should refactor Z", "start a task for...", or explicit `/canon-spec` invocation. Also triggers on "full send" / "full-send" / "yolo it" which carries through to pipeline launch without further interrupts. Don't use for existing in-progress tasks (use `/canon-pipeline`) or status checks (use `/canon-status`).
|
|
4
4
|
argument-hint: "[task description or title]"
|
|
5
|
-
allowed-tools: Read Glob Grep Write Edit Agent Bash(canon task *) Bash(canon run *) Bash(git branch *) Bash(git status *) Bash(git log *)
|
|
5
|
+
allowed-tools: Read Glob Grep Write Edit Agent Skill Bash(canon task *) Bash(canon run *) Bash(git branch *) Bash(git status *) Bash(git log *)
|
|
6
6
|
effort: high
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -66,7 +66,7 @@ Synthesize the sub-agent's findings before proceeding.
|
|
|
66
66
|
|
|
67
67
|
Before grilling, detect full-send intent from `$ARGUMENTS`: if it contains an explicit `--full-send` flag or the phrase `full send` / `full-send` (case-insensitive), enter full-send mode, print the acknowledgment line below, and carry that mode through the rest of the workflow.
|
|
68
68
|
|
|
69
|
-
`Full-send mode detected. I'll grill, write the spec, and run the pipeline through to a draft PR without further interrupts.`
|
|
69
|
+
`Full-send mode detected. I'll grill, write and review the spec, and run the pipeline through to a draft PR without further interrupts unless the review raises a scope question.`
|
|
70
70
|
|
|
71
71
|
Assess task size from the description and exploration findings:
|
|
72
72
|
- **XS**: more than a trivial one-file inline change (>1 file, or real logic), but little-to-no spec premise worth reviewing. This is the smallest way into the pipeline: choosing it over inline buys the pipeline's cross-review direction (Codex implements against written ACs, Claude reviews), a plan, and a real `code_review`.
|
|
@@ -154,6 +154,7 @@ Self-check before presenting:
|
|
|
154
154
|
- **Prefer positive or structural assertions** over prose negations for load-bearing constraints. Back a "must not" with a grep AC or positive reframe.
|
|
155
155
|
- **Symbols in ACs must exist** — grep for every named function or symbol; verify return shape matches the spec's assumed data contract.
|
|
156
156
|
- **Enumerate every caller and classify its execution context before asserting how a mechanism works.** "Counter X only increments on event Y" or "this writer can only be invoked from surface Z" is a control-flow claim, and control-flow claims need every caller traced — a helper named for one trigger routinely serves several, and whether a call site runs inside an agent's own session or in the orchestrator's process is invisible from the function body. Grep every caller of the function or counter (including skills and docs, not just source) and classify each site as in-agent-session or orchestrator-context before the spec asserts anything about it.
|
|
157
|
+
- **Find sibling implementations, not just callers** — before settling Affected Files, search for every other place that implements the behavior the spec changes: a second listener or entry path, a parallel component, or a test or doc that asserts the current behavior. A change that reaches one of two implementations ships half-done, and the gap usually surfaces only at code review.
|
|
157
158
|
- **Behavioral contracts, not mechanics** — ACs describe observable behavior; defer implementation mechanics to plan/implement. If review rounds start re-litigating literal regexes, exact file layouts, or verbatim command strings, the spec has dropped to code altitude and each round's "underspecified" finding just adds more reviewable surface: move the mechanics into a clearly-labeled non-binding *Implementation Notes* subsection owned by plan/implement, rather than wording the same mechanism more precisely. The recurring form of this trap is an AC that pins exact operation counts over a fixture in which an unchanged async subsystem (a generation queue, a worker pool) performs its own reads inside the measurement window — an adopter spec took five review rounds on one such AC because each revision worded the same brittle count more precisely instead of removing the dependency; make the side effects inert or assert the discriminating deltas, do not itemize the subsystem's arithmetic.
|
|
158
159
|
- **Bug and flake-fix specs need a confirmed mechanism and red-first test**: For a bug or flake fix, the spec author must state, in *Problem*, both the confirmed mechanism and how it was confirmed — not merely a plausible cause. Evidence must match the mechanism class: a deterministic mechanism (fixed inputs hit the same wrong branch every run) may cite a trace with the verified trigger values; a runtime-dependent mechanism (race, timing, environment/config interaction) needs executed confirmation — a throwaway prototype-fix spike that makes the symptom vanish, or a deterministic forced repro. The author must satisfy that checkpoint before the spec is marked done; on fast-tier (XS, non-delicate) tasks the `spec_review` checkpoint is skipped, so no reviewer will catch an unverified mechanism. The *Acceptance Criteria* must include a red-first regression-test AC: a test that fails on the pre-fix code for the stated reason and passes after the fix. If the mechanism is environment-bound and a faithful repro is impractical, *Problem* must say so and name a deterministic alternative (integration fixture or documented manual repro) instead of skipping verification silently.
|
|
159
160
|
- **At ≥3 spec_review iterations, read the rounds' content, not the count.** Label each round *edge-fine-tune* (it narrows an already-identified case — converging, safe to finish once the findings are addressed) or *scope-expansion* (it names a **new** structural case the spec hadn't covered — a real design gap). Round count alone is not the signal; a 6-round run of successive fine-tunes is convergence. On genuine scope-expansion, don't refine again: check whether the last two rejections share one structural root, and whether an existing layer already owns the concern. Dropping the whole mechanism class — or deleting the mechanism in favor of the layer that already owns it — is usually cheaper than another round of hardening.
|
|
@@ -161,7 +162,7 @@ Self-check before presenting:
|
|
|
161
162
|
- **Refactor specs need a correctness audit before "preserve behavior"**: For each behavior a refactor declares preserved, record in Problem whether it is correct today, and state one outcome: correct as-is, fixed deliberately (with its own AC), split into a separate task, or kept as a named quirk. A behavior confirmed correct needs only a one-line record. N/A for features and bug fixes.
|
|
162
163
|
- **Codebase-wide term renames: gate per string family, not per enumerated hit.** Hand-enumerated grep lists cause round-over-round scope expansion — each review round surfaces a new label *family*, not a missed instance. Decompose the stale term into its distinct string families up front via a structural sweep, then express each family's post-change invariant as a zero-result grep AC with a word-bounded pattern that catches all separator variants and cannot match the new term. Where the old string is a substring of the new one, zero-result gating is structurally impossible — verify those surfaces with positive targeted ACs instead, and document the asymmetry in the spec so reviewers don't read it as a gap. Two checks before finalizing any zero-result grep AC: (1) on prose surfaces (`docs/`, templates, backlog), read every affected file for *paraphrases* of the retired claim — an exact-string grep proves only that the literal phrase is gone, not that the retired behavior is undocumented everywhere; (2) scan the spec's own other ACs, Docs Impact, and Non-Goals for hits they already tolerate (historical docs, a release-time step, incidental test fixtures) and fold those into an explicit permitted-to-remain bucket inside the same AC, so a later section doesn't quietly contradict the gate.
|
|
163
164
|
|
|
164
|
-
**⛔ STOP — present the spec and wait for approval.**
|
|
165
|
+
**⛔ STOP — present the spec, strongly recommend running `/canon-spec-review` on it before approving, and wait for approval.** The recommendation applies at every size except an XS change with no logic to vet (a typo fix or version bump), which `/canon-spec-review` itself skips: on full tier it catches what Codex `spec_review` tends to miss, such as an unnamed second implementation of the changed behavior, and on fast tier (XS, non-delicate) it is the only automated spec review. If the human runs it, fold the findings they accept into the spec and re-present it. In full-send mode there is no approval stop, so run `/canon-spec-review` on the spec yourself instead, under the same exception. Apply every BLOCKING finding. For each STRONG or NIT finding, use your judgment as the spec author: apply it if it improves the spec, otherwise leave it. If a fix would change the scope the human approved during grilling, such as adding a surface or dropping a Non-Goal, stop and ask the human before applying it; that is the only interrupt full-send keeps. Then continue to Phase 6.
|
|
165
166
|
|
|
166
167
|
---
|
|
167
168
|
|
|
@@ -178,7 +179,7 @@ Self-check before presenting:
|
|
|
178
179
|
- **Async/stateful:** for async or stateful changes — re-entry, cancellation or unmount, stale state, and ownership.
|
|
179
180
|
|
|
180
181
|
A finding that changes a step goes in that step. If the check contradicts the spec, don't work around it in the plan — on the fast tier no Codex `spec_review` will catch the mismatch. Amend the spec, re-present the change to the human, and wait for renewed approval. The earlier Phase 5 approval does not cover a spec changed after it, so don't record approval in step 2 until the human has approved the amended spec.
|
|
181
|
-
2. Record the human's approval in `tasks/TASK-ID/spec-review.md`: check the **Approved** box and add a one-line note ("Fast tier — human conversational spec approval; Codex spec review skipped"). The phase gate reads this artifact before letting `spec_review` advance.
|
|
182
|
+
2. Record the human's approval in `tasks/TASK-ID/spec-review.md`: check the **Approved** box and add a one-line note ("Fast tier — human conversational spec approval; Codex spec review skipped"). In full-send mode no human approved the spec, so the note says that instead ("Fast tier full-send — no human spec approval; `/canon-spec-review` run before launch; Codex spec review skipped"), or "review skipped" when the no-logic exception applied. The phase gate reads this artifact before letting `spec_review` advance.
|
|
182
183
|
3. Advance the phases with the helpers (they rederive the top-level `status` pointer):
|
|
183
184
|
```bash
|
|
184
185
|
canon task phase TASK-ID spec done
|
|
@@ -210,7 +211,7 @@ canon run --full-send [--force] TASK-ID
|
|
|
210
211
|
|
|
211
212
|
## Related
|
|
212
213
|
|
|
213
|
-
- `/canon-spec-review` — adversarial pre-pipeline review of the spec.
|
|
214
|
+
- `/canon-spec-review` — adversarial pre-pipeline review of the spec. Strongly recommended after authoring any spec with logic to vet, before approving it and invoking the pipeline.
|
|
214
215
|
- `/canon-pipeline` — drive the pipeline after spec approval.
|
|
215
216
|
- `/canon-status` — check what other canon tasks are in flight before committing to scope.
|
|
216
217
|
- `docs/pipeline-orchestrator.md` — pipeline internals, sizing guide, model/effort matrix. The Validation Matrix is now inline in `.canon/templates/spec.md`.
|
|
@@ -49,7 +49,7 @@ Constraints: don't audit factual claims (Agent B's job); don't audit completenes
|
|
|
49
49
|
|
|
50
50
|
#### Agent B — Factual / ground-truth
|
|
51
51
|
|
|
52
|
-
Scope: verify every factual claim in the spec against the actual codebase. For each named symbol, file path, function, or behavior: does it exist, is the description correct, and are Affected Files entries real paths? For symbols in ACs, verify signatures, return shapes, and call sites.
|
|
52
|
+
Scope: verify every factual claim in the spec against the actual codebase. For each named symbol, file path, function, or behavior: does it exist, is the description correct, and are Affected Files entries real paths? For symbols in ACs, verify signatures, return shapes, and call sites. Then search for other implementations of the behavior the spec changes (a parallel listener, entry path, or component, or a test or doc that asserts the current behavior) that Affected Files doesn't name; one the change must also reach is BLOCKING.
|
|
53
53
|
|
|
54
54
|
Read whole functions and call sites, not excerpts, when verifying return shapes. Cite `file:line` for every claim. Don't audit shape (Agent A) or stylistic completeness (Agent C).
|
|
55
55
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Reference for driving canon's pipeline: CLI surface, flags, task-management subcommands, pipeline tiers, the model/effort matrix, environment variables, worktree mechanics, session resumption, auto-block thresholds, and recovery patterns. Read on demand when you need to know which flag to use, why canon picked a particular model, or how to recover from a stuck phase.
|
|
4
4
|
|
|
5
|
-
For **command patterns and snag-recovery flows**, see the `/canon-pipeline` skill at `.claude/skills/canon-pipeline/SKILL.md` (installed by `canon init`). For **adversarial pre-pipeline spec review
|
|
5
|
+
For **command patterns and snag-recovery flows**, see the `/canon-pipeline` skill at `.claude/skills/canon-pipeline/SKILL.md` (installed by `canon init`). For **adversarial pre-pipeline spec review**, strongly recommended for any spec with logic to vet, see `/canon-spec-review`.
|
|
6
6
|
|
|
7
7
|
Canon's phase prompts, skills, and templates deliver reusable roles, implementation rules, validation, git, and release guidance just in time. This file is the source of truth for *how to operate the pipeline*.
|
|
8
8
|
|
|
@@ -173,7 +173,7 @@ Claude writes QA summary → Human tests
|
|
|
173
173
|
- Spec and plan are written in separate Claude sessions.
|
|
174
174
|
- Codex runs a real spec review before the gate. Spec review starts with a **Shape Check** (is the problem real? is the framing right? is there a materially simpler solution? is the AC decomposition right?) before the implementability probe.
|
|
175
175
|
- Effective size selects both the Codex and Claude model/effort cells in the matrices below.
|
|
176
|
-
- **
|
|
176
|
+
- **Recommended pre-pipeline self-review**: after the spec is written and before invoking `canon run`, run `/canon-spec-review` (task ID optional — it defaults to the task under discussion) to dispatch three parallel sub-agents (structural / factual / spec-quality) at the spec and surface BLOCKING / STRONG / NIT findings inline. Catches the class of issues Codex's spec_review would surface across 2-3 iterations in one ~15-min pass, and its factual lens also finds gaps Codex's spec_review tends to miss, such as a second implementation of the changed behavior that the spec does not name. Strongly recommended for every spec with logic to vet; on the fast tier it is the only automated spec review.
|
|
177
177
|
|
|
178
178
|
**Where validation happens**: Project-specific checks (lint, type-check, unit tests, e2e, etc.) run inside agent phases — Codex runs them during `implement` and records outcomes in the handoff; Claude verifies the outcomes table in Stage 1 code review and re-runs selectively when anything looks off. There is no separate orchestrator-run validation phase.
|
|
179
179
|
|
|
@@ -219,7 +219,7 @@ Codex model and effort come from a fixed phase × size matrix:
|
|
|
219
219
|
|
|
220
220
|
| Phase | XS | S | M | L | XL / delicate |
|
|
221
221
|
|---|---|---|---|---|---|
|
|
222
|
-
| `spec_review` | — (skipped) | mini /
|
|
222
|
+
| `spec_review` | — (skipped) | mini / high | mini / high | mini / high | full / high |
|
|
223
223
|
| `implement` | mini / xhigh | mini / xhigh | mini / max | mini / max | full / high |
|
|
224
224
|
| `code_review` (cold lens) | mini / high | mini / high | mini / high | mini / high | mini / high |
|
|
225
225
|
|
|
@@ -227,7 +227,7 @@ Codex is tuned for token efficiency — the mini model handles most phases; the
|
|
|
227
227
|
|
|
228
228
|
The cold-Codex `code_review` lens is deliberately flat: as a mandatory hard-fail gate, it runs at `high` effort and stays on the mini model at every size, including XL/delicate.
|
|
229
229
|
|
|
230
|
-
`spec_review` runs at `high` from
|
|
230
|
+
`spec_review` runs at `high` at every size that runs it. S moved up from `medium` after a replay of approved specs whose tasks were later rerouted: `high` caught more of the known spec gaps than `medium` and blocked no more clean specs, for about twice the tokens of a short review. `xhigh` and `max` caught slightly more again but cost 3–5× `high`'s output tokens. M moved up earlier: task-history analysis found M's excess code_review iterations weren't an implement-quality gap (non-rerouted M and L tasks ran at nearly identical iteration counts) but a reroute-severity gap, with M's lighter spec_review effort the leading hypothesis. M and L also differ on loop cap and budget, so this isn't a proven sole cause; if you retune the matrix, re-measure your own M vs. L reroute rate.
|
|
231
231
|
|
|
232
232
|
## Claude Model/Effort Matrix
|
|
233
233
|
|
|
@@ -555,4 +555,4 @@ Task templates are managed by canon — `canon upgrade` overwrites `.canon/templ
|
|
|
555
555
|
- `docs/patterns.md` — implementation patterns and Known Pitfalls.
|
|
556
556
|
- `docs/decisions.md` — settled architectural decisions.
|
|
557
557
|
- `/canon-pipeline` — command patterns and snag-recovery flows for operating the pipeline.
|
|
558
|
-
- `/canon-spec-review` — adversarial pre-pipeline spec review (multi-agent fan-out)
|
|
558
|
+
- `/canon-spec-review` — adversarial pre-pipeline spec review (multi-agent fan-out); strongly recommended after authoring any spec with logic to vet.
|