Files
claude_mac/.claude/tasks/plans/2026-07-19-model-tiering-v2-analysis.md
T
Bastien Chanot 1c2d30dbf0 chore(tasks): model-tiering v2 — analysis + challenged plan v3 + TODO reconcile
Plan challenged by 3 blind lenses + 1 confirmation pass (1 BLOCKER closed
by fable-dispatch spike, 6 MAJORs + 8 MINORs fixed by named changes, 0
deferred). TODO: seo-geo-integrity 'UNMERGED' note was stale (92301fe
already in develop) — corrected.
2026-07-19 19:51:06 +02:00

278 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ANALYSIS: model-tiering v2 — Fable = orchestration + plan/solution reflection only; dispatched fleet tiered opus/sonnet/haiku by task complexity; split mixed-tier agents
Produced by /analyze (main loop, Fable) + 4 subagent sweeps (2× agent-body
classification, dispatch map, test-lock inventory), 2026-07-19. Facts verified
against: model-routing.test.sh, challenge-plan.md, verify-secure-loop.md,
model-gate.md, BDR-050/061/066/076, LRN-113/125/126 (read in full inline).
Subagent-reported details not re-verified inline are marked (sub) — LRN-132
applies: re-verify load-bearing ones before cutting code.
## CONTEXT
- Current state (branch `feature/opus-pin-audit-agents`, 2 commits, UNMERGED):
main loop = session model (Fable; model-gate blocks small models in 15
reflection skills). Dispatched pins: opus = analyzer, plan-challenger,
seo-analyzer, geo-analyzer, validator-analyzer (BDR-076); sonnet = 14
executors; haiku = status-reporter. Unpinned = interviewer,
client-handover-writer (inline-load only).
- Two execution modes with OPPOSITE tier semantics: Agent() dispatch →
frontmatter pin applies; inline-load ("you become it") → pin INERT, runs on
session model. 20 inline-load sites exist.
- Target policy (user directive): Fable does ONLY main-loop orchestration +
reflection on plan/solution. Everything dispatched runs opus (deep judgment)
/ sonnet (standard execution) / haiku (mechanical) by ACTUAL task
complexity. Agents mixing classes get split. Skills adapted. Zero loss, zero
regression.
## KEY COMPONENTS — per-agent verdict vs target
### Fits, no change
| agent | tier | note |
|---|---|---|
| plan-challenger | opus | coherent monolith; verdict grammar + PROOF load-bearing |
| feater / bugfixer / hotfixer | sonnet | closed-plan executors; NEED-DECISION / BLOCKED valves |
| security-auditor | sonnet | deterministic SAST gate; `SECURITY — VERDICT:` grammar |
| scaffolder | sonnet (effort: high) | but see INERT-PIN below — never dispatched today |
| status-reporter | haiku | exemplar mechanical |
| client-handover-writer | none (inline orchestrator) | one haiku-able seam: STEP 1-2 git/context preflight |
| interviewer | none (inline) | INTERACTIVE — asks user inline; a dispatched agent cannot ask (uniform ban). Structurally main-loop. |
### Tier-down candidates (no split)
| agent | current → candidate | evidence |
|---|---|---|
| validator-analyzer | opus → sonnet | NOT mixed: runs external validators (authoritative), fixed severity tables, base-100 deduction scoring, allowlist-driven fix bundle; ambiguity punted to user §6. No deep judgment present. (sub) |
| onboarder | sonnet → haiku candidate | template-fill + conditional writes; only light stack-block filtering. (sub) Also inert-pin today. |
| release-executor | sonnet (keep, borderline) | mostly script runs + CHANGELOG templating, but carries a NEED-DECISION judgment valve (MAJOR-bump wording). (sub) |
### Split candidates (mixed classes inside one body)
| agent | geometry (factual boundary) | complication |
|---|---|---|
| seo-analyzer | collection (STEP 2-5 curls/CWV/GSC/greps → haiku-class) / judgment (STEP 6-11 sampling, competitive, scoring, triage → opus) / templating (STEP 12-14 bundle+report → sonnet/haiku) | BDR-061: no Agent tool in analyzers (single-dispatch doctrine) → a split must be ORCHESTRATED BY THE SKILL at L1 with disk handoffs, or BDR-061 revised (nesting works ≥2.1.172 per BDR-060, but version-robust-by-design was chosen). seo-data.test.sh locks `fetch.sh` wiring strings IN the agent body (6 locks). STEP 1-2 context feeds every later step → large LRN-126 contract surface. |
| geo-analyzer | identical 3-way geometry | same complications; shares severity vocab + sentinel |
| commit-changer | MODE propose (narrative reconstruction + capitalize routing = deep) / MODE apply (stage+commit = mechanical) — boundary ALREADY exists as dispatch modes | 2 dispatch sites in /commit-change; per-dispatch `model=` override is an available lighter mechanism than a file split |
| doc-syncer | drift detection + semantic doc-type analysis + MINOR/SIGNIFICANT calls (deep) / discovery + template render + PATCHED_FILES emit (mechanical) | 9 consumers on BOTH modes: dispatched ×2 (/doc, onboard) + inline-load ×7 (bugfix, hotfix, feat, init-project ×2, ship-feature, scaffolder) — LRN-125 dual-use-across-tiers hazard; runs its own user validation gate (STEP 8) → gate must be hoisted before any dispatch conversion |
| handover-doc-writer | synthesis/vulgarization STEP 10-12 (deep) / render+deterministic gates STEP 13-16 (mechanical) | skill-leak ban list + `HANDOVER-DOC REPORT` grammar must survive |
| plugin-advisor | detection PHASE 1 (mechanical) / complexity scoring + decision-table reasoning PHASE 2.5 (deep) | INERT PIN: inline-loaded ×4 (plugin-check, onboard, init-project, ship-feature), NEVER dispatched — sonnet pin is dead config; PHASE 4 asks the user (inline-only capability) |
| verifier | STEP 2 evidence adjudication = deep judgment inside a sonnet procedural gate | BDR-066 kept sonnet DELIBERATELY (oracle-anchored to contract, ≤3×/loop). Tier-up = design arbitrage, not a mechanical fix. contract-verifier.test.sh locks name/tools/body (33 asserts). |
### INERT-PIN finding (structural gap vs target)
scaffolder, onboarder, plugin-advisor are pinned sonnet but NEVER dispatched —
inline-load only → they run on Fable today. doc-syncer's doc-commit steps
(bugfix/hotfix/feat/init-project/ship-feature/scaffolder) also run inline on
Fable. Under the target policy these are EXECUTION tasks burning Fable — a
bigger real gap than any pin value. Each inline→dispatch conversion must hoist
its user gates into the dispatcher first (dispatched agents cannot ask).
## CONSUMER MAP (summary; full tables in the dispatch-map sweep)
- ~50 Agent() dispatch sites across 20 skills + 2 lib includes +
client-handover-writer (9 internal dispatches, incl. skills-via-general-purpose).
- 20 inline-load sites (7× doc-syncer, 4× plugin-advisor, 3× analyzer, 2×
interviewer, 1× each onboarder/scaffolder/client-handover-writer/refactorer).
- Includes: model-gate.md ×15 skills (+5 locked EXCLUDED), challenge-plan.md
×12, verify-secure-loop.md ×5, contract-interview ×5, capitalize-commit ×6,
doc-commit ×6.
- ~30 prose refs claim current tiers (sonnet-pinned X, opus-pinned Y, BDR-066/
BDR-076 citations) → all go stale on tier changes (LRN-113 sweep required).
- Only onboard uses explicit `model="opus"` dispatch params (7 sites); every
typed agent relies on frontmatter pin; ship-feature/init-project mandate
`model: "sonnet"` on SDD subagents by prose.
## CONSTRAINTS (zero-loss bar)
1. Verbatim machine-parsed grammars must survive verbatim: `VERIFY — VERDICT:
CONFORME | ECARTS(n) | ERROR(<reason>)`, `SECURITY — VERDICT: PASS |
BLOCK(n) | ERROR(<reason>)`, `CHALLENGE — LENS: … — VERDICT: SOLID |
CONCERNS(n) | FATAL(n)`, mandatory `PROOF:` lines, sentinel `READY TO APPLY
— awaiting dispatcher confirmation`, `<NAME>-EXEC REPORT` + `STATUS : DONE
| NEED-DECISION | BLOCKED`, `PATCHED_FILES:`, `COMMIT PLAN`, labeled score
lines parsed by client-handover extractors, `HANDOVER-DOC REPORT`.
2. BDR-050 + LRN-083: loops + decisions live in the MAIN loop; gates dispatched
fresh, blind, zero iteration history. Splits must not move loop decisions
into children.
3. BDR-061: seo/geo/validator have no Agent tool by doctrine (version-robust
single dispatch level). Any intra-audit split is skill-orchestrated at L1
unless BDR-061 is explicitly revised.
4. LRN-126: every implicit data path (ARGUMENTS flags, detected vars, STEP-N
side outputs) must cross the new handoff contracts explicitly; census-style
tests will NOT catch severed wires — a data-flow read per split is required.
5. LRN-125: no dual-use agent across tiers; audit consumer routes to the
judgment agent, execution consumer to the executor.
6. Interactivity: dispatched agents cannot ask the user. All human gates
(AskUserQuestion / inline approval) stay in main loop or inline-loaded
orchestrators. doc-syncer STEP 8 + plugin-advisor PHASE 4 gates must be
hoisted before dispatch conversion.
7. Test locks (fire on this refactor): model-routing (~61, epicenter — pins,
dispatch strings, gate wiring loops, `model="opus"` literals, BDR-076 token),
plan-challenger (~43 — frontmatter, grammar, challenge-plan doctrine
sentences incl. BDR-066 token), loops-light (40 — verify-secure-loop 10
sentences, sonnet pins, report grammars, "Agent" ABSENT from
bugfixer/hotfixer — substring-fragile), contract-verifier (33),
security-auditor (31), seo-data (6 body-wiring locks on seo/geo bodies),
loops-heavy (19 skill prose), review-guards G3 (strict YAML on every agent
file incl. new ones), no-vacuous-locks (no `\n` in new lock patterns —
LRN-093), model-check (10 — tier vocabulary big/small; a new tier taxonomy
must co-evolve witness + test). Census `for`-loops (model-routing:13-19,
plan-challenger:42) must be edited for any new/renamed gated skill.
8. model-gate.md prose has NO deterministic lock (include-path only) — free to
rewrite, but behavioral-only verification.
9. Gitflow: feature branch(es) via gitflow.sh; no merge without human signal.
Unmerged branches in flight: `feature/opus-pin-audit-agents` (this refactor
supersedes/absorbs it), `bugfix/seo-geo-integrity` (10 commits touching the
seo surface → sequencing/conflict risk with a seo-analyzer split).
10. BDR-076 survival: opus tier for judgment agents survives as baseline;
validator-analyzer's opus pin would be superseded (tier-down); seo/geo pins
refined by splits; challenge-plan/plan-challenger doctrine text + census
§11 rewritten again.
## RISKS
- Severed implicit data paths on splits (LRN-126 precedent: 2 silent input
losses caught only by whole-branch review) — probability: HIGH without a
per-split data-flow pass.
- Consumer staleness (LRN-113): ~30 prose refs + 9 identical gate preambles +
2 census loops — partial sweep leaves contradictory doctrine — probability:
HIGH without whole-surface grep + new guards.
- Lost human gates on inline→dispatch conversions (doc-syncer STEP 8,
plugin-advisor PHASE 4) — probability: MEDIUM-HIGH; hoist-first pattern
exists (BDR-066 wave 4 did exactly this for client-handover).
- Census under-coverage: NEW agent files are silently unlocked unless
model-routing/census extended per agent (worse than a red) — MEDIUM.
- haiku reliability on long tool chains (seo/geo collection legs: GSC, CWV,
curl loops, retry policies): only haiku precedent is status-reporter
(short, deterministic) — MEDIUM; unproven.
- Split overhead: 3-dispatch audit pipeline re-serializes STEP 1-2 context per
child; latency + token duplication vs today's monolith — MEDIUM.
- Merge sequencing with `bugfix/seo-geo-integrity` (10 commits on seo surface)
— MEDIUM.
- Subagent-report trust (LRN-132): (sub)-marked classifications need spot
re-verification during design — MEDIUM.
## OPEN QUESTIONS (design arbitrage needed)
1. verifier: keep sonnet (BDR-066 oracle-anchored rationale) or lift to opus
(STEP 2 adjudication is the correctness gate)?
2. seo/geo split mechanics: skill-orchestrated L1 pipeline (BDR-061-compatible)
vs nested dispatch inside the analyzer (requires revising BDR-061;
version floor OK per BDR-060)?
3. Which inline-loads convert to dispatches (scaffolder, onboarder, doc-syncer
doc-commit steps, plugin-advisor detection) vs stay inline as reflection?
4. commit-changer: file split vs per-mode `model=` override at the 2 existing
dispatch sites?
5. haiku scope: which mechanical halves actually go haiku vs sonnet, given the
reliability unknown on long tool chains?
6. Gate taxonomy: keep binary big/small model-gate (guards main loop only) or
extend model-check.sh to the full 4-tier vocabulary?
7. Sequencing: land/absorb `feature/opus-pin-audit-agents` and
`bugfix/seo-geo-integrity` before or during this refactor?
## DESIGN AMENDMENT (2026-07-19, user arbitrage — supersedes open questions)
User approved all 7 recommendations, PLUS one addition:
**No-inherit rule + fable pins.** No dispatched agent may inherit the session
model anywhere. Every dispatch site carries an explicit tier: typed agents via
frontmatter pin (`model: fable|opus|sonnet|haiku`), built-ins
(general-purpose / Explore / Plan) via a `model=` param at EVERY call site.
Rationale: sessions may run on another model (gate admits Opus; user may
launch anything) — inheritance would silently mis-tier dispatched work.
`model="fable"` lands where a dispatched child performs REFLECTION /
ORCHESTRATION on behalf of the main loop:
- client-handover-writer's 8 internal general-purpose skill-runner dispatches
(/seo, /harden, /cso, /commit-change, /web-validate runs) — today they
inherit; they host gated orchestration → `model="fable"`.
- Doctrine line (model-gate.md or routing doctrine): ad-hoc reflection
dispatches from the main loop (Explore digest, Plan, general-purpose) carry
`model="fable"`; non-reflection ad-hoc dispatches carry their complexity
tier. New census locks accordingly.
- No TYPED agent moves to fable tier (plan-challenger/analyzer stay opus per
approved verdicts). Inline-loads that remain (interviewer,
client-handover-writer, analyzer-in-/analyze + DEBUG, init STEP 2) ARE the
main loop — covered by model-gate, not pins.
- External/gstack skills with inheriting general-purpose dispatches
(design-shotgun, review, graphify) — external ownership (BDR-015 class):
covered by doctrine, not edited, unless owned locally. Verify ownership at
implementation.
## TARGET MODEL MAP — ship-feature (example, per-step)
| Step | What runs | Where | Model (target) | Δ vs today |
|---|---|---|---|---|
| MODEL GATE | witness + self-check | main loop | session (Fable; Opus admitted) | — |
| 0 plugin check | detection probes | dispatched (plugin-advisor detection half) | haiku | today inline on session |
| 0 plugin check | complexity scoring + reco | dispatched (advisor judgment half) | opus | today inline on session |
| 0 plugin check | apply gate (user) | main loop | Fable | — |
| 0b/0c context + ctx7 | trivial bash probes | main loop | Fable (trivial) | — |
| 0d read-before digest | analyzer | dispatched | opus | pinned (BDR-076) |
| 0e contract | contract-interview + micro-gates | main loop | Fable | — |
| 1 brainstorm | superpowers:brainstorming | main loop | Fable | — |
| 2 plan | superpowers:writing-plans | main loop | Fable | — |
| 2b challenge | 3× plan-challenger | dispatched | opus | pinned |
| 2b synthesis + RE-THINK | severity merge, plan revision | main loop | Fable | — |
| 3 validation gate | human gate | main loop | Fable | — |
| 4 SDD implement | per-task implementers + reviewers | dispatched | sonnet (explicit `model:"sonnet"`) | — |
| 4 task decomposition / verdict arbitration | SDD driver | main loop | Fable | — |
| 4b error diagnosis | analyzer DEBUG (inline) | main loop | Fable (reflection on the solution) | — |
| 5 verify + secure | verifier, security-auditor (fresh) | dispatched | sonnet | — |
| 5 loop decisions | ECARTS/BLOCK routing | main loop | Fable | — |
| 6 code review | reviewer (superpowers) | dispatched | **opus explicit** | today INHERITS (leak) |
| 7 capitalize | registry gate + commit | main loop | Fable | — |
| 8 doc sync | doc-syncer | dispatched | sonnet | today INLINE on session |
| 9 finish | gitflow + human go | main loop | Fable | — |
## TARGET MODEL MAP — init-project (example, per-step)
| Step | What runs | Where | Model (target) | Δ vs today |
|---|---|---|---|---|
| MODEL GATE | witness + self-check | main loop | session (Fable; Opus admitted) | — |
| 0 plugin check | detection / scoring / gate | dispatched haiku / dispatched opus / main loop Fable | (as ship-feature) | today inline |
| 1 interview | interviewer (interactive Q&A) | main loop (inline — a dispatched agent cannot ask) | Fable | structural |
| 1 contract | contract-interview | main loop | Fable | — |
| 2 analyze brief | analyzer (inline — greenfield design reflection) | main loop | Fable | stays inline |
| 3 design | superpowers:brainstorming | main loop | Fable | — |
| 4 gate #1 + contract enrich | human gate | main loop | Fable | — |
| 5 scaffold | scaffolder | **dispatched** | sonnet (effort: high) | today INLINE on session — pin inert |
| 5b readme bootstrap | doc-syncer | **dispatched** | sonnet | today INLINE |
| 5c/5e/5f ctx7 + anim + gitflow init | deterministic bash | main loop | Fable (trivial) | — |
| 6 plan | superpowers:writing-plans | main loop | Fable | — |
| 6b challenge + synthesis | 3× plan-challenger / merge | dispatched opus / main loop Fable | — | pinned |
| 7 gate #2 | human gate | main loop | Fable | — |
| 8 SDD implement | implementers + reviewers | dispatched | sonnet | — |
| 8b graphify | bash | main loop | Fable (trivial) | — |
| 9 verify + secure | verifier, security-auditor | dispatched | sonnet | — |
| 10 code review | reviewer | dispatched | **opus explicit** | today INHERITS (leak) |
| 10b capitalize founding BDRs | registry gate | main loop | Fable | — |
| 10c doc sync | doc-syncer | **dispatched** | sonnet | today INLINE |
| 11 finish | gitflow + human go | main loop | Fable | — |
## RELATED MEMORY
- IN FORCE: BDR-066 — model routing waves 1-4 — the architecture being
re-tiered; its rationale table is the baseline [accepted]. BDR-076 — opus
pins on dispatched judgment — starting state, partially superseded by the
new target [accepted, this branch]. BDR-050 — verify+secure loops in main
loop, gates fresh [accepted]. BDR-049 — verifier fresh+blind+disk-contract
[accepted]. BDR-048 — pinned semgrep gate [accepted]. BDR-061 — fix-bundle
→ L1 apply, analyzers have no Agent tool [accepted]. BDR-060 — nested
dispatch floor v2.1.172 [accepted]. BDR-075+amendment — challenge phase in
12 orchestrators [accepted]. BDR-025 — unknown never silently passes
[accepted]. BDR-022 — doc-syncer never touches .claude/ [accepted].
LRN-125 — no dual-use across tiers. LRN-126 — splits sever implicit data
paths; forward every consumed field. LRN-113 — whole-surface sweep + guard.
LRN-083 — loops in main loop. LRN-093 — no `\n` in grep locks. LRN-096 —
flip-test new guards. LRN-112 — nesting supported. LRN-105/107 — explicit
tool bans in read-only mandates. LRN-011 — one subagent, N gated scores
(alternative to 3-way split). LRN-057 — match mechanism to consumer.
LRN-102 — final-text-only rendering guarantee. LRN-132 — subagent claims
need verification.
- ALREADY SEEN: BLK-004 — renamed/deleted agent files broke a consumer wrapper
[resolved] (rename sweep discipline). EVAL-023 — BDR-066 post-merge ronde
found 5 edge gaps [done] (plan a ronde here too). EVAL-026 — 3-way plan
challenge caught 4 real BLOCKERs on its own plan [done] (run it on this
refactor's plan).
- NON-BINDING: ~200 remaining headings surfaced nothing binding beyond the
above — BDR-067/068/069 (release/permissions), LRN-first-100 (tooling),
BLK-005..017 (env) — counted, not detailed.
- SELECTION: scanned ~230 headings — surfaced 28 = in-force 22 + seen 3 +
non-binding (counted).