# PLAN r3 — model-router wave 4-A: transition logs + residuals (2026-10-11) r1 → r2 after simplicity CONCERNS(4), robustness CONCERNS(5), correctness FATAL(5) (BLOCKER: an agent's model move happens at spawn, invisible at turn.step); r2 → r3 after the confirmation (correctness CONCERNS(5)). Precedence r3 > r2 > r1. Contract `.claude/tasks/contracts/2026-10-11-model-router-w4a-logs-residuals-*.md`. Base: develop f1cea54. Corrected facts: `Plan` = {model, effort} and `mainPlan` discards the `Call` (its `why`); `agentPlan` returns `e.model` verbatim (the spawn hook rewrote it already); `TurnStepInput` carries only `agentId`; `Loop` = {effort, explicitEffort}; `Routed` = {phase, route, source} (no skill name, no rule word); `mainRoute` excludes `turnFloor`; `mainEffort().by` ∈ sticky|turn|floor|engine; no `effortSource`; `st.lastPlan` holds main's previous plan (nulled on /clear); `st.logged` / `turnLogged` are the dedupe sets; `AgentSpawnInput.parentModel` exists; `askOr` swallows a rejected ask into LATER; `forget not applied (${String(err)})` lives in `forgetWrite` (and its twin in `askCommand`); `buildMemory` has no models/tiers to validate phases; the user's override sets `verbose: true`. ## D1 Logs: `verbose` stays boolean; true = transitions only - The four firehose `vlog` sites are DELETED (step line, "answered by", spawn line, route-tool JSON, skill-path line). No `trace` level. `vlog` stays the single gate; `/route verbose on|off`, argumentHint and show texts unchanged. - Main transition: `planStep` returns `{ plan, why }` where `why` = per-axis cause words computed at decision time (no `$` call, no re-decision): effort cause from `mainEffort().by` + its slot (`sticky /route`, `route tool` (turn, source model), `skill