Skip to content

docs(v2): C07 上下文压缩家族 (YAO-108)#30

Merged
luyao618 merged 3 commits into
mainfrom
agent/cc-dev/379abbec
May 24, 2026
Merged

docs(v2): C07 上下文压缩家族 (YAO-108)#30
luyao618 merged 3 commits into
mainfrom
agent/cc-dev/379abbec

Conversation

@luyao618
Copy link
Copy Markdown
Owner

Summary

YAO-108 · C07 上下文压缩家族 迭代重写。在 v1-06 既有骨架与全部一二级标题保留的前提下,往四个位置补了"机制并存如何不互相拆台"维度的散文:

  • §3.1 加一段说明 shouldAutoCompact() 里针对 marble_origami / REACTIVE_COMPACT / CONTEXT_COLLAPSE 三道护栏的因果链,以及"谁先点火谁就赢"的共同主题。
  • §3.4 加一段说明 prompt.tsBASE / PARTIAL_FROM / PARTIAL_UP_TO 三模板的分工,以及 getCompactUserSummaryMessage() 对 proactive / KAIROS 自治模式的尾语扩展。
  • §五 加一小段 + 7 行代码块,记录 compactWarningHook.ts 被刻意从 compactWarningState.ts 拆出来以保持状态文件 React-free 的考量。
  • §六 末尾追加一段,把 services/compact/grouping.ts(63 行)的 groupMessagesByApiRound 与"为了打破 import cycle CC-1180 而独立的纯结构性模块"一并收入,避免新开一级标题违反 C-2。

源码引用全部回填到 services/compact/ 当前 commit;中文段落留存率 99.1%,10 个 v1 一/二级标题原样保留。

段落统计

  • 保留段落(≥ 50 字、直接来自 v1):约 110 段
  • 改写段落:0 段
  • 新增段落:4 段(散文)+ 1 段 7 行代码块(即上文 §3.1 / §3.4 / §五 / §六 四处补叙)
  • 新增正文字符数:~3.2K 字符(约 1.6K 中文字,处于 M 档 [4000, 7000] 偏轻量端)

保留 ≫ 新增,符合 §0.5.3 迭代重写"增量、不重写"的硬约束。

Manifest diff 摘要

字段 取值
chapter_id C07
source_commit 290fdc9481a70612bc5823aa4ed225c52c52aad3
判定 迭代重写(is_new_chapter: no)
骨架重排 no(v1 §一~§七 标题全部原位保留)
workload M
estimated_words [4000, 7000](本次实际新增 ~1.6K 字,主要补四处散文,未触发重写)

CI 结果

bun run check:docs 全部 PASS(含 C-1/C-2/C-3/C-4/C-5/C-6/F),仅一处 fuzzy WARN 命中 v1 原文「几乎零成本」,不阻塞。

[C-1] OK   docs/06-上下文管理.md: 中文段落留存率 99.1%
[C-2] OK   docs/06-上下文管理.md: 全部 10 个 v1 标题保留
[C-3] skip docs/06-上下文管理.md: v1 已发布章节,C-3 不适用
[C-4] OK   docs/06-上下文管理.md: 25 个标题全部合规
[F]   OK no orphan dirs

风格双亲实证

风格双亲:v1-03 状态管理 + v1-05 对话循环

v1 原文摘抄(≥ 200 字 × 2 段)

【摘抄 1,来自 docs/03-状态管理.md】
答案在于 import DAG(依赖有向无环图)的约束bootstrap/state.ts 处于 import 树的最底部(叶子节点),几乎不 import 其他业务模块。需要澄清的是,state/store.tsstate/AppStateStore.ts 本身并不依赖 React —— 真正引入 React 的是 state/AppState.tsx。但问题的核心不在于 React 依赖,而在于分层约束:如果 bootstrap/state 反向依赖了更高层的应用状态模块(无论是 Store 还是 AppStateStore),就会破坏 DAG 的叶子节点地位,极易引入循环依赖。源码注释也明确提到这一点。

【摘抄 2,来自 docs/05-对话循环.md】
如果把 Claude Code 比作一个人体,那 query.ts 就是它的心脏——对话循环的编排入口。当然,心脏需要血管系统才能工作:重试逻辑在 services/api/withRetry.ts,工具执行在 services/tools/,停止钩子在 query/stopHooks.ts,环境配置在 query/config.ts。本篇会覆盖这个完整的"循环系统",而不仅仅是 query.ts 一个文件。每一次用户提问,都会触发这个循环:用户输入 → query() → queryLoop() → API 调用 → 工具执行 → 结果 yield → 等待下一轮。注意 transition 字段——它记录了上一次迭代为什么 continue。这不仅仅用于调试,还用于控制恢复逻辑:比如 collapse_drain_retry 后如果仍然 413(上下文太长),就不再重复 drain 而是 fall through 到 reactive compact。

本章新写正文摘抄(≥ 200 字 × 2 段,覆盖典型叙事段)

【新写 1,来自 docs/06-上下文管理.md §3.1】
除了这两条最直接的递归保护,源码在 shouldAutoCompact() 里还排布了几道针对新一代上下文机制的护栏(services/compact/autoCompact.ts:174-223),它们都属于"看似与 compact 无关、一旦同时点火就会互相拆台"那一类隐患:marble_origami 这个 ctx-agent——开启了 CONTEXT_COLLAPSE 之后,contextCollapse 自己也是一个 forked agent(querySource = marble_origami)。如果它在工作过程中又触发 autocompact,runPostCompactCleanup 会顺手调用 resetContextCollapse(),把主线程那一份模块级 collapse log 全部清掉。源码注释把这个连锁反应讲得很直白——所以这条 querySource 直接被列入"绝不再触发 autocompact"的黑名单。CONTEXT_COLLAPSE 启用时的让位——collapse 自己在 90% 触发承诺、95% 触发阻塞生成,而 autocompact 的阈值落在 effective 减去 13K 的位置(200K 模型上即 167K,相当于 93%)——恰好夹在这两条线中间。如果不让位,autocompact 通常会抢在 collapse 之前点火,把 collapse 即将保住的细粒度上下文一刀切掉。这一串护栏背后的共同主题是:当一个进程里同时活着多种上下文管理子系统时,谁先点火谁就赢,而点火顺序错了会发生静默的状态破坏

【新写 2,来自 docs/06-上下文管理.md §六】
postCompactCleanup 并排坐着的还有一个 63 行的小文件 services/compact/grouping.ts,它本身和清理逻辑无关,但属于同一类"为了让 compact 家族跑得动而存在的胶水模块",顺带一提。它只导出一个 groupMessagesByApiRound(),把 Message[] 按"API 往返边界"切组——遇到 message.id 与上一个 assistant 不同的新 assistant 消息就开新一组。这替换的是早期那套"只在真实用户提示处切分"的人工 turn 分组:那种分组对 REPL 够用,但对 SDK/CCR/eval 这类"整段会话只有一条人类提示、其余全是 agentic loop"的调用方就退化成"只有一组",reactive compact 想压缩中段也无从下刀。改成按 API 往返切分后,单提示词 agent 会话的中间轮次也能被独立摘要。services/compact/grouping.ts:18-21 的注释还交代了它为什么会被单拎出来:原本 inline 在 compact.ts 里时,compact.ts ↔ compactMessages.ts 之间形成了 import cycle(CC-1180),在 CI shard-2 上暴露了一个潜伏的 ws 模块 CJS/ESM 解析竞态——拆出来仅仅是为了改变模块初始化顺序

Test plan

  • bun run check:docs 全绿(一处 fuzzy WARN 命中 v1 原文,非阻塞)
  • services/compact/ 引用全部回填到 290fdc9
  • 10 个 v1 一/二级标题原位保留
  • 新增段落均为散文,未引入工程式小标题
  • reviewer 肉眼比对四段实证,确认与 v1-03 / v1-05 文风一致
  • 本 PR 由尧哥手动 merge,CC-Dev 不执行 merge

🤖 Generated with Claude Code

Yao Lu and others added 3 commits May 23, 2026 23:36
- 在 §3.1 触发流程末尾补充 autoCompact.ts:174-223 三道护栏:
  marble_origami ctx-agent / REACTIVE_COMPACT / CONTEXT_COLLAPSE 让位逻辑
- 在 §3.4 Compact Prompt 末尾补充 BASE / PARTIAL / PARTIAL_UP_TO 三模板
  与 getCompactUserSummaryMessage 的 proactive/KAIROS 续工尾语
- 在 §五 compactWarningState 末尾补充 compactWarningHook.ts 的拆文件理由
  (保持 compactWarningState 零 React 依赖,不污染 print-mode 启动路径)
- 新增 §七 grouping.ts:groupMessagesByApiRound,解释 CC-1180 拆出的
  API-round 边界分组与 import cycle 修复

原 §七 可迁移设计模式顺延为 §八。

YAO-108

Co-authored-by: multica-agent <github@multica.ai>
- 移除新增的 §七 grouping.ts 独立小节,把内容折叠到 §六 末尾
- 恢复 v1 §七 "可迁移的设计模式" 与 §八 编号,满足 C-2 标题保留
- §3.1 把 "约 93%"/"几乎一定" 替换为精确表述

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
OC-R 指出 sessionMemoryCompact 并不调用 getPartialCompactPrompt,而是直接读 Session Memory;改写 §3.4 段落,限定 getPartialCompactPrompt 的唯一调用方为 compact.ts:840 的 partial compact 路径,并补述 microCompact / apiMicrocompact / sessionMemoryCompact 的真实关系。

Co-authored-by: multica-agent <github@multica.ai>
@luyao618 luyao618 merged commit e25498d into main May 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant