Recover from summary-request overflow and rescue over-ceiling context / 摘要请求超窗自恢复与硬上限截断救援 - #9879
Merged
SivanCola merged 1 commit intoSep 7, 2026
Conversation
SivanCola
force-pushed
the
fix/compaction-overflow-recovery
branch
from
September 7, 2026 07:02
bdc1354 to
96aa681
Compare
This was referenced Sep 7, 2026
…ling context A summary request the provider rejects now feeds its real prompt count back into calibration, re-plans a smaller prefix, then falls back to a bounded transcript form and (manual only) the fragment path; chunk and merge retries treat provider overflow as a size failure. Prefix planning keeps 5% of the window as estimator headroom. At the ceiling, when no summary can form, a truncate projection elides the oldest tool results and drops the oldest replay units behind a marker instead of returning ErrCompactionRequired. Overflow rescues may fold the active turn's completed rounds, and the same-turn backoff lifts once the view has grown 5% of the window since the failed attempt. DeepSeek-style chat adapters report that ordinary reasoning is replayed so admission counts it. SPEC and the desktop maintenance notice follow. Fixes esengine#9818
SivanCola
force-pushed
the
fix/compaction-overflow-recovery
branch
from
September 7, 2026 07:59
96aa681 to
5412140
Compare
SivanCola
added a commit
to SivanCola/DeepSeek-Reasonix
that referenced
this pull request
Sep 7, 2026
Integrate the reviewed context-overflow recovery changes from esengine#9882 and esengine#9879. Preserve the kernel-reduced startup graph rather than restoring the pre-kernel raw budget. The integrated build measures 2,438,339 raw bytes (2381.190 KiB), 186 bytes above the repaired PR head. Set only the raw ceiling to 2381.2 KiB; all gzip, CSS, locale and largest-chunk gates remain unchanged. Validation: frontend build, test typecheck, context-maintenance notice tests, agent/control/provider/boot Go tests and repolint passed. Transcript measurement and session-command production repairs are unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary / 摘要
Fixes #9818.
In v1.37.0 a session could grow past the compaction threshold without an effective fold and end up 60% over the 1M window;
/compactthen sent a summary request that DeepSeek rejected (1108110 in the messages, 8192 in the completion) and re-sent the identical request on every retry. Root causes, all in the summary path:foldSummaryWithChunkedFallbackand the fragment splitter only recognisederrSummaryOutputTruncated/ErrCompactionRequired; a providerContextLimitErrorbypassed every fallback.ErrCompactionRequiredwith no lossy last resort, and a failed attempt silenced further automatic attempts for the whole turn.reasoning_contenton every assistant turn that carries it, but admission only counted it on tool-call turns.一句话:摘要请求自身超窗后既不回灌真实 token 数、也不缩小、也不走兜底;硬上限下没有有损救援;估算 shape 少算了普通轮次的 reasoning 回放。
Changes / 改动
fold_ladder.go,compact_summary_feedback.go): a summary overflow recalibrates prompt calibration from the reply'sPromptTokens, re-plans a smaller prefix (≤2), then sends the fold once in transcript form, then (manual only) the fragment path. Chunk/merge retries now treat provider overflow as a size failure. No request is ever re-sent byte-identical.compact_safe_prefix.go,compact_slim.go): planning keepsmax(256, 5% × window)under the output cap; the transcript-form request cuts tool results to 2000 runes, drops images and tool schemas, and is used only after the replay form overflowed, so healthy turns keep the cache-aligned prefix.truncate.go,maintenance_commit.go): at overflow or the hard ceiling, when no summary can form, atruncateprojection elides the oldest tool results outside the protected tail, then drops the oldest replay units behind an explicit marker (latest session context, digests and pinned revisions survive).ErrCompactionRequiredis returned only when even that cannot reclaim enough. Prune shares the same commit path.compact_active_turn.go,context_receipt.go): an overflow rescue may fold the active turn's completed rounds keeping the newest two; the same-turn backoff lifts once the view has grown by 5% of the window since the failed attempt, which bounds the retries one turn can pay.internal/provider/openai/output_budget.go): DeepSeek/Kimi/GLM clients reportReplaysOrdinaryReasoning, so admission counts what the wire actually sends.docs/SPEC.md/docs/SPEC.zh-CN.mddescribe the ladder, rescue and margin. Desktop:truncateaction label in en/zh/zh-TW; bundle ceiling re-aligned to the measured 2496.6 KiB (2496.5 → 2496.7).Tests / 测试
internal/boot/effect_compaction_test.go: through the realBuildstack, a DeepSeek-format 400 on the summary request makes the next summary request strictly smaller and the 30-round tool loop completes.internal/agent/compact_summary_limit_test.go: recalibrate-and-replan lands a digest without the fragment path; an overflow without token numbers (the GLM shape fix(agent,provider): un-stick compaction on thinking-model summaries and unnumbered overflows / 修复思考型模型摘要与无数字超窗导致的分段压缩死锁 #9882 parses) skips the re-plan and goes to the transcript form without learning a ratio or window; a provider that rejects every form never repeats a request and ends in the truncation rescue; slim request shape; active-turn boundary; elide-then-drop truncation; backoff relief.go vet ./...,make lint(repolint baseline unchanged at 1263), agent/boot/provider/tool/control/serve/cli suites, frontend typecheck andpnpm buildpass.ask-card-layout.test.tsfails identically on the base tree.Related: rebased onto the merge of #9882. Its reasoning-only surfacing now lives inside
runSummaryRequest, so the transcript form inherits it; its "reasoning with a tool call stays rejected" test is adapted to the ceiling policy here (the rejection is recorded, then the truncation rescue lands instead of a digest).Metadata
Cache-impact: none - healthy turns keep the provider-visible prefix byte-identical; the transcript-form summary request and the truncation projection exist only on the overflow failure path
Cache-guard: internal/boot/effect_compaction_test.go TestEffectSummaryOverflowShrinksNextSummaryThroughRealBuild; TestEffectRoleSettingsShareProviderToolSurface still pins the unified tool surface
System-prompt-review: SivanCola - no system prompt, memory, or skill text changes; the only internal/boot change is an effect test
Documentation-impact: updated - docs/SPEC.md and docs/SPEC.zh-CN.md now describe the overflow ladder, the truncation rescue, the 5% planning margin, and the same-turn backoff relief