chore(memory): model-router wave 0 — plan, LRN-203/204, BLK-029, journal

This commit is contained in:
bchanot
2026-10-08 15:25:11 +02:00
parent f24682b3f3
commit b73d1b127e
5 changed files with 188 additions and 0 deletions
+9
View File
@@ -1748,3 +1748,12 @@ Rule: when editing a doctrine file under structure locks, grep the test's lock s
## LRN-202 — Reading a stderr-then-stdout verb from a hook: `out=$(cmd 2>&1)`, last line = word, prefix line = reason; no temp file; lib path absolute before any cd
- **Context**: unpushed-guard plan used `2>"${TMPDIR:-/tmp}/x.$$"` + cat + rm: fail-OPEN when TMPDIR is full (`|| mode=auto`), predictable path, symlink-followable on shared /tmp, leaked on kill; `mode=$(cmd 2>&1 >/dev/null)` captures ONLY stderr. push-guard's `mktemp` variant added `set -u` trap hazards. The verb writes its stderr line BEFORE its stdout word in one process, so `${out##*$'\n'}` is the word and the `gitflow.sh push-mode:` line is the reason (select by prefix, not `head -1`: a bash startup warning could precede it). Resolve the lib path to an absolute one BEFORE the hook's `cd "$cwd"` (a relative invocation otherwise resolves into the target repo).
- **Apply**: hooks never touch temp files for a one-line capture; anything but the expected word is treated as the fail-closed state, never as the default. Links [[BDR-114]], [[LRN-196]], [[LRN-199]].
## LRN-203 — Mod hooks: model ALIAS set by a hook resolves through stale table (`sonnet` → `claude-sonnet-5`, 404); write full ids; oracle = transcript fields, not `CLAUDE_EFFORT`
- **Context**: model-router spike 2026-10-08, CLI 2.1.294. `agent.spawn` or `tool.call Agent` param rewrite with alias `sonnet` → API got `claude-sonnet-5`, HTTP 404 model_not_found. Same alias passed by the model in the Agent tool param → `claude-sonnet-5-5`, fine. Full id `claude-sonnet-5-5` from hook → fine, every step answered by 5-5. Agent tool schema enum refuses full ids, so full ids reach API only via hooks. Effort rewrite at `turn.step` proven by transcript record field `effort` (high → medium); `CLAUDE_EFFORT` env + `perTurnEffort` stay at turn setting, blind to per-request rewrite.
- **Apply**: any mod that sets a model carries its own alias → full-id table (one place to bump per tier release). Verify routing with transcript `message.model` + record `effort`, never env vars. Links [[BDR-108]] (aliases as pins: still right at the Agent-tool call site, wrong inside hooks), [[BLK-029]].
## LRN-204 — Main-loop model switch mid-turn works, costs one cold-cache step on the full context per switch INTO a model; return free (per-model cache, 1 h TTL)
- **Context**: spike 2026-10-08, fable → `claude-sonnet-5-5`/low for 3 steps on ~260k context, then back. Conversation intact (tools, results, thinking blocks from another model in history: no error). First sonnet step cache_read 0 (full 260k billed), next steps 237k cached; return to fable step read 263k cached.
- **Apply**: switch the main loop only for spans long enough to amortize one uncached read of the whole context (many mechanical steps), never per tool call; short mechanical work → small-context haiku sub-agent. Haiku 4.5 window 200k: a long main loop cannot go to haiku at all. Flag off by default in model-router. Links [[LRN-203]], [[BDR-107]].