diff --git a/.claude/memory/journal.md b/.claude/memory/journal.md index 3cdf920..799cddf 100644 --- a/.claude/memory/journal.md +++ b/.claude/memory/journal.md @@ -388,3 +388,5 @@ rules: - model routing WAVE 3 (same branch): /bugfix + /code-clean split like /feat — reflection inline, sonnet executors (bugfixer, code-cleaner). code-clean refactor now runs on sonnet (inline-load pin was inert). consumers rerouted (hotfix deeper-bug→/bugfix skill; onboard/tour read-only audit→big-model agent). Explore kept built-in (inherits big). census 42/0, loops-light 35/0. Branch still unmerged. - model routing waves 1-3 MERGED into develop (e5c7c51); LRN-125 added. WAVE 4 started on feature/client-handover-dispatch (off develop): client-handover doc-gen → sonnet. REDACTION-ONLY (user flipped from whole-writer — nested audits must run big either way). client-handover-writer trimmed to ship pipeline (STEP 1-8 preserved byte-for-byte) + delegates writing to NEW sonnet handover-doc-writer (gate-free, STEP 9-16). client-handover joins gated group. census 46/0. NOTE: a Task-20 implementer ran `git checkout -- settings.json`, discarding user /model=opus working-tree state (LRN-098) — flagged to user (re-run /model). Lesson worth an LRN: constrain SDD implementers from git ops on files outside their task. - wave-4 FINAL REVIEW (opus whole-branch): all 7 deliverable invariants hold, child gate-free, PACKAGE complete. Found 3 real regressions from the split — FIXED inline: (I2) DEPLOY_HINTS severed STEP2→STEP14 + (I3) --skip-seo flag dropped → both now forwarded via PACKAGE (parent resolved-list + dispatch template; child INPUT contract + gate); (I1) §7/§8 annex numbering drift in STEP 13/14 (operative steps said §6/§7 = stale 5-chapter scheme) realigned to authoritative §7/§8 + hard-rule renumbering M1/M2/M3 (Chapter 2/3/4 caps → 3/5/6; chapters 1–3 → 1–5, matching the gate windows). census lock added: lacks 'Agent(' on child (M5). census 47/0, shellcheck clean. Branch NOT merged (awaiting human signal). +- waves 1-4 MERGED to develop (d8917bf). LRN-126/127 added. +- post-merge RONDE (user "fais une ronde"): 4 big-model analyzer audits over 72 skills + 21 agents. Verdict: dispatch-graph INTACT (0 regressions), loops CLOSE (0 broken), tiering CORRECT (every dispatched agent), client-handover data-flow wired. The refactor preserved/improved everything it touched. NOTE: darwin-skill is a skill-PROMPT optimizer (mutates SKILL.md) — wrong tool for a post-merge verify; used bespoke analyzer fan-out on the big model (audit=reflection, dogfooded). Ronde surfaced edge findings → fixed on bugfix/model-routing-edge-fixes: F1 feater applier severed CONTRACT (real bug, LRN-126 instance — /seo,/geo dispatch feater as L1 applier with no CONTRACT but it mandated "read CONTRACT FIRST"; gave it hotfixer's applier carve-out); F2 /refactor inline-load→dispatch refactorer (sonnet pin was inert); F3 /analyze +MODEL GATE (ungated reflection); F4 interviewer drop inert sonnet pin; F5 census locks the ABSENT pin on seo/geo/validator-analyzer + client-handover-writer + interviewer (a stray sonnet pin would silently downgrade a live audit). census 47→57. Branch NOT merged. diff --git a/.claude/tasks/TODO.md b/.claude/tasks/TODO.md index 8d17db9..042ad35 100644 --- a/.claude/tasks/TODO.md +++ b/.claude/tasks/TODO.md @@ -1,5 +1,23 @@ # TODO +## 2026-07-16 — model-routing edge fixes (bugfix/model-routing-edge-fixes) +Post-merge ronde (4 big-model audits: dispatch-graph INTACT, loops CLOSE, +tiering CORRECT, data-flow client-handover wired). Fixing the edge findings +the ronde surfaced. Branch off develop, unmerged — human gate. +- [x] F1 (real bug) feater applier carve-out — /seo,/geo dispatch feater as + L1 applier with NO CONTRACT, but feater mandates "read CONTRACT FIRST" + (hotfixer has the carve-out, feater didn't) → mirror hotfixer.md:16-45. +- [x] F5 (guard) census: lock the ABSENT model: pin on seo/geo/validator- + analyzer + client-handover-writer (stray sonnet pin would silently + downgrade a live audit, uncaught). +- [x] F4 (cleanup) drop interviewer's inert `model: sonnet` (reflection role, + inline-loaded by gated init-project) + census guard. +- [x] F2 (tier) /refactor inline-load → true-dispatch refactorer (sonnet pin + was inert). refactorer verified dispatch-safe (no Ask/Agent, input=target). +- [x] F3 (gate) /analyze add MODEL GATE (inline-loads the analyzer reflection + agent, was ungated + undocumented). census: +analyze gated, +refactor excluded. +- [x] verify: census 57/0, shellcheck clean (my files), full suite green; NO merge. + ## 2026-07-15 — model routing (feature/model-routing) Spec + plan in docs/superpowers/ (transient, BDR-065). BDR-066. Branch unmerged — human gate. diff --git a/agents/feater.md b/agents/feater.md index 960f16a..9027847 100644 --- a/agents/feater.md +++ b/agents/feater.md @@ -7,9 +7,17 @@ model: sonnet # FEATER — plan executor -You receive a CLOSED plan from the /feat orchestrator. Your job is faithful -execution, not design. The thinking already happened; every choice you would -want to make was either made in the plan or is a NEED-DECISION to report. +You execute work ALREADY decided upstream — faithful execution, not design. +The thinking already happened; every open choice is a NEED-DECISION to +report, never an improvisation. Two dispatch sources, same job: + +- **/feat orchestrator** — a CLOSED plan + CONTRACT (see INPUT). +- **audit dispatchers (/seo, /geo)** — you are the L1 fix-bundle applier for + the larger items (new legal/city pages, `.htaccess`, sitemaps); the + dispatch prompt hands you a bundle item inline (files, concern, current, + expected fix) with NO CONTRACT. Apply exactly that item, self-verify, do + not commit. There is no FILE SCOPE contract on this path — the named files + in the item ARE the scope. ## INPUT (in the dispatch prompt) @@ -21,13 +29,20 @@ want to make was either made in the plan or is a NEED-DECISION to report. - `GAPS` (re-dispatch only): verifier/security verdict lines — fix ONLY those, touch nothing else. +Applier path (/seo, /geo): no CONTRACT/PLAN/BRANCH keys — the bundle item in +the prompt is the work to apply. Skip the contract read; the `## OUTPUT` +report below is optional on this path (the dispatcher needs the edit applied ++ self-verified, not the report grammar). + ## EXECUTION RULES - Follow the plan to the letter. A plan hole or an open choice (naming, data shape, API surface, dependency) → STOP, report `NEED-DECISION` with the precise question. Never improvise a design decision. - Stay inside the contract FILE SCOPE. A needed file outside it → - `NEED-DECISION` (the orchestrator owns scope changes); don't touch it. + `NEED-DECISION` (the orchestrator owns scope changes); don't touch it. On + the applier path the scope is the files named in the bundle item — apply + only those. - Write tests alongside the code, as the plan names them. Run the relevant suite incrementally; run it fully before reporting. - Follow existing code patterns and CLAUDE.md limits (function size, diff --git a/agents/interviewer.md b/agents/interviewer.md index f0eb232..bbddf47 100644 --- a/agents/interviewer.md +++ b/agents/interviewer.md @@ -2,7 +2,6 @@ name: interviewer description: Gather project info. Ask targeted questions, produce PROJECT BRIEF. First step of project init. tools: Read -model: sonnet --- # INTERVIEWER diff --git a/lib/tests/model-routing.test.sh b/lib/tests/model-routing.test.sh index c72347b..f0d08f5 100755 --- a/lib/tests/model-routing.test.sh +++ b/lib/tests/model-routing.test.sh @@ -9,12 +9,12 @@ has() { if grep -qF "$2" "$R/$1"; then ok; else ko "$1 missing: $2"; fi; } lacks() { if grep -qF "$2" "$R/$1"; then ko "$1 must NOT contain: $2"; else ok; fi; } fm_lacks() { if awk 'NR<=10' "$R/$1" | grep -qF "$2"; then ko "$1 frontmatter must NOT contain: $2"; else ok; fi; } -# 1) gate wired in the 14 reflection orchestrators -for s in ship-feature init-project feat bugfix onboard seo geo web-validate harden audit-delta tour code-clean hotfix client-handover; do +# 1) gate wired in the 15 reflection skills (orchestrators + /analyze) +for s in ship-feature init-project feat bugfix onboard seo geo web-validate harden audit-delta tour code-clean hotfix client-handover analyze; do has "skills/$s/SKILL.md" 'lib/model-gate.md' done -# 2) gate NOT wired in the excluded skills (encodes the spec exclusion list) -for s in commit-change doc status release-candidate; do +# 2) gate NOT wired in the pure-execution/read-only skills (exclusion list) +for s in commit-change doc status release-candidate refactor; do lacks "skills/$s/SKILL.md" 'lib/model-gate.md' done # 3) executor + gate pins @@ -53,6 +53,18 @@ has "agents/handover-doc-writer.md" 'model: sonnet' lacks "agents/handover-doc-writer.md" 'AskUserQuestion' lacks "agents/handover-doc-writer.md" 'Agent(' has "agents/client-handover-writer.md" 'subagent_type="handover-doc-writer"' +# 10) post-merge edge fixes (ronde): F1 feater applier carve-out, F2 /refactor +# dispatch + pin, F3 /analyze gated (in loop 1), F4 interviewer un-pinned, +# F5 audit agents' ABSENT pin locked (a stray sonnet pin would silently +# downgrade a live audit even though the skill's gate passed) +has "agents/feater.md" 'Applier path' +has "skills/refactor/SKILL.md" 'subagent_type="refactorer"' +has "agents/refactorer.md" 'model: sonnet' +fm_lacks "agents/seo-analyzer.md" 'model:' +fm_lacks "agents/geo-analyzer.md" 'model:' +fm_lacks "agents/validator-analyzer.md" 'model:' +fm_lacks "agents/client-handover-writer.md" 'model:' +fm_lacks "agents/interviewer.md" 'model:' printf 'model-routing census: %d pass, %d fail\n' "$pass" "$fail" [ "$fail" -eq 0 ] diff --git a/skills/analyze/SKILL.md b/skills/analyze/SKILL.md index 95cf3cb..d8b9416 100644 --- a/skills/analyze/SKILL.md +++ b/skills/analyze/SKILL.md @@ -5,6 +5,10 @@ argument-hint: -allowed-tools: Read, Write, Edit, Grep, Glob, Bash +allowed-tools: Read, Write, Edit, Grep, Glob, Bash, Agent --- -Load and follow strictly: `$HOME/.claude/agents/refactorer.md`. +Dispatch the refactorer executor — behavior-preserving norm application is +closed execution, so it runs pinned on **sonnet** (not the big session +model). The scope you name is the only reflection; the agent applies norms. -If unreachable, emit `Refactorer agent missing.` and STOP. Never improvise — silent behavior change is unsafe. +``` +Agent(subagent_type="refactorer") +prompt: "Refactor to strict project norms, preserving external behavior +exactly (zero behavioral regression, existing tests must pass). Target: +$ARGUMENTS" +``` -$ARGUMENTS +If the refactorer agent is unavailable, emit `Refactorer agent missing.` and +STOP — never improvise, silent behavior change is unsafe.