fix(usage): score every rate-limit lane instead of only the codex lane - #578
Conversation
`usage_health_for_snapshots` selected a single snapshot — the `codex` lane, or the first one — and discarded the rest. Accounts now expose two lanes, and when the generic `codex` lane reaches 100% the whole profile was reported exhausted while the `codex_bengalfox` (GPT-5.3-Codex-Spark) lane sat untouched. Measured on station01: 22 of 22 authenticated profiles reported exhausted, every one of them holding a lane under 100%. Each lane is now scored independently and a profile is exhausted only when EVERY lane is exhausted. The naive repair — scoring all lanes and taking the max — is the mirror failure: it converts a false Exhausted into a false Healthy and routes default-model work onto a genuinely spent lane. The per-lane result is therefore carried, so callers can name which model still has capacity rather than assuming any model will do. `remaining_percent` on the Exhausted arm was the literal `Some(0.0)` in both the CLI report and the model-visible tool handler. The classifier already computed the real limiting figure and threw it away. A lane blocked by spend control or depleted credits can still hold capacity — the regression test covers exactly that case at 80% remaining — so the measured figure is now reported. Two-sided fixtures: a profile with codex at 100% and codex_bengalfox at 0% must report usable and name the usable lane; a profile with every lane at 100% must stay exhausted and offer no lane.
|
[REVIEW] NO_GO — #578 @ 555608d — lens: correctness+security+gates, reviewer unresolved-account011 (1 of 1) Exact candidate read:
Setup and declared gates:
Forge checks read, by name and conclusion:
Blocking P0/P1 findings:
Non-blocking follow-ups:
Verdict: NO_GO. Fix the formatting, the seven argument-comment failures, and the stale serialization assertion; then rerun the affected format/lint/Rust-test forge lanes. Merge remains refused until the current-head authoritative checks are green. |
Agent: unresolved-account011
|
Focused remediation pushed at c722a49:
Verification before push:
|
|
[REVIEW] GO — #578 @ c722a49 — lens: correctness+security+gates, reviewer unresolved-account011 (1 of 1) Focused re-review scope:
Commands and measured results:
Declared repository gates:
Forge checks read, by name and conclusion:
Blocking P0/P1 findings: none. The prior blockers are resolved: formatting is green, both argument-comment lanes are green, Non-blocking follow-ups:
Verdict: GO. |
What was wrong
usage_health_for_snapshotspicked one snapshot and discarded the rest:Accounts now expose two lanes. When the generic
codexlane hits 100%,backend_blockedflips and the whole profile reportsExhausted— while thecodex_bengalfox(GPT-5.3-Codex-Spark) lane sits untouched. The function's doccomment still asserted "Only the 5h and weekly Codex windows participate", which
was the stale assumption behind the selection.
Measured on station01 against installed 0.1.90,
codewith usage --all --json:remainingPercent0.0on all 22codex(22),codex_bengalfox(22)codexlaneused_percent100.0on all 22codex_bengalfoxused_percent0.0×20,3.0×1,34.0×1Every authenticated profile on the box was reported unusable while every one of
them had a free lane.
The trap this deliberately avoids
The one-line repair is to score all lanes and take the max. That is wrong — it
converts a false
Exhaustedinto a falseHealthy. If thecodexlane really isspent, a run on the default model still dies, and the selector would now route work
into it with confidence.
So the fix scores every lane and keeps the per-lane result:
Exhaustedonly when every scored lane is exhausted;Healthy, carrying which lanes remain so a caller names a modelrather than assuming any model will do;
"everything is available".
remaining_percentwas a literal, not a measurementTwo sites hardcoded
Some(0.0)on the exhausted arm —cli/src/usage_cmd.rsandcore/src/tools/handlers/auth_profile_usage_control.rs(the model-visible toolhandler; this second one was not in the original report). The classifier already
computed the real limiting figure and threw it away.
This matters beyond tidiness: a lane blocked by spend control or depleted credits
can still hold capacity. The existing spend-control test now asserts 80.0%
remaining on an exhausted profile — a figure the old code reported as
0.0.AuthProfileUsageHealth::Exhaustedgained aremaining_percentfield, becausethe variant previously had nowhere to carry one.
Tests
Two-sided, and the negative fixture is the one that catches the bad fix:
usage_health_reports_capacity_when_a_sibling_lane_is_free—codexat 100%,codex_bengalfoxat 0%: must report usable and name the usable lane(
codex_bengalfox/GPT-5.3-Codex-Spark), while still carrying the spent lane.usage_health_stays_exhausted_when_every_lane_is_spent— every lane at 100%:must stay exhausted and offer no usable lane.
The first was observed failing against the pre-fix implementation
(
got Exhausted { retry_at: Some(100) }) before any implementation change; thesecond passed before and after, which is what makes it a guard rather than
decoration.
Scope — what this does not do
--profile any-healthyis not implemented. It appears in the rule corpus as aproposal; it does not exist in this codebase (0 occurrences). Nothing was invented
for it here. The lane data this PR carries is the prerequisite for building it.
core/src/usage_profile_health.rs, which carries the same single-lane selection viais_codex_limit(matchingcodexexactly, socodex_bengalfoxis excluded), and itis fed a single snapshot with health keyed per profile. Making it select a
(profile, model) pair is a genuine refactor across session, cooldown and selection
state, not a hotfix. Left deliberately untouched and flagged rather than half-done.
by this PR.
Pre-existing failure, not from this change
agent::control::tests::spawn_agent_fork_last_n_turns_strips_parent_usage_hintsaborts with a debug-build stack overflow. It matches a
usagetest filter by nameonly. Confirmed pre-existing by reverting the three changed files to
923fd0b0eand re-running that single test:codex-rs/core/src/agent/contains zero references to any symbol this PR touches.Not verified
cargo test -p codex-core --libplus asuccessful
codex-clicompile. The published binary is unaffected until built.codewith usageoutput was not re-measured against a rebuilt binary.exists only as a fixture, never as a live observation.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.