diff --git a/.claude/memory/decisions.md b/.claude/memory/decisions.md index 02928f0..cb36a38 100644 --- a/.claude/memory/decisions.md +++ b/.claude/memory/decisions.md @@ -1058,3 +1058,6 @@ Supersedes the "Excluded: hotfix" clause of [[BDR-075]]. hotfix now wired (STEP ### BDR-076 — Dispatched judgment agents pinned OPUS; session model = orchestration + inline reflection ONLY [accepted] (2026-07-19) Reverses the BDR-066 rejected alternative "opus pins on audit agents (session-independent)". Context changed: session default now Fable (Mythos tier, /model 2026-07-19) — inherit meant every dispatched audit/challenge burned Fable quota, exactly the waste BDR-066 killed for executors. New rule: Fable does ONLY main-loop orchestration + reflection (brainstorm, plan, contract, synthesis, gates); EVERY dispatched subagent pinned. Pinned `model: opus` (big tier, session-independent; NEVER sonnet — silent audit downgrade, the thing old §F5 guarded): analyzer, plan-challenger, seo-analyzer, geo-analyzer, validator-analyzer + onboard's 6 general-purpose audit dispatches (`model="opus"`) + tour Phase B. NOT pinned (justified deviation from approved "7 agents"): interviewer + client-handover-writer — inline-load only, never dispatched → frontmatter pin inert + misleading (BDR-066 wave-4 precedent: its inert opus pin was dropped); they ARE the main loop = Fable per the rule. Explore built-in stays inherit (wave-3 decision conserved: no owned prompt, search feeds inline reflection). Local session pin `opus-4-8[1m]` dropped from `.claude/settings.local.json` (gitignored) — Fable default from settings.json now applies in this repo too. model-gate.md unchanged (still guards inline reflection, Fable-or-Opus = big). Census: model-routing.test.sh §3 flip + §11 (61 pass), loops-light 35 pass, full `make test` green. User directives via gate: "Opus partout" + "Supprimer le pin". Branch feature/opus-pin-audit-agents, unmerged. + +### BDR-077 — Model-tiering v2: 4-tier explicit routing, mode-based splits, no-inherit dispatches [accepted] (2026-07-19) +Supersedes BDR-076 scope + amends BDR-066. Doctrine: session model (Fable) = main-loop reflection/orchestration/planning/logic ONLY; main-loop retention criteria = interactive | conversation-context access | orchestration decision | dispatch overhead > step cost. NOTHING dispatched inherits: typed agents = frontmatter pin, built-ins = `model=` at every call site (`fable` for skill-runner reflection children, else complexity tier). Spike+smoke proven: `model:"fable"` resolves claude-fable-5 (enum-validated, loud fail, no silent fallback); call-site override BEATS a typed pin (sonnet-pinned verifier ran haiku). Fail-safe pin rule: mixed-mode agents keep the HIGH tier as pin, overrides go DOWN — forgotten override over-tiers (cost), never downgrades judgment. Mode-based splits (commit-changer precedent generalized; file splits rejected): doc-syncer audit(opus)/patch(sonnet) — ALSO fixed a latent defect: /doc dispatched an agent whose STEP 8 interactive gate could never fire; gates hoisted to a DISPATCHER PROTOCOL section; handover-doc-writer synthesize(opus)/render(sonnet) via run-scoped `.audit/handover-draft-.md` + DRAFT COMPLETE sentinel; seo/geo collect(sonnet)/judge(OPUS PIN)/template(sonnet) via `.audit/*-signals-.md` + COLLECTION COMPLETE + fail-closed judge + dispatcher ERROR contract (mute/ERROR judge NEVER carried into templating; retry once, escalate). File split only for a genuinely new role: plugin-probe (sonnet, facts-only) + plugin-advisor repinned opus reasoner (fail-closed on missing PROBE REPORT) + lib/plugin-gate.md (checkpoint + apply gate, doc-commit ×N include pattern). Inline→dispatch conversions: scaffolder, onboarder, doc-commit steps ×5 flows — their sonnet pins were INERT since creation, now live; CHANGE SUMMARY crosses the doc dispatch into doc-commit (LRN-126 wire). Tier moves: validator-analyzer opus→sonnet (deterministic runner); commit-changer propose=opus/apply=pin; ship-feature/init-project code-review dispatches = opus explicit (WAS an inherit leak); client-handover-writer's 7 skill-runners = model:"fable". Every wave shipped an IN-WAVE planted-input smoke as its merge gate — all PASSED disk-verified. Census §12-18 (125 pass; one vacuous line-wrapped lock self-caught = LRN-093 live). 6 waves, branches feature/model-tiering-w1..w6, merged on user standing signal. Plan: challenged 3 blind lenses + 1 confirmation (1 BLOCKER closed by spike, 8 MAJORs + 8 MINORs closed by named changes, 0 deferred). Refs: `.claude/tasks/plans/2026-07-19-model-tiering-v2-{analysis,plan}.md`. diff --git a/.claude/memory/journal.md b/.claude/memory/journal.md index f0f66ac..1cb9ec8 100644 --- a/.claude/memory/journal.md +++ b/.claude/memory/journal.md @@ -412,3 +412,4 @@ rules: ## 2026-07-19 - BDR-076: dispatched judgment agents pinned opus (analyzer, plan-challenger, seo/geo/validator-analyzer + 6 onboard general-purpose dispatches); Fable now = inline orchestration/reflection only. interviewer + client-handover-writer left unpinned (inline-load, pin inert). Local opus-4-8 session pin dropped from settings.local.json. Census §11 added (61 pass), loops-light 35, make test green. feature/opus-pin-audit-agents, UNMERGED. +- BDR-077 model-tiering v2 SHIPPED: 6 waves (W0 baseline merge → W1 no-inherit+fable skill-runners → W2 plugin split + doc two-mode + inert-pin conversions → W3 tier moves → W4 handover two-mode → W5 seo/geo 3-mode pipelines → W6 doctrine sweep). Plan challenged 4 passes (1 BLOCKER closed by fable spike). Per-wave planted-input smokes disk-verified. Census 125/0, make test green throughout. [[BDR-077]] [[LRN-137]]. diff --git a/.claude/memory/learnings.md b/.claude/memory/learnings.md index c1a6dd1..61472ca 100644 --- a/.claude/memory/learnings.md +++ b/.claude/memory/learnings.md @@ -1342,3 +1342,10 @@ rules: ### LRN-136 — config-protection live state follows checked-out branch's symlinked settings.json (2026-07-17) ~/.claude/settings.json is a SYMLINK to the repo settings.json; Claude Code hot-reloads settings on change → the config-protection PreToolUse hook's active/inactive state tracks the CURRENT branch's settings.json. On feature/drop-config-protection (hook deregistered) a protected edit passed silently, sentinel unconsumed; after gitflow-switch to a branch off develop (hook still registered) the SAME class of edit was blocked. Apply: a change that removes a settings-registered hook is live only on that branch until merged; use the one-shot sentinel for protected edits on any branch that still registers it. ([[BDR-074]] context.) + +## LRN-137 — mode-based re-tiering beats file splits for mixed-tier agents +- **pattern**: three planned agent splits (doc-syncer, handover-doc-writer, seo/geo analyzers) shipped as MODES + per-dispatch `model=` instead of new files; only plugin-probe justified a real new file (genuinely new role, no shared body). +- **why**: a file split severs implicit data paths (LRN-126), relocates body-text test locks (seo-data fetch-wiring), breaks name/dispatch-string census locks, duplicates templates. A mode split keeps ALL locks and text in place; the dispatcher's gate sits BETWEEN mode dispatches; call-site `model=` precedence over the frontmatter pin is spike-proven (sonnet-pinned verifier ran haiku on override). +- **fail-safe pin rule**: keep the HIGHEST tier as the frontmatter pin and override DOWN at call sites — a forgotten override then over-tiers (costs money) instead of silently downgrading judgment (costs correctness). +- **future application**: before splitting any agent across model tiers, try MODE + `model=` first; create a new agent file only for a genuinely new role. Run-scoped `.audit/-` files + completeness sentinel + fail-closed consumer for any cross-dispatch artifact. +- **cousin**: [[LRN-125]] [[LRN-126]] [[BDR-077]]. diff --git a/.claude/tasks/plans/2026-07-19-model-tiering-v2-plan.md b/.claude/tasks/plans/2026-07-19-model-tiering-v2-plan.md index 1bc8e39..5980800 100644 --- a/.claude/tasks/plans/2026-07-19-model-tiering-v2-plan.md +++ b/.claude/tasks/plans/2026-07-19-model-tiering-v2-plan.md @@ -265,6 +265,26 @@ W6 DOCTRINE + CLOSE-OUT: model-gate.md rewrite (protects main loop; tier - simplicity: CONCERNS(1) — 3-way seo/geo YAGNI → 2-way worker/judge (fixed S3/S4); twin-templater share (dissolved by 2-way; divergence stated); plugin gate ×4 copies → lib/plugin-gate.md include (fixed S1). +## EXECUTION NOTES (2026-07-19 — as-built deviations, all justified in-commit) + +- S2/S3/S4/S5 shipped MODE-BASED (one agent, modes + call-site `model=`) + instead of file splits — the challenge's own commit-changer precedent + generalized; locks and body text stayed in place (LRN-137). plugin S1 + kept the `plugin-advisor` NAME for the reasoner (repinned opus) — only + plugin-probe is a new file. +- seo/geo keep the OPUS pin (not sonnet+judge-override): fail-safe + direction — a forgotten override over-tiers, never downgrades. /harden + narrow-scope + /onboard report-only keep legacy no-MODE single-shot on + that pin. +- W0's seo-geo-integrity arbitrage was phantom (branch already merged) — + TODO.md corrected instead. +- Per-wave smokes ran in-wave as merge gates (confirmation-pass fix) — + all PASSED, disk-verified. Registry note: a NEW subagent_type registers + at next session start; typed resolution re-checked post-restart before + the W2 merge. + +## CHALLENGE LOG (final) + - Confirmation pass (fresh robustness challenger on v2): CONCERNS(2) — v1 fixes HOLD (doc-commit CHANGE SUMMARY, plugin-probe sonnet, rollback order, fable spike, RUNID); 2 new MAJORs + 1 MINOR opened by the revisions, all diff --git a/agents/client-handover-writer.md b/agents/client-handover-writer.md index 6d0697a..386ba4c 100644 --- a/agents/client-handover-writer.md +++ b/agents/client-handover-writer.md @@ -1,6 +1,6 @@ --- name: client-handover-writer -description: Final ship-and-handover orchestrator — called by /client-handover. Runs the audit/fix/gate pipeline (SEO+GEO+HARDEN to ≥17/20, live VALIDATE) inline on the big session model, then delegates the non-technical client deliverable (Markdown + branded HTML + PDF) to the sonnet-pinned handover-doc-writer. +description: Final ship-and-handover orchestrator — called by /client-handover. Runs the audit/fix/gate pipeline (SEO+GEO+HARDEN to ≥17/20, live VALIDATE) inline on the big session model with fable-pinned skill-runner children, then delegates the client deliverable to the two-mode handover-doc-writer (synthesize opus / render sonnet — BDR-077). tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch, WebFetch, AskUserQuestion, Agent --- diff --git a/skills/client-handover/SKILL.md b/skills/client-handover/SKILL.md index 2fb9a7a..dad6e8b 100644 --- a/skills/client-handover/SKILL.md +++ b/skills/client-handover/SKILL.md @@ -29,9 +29,11 @@ Load and follow strictly: - $HOME/.claude/agents/client-handover-writer.md Execute the CLIENT HANDOVER WRITER agent on this project. It runs the -audit/fix/gate pipeline INLINE on the big session model (gated above), then -delegates the client deliverable (Markdown + branded HTML + PDF) to the -sonnet-pinned `handover-doc-writer` subagent (BDR-066). +audit/fix/gate pipeline INLINE on the big session model (gated above), its +skill-runner children dispatched `model: "fable"`, then delegates the +client deliverable to the two-mode `handover-doc-writer` subagent — +synthesize on opus, render (Markdown + branded HTML + PDF) on the sonnet +pin (BDR-077). The agent runs a **ship-and-handover pipeline** with explicit gates: diff --git a/skills/commit-change/SKILL.md b/skills/commit-change/SKILL.md index 0e86daa..d47c53f 100644 --- a/skills/commit-change/SKILL.md +++ b/skills/commit-change/SKILL.md @@ -82,8 +82,9 @@ AskUserQuestion: uncommitted for a later run. - `edit ` → re-dispatch `commit-changer` with `MODE: propose` and the user's correction for step N folded into the prompt, so all grouping / - message judgment stays on the sonnet subagent (never redrawn inline on - the session model); show the redrawn plan and re-ask. + message judgment stays on the dispatched propose mode (`model="opus"`, + BDR-077 — never redrawn inline on the session model); show the redrawn + plan and re-ask. - `skip` → exit cleanly, no commits created, no `MODE: apply` dispatch. Note: if the propose run created a `chore/*` branch (gitflow aiguillage off a protected base), that branch stays checked out with the work