You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] Ensure context truncation always makes measurable progress #1254
Fallback context truncation can report success without reducing context. With a short history such as an assistant tool_use followed by one oversized user tool_result, the current 50% message calculation rounds down to zero removable messages. Zoo Code still emits a truncation event, leaves the oversized history unchanged, and retries into the same failure indefinitely.
The reproduced signal is Context Truncated with 0 messages removed while the recalculated context remains above the allowed input budget.
Scope
Make context recovery monotonic and bounded.
Treat recovery as successful only when the recalculated model-facing token count decreases.
When message-level truncation cannot remove a valid turn/tool pair, shrink the largest eligible textual tool-result block while preserving its tool identifier and result shape.
Recount after degradation and verify the result fits the target or makes measurable progress.
If protected content makes the target impossible, return a distinct actionable error instead of emitting another successful truncation event or retrying indefinitely.
Keep retries bounded.
Acceptance criteria
One-to-four-message histories cannot emit a successful zero-progress truncation result.
An oversized tool_use/tool_result pair is reduced without orphaning either side.
newContextTokensAfterTruncation is lower than the pre-recovery count whenever recovery reports success.
An impossible budget produces a controlled error and does not loop.
Focused tests reproduce the 4 MB tool-result case and verify bounded recovery.
Out of scope
Preventing individual tools from producing oversized results
Condensation-input sanitization
Full-output spill files or resource references
Aggregate budgeting across parallel tool calls
Estimate
1 story point. Independently mergeable and non-stacked.
Confirmed on current main (745656a): the fallback branch in manageContext (src/core/context-management/index.ts) calls truncateConversation(messages, 0.5), and for short histories the Math.floor((visibleCount - 1) * fracToRemove) + even-rounding calculation yields messagesToRemove = 0. truncateConversation then returns the original messages with messagesRemoved: 0 but a fresh truncationId, so manageContext reports a success-shaped recovery, Task.ts emits the sliding_window_truncation event with messagesRemoved: 0, the oversized history is left unchanged, and the next request retries into the same over-budget failure — a zero-progress loop.
I'd like to take this. Plan:
In manageContext's fallback branch, treat messagesRemoved === 0 as zero progress: degrade by shrinking the largest eligible textual tool_result block (keeping its tool_use_id and block shape, so the tool_use/tool_result pair is never orphaned), then recount and report success only when newContextTokensAfterTruncation actually decreases.
When nothing eligible can shrink further (protected content makes the budget impossible), return a controlled error/errorDetails result instead of emitting another successful truncation event.
Add focused vitest coverage: a short history with an oversized tool_result that reproduces the zero-progress result on current code, plus bounded-recovery and impossible-budget cases.
Activity
yetuge commentedon Sep 12, 2026
Confirmed on current
main(745656a): the fallback branch inmanageContext(src/core/context-management/index.ts) callstruncateConversation(messages, 0.5), and for short histories theMath.floor((visibleCount - 1) * fracToRemove)+ even-rounding calculation yieldsmessagesToRemove = 0.truncateConversationthen returns the original messages withmessagesRemoved: 0but a freshtruncationId, somanageContextreports a success-shaped recovery,Task.tsemits thesliding_window_truncationevent withmessagesRemoved: 0, the oversized history is left unchanged, and the next request retries into the same over-budget failure — a zero-progress loop.I'd like to take this. Plan:
manageContext's fallback branch, treatmessagesRemoved === 0as zero progress: degrade by shrinking the largest eligible textualtool_resultblock (keeping itstool_use_idand block shape, so thetool_use/tool_resultpair is never orphaned), then recount and report success only whennewContextTokensAfterTruncationactually decreases.error/errorDetailsresult instead of emitting another successful truncation event.yetuge commentedon Sep 12, 2026
Claiming per the contribution guide.