Skip to content

Route factory session Steps across configured Plan usage routes - #2200

Merged
JacobStephens2 merged 5 commits into
issue-583from
issue-2183
Nov 14, 2026
Merged

JacobStephens2 merged 5 commits into
issue-583from
issue-2183

Conversation

@JacobStephens2

@JacobStephens2 JacobStephens2 commented Nov 14, 2026 •

Copy link
Copy Markdown
Owner

Summary

A factory Command whose Harness comes from [harness] routes now routes each session Step by machine-local Plan usage. It picks a route before the Step starts, and moves to the next route when a session stops on structured Plan-usage evidence.

 Sessions::run_step(purpose, kind, prompt)
+  routes = Router::of(User config, Command's Choice)   # empty when pinned
+  at_start = HEAD (+ pinned MERGE_HEAD of a conflict Repair)
+  pick first route: installed, not in cooldown, below max_utilization,
+                    included Plan windows first unless allow_credits
+                    (stale codex/muse snapshots refreshed by non-billed read)
   attempt(session, Resume)
+  on SessionFailure { plan_usage_exhausted }        # structured frames only
+     (or startup failure on security.harness)       # never a SafeguardRefusal
+    next untried route
+    if work began: git reset --hard; git clean -fd; re-merge pinned conflict
+    implement: Continuation prompt (naming an open PR) once commits/PR exist
+    fresh session, trace `<kind>-route-<n>`
  • Choosing the route: ChosenBy::Routes marks a Choice that harness.routes made. Only that routes. A Harness or Model named on the command (--harness, --model), a Step's Harness, Experiments and Scoring runs stay pinned. Spec Tickets inherit the marker through the hidden --sessions-routed flag, and a routed Command's continuation command names no Harness.
  • Security sessions: Security reviews and Security runs walk security.harness, then [security] routes, else [harness] routes, else harness.default. A pinned review keeps its existing one-time fallback.
  • Wiring:
  • Prompts: no prompt gains text about limits.
  • Out of scope: the Pass skip and Paused Command endings when every route is exhausted are Ticket 4 of Spec: view subscription Plan usage and route Steps across Harnesses #583.
src/plan_usage/router.rs   # Router: each Step's candidate routes, proactive pick
src/session.rs             # run_step: route loop, mid-Step reset, Continuation
src/plan_usage.rs          # refresh_for_routing (codex/muse reads, ≥1/min)
src/harness/interpretation.rs  # SessionFailure::plan_usage_exhausted
src/asks.rs, child_run.rs, args.rs  # ChosenBy::Routes through Commands and Tickets
src/implement.rs, prompt.rs         # implement Opening + PR-aware continuation

Evidence

Execution evidence

This host has no C compiler or linker, so cargo build and scripts/affected-tests could not run locally. The evidence below is this PR's CI runs.

  • Before (CI run 43557232726, head 490423bd): cargo nextest → FAIL thirdshift::codex_sessions implement_sessions_and_their_resumes_request_fresh_reviewers, panicked at tests/codex_sessions.rs:133. The routed implement session had lost the review-report launch policy.
    After (CI run 43559233125, head 51e5b03d): rust-x86 / run (1)–(4) all success. The full x86 suite passes, including:
    • tests/plan_usage_routing.rs, 11 tests: reserve routing, mid-Step commit kept and uncommitted changes discarded with an Implement continuation, continuation naming an open PR, conflict-Repair merge reset, security.routes and harness.routes walking, --harness and --model pins, no routing on 429 or agent text, exponential revalidation;
    • unit tests in src/plan_usage/router.rs, src/session.rs, src/session/kind.rs, src/asks.rs and src/child_run.rs.
  • Before (CI run 43558652727, head ab508c9c): FAIL session::tests::a_limit_after_work_keeps_commits_discards_the_rest_and_implements_on_as_a_continuation, with left: ["on claude", "on codex", "reset"].
    After (head 51e5b03d): passes. The next route is taken before the reset, so with no route left the worktree is kept for Failed run preservation.

Visual evidence

The only rendered change is one added paragraph, plus one sentence, in site/how-it-works/index.html. The cached chrome-headless-shell rendered that page blank on this host, with or without JavaScript, so no Before/After captures are attached. site-test passes in CI.

Merge Danger

Door: two-way

Routing turns on only when the User config lists two or more [harness] routes, or sets security.harness beside routes. Without routes, sessions run exactly as before.

Blast Radius: sessions

A routed Step that stops at a Plan-usage limit after doing work discards uncommitted changes in its thirdshift-owned linked worktree. The reset refuses any checkout that is not a linked worktree.

Review coverage

The Standards and Spec reviewers read every changed file. No changed file was left unread, and nothing was excluded as generated.

Unaddressed findings

Standards

  • Spec: thirdshift, turn a GitHub issue into a ready-for-review PR unattended #2: Router::pick and session::router create their own dependencies. Declined.
    • The rest of the module already works this way: plan_usage::credits_allowed (src/plan_usage.rs) loads the User config itself under the same cfg!(test) guard.
    • The pure selection rule select is unit-tested, and the I/O path is exercised end to end by tests/plan_usage_routing.rs in CI.
  • CI watching, CI-fix Repair and the Repair cap #9: OnMachine::routes and pick are Middle Men over Router. Declined.
    • Outside is the session module's test seam. The scripted Routed double in src/session.rs tests the route loop without a machine Plan usage snapshot, which a Router held directly would prevent.

Spec

  • Spec: thirdshift, turn a GitHub issue into a ready-for-review PR unattended #2: Built with names the Command's first route even when the implement session ran on another route.
  • Pre-flight checks #4 (partial): no integration tests for Custom-process Step pins, Experiment and Scoring pins, a SafeguardRefusal, or a Security run walking routes. Declined.
    • Added in this PR: [security] routes walking and the --model pin.
    • Router::of routes only ChosenBy::Routes and ChosenBy::SecurityConfig Choices. only_a_choice_the_routes_made_routes_ordinary_sessions (src/plan_usage/router.rs) asserts that Command, Step, UserConfig and Default stay pinned.
    • Experiments build ChosenBy::Command (src/trial.rs) and Scoring Graders ChosenBy::UserConfig (src/config/scoring.rs).
    • each_route_is_tried_once_and_other_failures_never_route (src/session.rs) covers the SafeguardRefusal. A refusal never reaches the reroute, so the Self-merge hold in src/run.rs is unchanged.
    • A Security run's sessions take the same Purpose::is_security path as the Security review tested in a_security_review_walks_security_routes_after_its_security_harness.

Closes #2183

Built with claude 2.1.322 · claude-opus-5-5 · high

Security review outcome

No unaddressed introduced findings.

Before each session Step, a Command whose Harness comes from the User
config's harness.routes starts on the first route machine-local Plan
usage says can take it, refreshing stale Codex and Muse snapshots with
their non-billed reads. A session that stops on structured Plan-usage
evidence starts its Step again as a fresh session on the next untried
route, after discarding uncommitted changes (keeping commits and
re-merging a pinned conflict merge); an implement session that made
commits continues with the existing Continuation prompt. Security
reviews and Security runs walk security.routes, else harness.routes,
after security.harness. Explicit Harness flags, Step Harnesses, Evals
and safeguard refusals stay pinned. Every route's Factory skills are
linked, and the Command record names each stage's actual Harness.

Refs #2183
- Keep the prompt's launch policy for routed implement sessions: the
  review-report contract still selects the code review session.
- Name the branch's open pull request in the Continuation prompt a
  rerouted implement session starts again with.
- Fall back on a startup failure only from security.harness.
- Record each stage's Harness, Model and Effort as separate fields.
- Share the Security purpose test, the current Choice, the read
  freshness rule and the windowed-read list; build the implement
  Opening in one place.
@JacobStephens2
JacobStephens2 marked this pull request as ready for review November 14, 2026 05:08
@JacobStephens2
JacobStephens2 merged commit 0d873ac into issue-583 Nov 14, 2026
27 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-2183 branch November 14, 2026 05:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant