Skip to content

fix(server): make Auto routing actually apply to turns sent from the app - #100

Merged
awtprod merged 1 commit into
mainfrom
fix/route-client-turns-through-efficiency
Sep 27, 2026
Merged

awtprod merged 1 commit into
mainfrom
fix/route-client-turns-through-efficiency

Conversation

@awtprod

@awtprod awtprod commented Sep 27, 2026

Copy link
Copy Markdown
Owner

Andrew set a new thread to Auto · Balanced. The next message showed Manual again, and no routing had happened. It turns out auto routing has never run for turns sent from the app since the upstream T3 Code v0.0.32 merge (#18, 2026-08-08). Production has zero turns with an efficiency_decision_json.

Cause. Auto routing (Jev tier and kind judgment, sticky continuations, the Opus 5.5 defaults) lives in OrchestrationCommandDispatcher. The fork's first PR (#1) had ws.ts dispatch through it. The v0.0.32 merge replaced that with a direct orchestrationEngine.dispatch path, so client commands skipped routing, and nothing reported it. The bootstrap thread.create in ws.ts also dropped routingMode and efficiencyTier, so even a routed first turn would have created a manual thread. That is why the composer snapped back to Manual.

Fix. It is the smallest change that restores the pre-merge behaviour:

  • The dispatcher exposes its existing routing step as resolve(command).
  • ws.ts runs it on every normalized command (inside the same startup gate) before its own bootstrap or direct dispatch. Client origin, analytics, the deletion fence and archive handling are unchanged.
  • The bootstrap thread.create now forwards routingMode and efficiencyTier.
  • Once the server is ready, startup.enqueueCommand runs commands inline, so a Jev call doesn't queue other clients' commands.

Tests. There are new router-seam tests in server.test.ts that go through the real dispatchCommand RPC:

  • an auto turn gets an efficiencyDecision and creates an auto thread with the decided model and tier;
  • with efficiency off, or on a manual turn, the dispatched command is unchanged.

All three fail if only the ws.ts change is reverted.

Verification (in apps/server):

  • vp test run src/efficiency src/server.test.ts: 238/238
  • vp test run src/orchestration: 415/415
  • vp test run src/command-center: 304 pass, 11 skipped
  • tsgo --noEmit: exit 0

server.test.ts and ProviderCommandReactor.test.ts each have one test that fails when the host's T3CODE_WEB_PUSH_SUBJECT or T3_SANDBOX_* variables leak into the test environment. That is pre-existing and not touched here.

Found but deliberately not changed. ensureThreadSandbox, the dispatcher's thread-creation sandbox setup, is bypassed on the same path. As a result, app-created threads record sandbox: null and any client sandboxConfig is dropped. When an image is configured, ProviderCommandReactor.ensureExecutionTarget still provisions a sandbox lazily at the first turn, so sandboxes work. The differences are that the base commit is pinned at first turn instead of at creation, and per-thread sandboxConfig is lost. That is a separate decision.

Diagnosis and review: claude-opus-5-5 via Claude Code. Implementation: claude-opus-5-5 subagent.

🤖 Generated with Claude Code

… again

Interactive auto routing (tier/kind judgment, sticky continuations, the
Opus 5.5 defaults) lives in OrchestrationCommandDispatcher's
resolveEfficiency, which only runs inside dispatchNormalized. When the fork
started, ws.ts dispatched every client command through that dispatcher. The
upstream T3 Code v0.0.32 merge (84b585b, PR #18) replaced it with ws.ts's
own dispatchBootstrapTurnStart / dispatchFromClient path straight to the
engine, so since then no turn sent from the app has been routed: none carry
an efficiency decision, and a thread started as "Auto" was created manual
because ws.ts's bootstrap thread.create also dropped routingMode and
efficiencyTier.

Expose the resolution step as OrchestrationCommandDispatcher.resolve and run
it in ws.ts's dispatchNormalizedCommand (inside the startup command gate,
before choosing bootstrap vs direct dispatch), which covers both the
dispatchCommand RPC and Command Center run dispatch, as before the merge.
The ws bootstrap thread.create now forwards routingMode and efficiencyTier,
so the resolved createThread fields reach the new thread. Everything else
ws.ts does (client origin, analytics, deletion fence, archive/session stop,
its own bootstrap cleanup) is unchanged. Manual turns and turns with
efficiency disabled are dispatched unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M labels Sep 27, 2026
@github-actions

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.9 KiB 13.9 KiB +7 B (+0.0%) 15.6 KiB ✅
Codex Thread snapshot wire 7.5 KiB 7.5 KiB +8 B (+0.1%) 7.8 KiB ✅
Codex Live turn WebSocket wire 6.5 KiB 6.5 KiB −1 B (−0.0%) 7.8 KiB ✅
Codex Live turn WebSocket decoded 55.7 KiB 55.7 KiB 0 B (0.0%) 66.4 KiB ✅
Codex Live turn messages 8 8 0 (0.0%) 21 ✅
Claude Total thread wire 14.0 KiB 13.9 KiB −16 B (−0.1%) 15.6 KiB ✅
Claude Thread snapshot wire 7.5 KiB 7.5 KiB −12 B (−0.2%) 7.8 KiB ✅
Claude Live turn WebSocket wire 6.5 KiB 6.5 KiB −4 B (−0.1%) 7.8 KiB ✅
Claude Live turn WebSocket decoded 56.6 KiB 56.6 KiB 0 B (0.0%) 66.4 KiB ✅
Claude Live turn messages 8 8 0 (0.0%) 21 ✅

Baseline: d61540f · PR result: bd44e59 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 113.1 KiB
  • Claude decoded thread snapshot: 113.9 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@awtprod
awtprod merged commit 2332cd9 into main Sep 27, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant