context-mode ADR-0004 深度解读:ctx_stats 单会话压缩率为何改用 strict-compression 严格公式
context-mode ADR-0004 深度解读ctx_stats 单会话压缩率为何改用 strict-compression 严格公式【免费下载链接】context-modeContext window optimization for AI coding agents. Sandboxes tool output (98% reduction), persists session memory, and enforces routing across 17 platforms via MCP hooks.项目地址: https://gitcode.com/GitHub_Trending/cl/context-mode本篇技术指南围绕 context-mode 仓库中的架构决策记录 docs/adr/0004-stats-strict-compression-formula.md 展开剖析ctx_stats报告Section 1Without context-mode / With context-mode 对照条在 v1.0.148PR #685 hotfix中从基础设施体量统计回归真实压缩率的完整过程。读者将掌握为什么eventDataBytes必须从单会话压缩率分子分母中剔除、strict-compression 公式的精确语义与空状态处理、该决策如何与data_hash去重列、lifetime 汇总及 ADR-0001 多写者约束共存以及对应的源码实现与回归测试证据。背景一次从诚实压缩率到基础设施体量统计的语义漂移ctx_stats是 context-mode 内置的 MCP 元工具之一Claude Code 中可通过/context-mode:ctx-stats调用其他平台在聊天中直接输入ctx stats即可触发其报告按会话Section 1、捕获统计Section 2、作用域递进Section 3与成本框架Section 4分层呈现。其中 Section 1 的Without context-mode / With context-mode横向条形图本意是回答一个用户最关心的直觉问题context-mode 到底把多少字节挡在了模型上下文窗口之外。然而在两次互不相关的 bug 级联之后这个条目的语义从诚实的压缩率悄悄漂移成了基础设施体量统计。v1.0.134 SLICE B一个为了掩盖退化 100%的应急补丁第一次偏移来自v1.0.134 SLICE B提交ce622752026-05-15针对的是 src/session/analytics.ts 中的一个退化显示缺陷在全新会话中bytesReturned 0时原始公式pct 1 - max(1, returned) / (avoided returned)会坍缩到约 100%——即便bytesAvoided同样为零也会画出一条虚高的条形图。SLICE B 的战术性修法是把eventDataBytes同时加进比值的两侧Without bytesAvoided bytesReturned eventDataBytes With max(1, bytesReturned eventDataBytes)提交信息将其命名为 bar ratio degenerate fix——这明确是一个UX 补丁而不是经过设计的指标语义。Git 考古Git Archaeologist 的审计结论同时确认真正驱动成本的rule_content重复问题在整个修复过程中从未被纳入考量。v1.0.148 Bug ACDEF 级联真实信号终于流入公式却开始说谎第二次偏移来自v1.0.148的 Bug ACDEF 级联修复PR #685。schema 迁移与 per-conversation 聚合器修复终于让公式看到了多年被静默低估的真实bytesAvoided数据。可当真实信号开始流动时SLICE B两侧都加 eventDataBytes的公式立刻暴露出问题对于用户凭直觉知道压缩率应该高达 95% 的会话报告显示的却是约 56%。报告者机器上产生了实证证据bytesAvoided 2,898 KBBash/Read 重定向节省 sandbox PID 突发流量bytesReturned 140 KB打印的 ctx_* 输出eventDataBytes 2,136 KB——其中84%约 496 份是同一份 CLAUDE.md 的重复副本由 SessionStart hook 在多次 resume 周期中反复捕获schema 中专门为此准备的data_hash去重列虽然被填充但公式从未使用它同一份数据两种公式给出天差地别的结论SLICE B 公式显示56%被挡在窗口外strict-compression 公式本 ADR显示95.4%被挡在窗口外这 49 个百分点的差距就是 SLICE B 引入的低估。决策Section 1 必须使用 strict-compression 严格压缩公式ADR 的核心裁决十分明确per-conversation 的 Section 1 条形图必须改用严格压缩公式且eventDataBytes从两侧同时剔除if (bytesAvoided bytesReturned 0) { // 空状态 —— 尚无可测量的重定向活动。 // 不要绘制退化的条形图。输出一行诚实的提示 No measurable redirect activity captured yet — bars will appear once context-mode diverts its first payload. } else { Without bytesAvoided bytesReturned With max(1, bytesReturned) pct (1 - With / Without) * 100 }为什么eventDataBytes必须被排除决策背后的理由是一条清晰的概念边界hook 捕获的 payload 字节被写入 SessionDB是为了构建知识库它们是分析基础设施analytics infrastructure而不是曾经进入模型上下文窗口的字节。把这类字节渲染进 Section 1等于把两个性质完全不同的量混为一谈产出的必然是一个误导性的数字。这一定义在源码中留下了完整的注释证据。src/session/analytics.ts 中渲染 Section 1 的代码段明确写道Without bytesAvoided bytesReturned—— 模型本应重新看到、却被 context-mode 转移走的字节With max(1, bytesReturned)—— 模型在 context-mode 介入后实际重新看到的字节注释特别标注eventDataBytes是hook 捕获的原始 payload工具参数、提示词正文用于知识库它们从不进入模型上下文窗口。SLICE B 把它们加进任一侧为了躲避退化 100% 条会错误地代表上下文成本把实时会话的真实压缩率从约 95% 压到约 56%。该实现同时把eventDataBytes归位到它真正属于的地方——Section 2捕获统计那里它以captures count1,000 things — files, errors, decisions, agent runs的形式正确表达 hook 层记录了什么。空状态用一句诚实的提示替代退化条形图公式中的空状态分支是对 SLICE B 症状的根治而非掩盖当bytesAvoided bytesReturned 0会话早期、schema 迁移恢复中、或工具密集工作尚未重新命中索引不再绘制 0% 或 100% 的退化条形图而是输出一行提示并跳过 Without/With 对照条——诚实优先于装饰源码注释原文honesty over decoration。值得注意的是空状态分支与诚实的 100%是两条不同的路径当bytesReturned 0但bytesAvoided 0时每个被测量的字节确实都被挡在了窗外With max(1, 0) 1百分比会如实逼近 99.99%——这是诚实的 100%测试明确允许其存在。边界lifetime 汇总Section 3/4不受影响ADR 特别划清了作用域lifetime 的 Section 3/4 汇总例如 14.7 MB kept out across 200 projects不受本 ADR 影响。它们聚合的是bytesAvoided eventDataBytes snapshotBytes而 lifetime 层级的用户预期一直是context-mode 存入存储的全部字节——对这一层级而言这是正确的口径。只有 per-conversation 的%条目的语义被修正。这一口径差异在 src/session/analytics.ts 的RealBytesStats接口注释中有完整定义四个字节来源分别对应session_events表的data_bytes、bytes_avoided、bytes_returned与session_resume表的快照长度而totalSavedTokens (eventDataBytes bytesAvoided snapshotBytes) / 4bytesReturned被报告但不并入totalSavedTokens——因为它代表模型已经付费看过的字节加进去会重复计入用户账单上已有的部分。修复前后对比同一份数据的三代口径ADR 给出了报告者机器数据在三代公式下的完整对照表指标v1.0.147损坏v1.0.148 SLICE Bv1.0.148 本 ADRWithout158 KB5,177 KB3,038 KBWith158 KB2,279 KB140 KB% kept out0%恒等56%SLICE B 附带95.4%Runtime multiplier1×2×22×Lifetime headline14.7 MB ✓14.7 MB ✓14.7 MB ✓其中 22× 乘数代表的是这场对话因 context-mode 的重定向而获得的实际上下文窗口跑道延长——这正是用户直觉上期望看到的指标。v1.0.147 的恒等是因为 schema 聚合器缺陷导致公式看不到真实的bytesAvoided只能把 Without 与 With 渲染成同一个 158 KB。源码级验证公式在仓库中的真实落点渲染实现strict-compression 公式的完整实现位于 src/session/analytics.ts先取realBytes.conversation的bytesAvoided/bytesReturned两个测量值命中空状态则输出提示行否则按convBytesWithout measuredAvoided measuredReturned、convBytesWith Math.max(1, measuredReturned)计算再换算 token4 字节/token并用dataBar()绘制两侧条形最终输出一行Without context-mode 3.0 MB ████████████████████████████ 759,500 tokens With context-mode 140 KB ██ 35,000 tokens 95.4% kept out of context · your AI ran 22× longer before /compact firedconvMultMath.round(convTokensWithout / convTokensWith)就是上表中 22× 乘数的来源。worktree 拆分的字节归属一个容易忽略的实现细节Section 1 的bytesReturnedWith context-mode与bytesAvoidedkept out并非简单读库汇总。在 src/session/analytics.ts 的 worktree 拆分逻辑中bytesReturned当前会话的检索返回真正进入当前实时窗口的字节bytesAvoided 整个 worktree 移动的字节avoided 每个会话的检索减去落入你窗口的部分并钳制在 ≥ 0保证边缘 DB 永远不会产生负条形图。这种按worktreeHash而非项目根 时间作用域的方式确保用户并行打开的其他 worktree 不会串入统计而本会话派生的子代理 fan-out 又能被完整计入。同样地src/session/retrieval-marker.ts 作为 server→hook 的桥接层专门度量With context-mode的检索字节——因为 context-mode 自己的ctx_search/ctx_fetch_and_index不会触发插件自身的 PostToolUse hook必须由 MCP server 侧直接测量。而bytesAvoided的写入路径由 src/session/event-emit.ts 的emitIndexWriteEvent承担配合 src/session/extract.ts 从ctx_fetch_and_index返回的 Fetched and indexed5 sections(47.50KB) 前导文本中解析出 KB 数值才能让每次检索的节省如实入账。回归测试四条硬断言ADR 决策第 4 条要求四个 fixture 测试断言新语义。v1.0.134 SLICE B的 describe 块在 tests/analytics/format-report.test.ts 中被重命名为v1.0.148 Bug G — Section 1 bar uses strict-compression formula四个用例分别钉死空状态eventDataBytes有 50,000 字节捕获确实存在但bytesAvoided bytesReturned 0时输出必须匹配No measurable redirect activity captured yet且不得渲染Without context-mode/With context-mode条形诚实的混合比例bytesAvoided6,000、bytesReturned4,000、eventDataBytes100,000时显示 60% 而非把 eventDataBytes 折进来后的约 5%——注释直白地警告若回退到 SLICE B 口径显示的比例会差得离谱诚实的 100%bytesReturned0但bytesAvoided10,000时Withmax(1,0)1比例如实落在 ≥ 99%一位小数精度真实 live-window 数据8.9 MB kept out / 10.2 KB retrieval真实比例 99.888%必须渲染为99.9%而不是四舍五入后的整数 100%——防止过度宣称。同语义的实库回归测试位于 tests/session/real-bytes-stats.test.ts用 Mert 机器上的真实行bytesAvoided2,898,000、bytesReturned140,000、eventDataBytes2,139,000硬断言百分比落在 9496 区间并注明三代口径的差异strict → ~95%SLICE B → ~56%Bug EF 修复前 → ~6%。后果与边界一次纯读侧的指标语义修正ADR 明确列出了六条可验证的后果显示百分比将跳变现有用户首次在 v1.0.148 后调用ctx_statsSection 1 会从约 56% 跳到约 95%。这是指标语义变更不是数据丢失lifetime 数字与捕获计数与 v1.0.147 完全一致。空状态处理显式化新会话不再看到退化的 0%/100% 条形图而是单行提示。data_hash去重列不再是正确性承重点去重是 EM 审计决策树中的候选修复之一Option B得票 86%但 strict-compression 才是正确修复——因为rule_content重复问题只有在你要统计eventDataBytes时才成立而我们恰恰不统计它。从源码看data_hash列如 src/adapters/openclaw/plugin.ts 与 src/adapters/pi/extension.ts 用sha256(data).slice(0,16)填充仍作为去重基础设施保留只是不再为 Section 1 的正确性负责。测试更新上述四个 fixture 断言即为其直接产物。README 与 release notes 同步此前基于 lifetime 公式引用的约 98% 节省数据仍然有效新的 per-conversation 头条数字与 strict-compression 比例一致。ADR-0001多写者保持不变这是最关键的架构边界——本 ADR 只改读侧公式。无 schema 新增、无锁、无 EXCLUSIVE pragmaSQLite WAL busy_timeout 不变量按 docs/adr/0001-sessiondb-multi-writer.md 原样保留。总结指标定义比显示美观更重要ADR-0004 的完整教训可以浓缩为一句话一个为掩盖显示缺陷而临时引入的公式会在真实信号涌入后变成系统性低估的源头。SLICE B 的eventDataBytes双加策略本质上是为了让条形图不难看而把分析基础设施字节伪装成上下文字节strict-compression 公式则回归了三个可辩护的原则——分子分母只容纳真正进出上下文窗口的字节、空状态用诚实提示替代退化条形图、lifetime 与 per-conversation 各用各的正确口径。对任何想为 Agent 工具链设计节省指标的开发者而言这个 ADR 提供了可复用的范式先明确什么才算真正进入了窗口再决定展示什么。【免费下载链接】context-modeContext window optimization for AI coding agents. Sandboxes tool output (98% reduction), persists session memory, and enforces routing across 17 platforms via MCP hooks.项目地址: https://gitcode.com/GitHub_Trending/cl/context-mode创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考