- Tip reviewed:
739d42b3("fix(harness): reserve output against the provider ceiling, not window_max") - Diff range:
a1412967..739d42b3 - Branch in this worktree:
ormax2453crev(review fix commitc358e6feon top; not pushed) - Verdict: PASS (with one Medium risk documented below that is upstream-data, not logic)
effective_window_max no longer treats window_max as a total context budget.
The removed line was:
input_cap = window_max if output_reserve is None else max(1, window_max - reservation)and the unknown-ceiling branch now returns max(1, int(window_max * shrink_factor)).
The reservation is subtracted only from a ceiling, via min(window_max, max(1, ceiling - reservation)),
where ceiling = served_ceiling(model) or context_limit.
Verified against the live LiteLLM catalog with window_max=150_000 (the model default,
src/aios/models/agents.py:1039):
| model | reserve | limit | budget @739d42b3 | budget @a1412967 |
|---|---|---|---|---|
anthropic/claude-opus-4-5 |
64000 | 200000 | 136000 | 86000 |
anthropic/claude-opus-4-6 |
128000 | 1000000 | 150000 | 22000 |
anthropic/claude-opus-4-1 |
32000 | 200000 | 150000 | 118000 |
openai/gpt-4.1 |
None | None | 150000 | 150000 |
openrouter/anthropic/claude-opus-4-1 |
0 | None | 200000 | 200000 |
claude-opus-4-5 lands on exactly the min(150000, 200000-64000) = 136000 the brief specifies.
claude-opus-4-6 — the repo's own canonical model (src/aios/cli/commands/init.py:38,
src/aios/models/agents.py:1006) — was the worst case of the P1: a 22k usable input
window. It is now 150000.
- No
window_max - reserve. Confirmed, line removed; the only subtraction isceiling - reservation. ✔ - Known ceiling ⇒
min(window_max, ceiling - reserve).context_budget.py:81. ✔ - Unknown ceiling ⇒
window_maxpreserved.context_budget.py:80. The ceiling comes from existing catalog helpers (litellm.get_model_info→max_input_tokens), mirroringdefault_max_output_tokensexactly — same source, same@cache, sameNone-is-a-real-answer stance. No invented map. ✔ - OpenRouter unchanged.
resolved_context_limitis gated on_uses_anthropic_max_tokens_default, which already excludes both theopenrouter/prefix andcustom_llm_provider="openrouter", so OpenRouter resolveslimit=Noneand keeps itswindow_max-only budget. Reservation behavior untouched. ✔ - Wire injection / caller precedence intact.
_apply_default_max_tokens,_normalize_explicit_output_capandresolved_output_reservationare unmodified in this diff;tests/unit/test_completion_max_tokens.py(incl. the real-LiteLLM wire-body test) passes untouched. Explicitmax_tokens/max_output_tokensstill win (limit - 1234asserted for both spellings). ✔ - Test coverage. Good, and notably the tests now assert relative to the resolvers rather than pinning catalog literals — correct, since unit tests run egress-blocked against the bundled backup map while production fetches the live map, and the two disagree. One real gap found and closed (§3). ✔
- Ruff / mypy clean. ✔
Gate agreement (checked, since a drift here is silent): resolved_output_reservation and
resolved_context_limit return non-None on exactly the same routes, because both funnel
through _uses_anthropic_max_tokens_default / the CacheChannel.ANTHROPIC gate and both read
the same get_model_info entry. A model LiteLLM cannot resolve yields None from both, so
there is no "reserve against a limit that doesn't exist" state.
739d42b3 changed precisely one branch: positive output_reserve + unknown ceiling. Nothing
in the suite covered that combination. Every Anthropic test resolves a ceiling, and both
OpenRouter tests resolve a zero reservation — and window_max - 0 == window_max, so
reinstating max(1, window_max - reservation) would have left the entire file green. Given
this formula has now been wrong once already (13e8d003), that is worth a pin.
The live instance is OpenRouter with a caller cap:
openrouter/anthropic/claude-opus-4-1 {"max_tokens": 8000}
-> reserve=8000 limit=None served=None budget=150000 (was 142000 @a1412967)
Added test_nonzero_reservation_without_a_ceiling_preserves_window_max, asserting the budget
passes through verbatim and that the overflow shrink ladder still tightens it.
4. Finding — stale catalog ceiling on claude-sonnet-4-5 (Medium, upstream data) — reported, not patched
Not a logic defect, but it should be on the record because it is the failure mode this PR's reservation exists to prevent.
LiteLLM's live map reports claude-sonnet-4-5: max_input_tokens=1000000 (the retired 1M
beta), while Anthropic retired context-1m-2025-08-07 for Sonnet 4/4.5 on 2026-04-30 — Sonnet
4.5's real window is 200k, and 1M went GA on the -4-6 models instead. So:
anthropic/claude-sonnet-4-5 -> reserve=64000 limit=1000000 budget=min(150000, 936000)=150000
wire: input ≲150000 + max_tokens 64000 = ~214000 > the real 200000 -> provider 400
Under a1412967's (wrong-but-conservative) formula this happened to be safe at 86000. The breakage starts once history exceeds ~136k tokens.
Why this is not a blocker and not patched here:
- The data is wrong upstream, not the derivation. The bundled backup map has the correct
200000; only the fetched live map is stale, and it self-corrects when LiteLLM updates. _SERVED_CEILINGSalready exists as the sanctioned override for exactly this ("Served ceilings can differ materially from public model-card context windows"), andserved_ceilingcorrectly outrankscontext_limit. The escape hatch is in place.- Exposure in this repo is an eval baseline (
evals/wam_fusion/run_eval.py:68) plus two unit fixtures. Production agents useclaude-opus-4-6, whose 1M figure is correct. - Patching it would mean hardcoding model strings into
_SERVED_CEILINGS, which is exact-string keyed and so cannot coverclaude-sonnet-4-5/anthropic/.../...-20250929/us.anthropic..../vertex_ai/...without whack-a-mole — against CLAUDE.md's "extreme simplicity, no defensive guards" and out of this fixround's scope.
Recommended follow-up (separate issue): add _SERVED_CEILINGS entries (or a normalizing
lookup) if Sonnet 4.5 is ever promoted to a production route before LiteLLM corrects the entry.
min(window_max, max(1, ceiling - reservation))floors at 1 when a caller cap exceeds the model ceiling (e.g.max_tokens=500000on a 200k model). Budget 1 ⇒read_windowed_eventsraises "no budget remains for events". That request would be rejected by the provider anyway, and fail-hard is the house stance; pre-existing on theserved_ceilingpath.model_context_limit's docstring cross-references_apply_default_max_tokens— verified present atcompletion.py:566.- Only one production call site of
effective_window_max(loop.py:1042); it passes both resolvers. Grepped the full tree for the new symbols — no stragglers.
| command | result |
|---|---|
uv run pytest tests/unit/test_context_budget.py tests/unit/test_completion_max_tokens.py -q |
31 passed (30 before the added test) |
uv run pytest tests/unit -q -n 4 -x -k "context or window or completion or budget or token" |
871 passed |
uv run ruff check <4 touched files> |
All checks passed |
uv run ruff format --check <4 touched files> |
already formatted |
uv run mypy <4 touched files> |
Success: no issues found |
Live-catalog probes were run through resolved_output_reservation / resolved_context_limit /
effective_window_max directly to produce the table in §1.
c358e6fe—test(harness): pin window_max preservation when a reservation has no ceiling
VERDICT: PASS