P1: model routing — preset pins, per-role seats, opus-4.8 default - #41
Conversation
The alias table lived in dev-review.sh, unreachable to the document pipeline and to any lib consumer; the base default still pinned the stale claude-opus-4-6. Move resolve_claude_model_alias into lib/co-evolution.sh as the one source of truth and resolve the base CLAUDE_MODEL default through `best` so a model bump is a one-line edit and every seat inherits the current Opus line. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Preset codex seats were left to the local codex config.toml, so the same --preset run resolved to different models on different machines and state.json recorded (default). Pin every codex preset seat to gpt-5.5 at xhigh (executor in codex-build; composer+verifier in claude-build) via fill-if-empty so explicit flags/env still win. Cross-machine reproducibility now holds for preset runs; ad-hoc runs may still inherit local config. Sims assert the pinned model reaches argv; docs and the runner-scorer contract move in lockstep. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every seat could inherit a wrong or unstated model. Give the document pipeline its own composer/reviewer seats (COMPOSER_MODEL/REVIEWER_MODEL + efforts, and matching flags) and dev-review's bounce counterparty its BOUNCER_MODEL seat, each layered onto the globals around the invocation with the same cross-agent leak guard so a claude-shaped override never reaches a codex argv or vice versa. Deliberately no global --effort on the bouncer: a bounce has two roles with different needs. Banners now log each role's resolved agent:model@effort (or inherit:<global>), and seat_models.bouncer lands in state.json. Hermetic sims prove the seat values reach argv with no cross-leak. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nothing documented which model each seat should run or how the axes trade off, so choices drifted per session. Pin the seat->model table and the decision rules (intelligence > taste > cost; gpt-5.5 for bulk under the codex-guard cap; the sonnet-wrapper pattern for reaching gpt-5.5 from Agent calls; Haiku unused in this repo) so routing is a lookup, not a judgment call each time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A preset run still recorded seat_models.bouncer as (default): the A-8 bounce seat had no preset pin, so a preset run was not fully reproducible and violated the "no (default) seat" bar. Pin it to the agent that actually reviews under each preset (codex-build: codex gpt-5.5; claude-build: opus best), so every seat in a preset run resolves concrete. Sims assert seat_models.bouncer and that no seat is (default). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regression: `--model o4-mini --preset codex-build` silently ran gpt-5.5 because the preset's seat pin outranked the flag-set base. Presets track which seat models THEY supplied (empty-at-expansion marker), so an explicit --model clears preset-supplied codex-seat pins (falling through to the flag) while user-set env seats keep winning, restoring master precedence without weakening the pins for flagless preset runs. The claude side keeps its pre-existing preset-wins precedence but the shadow now logs a WARNING instead of being silent. Sims lock both directions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A codex-shaped COMPOSER_MODEL silently no-oped on the claude compose phase: the leak guard dropped it correctly but invisibly, so operators could not tell which model actually composed. Keep the drop, log it explicitly, and add the compose phase's own resolved seat to the startup banner (it can differ from the bounce composer's seat, which runs on the other agent). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The adapter table predated F-5a and v1.5: it pinned claude-opus-4-6 and a --max-turns flag the adapter never passes, and omitted the tool flags and codex --skip-git-repo-check that it does. Match the table to the real invoke_claude/invoke_codex argv so readers stop copying a dead command line. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 97f00582fe
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| case "$seat" in | ||
| composer) COMPOSER_MODEL="" ;; | ||
| executor) EXECUTOR_MODEL="" ;; | ||
| verifier) VERIFIER_MODEL="" ;; |
There was a problem hiding this comment.
Clear the paired effort when overriding preset pins
When --model o4-mini --preset codex-build --verifier codex is used, this arm clears only VERIFIER_MODEL; the paired preset VERIFIER_EFFORT=max remains. Because the model is now blank, apply_seat_env no longer sees the original Claude-shaped best@max pair to drop, so the Codex verifier is invoked with -c model=o4-mini -c model_reasoning_effort=max even though the guard above documents max as off Codex's scale. Clear the paired effort too, or run the wrong-agent guard before removing the model.
Useful? React with 👍 / 👎.
| export CODEX_REASONING_EFFORT="${effort:-$CODEX_EFFORT_BASE}" | ||
| else | ||
| case "$model" in | ||
| gpt-*|codex*) model=""; effort="" ;; |
There was a problem hiding this comment.
Recognize o-series Codex models in the leak guard
The new document-pipeline guard only treats gpt-* and codex* as Codex-shaped, but Codex/OpenAI model values such as o4-mini are accepted elsewhere in this commit. With the default agents, co-evolve --composer-model o4-mini ... applies that value to the initial Claude compose phase instead of dropping it as a wrong-agent override, so Claude is invoked as --model o4-mini before the Codex composer pass can run. Expand the predicate (for example to include o[0-9]*/o*-* or centralize model-kind detection) so these overrides fall back consistently.
Useful? React with 👍 / 👎.
Phase 1 of the workflow-upgrade plan (plan @ e6db065,
.planning/notes/2026-07-05-workflow-upgrade-plan.md).What changed (8 commits)
lib/co-evolution.sh:55-77—resolve_claude_model_aliascentralized in lib (single source); base defaultclaude-opus-4-6→bestalias →claude-opus-4-8.dev-review/codex/dev-review.sh:144-163— presets pin every seat: codex seats →gpt-5.5 @ xhigh, incl. the bounce counterparty;seat_modelsshows{composer,executor,verifier,bouncer}all concrete, never(default).evals/RUNNER-CONTRACT.mdbumped 1.1→1.2 (optionalseat_models.bouncer).co-evolve-bouncer.sh— per-role seats for the document pipeline (COMPOSER_MODEL/EFFORT,REVIEWER_MODEL/EFFORT+ four per-seat flags; no global--effortby design), same cross-agent leak guard as dev-review; banner logs each role's resolvedagent:model@effortincl. the compose seat.0bef341): preset-supplied seat pins tracked viaPRESET_SUPPLIED_MODEL_SEATS; explicit--modelclears a codex preset pin (flag wins, preset effort survives — matches master) with a NOTE;--claude-modelvs claude pins keeps master's pre-existing precedence, now with a WARNING.CLAUDE.md— Model Routing section (seat table + rules: escalate-on-quality-miss, intelligence>taste>cost, gpt-5.5 wrapper pattern, no-Haiku scoped to this repo).tests/doc-pipeline-seats-simulation.sh(5 scenarios); preset-expansion grown to 13 incl. argv-level pin/override assertions.Verification
claude -p --model claude-opus-4-8→ "ok";codex exec -c model=gpt-5.5→ "ok" (both IDs accepted; no fallback needed).runners/codex-ps/**: zero diff (verified by reviewer).Notes: cross-machine reproducibility is guaranteed for preset runs; ad-hoc non-preset runs may still inherit local codex config (documented). Earlier 24/27–25/27 suite results were artifacts of two concurrent suite runs sharing one worktree (sims cross-read
runs/vialatest_run_dir()); chip filed for that harness assumption.🤖 Generated with Claude Code