Coding Harness 上下文处理方案深度调研报告

对 8 个主流开源 coding harness 近半年(2026-05-01 至 2026-11-04)上下文处理(context management / compaction)实现的源码级调研: 方案应用方式、横向方案对比、各方案详细设计、最新工程更新。以源码与 diff 为准,提交说明与文档为辅。
覆盖:DSH · codex · pi · ZCode · opencode · goose · gemini-cli · mcode 方法:逐文件源码阅读 + git 历史 + 设计文档交叉验证 报告日期:2026-11-04

目录

1. 背景与评测框架

1.1 问题定义

上下文处理(context management)指 agent 运行时在对话历史接近模型上下文窗口上限时,对历史消息进行摘要、裁剪、外部化或重置,使会话得以继续的一整套机制。它是 agent 可用性的第一决定因素:处理不好会丢失关键决策、产生重复问答、或因缓存失效导致成本与延迟飙升。评测一个方案的优劣,通常看六个维度:

1.2 样本

沿用前序行业报告的 9 个 harness;其中 Kiro 产品闭源、公开仓库无上下文处理代码,故本报告的源码级分析覆盖其余 8 个。所有路径相对各仓库根目录(均在 repos/<name> 下),所有提交哈希为 2026-05-01 后窗口内提交。

2. 总览:八家方案一览

harness语言核心机制触发摘要形态状态载体标志性设计
DSHTS四件套:basic 摘要 + 命令 + 工具结果裁剪 + 图片 offload压力比 0.8 + 余量 655368 段结构化 MarkdownSessionEvent 日志(事务性提交)摘要请求是末次路由请求的前缀扩展,直接复用 KV 缓存
codexRust三模式:本地摘要 / 服务端原生压缩 / token 预算窗口重置token 上限(默认窗口×9/10)、回合末比例、65% 后台、provider 溢出handoff 摘要(可自定义 prompt)Rollout 事件(CompactedItem 含完整替换历史)retained tool outputs 整条保留/丢弃;媒体按消息边界计费;压缩失败保留原历史
piTS轮次边界切分 + split-turn 双摘要 + 分支摘要contextTokens > window − 163846 段固定结构 + 文件聚合附录jsonl 会话条目(compaction entry)切点绝不落在 toolResult;尾部超大工具结果回退到前一 assistant 边界
ZCodeTSmicrocompact(工具结果清理)→ 完整压缩 双层 + 四阶段有效窗口−13k buffer;micro 为完整阈值 90% 或 idle 60min9 段式(含反归属声明)append-only 事件(CompactBoundary 等)四阶段模型(manual/pre_request/mid_turn/reactive);连续失败 3 次熔断;rapid-refill 熔断
opencodeTS拒绝恢复阶梯 + 后台预压缩 + native 通道estimate ≥ ceiling;拒绝后 overflow 一次性恢复7 段 Markdowncompaction 消息行 + keepID 引用被拒请求按 [0.85,0.7,0.5,0.35] 逐级降尺寸重截;后台摘要到期直接换入复用缓存
gooseRust结构化 JSON 摘要 + 双可见性冻结min(0.8, 225k/窗口) —— 价格护栏<analysis> 草稿 + 10 字段 JSON消息行(user_visible/agent_visible 标记)225k 刻意低于 OpenAI 272k 长上下文价格档;摘要模板可被用户覆盖
gemini-cliTS新旧双路径 + 工具输出三件套(masking/distillation/归一化)0.5×tokenLimit(旧);150k/65k profile(新);工具 token 80k 批量掩码XML state_snapshot + probe 自校验compression_state.json 文件缓存(contentHash 失效)增量/热启动/屏障三模式管线;掩码产物落盘换预览
mcodeTS分层阶梯:归档 → 裁剪 → LLM checkpoint(h0→hmin 六档)输入上限 95% 单调触发;provider 拒绝无条件恢复8 段 Markdown + recentUserQueries 逐字附录canonical history 替换 + v5 appendix工具结果 artifact receipt(可恢复);准入要求实测 footprint 真减小

3. 详细设计(逐 harness)

每节按“模块地图 → 触发 → 算法 → 状态与持久化 → 配置 → 近期更新”展开,全部结论可回溯到文件与提交。

DSH 事务性压缩族 + 缓存对齐的摘要请求

模块地图

packages/compaction/ 下五个可独立发布的包:compaction(核心类型:checkpoint、tool-pairing)、compaction-basic(摘要引擎)、command-compact(/compact 命令)、compaction-tool-result-pruner(工具结果裁剪)、compaction-image-offload(图片预算)。另有 packages/context/ 注入族:agent-instructions(指令摘要 digest)、file-reference(文件引用语法)、time-context(请求时区)、session-reference。

触发

  • 压力比 thresholdRatio 默认 0.8(请求压力占上下文窗口比例);余量 headroomTokens 默认 65,536(同时作为 maxTokens 上限);逐字保留尾部比例 retainRatio 默认 0.16(compaction-basic/src/config.ts)。
  • 支持按 provider/model 路由的精确覆盖(modelPolicies):不同模型可配不同的摘要 provider、模型、重试次数(compactionRetries、maxOverflowRetries)。
  • 配置在加载期校验并 deepFreeze 冻结(不可变原则贯穿全仓)。

算法

  • 事务性压缩(region.ts,600 行):selectCompactableRange 选范围 → validateSurfaceRegion 校验 → prepareCompaction/summarizeCompaction 摘要 → assertWholeSurfaceUnchanged 乐观并发断言(整个界面区间在摘要期间未被改动)→ commitCompactionBody 提交 → completeCompaction。任何阶段失败可整体回滚。
  • 缓存对齐摘要请求(summarizer.ts,标志性设计):摘要指令不是独立的系统提示,而是作为回放对话之后的最后一条 user 消息发出——前置的 system prompt、工具 schema、消息前缀逐字复现末次路由请求,使辅助调用成为该请求的真正前缀,直接命中 provider 的 KV 缓存而非重建。
  • 结构化摘要:固定 8 段(Primary Request and Intent / Key Technical Concepts / Files and Code / Errors and Fixes / Pending Jobs / Current Work / Next Step / Critical Context),空段必须写 “(none)” 不得省略;若历史中已有 <compacted-summary> 旧检查点,则合并而非复制(保留仍属实的事实、丢弃过时信息)。
  • 工具结果裁剪(pruner):超过 thresholdChars=8192 的结果只保留头 headChars=4096 + 尾 tailChars=1024,中间替换为标记 [... tool result middle pruned ...];按 codePoint 长度计算(Unicode 安全)。
  • 图片 offload:记录“省略最旧保留图片出现位置”的决策,将超限旧图替换为“附件名 + 只读路径”文本占位,跨 route/resume/replay 保持一致,且不消耗 provider 重试预算。

状态与持久化

压缩作为 SessionEvent 日志中的条目落地(append-only 事件溯源),压缩后由 deriveMessages 从日志派生消息视图;replay/fork 用旧日志播种。快照覆盖全 profile:snapshots/session/compaction-output-reserve、snapshots/sdk/manual-compact、snapshots/acp/image-compaction。

配置

compaction.basic.{thresholdRatio, headroomTokens, retainRatio, retainTokens, summarizationProvider, summarizationModel, maxTokens, compactionRetries, maxOverflowRetries, auto, modelPolicies}。

近期更新

  • cf7229e72a(10-22)超大摘要用更小前缀重试 → 10-23 被 3081c71bab revert,随后补文档说明重试成本与溢出恢复契约(dd87277afa、595f5a65f3)。
  • eb1713f856(#7754)修复 checkpoint 中 released units 的保留问题。
  • 10 月多份文档澄清压缩溢出恢复契约(cd6187f901、7ee39638b2)。
可借鉴点:①摘要请求伪装成“末次请求的前缀扩展”以白嫖 KV 缓存——把缓存对齐做进摘要协议本身;②压缩事务 + 界面稳定性断言,杜绝并发脏写;③四个 provider 独立成包,可按需组合(只要裁剪、不要摘要也可以)。

codex 三模式压缩:本地摘要 / 服务端原生 / 窗口重置

模块地图

core/src/:compact.rs(930 行,本地摘要主流程)、compact_token_budget.rs(窗口重置)、compact_remote_v2*.rs(服务端原生压缩,含 attempt/installation/media)、compact_retained_tool_outputs.rs、compact_model_fallback.rs、context/、context_manager/;独立 crate context-fragments(可注入片段体系)、rollout/src/compression(会话文件压缩);prompts/templates/compact/{prompt.md, summary_prefix.md}。

触发

  • 主阈值 model_auto_compact_token_limit:无显式配置时取模型目录值且被 min 到上下文窗口×9/10;作用域可选 total 或 body_after_prefix(只计压缩窗口 prefix 之后的新增 token)。
  • 回合末阈值 model_post_turn_compact_threshold_percent(缺省禁用)。
  • 远程/本地分流看 provider 能力 remote_compaction:OpenAI/Azure、Bedrock、GCP 为 V2(服务端原生压缩),其余 Unsupported → 本地摘要。
  • 异步后台压缩(feature async_compaction)在窗口 65% 即启动后台摘要;TokenBudget feature 开启时改为直接开新窗口不摘要。
  • 手动 /compact 与自动共用 CompactTask 三分支;PreTurn 在模型切换致缩窗时触发(reason=ModelDownshift)。

算法(本地摘要)

  • 把全历史 + 摘要 prompt(prompt.md:为接手模型写 handoff summary,含进展与关键决策、重要上下文/约束/用户偏好、剩余工作、关键数据)发给模型;prompt 可经 compact_prompt 配置替换。
  • 保留:真实用户消息按预算从新到旧保留(上限 COMPACT_USER_MESSAGE_MAX_TOKENS=20,000,超出转带标记的截断);客户端标记的 retained tool outputs;canonical 初始上下文重新注入到最后一条真实用户/摘要消息之前;World State 基线。
  • 丢弃:assistant 消息、工具调用/输出(除 retained)、developer/system 消息、旧摘要。摘要以 SUMMARY_PREFIX(“Another language model started to solve this problem…”)编码为 user 角色的 CompactionSummary。
  • ContextWindowExceeded 时从头部删最旧 item 重试以保前缀缓存;压缩失败保留原历史(400f2356d)。

算法(remote v2)

  • 客户端发全历史 + 尾部 CompactionTrigger,服务端必须返回恰好一个 Compaction item,客户端只安装 checkpoint(prefix 策略)。
  • 保留预算 RETAINED_MESSAGE_TOKEN_BUDGET=64,000:user 消息、hook prompt、≤10,000 token 的 agent 消息、客户端 developer 消息、retained tool outputs;newest-first 截断。
  • retained tool outputs = 客户端 author 的、无 call_id 的具名输出(FunctionCallOutput{call_id:None, name:Some}),整体保留或整条丢弃;超窗工具输出被替换为 “Output exceeded the available model context and was truncated”。
  • 媒体预算:resize 图按 7373 bytes、原文件图按 10000 patches、inline 按 URL 计费;媒体按消息边界整体保留/丢弃且 newest-first,不回填旧消息。
  • 便宜模型回退:先前模型压缩失败且当前模型为 OpenAI 时,用当前模型重试(遥测 codex.compaction.model_fallback);压缩请求 reasoning effort=Compaction。
  • 后台推测执行:快照历史 → 后台跑压缩 → turn 内 checkpoint 复用(9e03960cf 接入 turn 生命周期);安装时校验 prefix 的 history_version/auth_owner_generation,拼接 live suffix,拒绝则回退前台。

状态与持久化

replace_compacted_history 原子替换内存历史并写 RolloutItem::Compacted:message、完整 replacement_history、guardian_history、retained_context、window_number/ids、compaction_response_id、latest_token_usage_record、resume_metadata(拒绝音频文件、动态工具、多 agent 版本等)。不可逆(原始历史被替换)但 replacement_history 整体留存,resume 时选最新可回放的压缩作为基线;fork/resume 继承压缩窗口并保留 reasoning token 计数(c62e9df39)。全程有 pre/post compact hooks 与 ContextCompaction turn item,保证分析事件一致。

配置

model_auto_compact_token_limit(+scope)、model_post_turn_compact_threshold_percent、compact_prompt、experimental_compact_prompt_file;features:token_budget、async_compaction(默认 65%)、CompactionImageBudget、RetainClientToolOutputs、RetainClientDeveloperMessages。

近期更新(8-11 月,245 次触及本批文件)

  • 11-04 19438adcb 专用 context window ID 类型;1685f2d62 上传音频按实测时长计费。
  • 11-03 3780a5f75 压缩中给保留文件音频计费;f1b0721c8 上传音频持久化拒绝恢复。
  • 11-02 WebSocket↔HTTP fallback 会话级保持与压缩传输恢复(446044992);压缩后允许 volatile World State section 刷新(2fa67f03f)。
  • 10-28 resume/fork 保留 reasoning token 计数(c62e9df39);10-27 不可用图片引用替换(cb66dbecf)。
  • 10-14 400f2356d 压缩失败保留会话历史;10-20 改善压缩 rollout 读取失败诊断。
  • 10-13 后台压缩接入 turn 生命周期(9e03960cf)+ 推测性 remote v2 基础设施(1a69ad323)。
  • 10-10 保留 client 标记的 tool outputs(6c0c6759d);08-12 远程压缩后丢弃 descendant progress 更新、保留 client developer messages(bff03ecce)。
可借鉴点:①同一压缩生命周期挂 pre/post hook + turn item,本地/远程/重置三实现共用可观测性;②retained tool outputs 的“整条保留或整条丢弃”语义清晰;③媒体预算按消息边界计费且不回填——避免“修了旧图又超长”的反复横跳;④压缩失败零损失回滚是底线要求。

pi 轮次边界压缩 + split-turn 双摘要 + 分支摘要

模块地图

packages/coding-agent/src/core/compaction/:compaction.ts(1104 行,主逻辑)、branch-summarization.ts(会话树分支摘要)、utils.ts(序列化/文件聚合);token 计数在 packages/ai(catalog 提供模型窗口)。durable 会话的压缩状态迁至 pi-durable(原 packages/agent/src/harness/compaction 已于 10-01 7fd478a2 移除)。

触发

  • 判据:contextTokens > model.contextWindow − reserveTokens;reserveTokens 默认 16,384,逐字保留 keepRecentTokens 默认 20,000(settings-defaults.ts)。
  • token 估算:优先用最近一条合法 assistant 回复的 usage.totalTokens(含 cache 计数),尾部新增消息用 chars/4 保守估算。
  • 两条自动路径:下次 assistant 响应前(_exceedsCompactionThreshold);轮次结束后(_checkCompaction,含溢出恢复:上下文溢出错误 → 省略式恢复 → 按 “overflow” 压缩)。手动 AgentSession.compact() 先中止当前操作且不重试。
  • 支持 compaction.modelOverrides["provider/id"] 逐模型覆盖(含压缩专用模型)。

算法

  • 切点纪律:从最新往回累加估算 token 至 ≥ keepRecentTokens;切点只允许落在 user/assistant/turn-start 消息边界,绝不切 toolResult;尾部工具结果超预算时回退到其前的 assistant 边界(8bdcd449 #9740)。
  • split-turn:切点落在回合中部时,对该回合前缀单独生成 turn-prefix 摘要,与主摘要用分隔符合并;/compact 自定义指令同时作用于两段(adfc1446)。
  • 迭代合并:有 previousSummary 时用 UPDATE prompt 合并而非重写。
  • 摘要固定结构:Goal / Constraints / Progress / Key Decisions / Next Steps / Critical Context;序列化时工具结果截断 2000 字符、thinking 省略;文件操作聚合成 <read-files>/<modified-files> 附录(utils.ts)。
  • 分支摘要(branch-summarization.ts):会话树导航离开某分支时,把 old leaf 到公共祖先之间的分支条目总结成 branch_summary 条目,预算 = contextWindow − 16384,优先保留摘要类条目。

状态与持久化

压缩结果作为 compaction 条目 append 进 jsonl 会话文件:summary、firstKeptEntryId、tokensBefore、details{readFiles,modifiedFiles}、usage、边界处完整 systemMessage。投影规则:上下文 = [最新 compaction 条目,firstKeptEntryId 起原文,之后全部条目]。fork 复制全部条目(含 compaction)→ 压缩在 fork 后存活。生成失败(stopReason=length/error)拒绝落盘(97fa14e3)。扩展钩子:session_before_compact(可取消/供结果)、session_compact、session_compact_failed。

配置

compaction.{enabled, reserveTokens, keepRecentTokens, modelOverrides};branchSummary.{reserveTokens, skipPrompt}。

近期更新

  • d0fe2130(#11680)context edits 进分支摘要输入;269afc66(#11482)分支摘要传 thinking level。
  • 6fcb4867(#11036)摘要请求去除固定输出上限;90305d90摘要期禁用工具;15e7bdc1摘要省略 thinking。
  • cache-friendly 原语(cff1cf52,8-18)已被 8dab7028 revert——缓存对齐的收益不足以抵消复杂度(行业里少见的“加了又退”样本)。
可借鉴点:①“切点绝不落在工具结果配对中”是硬约束(防 tool_use/result 错配导致模型困惑);②split-turn 处理“半个回合”的摘要粒度;③分支摘要解决会话树导航的历史回收,与主线压缩正交。

ZCode 双层压缩(microcompact → 完整)+ 四阶段执行模型

模块地图

apps/zcode-cli/packages/core/src/compact/:policy.ts(触发策略)、microcompact.ts(轻量层)、rounds.ts(轮次分组)、manual.ts(手动流程)、prompt.ts(摘要 prompt)、compact-active.ts(运行时编排);契约在 contracts/src/compact/;事件在 contracts/src/events/session.events.ts;设计文档 docs/design/v2/compact/ + rewind-compact.md。

触发(policy.ts)

  • 默认上下文窗口 200,000;有效窗口 = 窗口 − 输出预留(min(maxOutput, 32k),preflight 策略上限 21k);阈值 = 有效窗口 − 13,000 buffer(注释明确:provider 窗口 input+output 共享,只能让出输入侧)。
  • token 来源优先 provider 真实 usage(base + cacheRead/Write + contextUsage + incremental + output),无 usage 时本地 chars/3 估算(覆盖正文+reasoning+toolCall name+JSON input)。
  • 决策 reason 五态:disabled / not_enough_messages / circuit_breaker(连续失败 3 次熔断)/ below_threshold / above_threshold。
  • microcompact:阈值 = min(完整阈值×0.9, 完整−2000);触发 = 时间驱动(idle > 60 分钟)或 token 压力;清理旧的可压缩工具结果(Read/Bash/Grep/Glob/WebFetch/WebSearch/Edit/Write/ApplyPatch),保留最近 5 个,至少省 256 token 才生效;媒体内容与已清理内容跳过;只改内存投影、写 microcompact_boundary 观测事件、不产生完整 boundary。

算法

  • 四阶段(CompactPhase × CompactReason):standalone_turn+user_requested(手动 /compact);pre_request+context_limit(turn 首个 model 请求前);mid_turn+context_limit(同 turn 工具批次后的下一次请求前);reactive+provider_overflow(主请求溢出后的压缩重试,成功后原请求重放)。
  • rounds 分组:groupByAssistantStartedRounds 按 assistant 消息 id 变化切轮次;自动/响应式保留最近若干组原文(基础 1 组),其余进摘要;minimumGroupsToPreserve 可配。
  • prompt:强制纯文本输出(preamble/trailer “Respond with TEXT ONLY”);<analysis> + <summary> 两段;9 段式(Primary Request / Key Technical Concepts / Files and Code / Errors / Problem Solving / All user messages(含反归属声明:模型生成的伪 user 轮不得归为用户)/ Pending / Current Work / Optional Next Step);安全约束须逐字保留。格式器剥离 analysis、抽取 summary;续写消息附 transcript 路径、REPL 状态、preserved-segment 尾注。
  • 手动路径:turn kind=compact、inputVisibility=model-only(v4 投影不渲染成用户气泡);历史不足时健康 no-op;自动路径最多 3 次尝试,中间失败发 retrying 时间线事件;rapid-refill 熔断(不足 3 个 tool turn 内连续 3 次快速回填即熔断)。

状态与持久化

append-only 会话事件:CompactStarted / CompactCompleted / CompactBoundary / MicrocompactBoundary;boundary payload 含 trigger/phase/reason/压缩前后 token 计数/preservedSegment/summaryMessageIds。原子写 bundle(摘要消息 user 角色 + compaction part,顺序=请求前公告→summary→附件),仅摘要成功才写;resume 从最近 boundary 后水合;事件存储对 turn-window 淘汰(封存 turn 的 model_request 瘦身为只留 messageCount)。

与 rewind/fork 的关系

active chain 从 compact boundary 开始;conversation rewind 只在 boundary 之后合法;compact 前的 file checkpoint 可做 file-only rewind 并标 covered_by_compact;回到 compact 前的对话点用 fork(append-only 分支切割);partial compact 记 preservedSegment{head/anchor/tailMessageId} 且不得拆 tool_use/result 对。

配置

AgentRuntimeConfig.compact.{enabled, contextWindow, maxOutputTokens, modelContextBudgetStrategy(legacy|preflight-v1), summaryReserveTokens, bufferTokens, thresholdPercentOverride, maxConsecutiveFailures, microcompact{enabled, thresholdTokens, idleThresholdMinutes, keepRecentToolResults, compactableToolNames, clearErrorResults, minTokenSavings}}。

近期更新(均为 sync 提交)

  • a9fe401e(v3.17.2,11-03):子会话不再收到主会话的五阶段 plan 提醒(compact-active 调整)。
  • 0a1fc56d(10-19):摘要请求的工具候选按 ToolSearch/registry 能力过滤,防 MCP schema 撑爆摘要请求;compact-persistence 重写。
  • a60ba6a7(10-30):rewind-compact 文档 + session-store compact bundle 测试;aac47556(v3.15.1):compact/README、plan、e2e 文档与 e2e 用例(断言 manual=standalone_turn/toolCount=0、auto=mid_turn、microcompact 占位符且不产生 full boundary、reactive 带 reason=provider_overflow)。
可借鉴点:①双层(micro→full)把“省 token”和“保语义”解耦;②四阶段模型把压缩时机精确到 turn 内(pre/mid/reactive),reactive 重放让恢复对用户无感;③反归属声明防止模型把“自己生成的用户消息”当真实用户意图;④rapid-refill 熔断识别“压了又填、填了又压”的空转。

opencode 拒绝恢复阶梯 + 后台预压缩 + native 通道

模块地图

packages/core/src/session/compaction.ts(1246 行,核心);触发点在 session/runner/llm.ts;配置在 config/plugin/compaction.ts;测试 test/session-runner.test.ts。

触发

  • 三类 Trigger:auto(每 step 前 estimatePrompt ≥ ceiling)、overflow(provider 拒绝后一次性恢复)、manual(/compact)。
  • ceiling = window − buffer;compaction.buffer 支持百分比("1%"–"99%",6700dd87b)或整数 token(旧键 reserved 经 normalize 迁移),默认留 max(15% 窗口, 16k);窗口未知 → ceiling=Infinity,auto 永不触发(只靠 overflow 恢复)。
  • 后台预压缩(experimental.background_compaction):达 ceiling×0.85(PRECOMPUTE_RATIO)且实测 ≥64k 时在后台摘要 anchor 前全部历史;压缩到期直接换入以复用 prompt 缓存;每 session 一份,失败 2 次停止到下次压缩。

算法

  • 切分:splitConversation 按 keep(默认 15k tokens)切出逐字尾部,其余整段发模型;7 段模板(Objective / Requirements / Decisions / Work State / Next Move / Relevant Files / Important Context);instruction 类内容(AGENTS.md 等)明确排除、下轮单独给。
  • 发送降级阶梯(flattenAndDropOldest):原样发(保缓存)→ 整段 → 工具输出截断 → 输出移除+输入截断 → 只留 user 文本 → 省略;头尾各 2000 字符 clip,最新 exchange 永不省略。
  • 拒绝恢复阶梯(6597f6cd6):被拒请求按 SHRINK_STEPS [0.85, 0.7, 0.5, 0.35] 对首次被拒尺寸逐级降 target 并从零重截;measured 请求被拒后只以纯文本重发;payload-too-large 转文本一次不计步。
  • native 通道:model.compaction.type==="native" 走 provider 原生压缩机制,保留最近 keep 的整条 user 消息;native 窗口仅原 provider 可回放。

状态与持久化

结果持久化为 type=compaction 消息(completed/failed + text + metadata.keepID);历史从最新 compaction 加载,previousCompaction 恒为第一条;进程重启靠 settleStaleCompactions 结算孤儿 running 行。后台摘要存内存 Map(firstID/keepID/tailLimit/failures),模型或指令变化即失效。事件 Compaction.Started/Delta/Ended/Failed 广播;失败/中断照常计费(spent map)。

配置

compaction.auto(默认 true)、compaction.keep.tokens(15k)、compaction.buffer、experimental.background_compaction;旧键 tail_turns/prune 被拒绝。

近期更新

  • 6700dd87b buffer 支持百分比配置;cb1e58fe4 prompt 大小封顶(fitOutput 压 maxTokens,floor 32k)。
  • 6a5973d26(后改名 f523f7713)后台预压缩上线。
  • 6597f6cd6 拒绝后不原样重发、逐级降尺寸重截。
可借鉴点:①“被拒后逐级降尺寸重截”把 provider 的硬拒绝变成可恢复信号;②后台预压缩 + 到期换入,让压缩等待与模型工作并行;③失败/中断照常计费的诚实计费策略。

goose 结构化 JSON 摘要 + 价格护栏 + 双可见性冻结

模块地图

独立 crate crates/goose-context-management/:lib.rs(三层 API)、summarize.rs、structured.rs(484 行,结构化解析)、format.rs、provider.rs(CompactingProvider)、model.rs(CompactionModel/TokenEstimator)、templates.rs、prompts/compaction.md;触发在 crates/goose/src/context_mgmt/mod.rs 与 agents/state_machine/proactive_compaction.rs。

触发

  • proactive:下次推理前比较 session.usage.total_tokens(+未上报工具结果)或全量估算 / context_limit > threshold;assistant 结尾(无后续推理)跳过。
  • threshold = min(GOOSE_AUTO_COMPACT_THRESHOLD 默认 0.8, GOOSE_AUTO_COMPACT_TOKEN_LIMIT 225,000 / context_limit)。225k 是价格护栏:刻意低于 OpenAI 272k 长上下文价格档(cd1da62a),是成本边界不是请求上限。
  • reactive:尾部 ContextLengthExceeded;同一上下文错误 >2 次(MAX_CONTEXT_ERROR_COMPACTIONS)不再自动压。manages_own_context 的 provider(claude_code/gemini_cli)整体跳过。

算法

  • agent 可见消息(剔除 turn-context 事件)经 format_message_for_compacting 扁平为 [role]: 文本(图片/文档/工具调用降级为短标记,Thinking 丢弃)。
  • 摘要 prompt(compaction.md):<analysis> 草稿(会被丢弃,仅作清单)+ 恰好一个 JSON block,10 字段:user_intent / technical_concepts / files[{path, summary, key_code}] / errors_and_fixes / problem_solving / user_messages / pending_tasks / current_work / next_step。
  • prompt 明确“摘要只给模型读、可以比给人看的摘要长得多,把全部长度预算花在 JSON 字段上,逐字引用”;错误消息/panic 文本/测试输出须逐字引用;不编造新想法(No new ideas unless user confirmed)。
  • lenient 解析(对象/数字自动 stringify、未知字段 flatten 保留);解析失败或全空 → 原始文本无损保留。摘要器自身溢出:REMOVAL_PERCENTAGES [0,10,20,50,100] 从中间向外删 tool response 重试;无 tool response 直接 fast-fail 报错。
  • CompactingProvider 包装任意 provider:遇 ContextLengthExceeded 自动压缩并以单条摘要重试一次。

状态与持久化

原消息 → user_visible=false & agent_visible=false(冻结);摘要消息 agent-only + compaction_summary 标记;追加 assistant continuation(“Your context was compacted…”,普通/工具循环/手动三文案)。保留最近一条纯文本 user 消息逐字(手动压缩不保留);当前 turn 的 turn-context 事件 carry 到最后且 created 时间戳重置(防持久化重排)。可见性投影:用户可见存档保留原 audience 注释,agent 回放去掉 user-only 内容。

配置

GOOSE_AUTO_COMPACT_THRESHOLD(0.8)、GOOSE_AUTO_COMPACT_TOKEN_LIMIT(225,000)、GOOSE_TOOL_PAIR_SUMMARIZATION(默认 false)、GOOSE_TOOL_CALL_CUTOFF;摘要模板可被用户 ~/.config/goose/prompts/ 覆盖;Python/Kotlin 经 uniffi 复用。

近期更新

  • cd1da62a 225k 封顶(价格护栏落地);0aa212e6 可选 context relevance 操作;c85a58d7 ACP 手动压缩失败上报;7f57d569 不向模型暴露压缩倒计时。
可借鉴点:①结构化 JSON 摘要(而非自由文本)让“待办/文件/错误”可被程序化消费;②“analysis 丢弃、只留 JSON”的两段式 prompt 让模型先粗读再精写;③按价格档设护栏阈值——压缩首先是成本决策;④双可见性冻结(用户存档 vs agent 投影)一份数据两种读法。

gemini-cli 新旧双路径 + 工具输出三件套(掩码/蒸馏/归一化)

模块地图

packages/core/src/context/:传统路径 chatCompressionService.ts(721 行);新架构 contextManager.ts + pipeline 图 + profiles;工具输出三件套 toolOutputMaskingService.ts、toolDistillationService.ts、agentHistoryProvider.ts;状态缓存 compression_state.json 配套 contextCompressionService.ts。

触发(新旧两条路径并存)

  • 传统路径:compressionThreshold 默认 0.5×tokenLimit(model);findCompressSplitPoint 按 JSON 字符占比 0.7 找切点(1−COMPRESSION_PRESERVE_THRESHOLD 0.3,保护最近 30%);上次失败后只做截断不再调 LLM。
  • 新架构:generalistProfile budget maxTokens 150k / retainedTokens 65k,gcStrategy=incremental;currentTokens > retainedTokens 时按 age-out 分级(retained→normalized),coalescingThresholdTokens 迟滞防抖。
  • 三模式:incremental(每次只处理最老必需节点,“minimum viable chunk, oldest 2 nodes”;stateSnapshotProcessor 为时点快照,max=accumulate 累积);hotstart(首次渲染后用真实 countTokens 校准估算器,一次性);barrier(render 前 await pipelines,view>maxTokens 触发同步 GC backstop,保证发出的请求不超窗)。

算法

  • 传统摘要:state_snapshot 两阶段——先生成再 probe 验证自我纠正;新 token 数反而更大则 COMPRESSION_FAILED_INFLATED_TOKEN_COUNT 放弃;anchorInstruction 处理已有快照的整合。
  • 掩码(masking):混合反向扫描 FIFO——protectionThresholdTokens 50k 保护窗 + protectLatestTurn;越窗后累计可掩码 > minPrunableThresholdTokens 30k 才批量触发(约 80k 工具 token 起步);完整输出写 tool-outputs/session-*/ 文件,原位换 <tool_output_masked> 预览(shell 保留 Error/Exit Code 段);EXEMPT_TOOLS 永不掩码。
  • 蒸馏(distillation):单输出 > maxOutputTokens×4 字符时——存盘 + 结构截断(头 20%/尾)+ 可选 intent summary(独立模型,15s 超时,只抽错误/路径/结论 <10 行);read_file 豁免。
  • 消息级归一化(agentHistoryProvider):normalMaxTokens 2500 / retainedMaxTokens 12000,高水位截断旧消息+摘要,边界不破坏 functionCall/Response 配对。

状态与持久化

compression_state.json 按文件路径缓存 FileRecord(level FULL/PARTIAL/SUMMARY/EXCLUDED + contentHash,内容变即失效),批量一次路由调用(chat-compression-2.5-flash-lite)决策;掩码产物按 session 隔离落盘;压缩 telemetry 事件记录 tokens/masked_count。

配置

compressionThreshold;contextManagement.{enabled, historyWindow.{maxTokens,retainedTokens}, messageLimits, tools.distillation.{maxOutputTokens,summarizationThresholdTokens}, tools.outputMasking.*}。

近期更新

  • e6f92d6 大简化;01635dd loose boundary(屏障 backstop);bedef96 工具输出体积上界;055e5f6 跨会话快照恢复;07792f9 自适应 token 计算器。
可借鉴点:①“先落盘、再截断、原位换预览”的工具输出外部化(掩码 + 蒸馏是两种粒度);②增量/热启动/屏障三模式把“压缩何时发生”做成管线节点而非函数调用;③按 contentHash 失效的文件级压缩缓存,跨轮次复用。

mcode 分层阶梯压缩(归档→裁剪→checkpoint)+ 可恢复收据

模块地图

packages/local-runtime-v2/src/service/turn-system/compaction/:automatic-context-compactor.ts(507 行,触发)、contracts.ts;algorithm/:compact-context.ts(991 行)、history-reduction.ts、tool-result-archiver.ts(783 行)、tool-trim-admission.ts、checkpoint-protocol.ts、checkpoint-format.ts、assistant-iteration-cadence.ts、todo-cadence.py、background-cadence.ts;execution/request-media-projection.ts;状态在 agent-host/compaction/。

触发

  • probeBeforeLlm 每次 LLM 调用前执行;footprint=本地估算(inputTokens + 序列化字节,usageAnchor 进程级缓存最近实测,压缩后 invalidate 防旧值误导)。
  • providerInputLimit = min(0.95×窗口, 窗口−16384, 窗口−outputFloor−2048);automaticTriggerAt = min(providerInputLimit, (窗口−min(output, 窗口/4))×0.95)。
  • contextManagement.compactionTriggerAt(a79348f #493):(0,1] 比例或 >1 整数 token,每次调用读取,只能降低内置触发(单调语义);非法值 warn 一次后忽略。
  • provider 拒绝 → 无条件压缩:prefixCached 模型直接 llm_checkpoint(保图片字节一致),否则先归档工具输出+全部图片(archiveImages 是 recovery 专属,触发性压缩不动图片)。

算法

  • 分层决策:tool_archive(可恢复归档)→ tool_trim(legacy 保留 30%,生产禁用)→ llm_checkpoint;准入(tool-trim-admission)要求实测 footprint 真减小且 ≤ providerInputLimit。
  • checkpoint 候选阶梯(从大到小):h0 原始 → htrim(归档后)→ hall(全部工具结果移除)→ hvideo(去附件)→ hmid(middle-out 删中间,保护 closure 0 + 含 user 的 closure)→ hmin(仅最近真实 user query);逐档 fits 检查,provider error 原地重试一次,媒体拒绝走 attachment-free 阶梯。
  • checkpoint prompt:8 段 markdown(Goal / Constraints / Completed Work / Current State / Blockers / Key Decisions / Pending User Asks / Critical Context);标题从 prompt 尾部解析防漂移;历史视为不可信数据;recentUserQueries 逐字附在版本化 appendix 外。
  • 工具结果归档:watermark 256KiB 总文本、单条 ≥2KiB、估计/实际节省 ≥256KiB、keepRecentRounds 5;控制工具(skill/todowrite/plan 等)豁免;receipt 含工具名/来源(grep pattern+path 等)/artifact 引用;无 read 工具时 materializeTrim 破坏性替换且不宣称可恢复。
  • cadence:todo/background 提醒按 15 次 assistant 迭代节奏,从历史重放投影。
  • 媒体投影:非 prefixCached 模型按 image 上限 + 请求体字节份额把超额图片换占位文本;占位不进持久历史;prefixCached 保持全图不动。

状态与持久化

压缩 = canonical history replaceMessages 操作(attemptId/compactionId 幂等,克隆消息);结果附 CompactionCompatibility v5 appendix(summary + recentUserQueries + todoState + cadence + subagents)。session-id 恢复(c460f08 #466):session_identity_reminder 在压缩丢 id 后重新注入;近期提交移除了拒绝后强制重发(绕过 before-LLM 管线导致截图上限/session-id 未重放)。

配置

contextManagement.{compactionTriggerAt, disableSystemReminderModels, cuMaxScreenshotsInContext: 2};toolResultCompaction.{enabled, maxInlineKiB: 64, mcpDetailsMaxInlineKiB: 32, watermarkKiB: 256, minSavingsKiB: 256, minCandidateKiB: 2, keepRecentRounds: 5};requestMedia.*。

近期更新

  • a79348f compactionTriggerAt 单调语义;c460f08 session-id 恢复 + 移除强制溢出压缩。
  • 5b4e0a4 oversized 重发改走正常恢复;1852771 图片上限与恢复;3123293 用量失效防误导;698a986 同步 MiniMax 0.7.2。
可借鉴点:①六档候选阶梯(h0→hmin)让“压到刚好装下”成为搜索问题而非一次决策;②归档 receipt(工具名+来源+artifact 引用)让裁剪可审计可恢复;③配置单调语义(compactionTriggerAt 只能调低)防止用户误配把系统调坏;④“历史视为不可信数据”的 prompt 纪律。

4. 方案对比

4.1 触发机制对比

harness阈值基数默认值自适应后台/预执行响应式恢复
codextoken 上限 / 窗口比例窗口×9/10(可配 scope)模型目录值兜底65% 后台摘要;TokenBudget 窗口重置provider 溢出;PreTurn 缩窗
ZCode有效窗口−buffer200k−输出预留−13kpreflight-v1 用 provider usagemicrocompact(90%/idle 60min)reactive 重放原请求
DSH请求压力比0.8 + 余量 65536按路由模型覆盖—overflow 重试(可配次数)
piwindow − reservereserve 16384 / keep 20000模型 catalog 窗口—溢出错误专项压缩
opencodewindow − buffermax(15%, 16k)Percent 可配85% 后台预压缩换入SHRINK_STEPS 四级降尺寸
goose比例 + 绝对上限min(0.8, 225k/limit)绝对上限=价格档护栏—同错误 >2 次熔断
gemini-cli0.5×limit / profile 65k0.5(旧)/ 65k retained(新)hotstart 真实计数校准增量管线持续 GCbarrier 同步 backstop
mcode输入上限 95%0.95×providerInputLimit单调 compactionTriggerAt 下调—拒绝无条件压缩 + 专属图片归档

4.2 压缩策略原型对比

原型含义采用者
本地 LLM 摘要把历史发给模型生成摘要,替换原历史DSH、pi、ZCode、opencode、goose、gemini-cli、mcode、codex(本地模式)
服务端原生压缩provider 端压缩,客户端只安装 checkpointcodex remote v2、opencode native
启发式裁剪/外部化不调 LLM,直接截断/掩码/归档工具输出DSH pruner、gemini-cli masking/distillation、mcode tool archive、codex retained outputs
窗口重置跳过摘要,直接安装新上下文窗口codex TokenBudget feature
分层组合上述手段按强度分层,逐档加码直到装下ZCode(micro→full)、mcode(archive→trim→h0..hmin)、gemini-cli(mask→distill→summarize)、codex(retained→local→remote)
趋势:单一手段已成过去式。头部方案全部是分层组合:先用零成本的启发式(裁剪/归档/掩码)争取空间,不够再上 LLM 摘要,还不够才考虑窗口重置或服务端压缩。

4.3 信息保留对比

harness逐字尾部工具输出处理用户原话迭代合并其他特色保留
DSHretainRatio 0.16裁剪头 4096+尾 1024,中间标记预算内 newest-first旧检查点合并不复制图片 offload 占位;最近单位保留
codex20k token 预算retained 整条保留/丢弃;超窗截断占位真实用户消息 newest-first—初始上下文重注入;World State 基线;agent 消息 ≤10k
pikeepRecentTokens 20k切点绝不落 toolResult;超大回退含在最近段UPDATE prompt 合并文件操作聚合附录;分支摘要
ZCode最近 ≥1 组轮次microcompact 保最近 5 条9 段含全部用户消息+反归属—preservedSegment;session memory
opencodekeep 15k截断工具输出(可恢复源)最新 exchange 永不省略previousCompaction 首条instruction 下轮单独给
goose最近纯文本 user 消息摘要器溢出时按 0-100% 删user_messages 字段逐字—结构化 JSON 10 字段;turn-context carry
gemini-cli保护最近 30%掩码落盘换预览 / 蒸馏截断+摘要state_snapshot 整合anchor 整合文件级压缩缓存(contentHash)
mcodehmin=最近真实 user query归档 receipt(可恢复)/ 控制工具豁免recentUserQueries 逐字附录—todoState/cadence/subagents 随附录存活

4.4 Prompt 设计对比

harness结构段数缓存对齐特殊纪律
DSH固定 Markdown 段8摘要请求=末次路由请求的前缀扩展(复现 system+tools+前缀)不得提及压缩、不得调工具;空段写 (none)
codexhandoff 摘要4 主题(进展/约束/下一步/数据)—可自定义 compact_prompt;压缩用独立 reasoning effort
pi固定结构 + 文件附录6—工具结果截断 2000 字符、thinking 省略
ZCode<analysis>+<summary>9工具段字节稳定契约反归属声明;安全约束逐字保留;纯文本输出强制
opencodeMarkdown 段7能原样发就原样发(保 cache);后台换入instruction 排除;头尾 clip 2000 字符
goose<analysis> 草稿 + JSON block10 字段—逐字引用错误/panic;不编造;模板可用户覆盖
gemini-cliXML state_snapshot两阶段(生成+probe)批量路由调用决策probe 自校验;膨胀即放弃
mcodeMarkdown 段8—历史视为不可信数据;标题从 prompt 尾部解析防漂移

观察:DSH 与 opencode 把缓存对齐做进摘要协议(前缀复用 / 原样发送 / 后台换入);goose 与 ZCode 用“<analysis> 丢弃 + 结构化产物”两段式;mcode 明确“历史不可信”的 prompt 纪律;各家摘要段数收敛在 6–10 段。

4.5 状态与持久化对比

harness载体压缩记录内容可回放/分叉可逆性
DSHSessionEvent 日志(事务提交)压缩条目;快照多 profilereplay/fork 用旧日志播种事务失败整体回滚
codexRollout 事件CompactedItem:完整 replacement_history + window ids + resume_metadataresume 回放;fork 继承压缩窗口不可逆但留全量替换历史;失败保留原历史
pijsonl 条目summary + firstKeptEntryId + details + usage投影重建;fork 存活生成失败拒绝落盘
ZCodeappend-only 事件boundary:trigger/phase/tokens/preservedSegment/summaryMessageIdsboundary 后水合;rewind 仅限 boundary 后;fork 回退点仅摘要成功才写;rapid-refill 熔断
opencodecompaction 消息行text + metadata.keepID;孤儿 running 行结算从最新 compaction 加载被拒阶梯重截;后台 Map 失效控制
goose消息行(可见性标记)双冻结 + compaction_summary 标记 + continuationagent 回放投影解析失败无损保留原文
gemini-clicompression_state.json + 落盘文件FileRecord(level + contentHash)跨会话快照恢复内容变即失效;膨胀即放弃
mcodecanonical history 替换 + v5 appendixsummary + recentUserQueries + todoState + cadence幂等 attemptId;session-id 恢复准入实测;无 read 工具时破坏性替换

4.6 健壮性对比

harness失败处理熔断/节流并发保护特殊机制
DSH事务回滚;overflow 重试可配—assertWholeSurfaceUnchanged 乐观并发断言released units 保留修复
codex失败保留原历史(400f2356d);超窗从头删保前缀缓存重试模型回退链hook pre/post;installation 校验 history_version便宜模型回退压缩;遥测完整
pi生成失败拒绝落盘手动不重试—摘要期禁用工具
ZCode自动最多 3 次尝试 + 时间线事件连续失败 3 次熔断;rapid-refill 熔断单写者生命周期reactive 重放原请求
opencodeSHRINK_STEPS 四级降尺寸重截后台失败 2 次停—失败/中断照常计费
goose解析失败无损保留;无 tool response fast-fail同上下文错误 >2 次停—摘要器自身溢出按 0-100% 删重试
gemini-cli失败后只截断不调 LLM;膨胀即放弃迟滞防抖;批量阈值屏障同步hotstart 一次性校准
mcodeprovider error 原地重试一次—幂等 attemptId准入要求实测 footprint 真减小

4.7 成本与缓存对比

harness摘要成本意识缓存策略价格护栏
DSHmaxTokens 独立配置;重试成本文档化摘要请求复现前缀直吃 KV 缓存—
codex独立 reasoning effort;媒体按字节计费保留 reasoning token;前缀保形重试—
pi去除固定输出上限cache-friendly 原语(曾加入后 revert)—
ZCode摘要输出上限 20k工具段字节稳定契约—
opencode失败也计费(诚实计费)能原样发就原样发;后台预压缩到期换入复用缓存—
goose——225k = OpenAI 272k 价格档护栏
gemini-cli批量路由调用(2.5-flash-lite)做决策文件级压缩缓存跨轮次复用—
mcode实测 footprint 后才准入prefixCached 模型保图不动触发点单调下调

5. 最新更新与趋势(2026-08 → 2026-11)

5.1 各家近期主线

harness近期更新主线代表提交/版本
codex后台压缩接入 turn 生命周期、推测性 remote v2、音频/媒体预算、跨压缩保留 reasoning token 与 world state、失败回滚9e03960cf、1a69ad323、1685f2d62、c62e9df39、2fa67f03f、400f2356d
opencodebuffer 百分比化、后台预压缩、拒绝恢复阶梯6700dd87b、f523f7713、6597f6cd6、cb1e58fe4
ZCode摘要请求工具候选按能力过滤(防 MCP schema 撑爆)、persistence 重写、子会话 plan 提醒隔离(随同步流 v3.15.1→v3.17.2)0a1fc56d、a9fe401e、a60ba6a7
pi分支摘要增强(context edits/thinking level 进输入)、摘要去固定上限与工具禁用、cache-friendly 原语加了又退d0fe2130、269afc66、6fcb4867、90305d90、cff1cf52/8dab7028
goose225k 价格护栏、可选 context relevance 操作、失败上报、不向模型暴露倒计时cd1da62a、0aa212e6、c85a58d7、7f57d569
gemini-cli大简化、屏障 backstop、工具输出体积上界、跨会话快照恢复、自适应 token 计算器e6f92d6、01635dd、bedef96、055e5f6、07792f9
mcodecompactionTriggerAt 单调语义、session-id 恢复、图片上限与恢复专属归档、用量失效防误导a79348f、c460f08、5b4e0a4、1852771、3123293
DSH超大摘要前缀重试(加后 revert + 文档化契约)、checkpoint released units 修复、多轮溢出恢复契约文档cf7229e72a/3081c71bab、eb1713f856、dd87277afa

5.2 跨家趋势(从代码变化归纳)

  1. 后台/推测执行压缩进入 turn 生命周期:codex(9e03960cf 接入、1a69ad323 推测基础设施)与 opencode(后台预压缩到期换入)不约而同把压缩从“阻塞式后处理”变成“与模型工作并行的预取”。压缩等待正在被工程化消除。
  2. 分层压缩成为标配:ZCode 的 micro→full、mcode 的 archive→trim→h0..hmin 六档、gemini-cli 的 mask→distill→summarize、codex 的 retained outputs→local→remote v2——先用零 LLM 成本的启发式,再逐级加码。
  3. 媒体预算独立化:codex 按消息边界为图片/音频计费(7373 bytes/张、10000 patches、实测音频时长),mcode 的 recovery 专属图片归档 + 每请求截图上限(cuMaxScreenshotsInContext=2),DSH 的图片 offload 占位——多模态上下文开始有自己的预算学。
  4. 跨压缩状态保留:codex 保留 reasoning token 计数与 world state section;mcode 的 v5 appendix(todoState + cadence + subagents + recentUserQueries);ZCode 的 boundary 事件携带 preservedSegment——压缩不再被视为“清空重来”,而是状态迁移。
  5. 价格护栏显式化:goose 225k 封顶(cd1da62a)把 OpenAI 272k 价格档写进常量;mcode 触发点单调语义(a79348f)防用户误配;DSH 把重试成本写进文档(595f5a65f3)。
  6. 摘要请求自身的卫生:ZCode 按 ToolSearch/registry 能力过滤摘要请求的工具候选(0a1fc56d,防 MCP schema 撑爆);pi 摘要期禁用工具(90305d90);codex 压缩用独立 reasoning effort——辅助调用正在被当作一等公民治理。
  7. 诚实计费与可观测:opencode 失败/中断照常计费;goose 不向模型暴露压缩倒计时(7f57d569);codex 全流程遥测(CompactionImplementation/Phase/Reason/Strategy);ZCode 的 reason 五态决策可解释。

6. 结论与设计模式建议

6.1 七条可复用的设计模式

  1. 压缩即生命周期:把压缩建模为带 pre/post hook、turn item、稳定事件名的生命周期(codex/ZCode/DSH 共识),而不是一个函数——可观测、可拦截、可组合。
  2. 分层加码:启发式(裁剪/掩码/归档)→ LLM 摘要 → 窗口重置/服务端压缩,逐档直到装下(ZCode/mcode/gemini-cli/codex 共识)。每层都有明确的“够了就停”判据。
  3. 缓存对齐的摘要请求:摘要调用复现末次请求的 system+tools+前缀(DSH)、能原样发就原样发(opencode)、后台到期换入(opencode)——把压缩成本压到最低。
  4. 结构化摘要 + 迭代合并:固定段数(6–10 段)+ <analysis> 丢弃两段式(goose/ZCode/mcode)+ previousSummary 合并而非重写(DSH/pi/opencode)。
  5. 切点硬约束:绝不切 toolResult 配对(pi)、绝不拆 tool_use/result(ZCode)、保最近 N 组轮次(ZCode)——错配的代价是模型幻觉。
  6. 配置单调语义:触发点只能向严的方向调(mcode compactionTriggerAt);用户误配不得把系统调坏。
  7. 失败零损失 + 熔断:失败保留原历史(codex 400f2356d)、连续失败熔断(ZCode 3 次)、rapid-refill 空转熔断(ZCode)、同错误计数熔断(goose >2)。

6.2 对自建上下文处理方案的建议

优先级建议参照
P0先建“分层”骨架:触发探测 → 启发式裁剪(带 receipt)→ LLM 摘要(带 prompt 模板)→ 兜底(窗口重置或拒绝恢复)。不要一上来就只做摘要。mcode 六档阶梯、ZCode micro→full
P0触发探测优先用 provider 真实 usage(含 cache 计数),本地估算只补尾部;阈值 = 有效窗口(扣输出预留)− buffer。codex body_after_prefix、ZCode preflight-v1、goose 225k 护栏
P0摘要 prompt 采用“<analysis> 丢弃 + 结构化产物”两段式,段数 6–10,空段显式占位,历史视为不可信数据;模板可配置。goose compaction.md、ZCode prompt.ts、mcode checkpoint-protocol
P1工具输出外部化:超阈值落盘 + 原位占位 + 可恢复 receipt(工具名+来源+artifact 引用);控制类工具豁免。mcode tool-result-archiver、gemini-cli masking、codex retained outputs
P1压缩事件进会话事件流(trigger/phase/reason/前后 token),支持 resume 回放与 fork 继承;压缩失败保留原历史。ZCode boundary、codex CompactedItem、pi compaction entry
P1缓存对齐:摘要请求复用主请求前缀;预算允许时后台预压缩并在到期时换入。DSH summarizer、opencode background compaction
P2媒体预算:图片按消息边界保留/丢弃、按字节计费;非 prefixCached 模型才换占位。codex media budget、mcode request-media-projection、DSH image-offload
P2切点纪律 + 熔断:toolResult 不切、连续失败 3 次熔断、rapid-refill 检测、同错误计数上限。pi 8bdcd449、ZCode circuit breaker、goose >2
一句话总结:八家方案的差异主要在“触发哲学”(token 阈值 / 使用比例 / 时间驱动 / 价格护栏)与“状态载体”(事件日志 / 消息行 / 文件缓存),但收敛方向高度一致——分层加码、缓存对齐、结构化摘要、切点纪律、失败零损失、全程可观测。自建方案建议直接从 mcode 的阶梯骨架与 goose 的 prompt 纪律入手,用 codex 的生命周期事件与 ZCode 的双层策略补齐健壮性。

7. 附录:证据索引

7.1 关键源码文件

harness上下文处理核心文件
DSHpackages/compaction/compaction-basic/src/{config.ts,region.ts,summarizer.ts}、compaction-tool-result-pruner/src/config.ts、compaction-image-offload/src/image-offload.ts、command-compact/src/index.ts、context/agent-instructions/src/digest.ts
codexcore/src/{compact.rs, compact_token_budget.rs, compact_remote_v2*.rs, compact_retained_tool_outputs.rs, compact_model_fallback.rs}、context-fragments/src/*、rollout/src/compression.rs、prompts/templates/compact/{prompt.md, summary_prefix.md}
pipackages/coding-agent/src/core/compaction/{compaction.ts, branch-summarization.ts, utils.ts}、core/settings-defaults.ts
ZCodeapps/zcode-cli/packages/core/src/compact/{policy.ts, microcompact.ts, rounds.ts, manual.ts, prompt.ts, compact-active.ts}、contracts/src/compact/index.ts、docs/design/v2/compact/
opencodepackages/core/src/session/compaction.ts、session/runner/llm.ts、config/plugin/compaction.ts
goosecrates/goose-context-management/src/{lib.rs, summarize.rs, structured.rs, format.rs, provider.rs, prompts/compaction.md}、crates/goose/src/context_mgmt/mod.rs
gemini-clipackages/core/src/context/{chatCompressionService.ts, contextManager.ts, toolOutputMaskingService.ts, toolDistillationService.ts, agentHistoryProvider.ts, compression_state.json 配套服务}
mcodepackages/local-runtime-v2/src/service/turn-system/compaction/{automatic-context-compactor.ts, algorithm/*}、agent-host/compaction/、execution/request-media-projection.ts

7.2 调研方法说明