# 市场上下文压缩方案对标(2026-10-28) > 目的:为「DSH 上下文压缩插件」提供可直接指导实现的技术对比,不是行业综述。 > 纪律:每个数字都标来源(论文 §几 / README 原句 / 源码文件);抓不到的一律写「未验证」。 > 证据等级沿用论文自己的标记:**[V]** = 生产日志实测,**[A]** = 分析/模拟,**[P]** = 计划中。 --- ## 一、结论速览(5 条,可直接指导实现) 1. **唯一必须照抄的架构不变量是「只压已消费增量 + 追加不改写 + 摘要块可逐块还原」。** billion-context(下称 BC)论文 §3.6 明确把「每轮只压上次压缩之后新增的内容」定为 load-bearing:它同时是质量(只丢已用完的东西)、缓存(94.2% 命中,§6.3)、保留率(不随轮次复利衰减,§4.2)、成本(O(increment))四条结论的结构性根因。任何「每轮重新摘要全history」的方案(含 DSH 自带 `dsh-compaction-basic`)保留率按 ρ^k 几何衰减,ρ≈0.4–0.6,四轮后只剩 3–13%(论文 §4.2 [A]);Compaction Cliff 在 20 个生产配置上实测:Claude Code `/compact` 一轮后安全规则存活 53%,五轮后 10%(arXiv 2608.22752 摘要 [V])。 2. **差异化空间不在「压缩」,在「可逆 + 增量 + 判断规范」。** DSH 已有 `dsh-compaction` seam + `dsh-compaction-basic`(0.8 阈值 / 0.16 保留 / 8 段模板 / 不可逆 replace / 从第一个被遮蔽 token 起缓存失效),`dsh-compaction` 自己的 dev-note 写着「面向模型的压缩工具,尚未决定」——这正是本插件要占的坑位。必须继承 seam 的 `compactRegion`/`compactNow` 语义与 `surfaceOp: replace` 事务,而不是另起一套。 3. **判断必须做成「可版本化的 prompt 规范」(doctrine),不能训练。** BC 的五部分 doctrine + 六条交互机制(§4)是训练无关的 SFT 替代品,跨 GLM-5.1/5.2/5.3、Qwen、GPT 类模型免重训迁移 [V: run-level]。其中三条是反直觉但必须照做的:**(a) 永不给模型看填充比例**(模型看到「20%」会锚定「还健康」并拒绝压缩);**(b) 模型有拒绝压缩的权利**(拒绝是质量阀,不是失败);**(c) 候选区间必须带真实大小**(token 数/消息数/工具-文本构成),否则模型会压一堆零散低价值区间。 4. **触发用「双闸」:窗口下限 0.45 × 窗口 **且** 自上次压缩以来增长 ≥ 50K(有效下限 22.5K = 50K × 0.45)。** 单看比例会误触发,单看增长会在大窗口上永不触发。BC 生产实测默认 50K 增长闸、每次压缩折叠中位数 2.6K、每轮产出中位数 185 tokens(97.5% ≤ 2K)——压缩是「高频、小粒度、贴任务相位」,不是「低频、恐慌式」(§6.2)。 5. **必须解决「模型不会主动用还原工具」这个已被实测的死穴。** BC §8.1:restorability 6/6 通过(当被指示时),但「spontaneous tool adoption is zero at this model scale」——模型自发调用恢复工具的次数为 0。DSH 插件若把 `decompress` 只做成一个被动工具,收益接近零;必须在 nudge/系统提示里显式指示「何时该 restore」,或直接把最近 N 条被压缩区间的原文摘要以「可还原指针」常驻。 --- ## 二、billion-context / acp-kernel(最强对标) **身份**:`ranxianglei/billion-context`(npm 包 `billion-context`,命令行 `bili`)+ 内核 `ranxianglei/acp-kernel`;论文 Preprint v0.2,2026-09-07,MIT(+ 一条署名附加条款,README「Attribution requirement」)。内核 ~10k 行 TypeScript、零宿主依赖、550+ 测试(论文 §3.1)。系统四个公开工程:内核 `acp-kernel`、三线协议通吃代理 `billion-context`(Anthropic / OpenAI chat / OpenAI Responses)、ACP 原生扩展 `billion-context-pi`、`opencode-acp`(§3.1)。 **⚠ 与本项目直接相关的竞争事实(必须先知道)**:BC 已经把 DSH 做成一等宿主。`CLIENTS.md` 的 `## dsh (deepseek-harness)` 节:两条通道(`bili dsh` 启动器经 `--patch` 覆盖层注入全量原生插件;`bili plugin install dsh` ≡ `dsh plugin --profile add billion-context`),插件加载时自起代理、用全局 fetch patch 把模型流量重写到 `/bili/`、原样注册 manifest 工具。**并且它在同一补丁里把 DSH 自己的 `compaction-basic` 改成 `auto: false`**,Web profile 里嵌在 agent preset 内部的实例由常驻 bundle 条目 `bili-compaction-gate`(cordis `internal/config` overlay)在加载时置 `disabled: true`,其 bundle patch 还会给内置 DeepSeek 路由的 retry 白名单加上 `MALFORMED_RESPONSE`(CLIENTS.md dsh 节)。⇒ 本插件若要与 BC 共存,必须处理「双压缩」互斥,且不能假设 DSH 原生 compaction 一定在跑。 ### 2.1 架构与 9 阶段流水线 职责切分一句话(§3.1):**模型写摘要;库编排其余一切。** 内核暴露 `processTurn(state, messages, config) → (state', rendered, effects)`;宿主拥有模型 I/O 与工具分发,内核拥有全部上下文记账。内核**从不调用模型**——摘要文本作为参数传入(`acp-kernel/DESIGN.md` §1:「The core holds no state and performs no I/O」)。 每轮流水线(论文 §3.1,9 段): | # | 阶段 | 做什么 | |---|---|---| | 1 | `assign-refs` | 给新消息铸稳定 ID `mNNNNN` | | 2 | `sync-blocks` | 把新内容投影到块边界;`advanceSurvival` 做 young→old 晋升 | | 3 | `merge-blocks` | 合并相邻可压缩区间(old-gen 批量合并,`merge.maxSummaryLength` / `minOldGenBlocks`) | | 4 | `prune` | 强制预算不变量:被 active 块覆盖的消息丢弃,块的渲染摘要 `[Compressed conversation section]`(id `acp_summary_bN`)插回最早被覆盖位置(配对安全,`pairSafeAnchorIndex`) | | 5 | `filter` | 按 role/内容类型的可见性规则(保护区在此,不在 prompt 里) | | 6 | `hide-compress-calls` | 从渲染视图抹掉压缩工具调用噪音 | | 7 | `nudge-inject` | 注入增长闸提示(§2.3) | | 8 | `emergency-truncate` | 最后手段硬截断(`truncate.threshold`,bili 默认映射到 95% 用量;生产 4.5 天里 95% 紧急 nudge 触发 65 次,终局硬截断**从未触发**,§5) | | 9 | `render-refs` | 输出带 per-message ref 标签的最终消息列表 | **文档漂移(实现细节,值得本插件记住)**:`acp-kernel/DESIGN.md` §4 写的是 **10 个节点**,比论文多一个 `ccr-store`(内容存储节点),顺序为 `assign-refs → sync-blocks → merge-blocks → prune → ccr-store → filter → hide-compress-calls → nudge-inject → emergency-truncate → render-refs`。以 DESIGN.md 为准,论文少写了一节。 **降级安全设计(可直接抄)**:`parseCompressArgs` 是宽容解析器(围栏、尾逗号、被截断数组的抢救、字段名变体 startRef/startId),且工具 schema 刻意做成「解析器的超集」,并在注释里指明 **Anthropic 拒绝顶层带 `oneOf`/`allOf`/`anyOf`/`not` 的 `input_schema`**(400),所以 content-vs-flat 的二选一只写在描述里、不用顶层组合子、不设顶层 `required`(`src/compress-tools.ts` L71–148)。 ### 2.2 分层 DAG 与保留率 **`CompressionBlock` 字段**(论文 §3.2 与 `DESIGN.md` §3 完全一致,9+2 个): ``` blockId: string // "b0","b1",... runId: string tier: 1 | 2 | 3 topic?: string summary: string // 模型产出 directMessageIds: string[] effectiveMessageIds: string[] // 传递闭包:本块汇总的全部原始消息 directBlockIds: string[] // 被吞掉的子块(tier-2/3 用) createdAt: number survivedCount: number generation: "young" | "old" active: boolean // active=渲染进上下文;非 active 仍留在 state 里 ``` 配套 `CompressionState`:`{ blocks, messageRefs: {byRaw, byRef}, nudge: {lastPerMessageNudgeTokens, lastNudgeShownTokens, baselineTokens, anchors}, stats: {tokensCompressed, compressionCount}, nextBlockId, nextRunId }`;`Config`:`{ tiers: {enabled, tier2Trigger, tier3Trigger}, nudge: {maxContextLimitPct 0.55 咨询性, minContextLimitPct 0.45 闸门, frequency, iterationThreshold, force: "soft"|"strong"}, promotionThreshold, truncate: {threshold}, merge: {maxSummaryLength, minOldGenBlocks}, protectedTools, preserveRecentMessages, modelContextLimit }`。 **关键设计声明(DESIGN.md §4 尾注)**:`No gc(): age-based deactivation was removed (it caused memory-loss upstream)` —— **没有按年龄的 GC,也没有摘要截断**。块只会被晋升、合并、被新的压缩消费,不会被时间淘汰。这条值得本插件照抄:按时间淘汰是上游踩过的坑。 **分层规则**: - **tier-1**:压连续**消息区间**,通常一次压缩决策产生一个块。 - **tier-2**:tier-1 质量积累到阈值后,把**块**折成新块,`directBlockIds` 指向源块。 - **tier-3**:同理折 tier-2。 - 结构是「**over prose 的 LSM tree**」:young 代吸收写入,old 代持压实后的历史,压实是增量的(§3.2)。`effectiveMessageIds` 保证血缘在任意次重压缩后仍可追溯。 **塔式比例(实测,图 1,n=116 会话)**:tier-1 占常驻空间 **92%**,tier-2 **7%**,tier-3 **<1%**;而 tier-2+3 承载了**被表示历史的 37%**。 **保留率(§4.2)**: - tier-1 块级保留 ~**1/8**(全块中位数 **7.9×**;工具主导块中位数 **24×**,p75 **45×**,最大 >3000×,§6.2)。 - tier-2 蒸馏比 ~**1/4**(对 57 个可解析 tier-2 事件做 volume-weighted 拟合;逐事件中位数约 1/3);tier-3 压缩比 ~**1/3**(**未观测**,取自设计值)。 - 生产里 tier-2 只碰了 **60/1,711 个块(3.5%)**——级联蒸馏存在但罕见,定位是安全阀而非常规路径。 - 结论:`R_∞(BC) = ρ₁ ≈ 1/8 > 0`,`R_∞(传统阈值摘要) = 0`。 **生命周期与可逆性**:块 `active`/非 active;`decompress` 重新激活源、停用块本身;**`decompress-to-file`** 把完整原文写文件而不是塞回上下文——保住 KV 前缀,同时给模型全保真读取权;`search_context` 在块摘要 + 近期消息上做关键词召回;`acp_status` 报每轮构成(system / tool / summaries / code / text)与可压缩区间;被后续压缩消费的块保留为「consumed lineage」,可批量还原整段 run。 **首条 user 消息钉死(wire 级不变量,DESIGN.md §8.1)**:`rebuildMessages` 里「钉住检查」跑在「是否被 active 块覆盖」之前 ⇒ 压缩包含首条 user 消息的区间后,重建出的 wire 里**同时**有渲染摘要**和**首条 user 消息原文(其余被覆盖消息照常丢弃)。理由:严格 provider 要求对话以 user 起头。**下游断言必须预期这条消息仍在**,token 估算也要算上它(它常是任务描述且可能很长)。只钉第一条,后续被覆盖的 user 消息正常剪。 ### 2.3 触发策略(growth-gated) 论文 §3.4:提示(nudge)在 **(i) 上下文超过窗口下限比例(默认 ≈0.45)** 且 **(ii) 自上次压缩以来增长超过闸门量**时注入;tier-1 质量占优时还有 tier 专属触发。增长闸实现一条 doctrine 规则——**「在任务步之间压,不在步中压」**——每次压缩后重置基线。 具体数值(论文 §4 机制 i + `CONFIGURATION.md` 的实现口径,两处一致): - 增长步长 `compress.nudgeGrowthTokens = 50000`,**扁平、与窗口无关**(内核 `nudge.growthFloor == nudge.growthCap == 50000`,golden-pinned;窗口百分比伸缩已被刻意移除)。 - 增长闸实际门槛 = `max(20k, 0.45 × step) ≈ 22.5k`。 - T1 路径额外要求 ≥ 一个 step(50k)的可压缩质量。 - 每层触发:`compress.tierNudgeTokens` 的 T2/T3 默认 = step × 1.5(可逐层覆盖)。 - 出厂默认 0.45 下限是**跨工作负载的稳健点**,不是「未挖掘的潜力」(§9)。 - 已知副作用(README FAQ「Why does the first compaction wait until ~200k?」):压缩不按窗口绝对位置触发而按增长区间触发,**默认第一次软压缩发生在启动内容之后 50k**;若启动内容 ≈100k(大 AGENTS.md + 工具 + 技能),第一次压缩会等到 ~200k。缓解:裁系统提示/关无用工具/裁技能、把 `nudgeGrowthTokens` 降到 ~50k、或开 lean 模式。 - 压力带补丁:usage 已 ≥ `maxContextLimit` 时,还有一条「压力带 nudge」,绕过增长闸与节奏;为避免「每次刚过线就小压一下」的抖动,加了 `nudge.minPressureBenefitTokens` 下限(建议 50000),低于下限的压力 nudge 记 suppressed,`truncate.threshold` 仍兜底。 ### 2.4 Doctrine(判断规范) 五部分(§4,全文在 `acp-kernel/DESIGN-prompts.md`,由 `src/system-prompt.ts` 渲染;实现常量在 `src/compression-rules.ts`,本报告已逐字核对): 1. **两种失败模式**:过压毁掉后需细节(任务质量损失);欠压淹没上下文(检索质量损失→溢出)。两者都不占主导,doctrine 做平衡而不是最小化其中一个。 2. **唯一判据**:「该内容**是否仍被当前任务步需要**」。不是「旧」,不是「大」。 3. **保护内容与区域**:硬保护 = 压缩调用自身;软保护 = 近期区、最后一条 user 消息。在内核兜底之上,doctrine 要求逐字保留用户意图、约束、未决问题。 4. **摘要工艺规则**: - **KEEP VERBATIM**:带行号的完整文件路径(目录前缀每次都要写,绝不缩成裸文件名);函数/类/类型签名**以及**编码逻辑的关键代码行;错误消息与栈追踪原文;报告里的关键细节(保留对比数字与机制,不只留结论——「1.76× PPL gap because KV store is static」而不是「KVNet underperforms」);决策**及其理由**(「because」是承重的);发现的约束;精确值(版本、配置键、阈值、magic number);用户意图(**引用必须带 ref**:`User said (m00132): "ship it tonight"`,无 ref 只能转述,禁止把重构出来的话当逐字引用);**Open objectives 携带规则**(区间内未完成/未被取代的用户目标,必须留一行 `Open objectives: <目标> (m00746)`,且该行在每一层蒸馏里「最后才丢、最先被恢复」);用户总目标及其演化(含转向);每个重要动作的目的;未决问题与 TODO;关键锚点的消息 ref。 - **DROP**:抓到错误行或结果后的冗长日志;重复读文件;已消费的探索(搜索命中、成功工具输出);死胡同探索**但保留一行教训**(「tried X, failed because Y」);往返讨论与自我修正(留结果,丢旅程);重复状态检查。 - **DROP 的补偿**:对每个被丢的大件加一行**内容描述**而不是位置描述(坏:「probe script at /path/probe_kvnet.py」;好:「probe_kvnet.py: tests n-gram baseline, generation quality, ...」),让后续 decompress 能按相关性定位。 - **优先级(预算紧时)**:目标+目标演化+意图+硬约束 > 决策与理由 > 精确技术产物(路径/签名/错误/值)> 结论与关键发现 > 教训。 - **文风**:dense、可扫描的 bullet;跨关心点用短主题小标题;「Do not mimic the style of existing summaries in context」。 5. **六条交互机制**(把 doctrine 从「建议」变成「可执行」): - **(i) 节流、只压增量**:50K 增长地板;待压质量低于地板时,有效要求降到地板的 45%(≈22.5K),宁可推迟也不做过早的小折叠。 - **(ii) 不披露比例**:nudge 只带指令 + 可压缩区间列表,**不含百分比**。 - **(iii) 拒绝权**:nudge 措辞是「an efficiency nudge to compress early and keep context lean --- not an overflow warning」,不是义务;关键节点(调试中、重构中)可拒绝。 - **(iv) 对源内容的瞬时注意力**:待压区间在 compress 调用期间完整呈现,调用完成后从活上下文切除(compress 调用本身也被隐藏)——决策时注意力完整,之后源离开工作集。 - **(v) 推荐列表带真实大小**:候选区间的 token 数、消息数、工具/文本构成。带大小 → 模型选结构上合理的区间;不带大小(pilot 的 parse-failure 组)→ 模型去压零散低价值区间。 - **(vi) 唯一消息编号**:每条消息一个稳定 ref;区间选择、块血缘、解压全部按 ref 寻址;生产日志显示模型会在选择里引用 ID,且即使不压缩,稳定的 per-message 锚点本身也能改善长上下文注意力。 **摘要长度与格式(可直接抄的产出约束)**: - 生产实测:单次压缩输出中位数 **185 tokens**,p90 **1.2K**,**97.5% ≤ 2K**(doctrine 的 summary-length 规则强制的天花板,§6.2)。 - 块摘要中位数 **1.6K 字符**,平均汇总 **29 条**源消息(p90 140)。 - 内核硬上限 `compress.maxSummaryLength = 20000` **字符**,超长整条拒绝(不截断、不重试);下限 `minSummaryLength`(bili 层 `0` 关掉)。 - 格式是 **Markdown**:dense bullets + 短主题标题;行式输出用首行 `m00150–m00220 optional topic` 作为头,其后是逐字 markdown 摘要(`COMPRESS_TOOL.description` 原文)。 - tier-2 格式强制带源头:`Source: bN+bM+... (XK→YK tok, Zx). [original topic]`,**每个源块 3–5 条自足事实**,尺寸目标 **50–150 tok/源块**;tier-3 目标 **30–60 tok/源块**(含头),每条一行「[PR/Issue/Version] — [outcome in ≤8 words]」。 - 写侧保真修正(prod 事故驱动,`src/compression-rules.ts` 头注):用户逐字引用必须带 ref;记录的任务状态标注为历史(`TASK AS OF THIS BLOCK`)而不是活指令;unicode 直接写,禁止把 `\uXXXX` 转义从工具输出里抄出来——事故是某会话把伪造的 `user verbatim '合并了 下一个'` 当「CURRENT TASK」,导致循环复发。 **API 表面(可配置化程度,`DESIGN-prompts.md`)**:Layer 0 已发布——四条承重规则(`compressPhilosophy` / `howToCompressRules` / `tier2DistillRules` / `tier3CondenseRules`)可被覆盖但必须带 `acknowledgeRisk: true`,否则 `resolvePrompts` 直接抛错并点名违规键;Layer 1 已发布——所有**表面文本**(站姿提示分段、工具描述、参数描述)三态覆盖(string 替换 / null 删除 / 省略取默认),无风控闸。Layer 2–4(prompt-set 文件格式、adapter 管线、第三方 prompt 包)仍是设计意图。**工具名不可改**(nudge 文本与内核错误信息里硬编码了 `compress(...)` / `acp_status`)。 ### 2.5 四个工具 schema(实抓源码,非论文转述) 来源:`acp-kernel/src/compress-tools.ts`。实际有 **5 个**工具(论文只讲 4 个,第 5 个 `acp_cache` 是后来加的): **1) `compress`** — `input_schema` = `COMPRESS_PARAMETERS`(顶层纯 object,无组合子): ```jsonc { type: "object", properties: { topic: { type: "string", description: "Optional short title for the compressed range" }, content: { // 必需,除非用 flat 单区间形式 oneOf-ish(anyOf): [ { type: "array", items: anyOf[ { type: "string", // 行式:首行 "m00150–m00220 optional topic",其余行为逐字 markdown description: "Line form: ... A single string may carry MULTIPLE ranges" }, { type: "object", required: ["startId","endId","summary"], properties: { topic, startId, endId, startRef, endRef, summary } }, { type: "object", required: ["startRef","endRef","summary"], ...同上 } ] }, { type: "string" } // 单字符串,首选用于多区间批处理(最抗有损网关) ] }, startId, endId, startRef, endRef, summary // flat 单区间形式(不用 content) } // 注意:无顶层 required —— 顶层 required:["content"] 会让严格宿主杀掉 flat 形式 } ``` 工具描述要点(原文语义):用 ref 标识区间;**一次调用批量压多个区间,不要一个区间一次调用**;仅在内容确实已消费时使用。 **2) `decompress`** — `required: ["blockId"]`: ```jsonc { properties: { blockId: { type: "string", description: "Block ID to decompress (e.g. b5)" }, toFile: { type: "string", description: "Optional: write content to file instead of context" }, full: { type: "boolean", description: "Restore all the way to original messages" } } } ``` 描述原文:默认只还原一层(一个 tier),`full:true` 一路还原到原始消息;`toFile` 写文件而不是膨胀上下文。 **3) `search_context`** — `required: ["query"]`: ```jsonc { properties: { query: {type:"string"}, limit: {type:"number", description:"Max results (default 5)"} } } ``` 描述:在块摘要上按关键词搜索;**先搜再解压**,用来找对块。 **4) `acp_status`** — `parameters: { type:"object", properties:{} }`(无参)。描述:显示上下文用量与仍可压缩的区间;用来找下一步压什么。 (内核另有 `StatusReport` 结构,含 breakdown 与 compressibleRanges。) **5) `acp_cache`**(论文未提)— `properties: { detail: {type:"string", enum:["summary","full"]} }`。描述:prompt-cache 对账——总账(input/cached/output、命中率)+ 每次请求的 miss 拆成「新内容 / 压缩重付 / 上游 TTL 或客户端改写(未归因的稳定前缀 miss)」+ 每次折叠的经济性(回本所需轮次 vs 实测节奏)。 **参数解析契约(实现要点)**:schema 是解析器的**超集**,`parseCompressArgs` 宽容接受行式/对象式/JSON 字符串/flat 形式;`resolveBoundaries` 返回 `{startIndex, endIndex, protectedGaps}`(`protectedGaps` 目前恒为 `[]`,保护区硬排除**不在内核里实现**,见 README「Known limitation」);`applyCompression` 成功后**重置 nudge 增长基线**(a §5.7 反馈回环修正)。 ### 2.6 实测数字表 | 指标 | 数字 | 来源 | |---|---|---| | 观测窗口 / 会话 / 调用 | 2026-04-23→09-07(~4.5 月);4,843 会话(917 有 usage 记录);174,327 次模型调用 | 论文 §6.1 表 1 [V] | | 累计输入 token | **18.76B**(1.75B 新 + 17.01B 缓存读);三宿主合计 **≈24.7B** | §6.1 [V] | | 每调用上下文(主宿主) | 均值 107,603 | §6.1 表 1 [V] | | **20 万窗口零溢出** | **42,986 次调用跑在 204,800 窗口模型上,零越界,峰值 198,628** | §6.1 表 1 / 附录 B [V] | | 每调用上下文(干净宿主 Pi) | 均值 88,218 / 中位 72,113 / p90 144,909 / p99 217,742(3.58B 输入,80.8% 缓存) | §6.1 [V] | | 马拉松会话 | 8,584–12,049 次调用,1.01–1.52B token,峰值上下文 257,721–374,946 | §6.1 表 2 [V] | | **计费 token 节省** | **−31.5%(默认)/ −53.7%(extreme)/ −52%(置换重跑)** | §8.1 [V: pilot] | | **KV 缓存命中** | **94.2%** 读占比(调用间隔 <2 分钟,占 89% 流量);2–10 分钟 70.2%;10–60 分钟 43.7%;>60 分钟 9.1% | §6.3 图 4 [V] | | 混合口径读占比 | 主宿主 90.7%(17.01B / 1.75B);ework 88.3%;缓存读:输入 ≈ 9.7:1 | §6.1 / §6.3 [V] | | miss 归因 | **仅 16%** 的 miss token 可由「新增尾部」解释,84% 是提供方驱逐特征 | §6.3 [V] | | **重取(re-fetch)下降** | **−63%(2.7×)**;静默对照(不做任何压缩、只留 doctrine+ref 标签)−62% | §8.1 [V: pilot] | | 召回探针 | 与「实际未截断」基线打平(78/84);aggressive 调参才掉分 | §8.1 [V] | | **每次压缩产出** | 中位 **185 tokens**,p90 1.2K,**97.5% ≤2K** | §6.2 [V,17,783 块] | | 每次压缩输入 | 被压 token 中位 2.6K,p90 40K;pending 质量均值 13.7K(max 169K) | §6.2 [V] | | **分层保留率** | 全块中位 **7.9×**;工具主导块中位 **24×**(p75 45×,max >3000×);**≈1/8(工具块 ≈1/24–1/45)** | §4.2 / §6.2 [V] | | **tier 比例** | tier-1 **92%**、tier-2 **7%**、tier-3 **<1%** 常驻;tier-2+3 承载 37% 历史 | 图 1(n=116)[V] | | 常驻宏观折叠 | 重度会话压缩质量均值 ~910K(中位 530K,p90 2.1M)→ 常驻摘要仅 ~13K,**≈70×**;活跃块中位 13 个(p90 53) | §6.1 [V] | | 压缩活动分布 | **62% 的压缩发生在只占 1.3% 的长会话**(>1000 消息)中;≥100 消息的 4.4% 占 93% | §6.5 [V] | | 模型自发压缩 | 5 天窗口内 103 次有效压缩中 **23 次(22%)**发生在引擎故意不注入 nudge 的轮次;另有 11 次自发请求被内核 no-op | §3.7 [V] | | 生产安全阀 | 4.5 天:95% 紧急 nudge 触发 65 次;终局硬截断 **0 次** | §5 [V] | | 单会话容量上界 | 1M 窗口 28.6B token / 106 天(**模拟**,约 19× 外推;tier-2 比例用 57 个事件拟合;tier-3 未观测) | §7 [A] | | 无 fold 对照 | 同一会话 ~104 次调用(~53M 累计输入,不到一天)撞墙 | §7 [A] | | 小窗口成本 | 16K 窗口下 BC 的 ~2K token doctrine 是每调用 ~25% 固定开销;≥64K 窗口才摊销回来 | §8.1 [V] | | 第三宿主(自主服务) | 12.2 天 / 629 会话 / 32,733 调用 / 270M 输入 + 2.04B 缓存读(7.6:1)/ 262,144 窗口零越界 / 峰值 229,355(87.5%) | §5 [V] | | 实测规模口径提醒 | README 顶部写「100K 就够 / 5× fewer tokens」,与论文「200K 够 / −31~54%」是不同口径的营销表述 | README vs 论文 §8.1 | ### 2.7 可复用到本插件的部分 / 不能照搬的部分 **可复用(按优先级)** 1. **`CompressionBlock` 数据结构 + `effectiveMessageIds` 传递闭包**:DSH 的 session log 本身就是 append-only + `surfaceOp`,把「块」做成日志层的独立事件、把被遮蔽区间做成 `replace` 操作,天然对齐;血缘用 `effectiveMessageIds` 而不是「引用父块」,重压缩后仍可寻址到原始消息。 2. **9/10 阶段纯函数流水线**:每阶段一个纯函数、独立测试,宿主不直接改历史。DSH 的 `compactRegion` 已经是「一次表层替换 + 日志包围」的事务模型,可以把 `prune/filter/hide/nudge` 拆成 `pre-step` 与 `request` 之间的纯投影。 3. **growth-gated 双闸 + 扁平 50K 步长**:窗口无关的绝对步长是关键(窗口百分比伸缩被 BC 刻意移除)。直接照抄 50000 / `max(20k, 0.45×step)` / T2·T3 = step×1.5。 4. **六条交互机制**,尤其「不披露比例」「拒绝权」「候选区间带真实大小」「唯一 ref」——这四条几乎零成本,收益最大。 5. **doctrine 的 KEEP/DROP 清单与优先级顺序**:这是已被 17,783 个生产块检验过的文本资产;直接改写成本地化中文版即可(注意 BC 自述 doctrine 是「English-centric」,§9 限制)。 6. **`decompress-to-file`**:还原时不破坏前缀的唯一正确做法,DSH 插件可直接落成「还原到临时文件 + 给模型文件路径」,而不是把原文塞回对话。 7. **首条 user 消息钉死**:DSH 侧的 `deriveMessages()` 同样要保证重建 wire 以 user 起头;这是 provider 约束,不是可选项。 8. **`maxSummaryLength` 的「整条拒绝而非截断」**:截断会产生半截摘要(比没有更坏),拒绝 + 报错让模型重写才是对的。 9. **`protectedLatestTools`(最新快照保护)**:todo/task 这类「累计快照」工具只保护最新一条,否则要么忘任务清单(#639)要么历史无限增长。DSH 有 `todowrite`/`todo_read`,这是必抄项。 **不能照搬** 1. **代理层方案(MITM / fetch patch / base-URL 重写)**。BC 的宿主接入有一半复杂度来自「跨协议代理 + 证书 MITM + 端口漂移自愈」(README 各客户端矩阵、`--host` 安全说明)。DSH 插件在进程内,直接拿 `ctx.llm` / `agent/pre-step` / 工具注册面,**不必也不该**引入代理。 2. **`opencode-acp` 那套 ~9k 行/宿主的适配层**:BC 自己承认「下游 bili 系列集成为每宿主 ~9k 行」;DSH 已有 compaction seam,重写适配层是纯浪费。 3. **28.6B / 106 天这类容量外推**:论文自己标注 [A]、约 19× 外推、tier-3 比例未观测、且自陈「与自身拟合语料一致是表述而非验证」。本插件不要拿它当指标。 4. **激进的 extreme 调参**(floor 0.10 / growth 0.02×window / range 0.06×window):在重复型负载上省 32%,但在**相位结构化负载上探针从 81.6% 掉到 75.7%、执行错误从 1 增到 3**(§8.1 表 4,三 seed 稳定)。它还因为 growth 闸(≈1.3K)永远满足而过度 nudge。要用必须配「限速 nudge」(论文列为 future work)。 5. **「模型会主动 restore」这个假设**:实测为 0(§8.1)。 6. **纯内核式「不做 GC 也不做截断」**:BC 有 `emergency-truncate` 兜底且生产从未触发,但这依赖它把窗口吃到 0.45 就开始管;DSH 插件的兜底必须同时保留原生 `dsh-compaction-basic`(或明确接管并在阈值 0.95 前硬压),不能只信「永远不会满」。 --- ## 三、opencode-dcp(`@tarquinen/opencode-dynamic-context-pruning`) **抓取状态**:GitHub `master` 分支 README 抓取成功(11,064 字节,242 行)。**它没有发布任何量化效果数字**(无节省百分比、无缓存命中率、无对照实验)——这是它和 BC 最大的差别:BC 的 `acp-kernel/DESIGN.md` §7 明确写着内核是对 **DCP 派生模块的「fresh expression」重实现**(「DCP-derived-reimplement」见其 `PROVENANCE.md`),即 **DCP 是 BC 的算法祖先**,BC 是它的「加测量、加分层、加 doctrine、加数据」版。 **机制一句话**:OpenCode 插件,在请求发给 LLM 前把已过期/重复的内容替换成占位符——**磁盘上的会话历史永不修改**,只在出站请求里改写;核心是一个暴露给模型的 `compress` 工具(模型自己选时机与消息)+ 三项自动策略(去重、清错、还有可选的 turn 保护)。 **两个压缩模式**:`range`(连续区间压成一个或多个摘要,**默认**);`message`(实验性,逐条原始消息独立压缩,粒度更细)。`range` 模式下**新压缩与旧压缩重叠时,旧摘要被嵌套进新摘要**(分层保留,而不是被稀释)。 **三项自动清理策略**(与 compress 解耦,但**都在 compress 运行时重算**,以把缓存影响限制在压缩同期): - **Deduplication**:识别重复工具调用(同工具 + 同参数),只留最近一次输出。 - **Purge Errors**:出错工具调用的**输入**在 N 轮后剪掉(默认 4 轮),**错误消息保留**——只删可能很大的输入内容。 - **turnProtection**:工具调用后 N 轮内(默认 4)免剪,默认关闭。 **关键参数(默认配置原文)** | 键 | 默认 | 说明 | |---|---|---| | `compress.mode` | `"range"` | `range` / `message`(实验) | | `compress.permission` | `"allow"` | `allow` / `ask` / `deny`(deny = 不注册该工具) | | `compress.minContextLimit` | **50000** | 软下限:低于此不注入提醒(压缩可能性低) | | `compress.maxContextLimit` | **100000** | 软上限:高于此持续注入强 nudge(压缩可能性高);接受数字或 `"X%"` | | `compress.nudgeFrequency` | **5** | 每 5 次 fetch 注入一次上限 nudge | | `compress.iterationNudgeThreshold` | **15** | 自上次 user 消息起满 15 条消息后开始加压缩提醒 | | `compress.nudgeForce` | `"soft"` | `strong` = 更易压 | | `compress.summaryBuffer` | `true` | 活跃摘要 token 可扩展有效上限 | | `compress.protectUserMessages` | `false` | 逐字保用户消息(警告:大段粘贴的日志将永不被压) | | `compress.protectTags` | `false` | 保 `...` | | `turnProtection.turns` | 4 | 工具调用后 N 轮免剪 | | `strategies.purgeErrors.turns` | 4 | 出错输入剪除延迟 | | `experimental.allowSubAgents` | `false` | 是否处理 subagent 会话 | | `manualMode.enabled` | `false` | 关自主管理,只由 `/dcp` 命令触发 | | 硬保护工具(默认 10 个) | — | `task`、`skill`、`todowrite`、`todoread`、`compress`、`batch`、`plan_enter`、`plan_exit`、`write`、`edit` | | `protectedFilePatterns` | `[]` | 按 glob 匹配工具参数 `filePath`(read/write/edit) | | `compress.protectedTools`(另义) | `[task, skill, todowrite, todoread]` | 这些工具的输出被**追加进摘要**而不是被丢弃 | **它对缓存的态度(比 BC 诚实也悲观)**:README 单列一节「Impact on Prompt Caching」,明说「When DCP prunes content, it changes messages, which invalidates cached prefixes from that point forward」,并把「剪枝减上下文 vs 缓存 miss 增加」列成 trade-off,只对「按请求计费」「缓存与未缓存同价」的提供方标为「无影响」。**它没有 append-only / deactivate 的设计**,所以缓存友好性远不如 BC——这也解释了为什么 BC 要把它重写成「块 + deactivate + 摘要插头部」的形态。 **形态事实**:AGPL-3.0;项目状态「Development on DCP has slowed」,新工作移到闭源方向的 `sleev`(本地代理,已支持 Claude Code / Codex / OpenCode / Pi / Hermes)。 **能否用于 DSH**:**不能直接用**(它是 OpenCode 插件,靠 OpenCode 的 plugin/TUI 面与 `~/.config/opencode/dcp.jsonc`)。但**算法可移植**:整套阈值/策略语义与 DSH 毫无冲突(DSH `agent/pre-step` + `session` 表层投影完全能实现同样三项策略)。 **可借鉴点**:(1) **「重复工具调用只留最新」的去重**——这是零模型调用、零质量风险的纯赚项,BC 的 doctrine 只是让模型「DROP 重复读取」,DCP 把它做成确定性策略;DSH 插件应当做成确定性 stage。(2) **「清错保留错误消息、只删输入」**——错误串是 doctrine 里 KEEP VERBATIM 的高价值项,输入往往是最大低价值块,这个切分是精准的。(3) **「自动清理只在 compress 时重算」**——把缓存破坏集中到压缩事件,而不是每轮都改(这个思路 BC 用 append-only 做得更彻底)。(4) **`permission: allow/ask/deny` 三态 + `manualMode`**——治理面设计,DSH 插件该有。(5) **实验性 `message` 模式**:按消息粒度压,配合 `protectUserMessages`,适合「日志粘贴型」会话。 --- ## 四、其他方案(逐个) ### 4.1 LLMLingua / LongLLMLingua / LLMLingua-2 - **机制一句话**:用一个小语言模型(GPT2-small / LLaMA-7B)算 token 级重要性,删掉非必要 token——**在 token 粒度上做有损压缩,需要跑一个本地模型**。LLMLingua-2 改成「从 GPT-4 蒸馏的 token 分类器(BERT 级编码器)」,任务无关、比 LLMLingua 快 3–6×。 - **关键数字**(`microsoft/LLMLingua` README 原文):LLMLingua「up to **20x** compression with minimal performance loss」;README 自带示例 **2365 → 211 tokens**;LongLLMLingua 缓解「lost in the middle」,用 **1/4 的 token** 让 RAG 性能**最高 +21.4%**;LLMLingua-2「3x-6x speed improvement over LLMLingua」。 - **能否用于 DSH**:**不建议做主干**。理由不是性能而是结构:token 级删除会**破坏工具调用的 JSON 结构、ref 编号、文件路径、错误串**——恰好是 doctrine 要求逐字保留的类别;它**不可逆、不可寻址**(没有 `decompress`)、而且每个请求都要跑一次压缩器,**前缀每次都变 ⇒ 与 KV cache 缓存天然冲突**。作为「超长纯文本工具输出」的局部预处理可以试,但收益/风险比不如确定性剪枝(见 §4.8)。 - **可借鉴点**:**「perplexity / 信息密度」作为选择依据**可以做一个廉价启发式(比如按行熵、重复率给工具输出打分),但只用于**排序候选区间**、不用于删 token。 ### 4.2 ACON(Agent Context Optimization,2026) - **机制一句话**:**不用训练、不碰参数**,在**自然语言空间**里迭代优化「压缩 guideline」——先让 agent 跑失败,分析失败原因,据此改写压缩指令,再把优化后的压缩器**蒸馏进小模型**;同时压**观测(observations)与历史(history)**,保护关键状态信息(输出是「简洁且信息完整」的表示,不是摘要)。 - **关键数字**(arXiv 2510.00615v3 摘要,ICML 2026,微软):在 AppWorld / OfficeBench / Multi-objective QA 上**峰值 token 用量降 26–54%**,且任务成功率**优于**已有压缩基线;让小模型也能做长程 agent,**最高 +46%** 性能(缓解上下文分心)。代码 `github.com/microsoft/acon`。 - **能否用于 DSH**:能,且**思路比实现更值得抄**——「用失败分析反推压缩指令」正好解决我们「doctrine 从哪来」的问题:本插件可以先上 BC 式 doctrine,再用自己的失败样本迭代它。蒸馏小模型那一步与 DSH 无关(我们是插件,不是模型方)。 - **可借鉴点**:**(a) 把压缩指令当可优化对象,而不是一次性写死的 prompt**;**(b) 用「任务失败样本」驱动 prompt 迭代**的工程闭环——BC 的 doctrine 也是这么演化出来的(`compression-rules.ts` 头注记了两次由生产事故驱动的修订:伪造引用事故、open-objectives 丢失事故)。 ### 4.3 ReSum / ReSum-GRPO - **机制一句话**:**周期性调用一个外部工具把交互历史压成紧凑摘要**(训练无关、即插即用、不改架构);再进一步用 **GRPO + advantage broadcasting** 让模型学会在压缩后的上下文上推理(ReSum-GRPO)。 - **关键数字**(arXiv 2509.13313v3 摘要):训练无关设置下比 ReAct **+4.5%**;ReSum-GRPO 再**+8.2%**;**仅 1K 训练样本**,一个 30B agent 就能与领先开源模型竞争。另一篇同名 RLVR 工作(arXiv 2606.13316v2,2026-07-31):平均**+4%** 且 rollout 长度 **−18.6%**。 - **能否用于 DSH**:**「训练无关」那一半能**(周期性摘要 = 我们已经要做的定期压缩);GRPO 那一半不能(要改权重)。 - **可借鉴点**:**「周期性、按探索步数触发」而不是纯按 token 触发**——对 web/搜索型 agent 有用;对编码 agent,BC 的 growth-gate 更贴(ReSum 的固定周期正是 BC §8.1 里被「确定性引擎节奏」arm 代表的那类,在相位结构化负载上表现更差)。 ### 4.4 AgentFold(SFT 训练 fold 操作) - **机制一句话**:让模型**学会执行一个 `fold` 操作**——把历史轨迹在多个尺度上管理:细粒度凝结(保住关键细节)或深度巩固(把整个多步子任务抽象掉);靠 SFT 训练,不是 prompt。 - **关键数字**(arXiv 2510.24699v1 摘要):30B-A3B 模型,**BrowseComp 36.2%**、**BrowseComp-ZH 47.3%**;仅 SFT(无持续预训练、无 RL)就超过/追平 DeepSeek-V3.1-671B-A37B 这类大得多的开源模型,并超过 o4-mini 等专有 agent。 - **能否用于 DSH**:**不能**(要自定义 checkpoint)。但它证明了「fold 这个动作是可学的」——这是 BC §9「doctrine → weights」路线的外部佐证。 - **可借鉴点**:**「多尺度折叠」的操作粒度**:一次 fold 可以选择「细凝结」或「深巩固」,这与 BC 的 tier-1/2/3 是同构的;本插件的 `compress` 工具应当允许模型**在一次调用里对不同区间给不同详细度**(BC 的做法是 tier 分层 + 每块 3–5 条事实)。 ### 4.5 LCM(Lossless Context Management) - **机制一句话**:**确定性**(引擎驱动,非模型判断)的递归上下文管理,两根支柱:**递归上下文压缩**(层级摘要 DAG,自动压实较旧消息,但**保留指向每条原始消息的无损指针**)+ **递归任务划分**(引擎管理的并行原语如 `LLM-Map` 替代模型自己写的循环)。 - **关键数字**(arXiv 2605.04050v1 摘要):用 Opus 4.6 评测,LCM 增强的编码 agent(Volt)在 **OOLONG** 长上下文评测上**超过 Claude Code**,且在 **32K–1M 的每一个上下文长度上**都超过。 - **能否用于 DSH**:**能,且它和 BC 是同一枚硬币的两面**——「层级 + 指针」本插件一定需要;分歧只在「谁做决策」(引擎确定 vs 模型判断)。 - **可借鉴点**:**(a) 无损指针是硬要求**:每条原始消息必须始终可达(DSH 的 append-only log + `sourceEventSeqs` 天然支持,压缩只写 `surfaceOp: replace`,原件永不删);**(b) 提供「引擎兜底 + 模型优先」的双模**:BC 的对照实验说明两者各有胜负(重复型负载确定性节奏便宜 37%,相位型负载模型判断全面胜出,§8.1),所以本插件应当**默认模型判断、可切换确定性节奏**,而不是二选一。 ### 4.6 Claude Code / Codex 的生产 compaction(8 段模板,不可逆) - **机制一句话**:接近窗口上限时,一次性把整段历史摘要成一份固定结构模板,**丢弃原文**,会话从摘要继续。 - **关键数字 / 事实**: - **DSH 自带的 `dsh-compaction-basic` 就是这个形态**,模板是 **8 段**(原文逐字):`## Primary Request and Intent` / `## Key Technical Concepts` / `## Files and Code` / `## Errors and Fixes` / `## Pending Jobs` / `## Current Work` / `## Next Step` / `## Critical Context`,规则含「每个 section 都必须出现,空则写 `(none)`」「**Do NOT mention this summarization request or that the context was compacted**」「若对话里已有 `` 块,它是上一份检查点:不要逐字复制,保留仍为真的事实、丢掉过时的、把新信息合并进同一结构」(`dsh-compaction-basic.README.zh.md`「压缩指令(最终 user 消息)」节 [V])。 - 触发:`floor(min(W×0.8, W − O − headroom))`,`headroomTokens = 65536`,`retainRatio = 0.16`,`thresholdRatio = 0.8`;摘要输出上限 `maxTokens` 默认 = headroom(`dsh-compaction-basic` 配置表 [V])。 - **不可逆 + 破缓存**:同 README「压缩运行时会发生什么」「KV Cache 影响」两节:替换而非追加,**每个检查点都会使从第一个被替换历史 token 起的复用失效**。 - **保真度崩塌有实测**:Compaction Cliff(arXiv 2608.22752,CIKM 2026)——20 个生产 agent 配置上,Claude Code 的 `/compact` prompt 在 Sonnet 4.6 上**一轮后安全规则保留 53%,五轮后 10%** [V]。 - **9 段模板**:**未验证**——本次没抓到 Anthropic / OpenAI 官方 compaction 模板原文,只有 DSH 的 8 段实现与 Compaction Cliff 的数字;不做推断。 - **能否用于 DSH**:**已经是 DSH 的现状**(`dsh-compaction-basic`),不需要「移植」,需要的是**替代/补强**。 - **可借鉴点**:**模板的 section 划分本身很好**(尤其 `Pending Jobs` / `Next Step` / `Critical Context` 三段),可直接用于本插件 tier-1 摘要的**默认骨架**,再叠 BC 的 KEEP/DROP 规则。**必须避免**:整段一次摘要、丢弃原文、每轮重摘要。 ### 4.7 dsh-compaction-tool-result-pruner(字符级修剪,只在压缩时触发) - **机制一句话**:**只在压缩触发条件满足后**、选择压缩范围之前运行;把超过预算的工具结果文本换成「受限头部 + `[... tool result middle pruned ...]` 标记 + 受限尾部」;**不发起模型调用**,可能充分缓解压力以致压缩**跳过摘要**;完整原件仍在会话日志中可精确回放。 - **关键数字**(README 配置表 [V]):`thresholdChars = 8192`(Unicode 码点)、`headChars = 4096`、`tailChars = 1024`;不变式「头部+标记+尾部 ≤ 阈值」,所以每个超预算结果一定会变短、不会增长或重复改写;只动文本块,富内容(图片、结构化块)保序;切片按码点,绝不会劈开 emoji 代理对,但可能劈开多字符字素簇。 - **能否用于 DSH**:**它本身就是 DSH 包**,可直接与后端组合挂载(挂载顺序 `token-meter → pruner → compaction-basic`)。 - **可借鉴点**:**(a) 「零模型调用的确定性预压缩」应当是我们的第一道闸**——先免费拿回 token,再决定要不要花钱压缩;**(b) 「修剪后重新计量,够用就跳过摘要」**这个短路非常聪明;**(c) 影子价格事件(`compaction/prune` 紧邻替换事件并位于其前,为被替换的精确范围定价)**——DSH 的账本模式,本插件的事件也该照此成对出现。 - **局限(README 自陈)**:字符预算 ≠ token 预算;只按语法留头留尾、**不解释中间哪些行语义重要**;字素簇可能被拆。 ### 4.8 dsh-ops(对照项:不是压缩插件) - **定位**:**工具层** token 效率插件——用 ops_* 系列工具替换/隐藏官方工具(compact 返回、行号、更好的错误回馈以遏制报错循环)、启用 DSH 预留的 `tools_addition` 动态工具加载(渐进披露,避免系统提示膨胀)、为 PTC 模式提供结构化 JSON 工具(PTC SDK 18 个 API:15 个文件/文档工具 + 批处理 + 结果引用 + 加载器)。八行 bundle:`mode-minimal`/`mode-standard`/`mode-ptc`/`mode-cordis`/`discovery`/`compat`/`panel`/`tui`;宿主兼容范围声明为 DSH **0.2.0-rc.2 与 0.2.1-rc.2**;MIT;0.3.2 之前内置过 Apache-2.0 的 FastCtx,现 `native/` 为原创。 - **关键数字**:README **没有任何压缩比/节省百分比**(图里只有「自用 benchmark 的成绩」,无可引用数值)⇒ **未验证**。 - **能否用于 DSH**:是 DSH 插件,且与本插件**正交互补**(它减「每轮固定开销与工具输出体积」,我们减「历史累积」)。但要注意两者都会动工具面,**安装顺序与工具替换冲突需要协调**(都涉及 read/glob/grep/bash 的替换)。 - **可借鉴点**:**「隐藏/精简工具描述」是比压缩更便宜的 token 来源**——系统提示与工具 schema 是每轮固定成本,压缩历史一次只省一波;本插件不该重复它的工作,但应当在 `status` 面把「固定开销 vs 历史开销」分开报(BC 的 `acp_status` breakdown:system / tool / summaries / code / text 就是这个思路)。 --- ## 五、总表 | 方案 | 机制 | 可逆性 | 分层 | 触发方式 | 模型调用成本 | KV cache 友好 | 实测节省 | 缺陷 | |---|---|---|---|---|---|---|---|---| | **billion-context / acp-kernel** | 模型判断 + 内核编排;块(tier1/2/3)替换消息区间,deactivate 不删;doctrine 六机制 | **可逆**:`decompress` 逐块还原 / `full` 到原文 / `toFile` 不占上下文 | **3 层 DAG**(LSM over prose),92/7/<1% | **需求侧双闸**:≥0.45 窗口 **且** 增长 ≥50K(有效 22.5K);tier 专属触发;95% 紧急+硬截断兜底 | 每次压缩 1 次调用;产出中位 **185 tok**;doctrine 常驻 ~2K tok(16K 窗口时是 25%/调用开销) | **最好**:append-only + 只 deactivate 后缀;94.2%(<2min 间隔);压缩本身 ≤2% | 计费 **−31~54%**;重取 **−63%**;20 万窗口 **零溢出**;宏观折叠 **~70×** | 生产是单用户观测(生态效度≠总体代表性);doctrine 英文中心;模型**不会自发**用恢复工具;小窗口下 doctrine 固定开销高;规模口径混用(README「5×」vs 论文「−31~54%」) | | **opencode-dcp** | 出站请求改写(磁盘历史不动)+ 模型自选 `compress`(range/message)+ 去重 + 清错 | 部分(历史未改,但摘要本身一层的;无 decompress 工具) | 弱:重叠摘要**嵌套**,无显式 tier | 双阈值(min 50K/max 100K)+ nudgeFrequency 5 + iterationThreshold 15 + purgeErrors 4 轮 | compress 1 次调用;去重/清错零调用 | **差**:自陈「invalidates cached prefixes from that point forward」,无 append-only 设计 | **无任何公开数字(未验证)** | AGPL-3.0;开发已放缓转向闭源 Sleev;无量化证据;缓存取舍坦白但对 agent 长期会话不利 | | **LLMLingua / LongLLMLingua / -2** | 小模型算 token 重要性 → 删 token(token 级有损) | **不可逆**(无原文指针) | 无 | 每请求/按目标 token 预算 | 每请求跑一个小模型(-2 快 3–6×) | **差**:每次请求前缀都变 | 最高 **20×** 压缩;示例 2365→211 tok;LongLLMLingua 1/4 token 下 RAG **+21.4%** | 破坏工具调用结构/路径/错误串/ref;不可寻址;无任务级判断;不适合 agent 轨迹 | | **ACON** | 自然语言空间迭代优化「压缩 guideline」(失败分析驱动),再蒸馏进小模型 | 不可逆(输出是压过的表示) | 无(分 observations / history 两类) | 每步/每段 | 优化期有成本;推理期是一个小压缩器 | 未验证(论文未讨论前缀缓存) | 峰值 token **−26~54%**;小模型任务性能 **+46%** | 评测评的是 web/办公类 agent,非编码 agent;实现是研究代码;蒸馏需训练 | | **ReSum / ReSum-GRPO** | 周期性调外部工具压历史;GRPO + advantage broadcasting 让模型适配压缩上下文 | 不可逆(摘要替换) | 无 | **固定周期** | 每周期 1 次调用 | 周期性整段替换 ⇒ 破坏 | 训练无关 **+4.5%**(vs ReAct);GRPO 再 **+8.2%**;1K 样本 30B 有竞争力 | 固定周期在相位结构化负载上劣于需求侧触发(BC §8.1 的对照旁证);GRPO 需改权重 | | **AgentFold** | SFT 学会 `fold` 操作,多尺度(细凝结/深巩固) | 不可逆(训练出的行为,无指针) | 多尺度(=tier 同构) | 模型自发(已内化) | 无需额外调用(模型内化) | 未验证 | 30B-A3B:BrowseComp **36.2%**、ZH **47.3%**,超 o4-mini | 需自定义 checkpoint(每框架一个);策略冻结在训练时;不可用于第三方模型 | | **LCM** | 引擎确定性的层级摘要 DAG + **指向每条原始消息的无损指针** + 递归任务划分(LLM-Map) | **完全无损**(指针保证) | DAG,深度可配 | 引擎判定(非模型) | 每次递归摘要 1 次调用 | 未验证(论文未报缓存数字) | OOLONG 上**超过 Claude Code**,32K–1M 每个长度都超 | 常驻质量不衰减 ⇒ 窗口更快满、压缩更频繁;无需求侧触发、无 doctrine、无部署数据 | | **Claude Code / Codex 生产 compaction(= DSH `dsh-compaction-basic`)** | 接近上限时整段摘要成固定模板 | **不可逆**(丢弃原文) | **单层** | **供给侧阈值** 0.8(`floor(min(W×0.8, W−O−64K))`),保留 0.16 | 1 次调用(收敛重试可能多次付费) | **差**:从第一个被替换 token 起失效 | 保真崩塌实测:安全规则 **一轮 53% / 五轮 10%**(Compaction Cliff) | 早期内容 ρ^k 几何衰减;无还原;无任务判断;每轮重摘要 | | **dsh-compaction-tool-result-pruner** | 字符级:头 4096 + 标记 + 尾 1024,只动文本 | 半可逆(原件在日志,但模型侧只看到剪枝版,无工具还原) | 无 | **只在压缩触发后**、选范围之前 | **0 次** | 中:替换会使从第一个改变 token 起失效 | 无公开token节省数字(**未验证**);机制上保证每个超预算结果 ≤8192 码点 | 只按语法留头尾;字符预算≠token 预算;字素簇可能被拆 | | **dsh-ops(对照:非压缩)** | 工具层:精简/隐藏官方工具 + 动态工具加载,减固定开销 | N/A | N/A | N/A | 0 次 | 好(不改历史) | **未验证**(README 无数字) | 不解决历史累积;与其它工具替换型插件有冲突面 | | **本插件(目标位)** | 增量块 + 可逆 + doctrine + 双闸触发 + 确定性预修剪 | 可逆(`toFile` 优先) | 3 层 | 双闸 0.45/50K | ≤1 次/压缩事件 | 追加为主 | 目标:重取下降、缓存命中 ≥90% | 见 §六 | --- ## 六、对本插件的设计约束(吸收 / 避免) ### 6.1 必须吸收(按实现顺序) 1. **数据模型先定,其余后做。** `CompressionBlock { blockId, runId, tier, topic, summary, directMessageIds, effectiveMessageIds, directBlockIds, createdAt, survivedCount, generation, active }` + `messageRefs{byRaw,byRef}` + `nudge{baselineTokens,...}` + `stats`。DSH 侧把块落成**日志事件**(参照 `compaction/summary` 的成对包围模型),消息映射落成 session 的 ref 表。**没有 `effectiveMessageIds` 就不要做 tier-2**——否则重压缩后无法寻址原始消息。 2. **压缩 = deactivate + 追加一条 replace,不是删除。** DSH 的 `surfaceOp: { op:'replace', startSeq, endSeq }` 正好是这套语义;原件永远留在 append-only log 里(这是 LCM 的「无损指针」与 BC 的「consumed lineage」共同的硬要求)。 3. **双闸触发**:`usage ≥ 0.45×W` **且** `growth_since_last ≥ max(20K, 0.45×50000≈22.5K)`;T1 另需 ≥50K 可压质量;T2/T3 阈值 = step×1.5;每次成功压缩后重置基线。不要做窗口百分比伸缩。 4. **六条交互机制全上**:不披露比例 / 拒绝权 / 带真实大小的候选列表 / 唯一 ref / 瞬时注意力(压缩调用后隐藏)/ 节流增量。 5. **保护区的三层结构**(分别落在不同层,不要塞进 prompt): - 硬保护,内核层拒绝:`compress` 调用自身;`protectedTools` 命中的工具(整段历史);`protectedLatestTools` 命中的最新快照(todo/skill 必配)。 - 软保护,filter 层不可见:最近 `preserveRecentMessages`(BC 生产 3)条 + `preserveRecentTokens`(≈5000)——注意生产实际原文区远大于内核地板(数十 K)。 - wire 不变量:**首条 user 消息无条件钉住**(provider 约束);最后一条 user 消息恒可见;assistant 消息不注入 ref 标签(防模型回声)。 6. **摘要产出约束**:强制 Markdown + dense bullets;`maxSummaryLength` 超限**整条拒绝**(不截断);默认骨架借 DSH 的 8 段(尤其 `Pending Jobs`/`Next Step`/`Critical Context`),内容规则借 BC 的 KEEP/DROP/优先级;tier-2 强制 `Source: bN+bM (XK→YK tok, Zx)` 头 + 3–5 条事实 + 50–150 tok 目标;tier-3「1–3 条一行事实」+ 30–60 tok 目标。 7. **确定性预压缩先跑**:按 `thresholdChars/head/tail` 剪大工具输出(零模型调用),**剪完重新计量,够用就跳过摘要**——这是纯赚的第一道闸,成本为零。 8. **还原必须做成「不破前缀」**:默认 `decompress toFile`(写文件 + 给路径),`full` 才把原文塞回;并且**在 nudge/系统提示里显式教模型何时还原**(实测自发调用为 0)。 9. **可观测面**:`status` 报 system / tool / summaries / code / text 构成 + 可压缩区间;`cache` 报总账 + miss 三分解(新内容 / 压缩重付 / TTL·客户端改写)+ 每次折叠的回本轮次。这两张表是本插件「不是又一个摘要器」的证据来源。 10. **治理面**:`permission: allow|ask|deny`、`manualMode`、承重规则覆盖需 `acknowledgeRisk`、工具名不可改。 ### 6.2 必须避免 1. **不要每轮重摘要全历史**(ρ^k→0;Compaction Cliff:一轮 53% → 五轮 10%)。 2. **不要一次调用压整段历史**(单粒度、不可拒、不可选区间)。 3. **不要按窗口百分比触发**(大窗口永不触发、小窗口过早触发;BC 刻意移除了百分比伸缩)。 4. **不要告诉模型「你用了 X%」**(会锚定「还健康」并拒绝压缩)。 5. **不要把 drain 掉首条 user 消息**(provider 400;且任务意图丢失)。 6. **不要做按年龄的 GC / 摘要截断**(BC 上游明确记录:age-based deactivation 造成过 memory-loss,已移除)。 7. **不要压 `todo`/`task` 类累计快照工具的整段历史**(要么忘任务清单,要么无限增长)——用 `protectedLatestTools` 语义。 8. **不要用 aggressive 调参做默认**(相位结构化负载:探针 81.6%→75.7%、执行错误 1→3、nudge 过度触发)。 9. **不要假设模型会主动 restore**(实测 0 次自发调用)。 10. **不要引入代理/MITM/URL 重写**(BC 的一半复杂度来自跨进程代理;DSH 插件在进程内,`ctx.llm` 直接可见)。 11. **不要与 DSH 原生 `compaction-basic` 同时自动跑**(双压缩;BC 的处理是先置 `auto:false` 再接管,且 Web profile 里还得用 cordis `internal/config` overlay 关掉 preset 内嵌实例——这个坑本插件必须显式处理并给出可见提示)。 12. **不要拿模拟数字当指标**(28.6B/106 天是 [A] 外推)。 13. **不要用字符预算冒充 token 预算**(DSH 自己也承认 token-meter 4 字符/token 的启发式对 CJK 与 JSON Schema 定价偏低)。 ### 6.3 差异化定位(一句话) > DSH 已有「阈值 + 一次性 + 不可逆 + 破缓存」的 compaction;市场最强方案证明了「增量 + 可逆 + 追加 + 模型判断」是同时拿到长会话、质量、成本三者的唯一组合。**本插件 = 把 fold 这套架构落在 DSH 原生 compaction seam 上,保留 DSH 的事务/日志不变量,换掉它的决策层与可逆性。** ### 6.4 与本项目「棋谱 DAG」设计的对应(读市场后需要修正/确认的判断) 本项目的设计意图是「把历史存成可回溯、可判重、带失败记忆的棋谱 DAG,并为模型每轮重建一份极小的热上下文(根目标 + 当前路径 + 已知失败边清单)」。把它逐条压到上面的证据上: | 本项目要素 | 市场对标结论 | 判定 | |---|---|---| | **增量 fold(只压上一个 checkpoint 之后)** | BC §3.6 独立得出同一结论,并给出四条收益(质量/缓存/保留率/成本)与实证(−31~54%、94.2%、1/8 恒定)。**这是本项目的核心修复,方向正确。** | ✅ 确认,且应当作为**第一条不变量**写进引擎 | | **可回溯** | LCM 的「无损指针」与 BC 的 `decompress`/`decompress-to-file`/`search_context` 是同一个要求;DSH 侧 append-only log 天然满足「原件不丢」,缺的是**寻址层**(块→原消息闭包 + ref) | ✅ 确认;**补 `effectiveMessageIds` 式闭包**,否则 DAG 回溯在二次压缩后断链 | | **可判重** | DCP 把「同工具 + 同参数只留最新」做成确定性策略(零模型调用);BC 只把它写进 doctrine 的 DROP 清单(依赖模型自觉) | ⚠️ **应当做成确定性 stage**,不要只写进 prompt——这是免费收益 | | **带失败记忆(失败边)** | 三处独立证据:BC doctrine「死胡同探索**保留一行教训**(tried X, failed because Y)」;ACON 用**失败分析**反推压缩指令;ReSum 发现「引入 summarization 短语能缓解错误前缀传播」。**「失败边」是有文献支撑的独立语义,不是发明。** | ✅ 确认,且应当**显式建模为 DAG 边类型**,并在热上下文重建时**优先携带**(BC 把它列在 DROP 的补偿项,本项目的做法更强) | | **根目标 + 当前路径** | BC:首条 user 消息**无条件钉住** + `Open objectives` 行在每层蒸馏里「最后丢、最先恢复」+ 目标演化必须记录。这三条正好覆盖「根目标」与「当前路径」的持久化 | ✅ 确认;**「根目标」要做成不可压缩的 pinned 节点**,而不是靠摘要保真 | | **极小的热上下文** | BC 的实测概率区间:干净宿主 p50 72K / p90 145K,204,800 窗口零越界、峰值 198,628。**「极小」在编码 agent 上现实区间是 ~50–150K,不是 <10K**;BC 的「~50K 原始区 + tiny 摘要」说明摘要部分可以极小(常驻摘要 ~13K,宏观 70×),但原文热区省不掉 | ⚠️ **修正预期**:目标应是「摘要质量极小(~10–20K)+ 原文热区受控(~50K 量级)」,而不是把整个上下文压到极小 | | **单实例、disable `compaction-basic`** | BC 在 DSH 上正是这么做的(补丁里 `auto:false`,Web profile 还得用 cordis `internal/config` overlay 关掉 preset 内嵌实例——`cordis.patch.yml` 打不中嵌套行)。**本项目 AGENTS.md 的硬规则与之一致,但同一坑也会踩:patch 只索引顶层行与真组子节点。** | ✅ 确认;**必须为 Web profile 的 preset 内嵌实例准备 overlay 方案**,否则「只 warning 不报错」会让你以为关掉了 | | 每次压缩都重摘要上一次 checkpoint | 官方 `dsh-compaction-basic` 的模板里就写着「若对话已有 `` 块,它是上一份检查点……保留仍为真的事实、丢掉过时的」——**结构性 ρ^k 衰减的根源找到了**(Compaction Cliff 实测 53%→10%) | ✅ 确认这是官方实现的真实缺陷,不是误读 | --- ## 七、未验证项 | # | 项 | 状态 | 说明 | |---|---|---|---| | 1 | opencode-dcp 的任何量化效果(节省比例、缓存命中、对照实验) | **未验证** | 抓到的 README 全文没有任何效果数字;它只描述机制与配置。 | | 2 | 「Claude Code / Codex 生产 compaction 的 **9 段**模板」 | **未验证** | 只核到 **DSH 的 8 段**实现(`dsh-compaction-basic` README 逐字);Anthropic / OpenAI 官方模板原文本次未抓到,不推断段数。 | | 3 | BC tier-3 的 ~1/3 压缩比、tier-3 的常驻比例 | 论文自述**未观测** | 论文 §7 明写「tier-3 condenses at ~1/3 (unobserved; carried from design values)」;tier-3 <1% 来自图 1 语料。 | | 4 | BC 单会话容量 28.6B / 106 天 | **[A] 模拟**,非实测 | 论文自标注:约 19× 外推、tier 比例用 57 个事件拟合、需 hold-out 校验(列为计划)。 | | 5 | BC 的 `−58%` 硬化探针轮、`1.2–1.8×`(200K 窗口反事实) | 未进表 / [A] | 前者论文自陈「not tabled」;后者基于 80% 触发与 30–50% 残留的假设(论文 §7 明写这些是假设)。 | | 6 | BC `/acp` 状态面板在 **dsh** 上的覆盖 | **未完成**(上游自陈) | README 509 行注:「`/acp` (OpenCode hosts today — pi/dsh coverage tracked in #2084)」。 | | 7 | BC 的 `bili plugin install dsh` 在实际 DSH 版本上的行为 | 只读文档,**未实机验证** | 本次任务是文档对标,未安装;CLIENTS.md 还登记了 #1158(部分 `llm-pi-ai` 传输层零代理流量)这类未结问题。 | | 8 | LLMLingua 在 **agent 轨迹**(含工具调用)上的实测表现 | **未验证** | 公开数字都来自 prompt/RAG 场景;没有 agent 场景的对照数据。 | | 9 | ACON 在编码 agent / DSH 上的可迁移性 | **未验证** | 论文评测域是 AppWorld / OfficeBench / Multi-objective QA。 | | 10 | LCM 的 KV cache 影响、常驻质量增长曲线 | **未验证** | 论文摘要与 BC 的转述均未给缓存或质量超时的数字。 | | 11 | dsh-ops 的实际 token 节省 | **未验证** | README 只有图表,无可引用数值。 | | 12 | DCP 的 npm 下载量 / GitHub star(选型权重用) | 未查 | 本次未取 registry/GitHub 指标。 | | 13 | BC 的 `ACON`/`Paritok-4B`/`SWE-Pruner` 等二级文献细节 | 仅取论文转述 | 未逐篇精读,只在 §2 的家族划分里作为定位引用。 | | 14 | DSH 插件能否在 `pre-step` 里拿到「压缩调用之后模型回写的摘要文本」的完整控制权 | 需实测 | 文档层面 `compactRegion` 可编程触发、`summarize()` 是子类钩子;但「模型侧工具 → 后端执行」这条链在本插件里要自己接,属实现验证项。 | --- ## 附录 A · 来源与抓取记录(2026-10-28) **本机材料(`D:\主工作区\tmp\context-plugin\docs\`)** - `billion-context.paper.md`(95,725 B,387 行)—— 全文精读,§3/§4/§6/§7/§8 逐节引用。 - `billion-context.README.md`(68,237 B,685 行)—— 全文精读(客户端矩阵、FAQ、配置、会话身份)。 - `dsh-compaction-basic.README.zh.md`(261 行)、`dsh-compaction.README.zh.md`(176 行)、`dsh-compaction-tool-result-pruner.README.zh.md`(149 行)、`dsh-hook-protocol.README.zh.md`(143 行)、`dsh-ops.README.md`(154 行)。 **网络抓取(`curl.exe`,`raw.githubusercontent.com` / `api.github.com` / `export.arxiv.org`;MSYS 自带 curl 在本机被重置,必须用 `curl.exe`)** - `Opencode-DCP/opencode-dynamic-context-pruning` `master/README.md` → 200,11,064 B,242 行(全文精读)。 - `microsoft/LLMLingua` `main/README.md` → 200,19,363 B。 - `ranxianglei/acp-kernel`:`DESIGN.md`(15,947 B)、`DESIGN-prompts.md`(10,303 B)、`src/compress-tools.ts`(33,408 B)、`src/compression-rules.ts`(14,166 B)、`src/decompress.ts`(9,971 B)、`src/report.ts`(17,275 B)、`src/search.ts`(761 B)、`git/trees/master` 文件树。 - `ranxianglei/billion-context`:`CONFIGURATION.md`(368,797 B,按 key grep)、`CLIENTS.md`(76,648 B,`## dsh` 节全文)。 - arXiv API(`export.arxiv.org/api/query`):`2510.24699`(AgentFold)、`2605.04050`(LCM)、`2608.22752`(Compaction Cliff)、`2607.20064`(PRO-LONG)、`2510.00615`(ACON)、`2509.13313` + `2606.13316`(ReSum / ReSum-GRPO)—— 均取摘要原文。 - **抓取失败**:`billion-context` 的 `TECHNICAL-NOTES.md`(两次 `Connection was reset`,第三次成功为 49,071 B,未深入读);`CONFIGURATION.md` 首轮失败、重试成功。