Skip to content

Context overflow is not failure-proof: one persisted flag disables every recovery path, goal re-prompts a deterministic overflow, astra contextWindow overstates the 922k input cap #1422

Description

@code-yeongyu

Summary

Session 01a07542-3b63-7cfb-9b87-4ea321e750a2 (omo, 2026-09-06 05:47Z → 09-07 01:40Z, openai/gpt-6-astra) grew from 440k to 916,628 prompt tokens with zero compactions, then died on Error Code context_too_large: Your input exceeds the context window of this model. The goal extension re-prompted the identical context three times in 30 s (each one failed the same way) until the user aborted and switched models by hand.

Nothing in the runtime defended the session. Every layer that should have kept it alive was either switched off by one flag or was measuring the wrong budget.

Root-cause chain (all verified on origin/main 5a23f6edf)

1. compaction.enabled=false is persisted globally by a per-session RPC command (origin)

  • ~/.omo/agent/settings.json carries "compaction": {"enabled": false} since at least 2026-08-30 (absent in the 08-26 backup, present in every backup from 08-30 on).
  • The only writer of that key is SettingsManager.setCompactionEnabled (packages/coding-agent/src/core/settings-manager.ts:1230), reached from AgentSession.setAutoCompactionEnabled (agent-session.ts:6723), which is what the RPC command set_auto_compaction calls (modes/rpc/connection-handler.ts:1339-1342).
  • OmO Desktop relays its per-thread toggle omo.autoCompaction.set straight onto that RPC (apps/server/src/provider/omo/omoSessionStats.ts:145). One thread flipping its own toggle rewrites the machine-wide persisted setting and silently disables auto-compaction for every senpi/omo session on the host, forever.
  • Field impact: since 08-30 this host recorded 30 provider overflow deaths across 40 session files (26x Anthropic prompt is too long at 985k-999k/1M on opus-5 and fable-5-1, 3x astra context_too_large, 1x sol) — all with zero compaction entries.

2. That one flag disables every recovery path, including emergency ones

  • _getAutoCompactionReason returns undefined for overflow as well as threshold when !settings.enabled (agent-session.ts:2107-2110).
  • _checkCompaction returns false at the top when !settings.enabled (:6177), so the one-shot overflow recovery (compact + retry, :6234-6262) never runs.
  • _enforceCompactionBeforeProvider skips the hard reserve gate (window - reserve) when !settings.enabled (:6080); _enforceFinalProviderAdmission likewise (:6143).
  • Result: "auto-compaction off" is implemented as "no compaction ever, even when the provider has already rejected the request". The session cannot make progress by any path other than a human running /compact or switching models.

3. Goal continuation re-prompts a deterministic failure

  • didTerminalProviderErrorEndTurn (extensions/builtin/goal/terminal-provider-error.ts:22-28) treats any stopReason: "error" turn as a provider failure and afterProviderFailureafterAgentSettled queues a providerRecovery continuation (monitor-continuation.ts:189-230).
  • A context overflow is not transient: the same context is sent again and rejected again. Session evidence: #1320 error → #1322 goal-continuation → #1323 error → #1325 goal-continuation → #1326 error → #1328 goal-continuation → user abort.
  • The PROVIDER_ERROR_BLOCKED_REASON mechanical block exists but only after a retry budget; overflow needs to block immediately with a reason that names compaction.

4. gpt-6-astra contextWindow: 1,050,000 overstates the real prompt budget by 128k

  • OpenAI splits the window into a hard input cap and a separate output cap: astra = 922,000 input + 128,000 output; GPT-5 family = 272,000 + 128,000 (the request is rejected with context_too_large regardless of max_output_tokens).
  • senpi uses model.contextWindow everywhere as the prompt budget (core shouldCompact, getContextUsage, hard valve, clampMaxTokensToContext). The generator even says so — packages/ai/scripts/generate-models.ts:400-408: "GPT-6 Astra ships the documented maximum (1,050,000 = 922,000 input + 128,000 output)" — and then ships 1,050,000 as contextWindow.
  • The catalog already uses the input-cap convention for gpt-5.4/5.5/5.6-luna/terra (contextWindow: 272000), so astra is the inconsistent row. Codex's own models.json caps astra at 272k default / 872k max.
  • Consequence even with compaction enabled: the core reserve gate sits at 1,033,616 and the scaled hard valve at ~1,000,848 — both above the provider's 922k cap, so the core paths can never fire before the provider rejects. The observed rejection (916,628 succeeded, +~14k tool results failed) matches the 922k cap exactly.

5. (Related, tracked separately) extension-triggered turns skip before_agent_start

sendCustomMessage({triggerTurn:true}) (goal continuations, task/monitor wakes) runs _enforceCompactionBeforeProvider + _promptAgent but never emitBeforeAgentStart, so the builtin adaptive threshold/valve does not evaluate on those turns (already noted 2026-09-03). Not causal here (the flag in #2 was off), but it narrows proactive compaction to user-typed turns in goal-driven sessions. Needs a design decision on what the hook receives for a non-user prompt; out of scope for this PR.

Ideal end state

  1. set_auto_compaction (RPC) is session-scoped: it changes this session's behaviour and is reported back through get_state, but never rewrites the persisted global setting. The interactive /settings toggle keeps persisting (it is the settings editor).
  2. compaction.enabled=false means no proactive compaction (threshold, speculative, idle, adaptive). Emergency paths stay armed: provider overflow → one-shot compact-and-retry; pre-prompt hard reserve gate; final admission gate. A session must never be able to reach a state where the only exit is a human.
  3. Goal continuation never re-prompts after a turn ended by a context overflow that recovery did not fix; it records a mechanical block (context overflow ended the turn (compaction did not recover)) so the next user message resumes it.
  4. gpt-6-astra catalog contextWindow = 922,000 (the input cap), consistent with the 272k rows and with the generator's own comment.

Tracking

  • Issue filed with evidence (this)
  • RED tests: overflow recovery + hard gates with compaction.enabled=false
  • Fix: emergency compaction independent of enabled
  • RED + fix: RPC set_auto_compaction session-scoped
  • RED + fix: goal continuation blocks on unrecovered overflow
  • Fix: astra contextWindow 922,000 (generator + regenerated catalog + tests)
  • Changelog
  • Remote bun test green (ascii box / mengmotaMac), typecheck + lint
  • Reproduction: replay of the failing session shape passes on the fixed build
  • PR merged; this issue updated with the SHA

Evidence pointers

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions