canon-ai 3.14.0 → 3.15.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 +11 -0
- package/README.md +3 -3
- package/dist/cli/index.js +6 -6
- package/dist/orchestrator/run-task.js +17 -15
- package/package.json +1 -1
- package/templates/docs/pipeline-orchestrator.md +19 -13
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [3.15.0] — 2026-10-27
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **Codex implementation runs at higher reasoning effort, and the full Codex model defaults to GPT-6.1 Sol.** Extra-small and small tasks now implement with the mini model at `xhigh` effort (was `medium`), and medium and large tasks at `max` (was `high`). Extra-large and delicate tasks stay on the full model at `high`, so `delicate` now means a stronger model rather than more effort. The full-model default moves from `gpt-6-sol` to `gpt-6.1-sol`; set `CODEX_MODEL_FULL=gpt-6-sol` to keep the old one. Effort has no environment override, so restoring the old effort settings means installing the previous release. `max` needs a Codex CLI and mini model that accept it; the pipeline guide names the verified pair and what to do if Codex rejects it.
|
|
12
|
+
- **QA defaults to Claude Haiku 5.5 instead of Sonnet.** The QA step runs `claude-haiku-5-5` at medium effort at every task size, including delicate tasks; spec, plan, and code review keep their models. QA no longer follows the light-tier model, so `CLAUDE_MODEL_LIGHT` stops reaching it: if you set only `CLAUDE_MODEL_LIGHT`, QA moves to Haiku, and if you also set `CLAUDE_MODEL`, QA uses that value. `CLAUDE_MODEL_QA` still wins over both. To keep your previous QA model, set `CLAUDE_MODEL_QA` to it (`sonnet` if you set nothing).
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **`canon run --interactive` applies the selected reasoning effort.** Interactive Codex sessions used to ignore it and run at your Codex config's or the model's default effort, even though canon logged the selected value.
|
|
17
|
+
|
|
7
18
|
## [3.14.0] — 2026-10-25
|
|
8
19
|
|
|
9
20
|
### Added
|
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ Canon is what happens when you treat those failure modes as engineering problems
|
|
|
62
62
|
| Agent forgets a past mistake | **`docs/lessons-learned.md`** — distilled cross-task wisdom that promotes into permanent rules over time |
|
|
63
63
|
| Reviews loop forever on the same disagreement | **Auto-block on runaway review loops** — per-size caps (see `pipeline-policy.ts`), escalation to human after the cap |
|
|
64
64
|
| Spec drift between conversation and pipeline | **File-based handoff protocol** — every artifact lives in `tasks/<id>/`, no copy-pasting |
|
|
65
|
-
| Sensitive surfaces (auth, payments) get refactored on theoretical grounds | **`delicate: true` flag** that
|
|
65
|
+
| Sensitive surfaces (auth, payments) get refactored on theoretical grounds | **`delicate: true` flag** that moves Codex spec review and implementation to the full model and triggers extra review discipline |
|
|
66
66
|
|
|
67
67
|
## How it works
|
|
68
68
|
|
|
@@ -79,14 +79,14 @@ The orchestrator drives this. For each task:
|
|
|
79
79
|
spec → spec_review → plan → implement → code_review → qa → human_review
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
The human gates between `spec_review` and `plan` — they approve the spec before the pipeline advances to implementation. Within the chain: automatic loops on `changes_requested` verdicts, model
|
|
82
|
+
The human gates between `spec_review` and `plan` — they approve the spec before the pipeline advances to implementation. Within the chain: automatic loops on `changes_requested` verdicts, model selection by task size, optional git-worktree isolation, session resumption across phases, and auto-block on runaway loops. See `docs/pipeline-orchestrator.md` for the full mechanics.
|
|
83
83
|
|
|
84
84
|
The pipeline supports two tiers:
|
|
85
85
|
|
|
86
86
|
- **Fast tier** (XS tasks): spec + plan in one Claude session, skip Codex spec review, human gate replaces it.
|
|
87
87
|
- **Full tier** (S / M / L / XL / delicate tasks): every phase runs separately, Codex reviews specs before they reach the human.
|
|
88
88
|
|
|
89
|
-
`delicate: true` (set in `status.json` at task creation) promotes any task to full tier and upgrades the model and effort for spec, plan, and code review, plus Codex spec review and implementation; QA and the cold-Codex review lens stay on their regular cells. Use it for sensitive surfaces — auth, payments, persistent storage, anything where a regression has unbounded blast radius.
|
|
89
|
+
`delicate: true` (set in `status.json` at task creation) promotes any task to full tier and upgrades the model and effort for spec, plan, and code review, plus moves Codex spec review and implementation to the full model; QA and the cold-Codex review lens stay on their regular cells. Use it for sensitive surfaces — auth, payments, persistent storage, anything where a regression has unbounded blast radius.
|
|
90
90
|
|
|
91
91
|
A single command runs a task end-to-end:
|
|
92
92
|
|
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.15.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.15.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.15.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.15.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.15.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.15.0");
|
|
6655
6655
|
}
|
|
6656
6656
|
switch (command) {
|
|
6657
6657
|
case "doctor":
|
|
@@ -482,7 +482,7 @@ var WORKTREES_ROOT = process.env.CANON_WORKTREES_ROOT ? path2.resolve(REPO_ROOT,
|
|
|
482
482
|
var STALL_TIMEOUT_MS = Number(process.env.PIPELINE_STALL_TIMEOUT_MS) || 10 * 60 * 1e3;
|
|
483
483
|
var STALL_KILL_GRACE_MS = 3e3;
|
|
484
484
|
var LEGACY_FALLBACK_ENV_VARS = [
|
|
485
|
-
{ old: "CLAUDE_MODEL", replacement: "CLAUDE_MODEL_LIGHT / CLAUDE_MODEL_STRONG (still honored as a fallback for every Claude phase, including qa)" },
|
|
485
|
+
{ old: "CLAUDE_MODEL", replacement: "CLAUDE_MODEL_LIGHT / CLAUDE_MODEL_STRONG, and CLAUDE_MODEL_QA to keep a legacy model on qa (still honored as a fallback for every Claude phase, including qa)" },
|
|
486
486
|
{ old: "CODEX_MODEL_DEFAULT", replacement: "CODEX_MODEL_MINI (still honored as fallback)" },
|
|
487
487
|
{ old: "CODEX_MODEL_DELICATE", replacement: "CODEX_MODEL_FULL (still honored as fallback)" }
|
|
488
488
|
];
|
|
@@ -2178,10 +2178,10 @@ function codexMatrix(config3) {
|
|
|
2178
2178
|
XL: { model: config3.codexModelFull, effort: "high" }
|
|
2179
2179
|
},
|
|
2180
2180
|
implement: {
|
|
2181
|
-
XS: { model: config3.codexModelMini, effort: "
|
|
2182
|
-
S: { model: config3.codexModelMini, effort: "
|
|
2183
|
-
M: { model: config3.codexModelMini, effort: "
|
|
2184
|
-
L: { model: config3.codexModelMini, effort: "
|
|
2181
|
+
XS: { model: config3.codexModelMini, effort: "xhigh" },
|
|
2182
|
+
S: { model: config3.codexModelMini, effort: "xhigh" },
|
|
2183
|
+
M: { model: config3.codexModelMini, effort: "max" },
|
|
2184
|
+
L: { model: config3.codexModelMini, effort: "max" },
|
|
2185
2185
|
XL: { model: config3.codexModelFull, effort: "high" }
|
|
2186
2186
|
},
|
|
2187
2187
|
code_review: {
|
|
@@ -2193,6 +2193,7 @@ function codexMatrix(config3) {
|
|
|
2193
2193
|
}
|
|
2194
2194
|
};
|
|
2195
2195
|
}
|
|
2196
|
+
var QA_DEFAULT_MODEL = "claude-haiku-5-5";
|
|
2196
2197
|
var CLAUDE_CELLS = {
|
|
2197
2198
|
spec: {
|
|
2198
2199
|
XS: { tier: "light", effort: "medium" },
|
|
@@ -2216,11 +2217,11 @@ var CLAUDE_CELLS = {
|
|
|
2216
2217
|
XL: { tier: "strong", effort: "high" }
|
|
2217
2218
|
},
|
|
2218
2219
|
qa: {
|
|
2219
|
-
XS: { tier: "
|
|
2220
|
-
S: { tier: "
|
|
2221
|
-
M: { tier: "
|
|
2222
|
-
L: { tier: "
|
|
2223
|
-
XL: { tier: "
|
|
2220
|
+
XS: { tier: "qa", effort: "medium" },
|
|
2221
|
+
S: { tier: "qa", effort: "medium" },
|
|
2222
|
+
M: { tier: "qa", effort: "medium" },
|
|
2223
|
+
L: { tier: "qa", effort: "medium" },
|
|
2224
|
+
XL: { tier: "qa", effort: "medium" }
|
|
2224
2225
|
}
|
|
2225
2226
|
};
|
|
2226
2227
|
function claudePinFor(phase, size, config3) {
|
|
@@ -2239,6 +2240,7 @@ function resolveClaudeModel(phase, size, config3) {
|
|
|
2239
2240
|
const pin = claudePinFor(phase, size, config3);
|
|
2240
2241
|
if (pin !== null) return pin;
|
|
2241
2242
|
const tier = CLAUDE_CELLS[phase][size].tier;
|
|
2243
|
+
if (tier === "qa") return config3.claudeModelLegacy ?? QA_DEFAULT_MODEL;
|
|
2242
2244
|
const tierModel = tier === "light" ? config3.claudeModelLight : config3.claudeModelStrong;
|
|
2243
2245
|
if (tierModel !== null) return tierModel;
|
|
2244
2246
|
if (config3.claudeModelLegacy !== null) return config3.claudeModelLegacy;
|
|
@@ -2295,7 +2297,7 @@ var config2 = {
|
|
|
2295
2297
|
claudeModelStrong: process.env.CLAUDE_MODEL_STRONG || null,
|
|
2296
2298
|
claudeModelLegacy: process.env.CLAUDE_MODEL ?? null,
|
|
2297
2299
|
codexModelMini: process.env.CODEX_MODEL_MINI ?? process.env.CODEX_MODEL_DEFAULT ?? "gpt-6-luna",
|
|
2298
|
-
codexModelFull: process.env.CODEX_MODEL_FULL ?? process.env.CODEX_MODEL_DELICATE ?? "gpt-6-sol",
|
|
2300
|
+
codexModelFull: process.env.CODEX_MODEL_FULL ?? process.env.CODEX_MODEL_DELICATE ?? "gpt-6.1-sol",
|
|
2299
2301
|
maxReviewLoops: parseMaxReviewLoops(process.env.MAX_REVIEW_LOOPS),
|
|
2300
2302
|
claudeBudget: process.env.CLAUDE_BUDGET ?? null
|
|
2301
2303
|
};
|
|
@@ -2814,7 +2816,7 @@ ${renderedPrompt}`;
|
|
|
2814
2816
|
}
|
|
2815
2817
|
|
|
2816
2818
|
// src/orchestrator/agents/codex.ts
|
|
2817
|
-
var VALID_CODEX_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh"];
|
|
2819
|
+
var VALID_CODEX_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
2818
2820
|
function invalidCodexEffortMessage(effort) {
|
|
2819
2821
|
if (VALID_CODEX_EFFORTS.includes(effort)) return null;
|
|
2820
2822
|
return `Invalid Codex reasoning effort "${effort}" \u2014 canon resolved this value for the current phase/size and passes it via \`-c model_reasoning_effort=${effort}\`, but the Codex CLI only accepts: ${VALID_CODEX_EFFORTS.join("|")}. Effort is not configurable \u2014 canon resolves it from a fixed phase/size matrix, so this is a bug in canon rather than in your setup. Editing model_reasoning_effort in ~/.codex/config.toml will not help: the per-invocation override supersedes it. Please report this along with the task size and phase.`;
|
|
@@ -2832,6 +2834,7 @@ ${renderedPrompt}`;
|
|
|
2832
2834
|
let status = "ok";
|
|
2833
2835
|
let tokens;
|
|
2834
2836
|
let sessionId = null;
|
|
2837
|
+
const effortFlag = ["-c", `model_reasoning_effort=${effort}`];
|
|
2835
2838
|
try {
|
|
2836
2839
|
if (interactive) {
|
|
2837
2840
|
console.log("");
|
|
@@ -2839,7 +2842,7 @@ ${renderedPrompt}`;
|
|
|
2839
2842
|
console.log("Prompt loaded. You're in the driver's seat.");
|
|
2840
2843
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2841
2844
|
console.log("");
|
|
2842
|
-
runCommandOrDie("codex", ["-m", model, "-C", cwd, effectivePrompt], { cwd });
|
|
2845
|
+
runCommandOrDie("codex", ["-m", model, ...effortFlag, "-C", cwd, effectivePrompt], { cwd });
|
|
2843
2846
|
return {
|
|
2844
2847
|
exitCode: 0,
|
|
2845
2848
|
signal: null,
|
|
@@ -2850,7 +2853,6 @@ ${renderedPrompt}`;
|
|
|
2850
2853
|
sessionId: null
|
|
2851
2854
|
};
|
|
2852
2855
|
}
|
|
2853
|
-
const effortFlag = ["-c", `model_reasoning_effort=${effort}`];
|
|
2854
2856
|
const sandboxFlags = resumeId ? [] : ["--sandbox", "workspace-write"];
|
|
2855
2857
|
const args = resumeId ? ["exec", "resume", resumeId, "--json", ...effortFlag, effectivePrompt, "-m", model] : ["exec", "--json", ...effortFlag, ...sandboxFlags, effectivePrompt, "-m", model, "-C", cwd];
|
|
2856
2858
|
const displayChunks = [];
|
|
@@ -5845,7 +5847,7 @@ function isInstalledSourcePath(sourcePath) {
|
|
|
5845
5847
|
return sourcePath.includes("/node_modules/") || sourcePath.includes("\\node_modules\\") || sourcePath.includes("/_npx/") || sourcePath.includes("\\_npx\\");
|
|
5846
5848
|
}
|
|
5847
5849
|
function resolveCanonVersion(explicit) {
|
|
5848
|
-
return explicit ?? "3.
|
|
5850
|
+
return explicit ?? "3.15.0" ?? "dev";
|
|
5849
5851
|
}
|
|
5850
5852
|
function resolveOrchestratorCommit(repoRoot, upstreamCommit, runGitAt) {
|
|
5851
5853
|
const ownToplevel = captureGitOutput(repoRoot, ["rev-parse", "--show-toplevel"], runGitAt);
|
package/package.json
CHANGED
|
@@ -209,38 +209,38 @@ Set in `status.json` at task creation:
|
|
|
209
209
|
|
|
210
210
|
Canon's recommended starting policy for when to scope a task as `delicate: true`: *require evidence of real production impact, not theoretical correctness.*
|
|
211
211
|
|
|
212
|
-
A `delicate` task carries meaningful regression risk on a security-sensitive surface and
|
|
212
|
+
A `delicate` task carries meaningful regression risk on a security-sensitive surface and promotes Codex spec review and implementation to the full model, alongside stronger Claude review. "It's technically wrong" is not sufficient justification on its own — a hardening pass on auth/payments/storage that no user has ever hit can take significant pipeline time, introduce regression risk, and produce zero customer-visible value. Before scoping any task as `delicate: true`, require at least one confirmed production incident or a concrete upcoming flow that depends on the fix. Note the incident in the spec's *Problem* section.
|
|
213
213
|
|
|
214
214
|
This is a default — your project can adopt a stricter or looser bar in `docs/decisions.md` if it has different risk tolerance (e.g., a medical-data project with regulatory exposure may want proactive hardening).
|
|
215
215
|
|
|
216
216
|
## Codex Model/Effort Matrix
|
|
217
217
|
|
|
218
|
-
Codex model and effort
|
|
218
|
+
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
222
|
| `spec_review` | — (skipped) | mini / medium | mini / high | mini / high | full / high |
|
|
223
|
-
| `implement` | mini /
|
|
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
|
|
|
226
|
-
Codex is tuned for token efficiency — the mini model handles most phases; the full model only comes out for XL or delicate work.
|
|
226
|
+
Codex is tuned for token efficiency — the mini model handles most phases; the full model only comes out for XL or delicate work. Effort comes only from this matrix; there is no Codex effort environment override. M/L implement runs use Luna at `max`, while XL/delicate runs use Sol at `high`: delicate work already gets the stronger model, and Sol at `xhigh` costs about 1.5–2× Sol at `high`. Re-evaluating the full model's effort curve remains a separate follow-up.
|
|
227
227
|
|
|
228
|
-
The cold-Codex `code_review` lens is
|
|
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
230
|
`spec_review` runs at `high` from M upward. 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
|
|
|
234
|
-
Claude model and effort scale with effective task size. The light tier defaults to `sonnet`,
|
|
234
|
+
Claude model and effort scale with effective task size. The light tier defaults to `sonnet`, the strong tier defaults to `opus`, and `qa` uses its own default model, `claude-haiku-5-5`:
|
|
235
235
|
|
|
236
236
|
| Phase | XS | S | M | L | XL / delicate |
|
|
237
237
|
|---|---|---|---|---|---|
|
|
238
238
|
| `spec` | sonnet / medium | sonnet / medium | opus / medium | opus / medium | opus / high |
|
|
239
239
|
| `plan` | sonnet / medium | sonnet / medium | opus / medium | opus / medium | opus / high |
|
|
240
240
|
| `code_review` | sonnet / medium | sonnet / medium | opus / medium | opus / medium | opus / high |
|
|
241
|
-
| `qa` |
|
|
241
|
+
| `qa` | claude-haiku-5-5 / medium | claude-haiku-5-5 / medium | claude-haiku-5-5 / medium | claude-haiku-5-5 / medium | claude-haiku-5-5 / medium |
|
|
242
242
|
|
|
243
|
-
`spec`, `plan`, and `code_review` move to the strong tier at M, where sustained judgment matters; only XL/delicate raises effort to `high`.
|
|
243
|
+
`spec`, `plan`, and `code_review` move to the strong tier at M, where sustained judgment matters; only XL/delicate raises effort to `high`. QA writes completion artifacts and cannot block or reroute a task, so it uses its own default model rather than the light tier. The operator reports an uncontrolled field sample of about 37 tasks across canon-ai and an adopter with no QA failures, budget-cap hits, or retries; the 20 canon-ai `claude-haiku-5-5` QA invocation rows are all `ok` and took 44–214 seconds. Set `CLAUDE_MODEL_QA=sonnet` to restore the previous QA model. No Claude cell runs above `high`.
|
|
244
244
|
|
|
245
245
|
## Claude Budget Matrix
|
|
246
246
|
|
|
@@ -255,18 +255,18 @@ Claude phase budgets scale with task size. `spec`/`plan`/`qa` are single-pass Cl
|
|
|
255
255
|
|
|
256
256
|
## Environment Variables
|
|
257
257
|
|
|
258
|
-
Claude uses the light tier for XS/S spec, plan, and code review
|
|
258
|
+
Claude uses the light tier for XS/S spec, plan, and code review only. QA uses its own default model. M and above use the strong tier for spec, plan, and code review. A phase pin changes only the model; effort comes from the matrix.
|
|
259
259
|
|
|
260
260
|
| Variable | Default | Purpose |
|
|
261
261
|
|---|---|---|
|
|
262
|
-
| `CLAUDE_MODEL_LIGHT` | `sonnet` | Model for light-tier cells: XS/S `spec`/`plan`/`code_review`,
|
|
262
|
+
| `CLAUDE_MODEL_LIGHT` | `sonnet` | Model for light-tier cells: XS/S `spec`/`plan`/`code_review`, unless a phase pin applies. |
|
|
263
263
|
| `CLAUDE_MODEL_STRONG` | `opus` | Model for strong-tier cells: M and above `spec`/`plan`/`code_review`, unless a phase pin applies. |
|
|
264
264
|
| `CLAUDE_MODEL_SPEC` | _(unset)_ | Pins the `spec` model at every size, replacing the model only; effort still comes from the matrix. |
|
|
265
265
|
| `CLAUDE_MODEL_PLAN` | _(unset)_ | Pins the `plan` model at every size where a separate plan phase runs (XS fast tier combines spec and plan under the `spec` cell), replacing the model only; effort still comes from the matrix. |
|
|
266
266
|
| `CLAUDE_MODEL_REVIEW` | _(unset)_ | Pins the `code_review` model for XS/S/M/L only, replacing the model only; effort still comes from the matrix. Does not reach XL/delicate. |
|
|
267
267
|
| `CLAUDE_MODEL_REVIEW_LARGE` | _(unset)_ | Pins the `code_review` model for XL/delicate only, replacing the model only; effort still comes from the matrix. `_LARGE` means task size, not model tier. Does not reach XS–L. |
|
|
268
|
-
| `CLAUDE_MODEL_QA` | _(unset)_ | Pins the `qa` model at every size, replacing the model only; effort still comes from the matrix. |
|
|
269
|
-
| `CLAUDE_MODEL` | _(unset; deprecated)_ | Legacy catch-all model for every Claude phase, including `qa`, only where no phase pin or
|
|
268
|
+
| `CLAUDE_MODEL_QA` | _(unset; QA default is `claude-haiku-5-5`)_ | Pins the `qa` model at every size, replacing the model only; effort still comes from the matrix. This is QA's only override besides legacy `CLAUDE_MODEL`. Set it to `sonnet` (or the previous light-tier model) to restore the pre-change QA model. |
|
|
269
|
+
| `CLAUDE_MODEL` | _(unset; deprecated)_ | Legacy catch-all model for every Claude phase, including `qa`, only where no phase pin or tier variable applies. Phase pin → tier variable (tiered cells only) → this fallback → default (`sonnet` light, `opus` strong, `claude-haiku-5-5` for `qa`). For QA, this fallback applies when `CLAUDE_MODEL_QA` is unset. |
|
|
270
270
|
| `CLAUDE_BUDGET` | _(phase- and size-aware)_ | Max spend per Claude phase (USD). Unset → resolved from the Claude Budget Matrix above (phase × size). Set → flat cap applied uniformly across every phase and size (e.g. `CLAUDE_BUDGET=15.00` overrides every phase to $15). |
|
|
271
271
|
| `CANON_PROJECT_NAME` | _(reads `package.json` "name" or "your project")_ | Name injected into agent prompts. |
|
|
272
272
|
| `CANON_WORKTREES_ROOT` | .canon/worktrees | Where task worktrees are created. When overridden, the orchestrator warns if the path isn't in `.claude/settings*.json` `additionalDirectories`. |
|
|
@@ -279,9 +279,15 @@ Codex model overrides:
|
|
|
279
279
|
| Variable | Default | Purpose |
|
|
280
280
|
|---|---|---|
|
|
281
281
|
| `CODEX_MODEL_MINI` | `gpt-6-luna` | Codex model for XS/S/M/L non-delicate phases. |
|
|
282
|
-
| `CODEX_MODEL_FULL` | `gpt-6-sol` | Codex model for XL or delicate phases. |
|
|
282
|
+
| `CODEX_MODEL_FULL` | `gpt-6.1-sol` | Codex model for XL or delicate phases. |
|
|
283
283
|
| `MAX_REVIEW_LOOPS` | _size-aware_ | Max `spec_review` and `code_review` iterations before auto-block. Unset → 3 for XS/S/M, 5 for L/XL. |
|
|
284
284
|
|
|
285
|
+
M/L implementation uses `max`, which requires a Codex CLI and mini model
|
|
286
|
+
that accept that effort. This was verified only with Codex CLI 0.164.0 and
|
|
287
|
+
`gpt-6-luna`. If an M/L implement call fails on `max`, upgrade the Codex CLI,
|
|
288
|
+
point `CODEX_MODEL_MINI` at a model that accepts `max` (or unset it), or
|
|
289
|
+
install the previous canon release. There is no effort environment override.
|
|
290
|
+
|
|
285
291
|
These are canon's shipped defaults at the time of release and may lag
|
|
286
292
|
behind what your local `codex` CLI accepts. **Verify they resolve on your
|
|
287
293
|
install before relying on the pipeline** — a stale identifier produces a
|