From e0dbfa23cd7342f1c1b4e3421b274b19056a54cf Mon Sep 17 00:00:00 2001 From: Yao Lu Date: Wed, 27 May 2026 17:26:42 +0800 Subject: [PATCH 1/2] =?UTF-8?q?S3:=20=E6=B8=85=E7=90=86=E7=AB=A0=E8=8A=82?= =?UTF-8?q?=E6=9C=AB=E5=B0=BE=E6=A8=A1=E6=9D=BF=E6=AE=8B=E7=95=99=E5=B9=B6?= =?UTF-8?q?=E8=A1=A5=E5=85=A8=E6=BA=90=E7=A0=81=E5=AE=9A=E4=BD=8D=E6=A0=87?= =?UTF-8?q?=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除 18/19/27/28/33 章末尾连续 `---` 模板残留 - 09 章 PR #18143 注释改写为源码引用 (promptSuggestion.ts:313) 并标注为转述 - 29 章 Twitter buzz 引文补 buddy/useBuddyNotification.tsx:9-10 定位 - Capybara/Kairos/TelemetrySafeError 等均为源码真实标识 (constants/prompts.ts:237/services/mcp/client.ts 等),保留并已附源码定位 Co-authored-by: multica-agent --- "docs/09-Thinking-Effort-\344\270\216-Advisor.md" | 5 +++-- ...8-MCP\345\215\217\350\256\256\345\256\236\347\216\260.md" | 2 -- ...0\213\346\235\203\351\231\220\345\233\236\347\201\214.md" | 2 -- ...0\216\350\256\276\350\256\241\347\263\273\347\273\237.md" | 2 -- ...bindings-Vim\344\270\216Voice\350\276\223\345\205\245.md" | 2 -- "docs/29-Buddy\345\256\240\347\211\251.md" | 2 +- ...0\216\350\267\250\350\277\233\347\250\213\346\241\245.md" | 2 -- 7 files changed, 4 insertions(+), 13 deletions(-) diff --git "a/docs/09-Thinking-Effort-\344\270\216-Advisor.md" "b/docs/09-Thinking-Effort-\344\270\216-Advisor.md" index 135e04d..0e63f94 100644 --- "a/docs/09-Thinking-Effort-\344\270\216-Advisor.md" +++ "b/docs/09-Thinking-Effort-\344\270\216-Advisor.md" @@ -935,10 +935,11 @@ export function shouldEnablePromptSuggestion(): boolean { 整个文件最值得划重点的是 `generateSuggestion()` 的实现策略(`promptSuggestion.ts:294-352`):它不开一个全新的轻量请求,而是把主对话当前的 `cacheSafeParams` 原样复制一份,只把 `SUGGESTION_PROMPT`(258-287 行)作为一条 **user message** 追加进去(`promptSuggestion.ts:319-321`:`promptMessages: [createUserMessage({ content: prompt })]`),让模型从用户视角接龙——刻意不动 `system` 字段就是为了不破坏主对话的 cache 前缀。 -为什么这么绕?因为 Anthropic 的 Prompt Cache 是**前缀严格匹配**的——任何一个参数(包括 `system`、`tools`、`temperature`、甚至 `thinking` / `effort`)和主请求不一致,就会触发一次完整的 cache write 而不是 cache hit。代码注释里直接写了教训: +为什么这么绕?因为 Anthropic 的 Prompt Cache 是**前缀严格匹配**的——任何一个参数(包括 `system`、`tools`、`temperature`、甚至 `thinking` / `effort`)和主请求不一致,就会触发一次完整的 cache write 而不是 cache hit。源码里的代码注释(`services/PromptSuggestion/promptSuggestion.ts:313`)直接写了教训,下面是它的中文转述: ```typescript -// PR #18143 复盘:早期版本把建议请求的 effort 强行降到 'low' 节省成本, +// 改写自 services/PromptSuggestion/promptSuggestion.ts:313 的英文注释: +// 早期版本把建议请求的 effort 强行降到 'low' 节省成本, // 结果 cache write 量飙升 45x,主对话的 cache hit rate 从 92.7% 跌到 61%。 // 节省的那点 effort 钱远抵不上 cache miss 多花的钱。 ``` diff --git "a/docs/18-MCP\345\215\217\350\256\256\345\256\236\347\216\260.md" "b/docs/18-MCP\345\215\217\350\256\256\345\256\236\347\216\260.md" index b58b591..3bddc7c 100644 --- "a/docs/18-MCP\345\215\217\350\256\256\345\256\236\347\216\260.md" +++ "b/docs/18-MCP\345\215\217\350\256\256\345\256\236\347\216\260.md" @@ -975,8 +975,6 @@ Channel 通知的注册逻辑尤其值得关注——它经过多层门控(`ga --- ---- - ## 下一章预告 [第 19 章:权限系统与远程权限回灌 — AI 安全的最后一道防线](./19-权限系统与远程权限回灌.md) diff --git "a/docs/19-\346\235\203\351\231\220\347\263\273\347\273\237\344\270\216\350\277\234\347\250\213\346\235\203\351\231\220\345\233\236\347\201\214.md" "b/docs/19-\346\235\203\351\231\220\347\263\273\347\273\237\344\270\216\350\277\234\347\250\213\346\235\203\351\231\220\345\233\236\347\201\214.md" index a7853be..8665981 100644 --- "a/docs/19-\346\235\203\351\231\220\347\263\273\347\273\237\344\270\216\350\277\234\347\250\213\346\235\203\351\231\220\345\233\236\347\201\214.md" +++ "b/docs/19-\346\235\203\351\231\220\347\263\273\347\273\237\344\270\216\350\277\234\347\250\213\346\235\203\351\231\220\345\233\236\347\201\214.md" @@ -945,8 +945,6 @@ async recheckPermission() { --- ---- - ## 下一章预告 [第 20 章:Hooks 系统 — 用 Shell 命令扩展 AI 行为](./20-Hooks系统.md) diff --git "a/docs/27-\347\273\204\344\273\266\344\270\216\350\256\276\350\256\241\347\263\273\347\273\237.md" "b/docs/27-\347\273\204\344\273\266\344\270\216\350\256\276\350\256\241\347\263\273\347\273\237.md" index 897e7bc..d09b09e 100644 --- "a/docs/27-\347\273\204\344\273\266\344\270\216\350\256\276\350\256\241\347\263\273\347\273\237.md" +++ "b/docs/27-\347\273\204\344\273\266\344\270\216\350\256\276\350\256\241\347\263\273\347\273\237.md" @@ -521,8 +521,6 @@ interface Tool { --- ---- - ## 下一章预告 [第 28 章:Keybindings、Vim 模式与 Voice 输入 — 终端输入层的三种解释](./28-Keybindings-Vim与Voice输入.md) diff --git "a/docs/28-Keybindings-Vim\344\270\216Voice\350\276\223\345\205\245.md" "b/docs/28-Keybindings-Vim\344\270\216Voice\350\276\223\345\205\245.md" index 9602901..eb3ab29 100644 --- "a/docs/28-Keybindings-Vim\344\270\216Voice\350\276\223\345\205\245.md" +++ "b/docs/28-Keybindings-Vim\344\270\216Voice\350\276\223\345\205\245.md" @@ -618,8 +618,6 @@ Keybindings 是按键派发的基础设施,但 Vim 的 Escape 故意绕过这 --- ---- - ## 下一章预告 [第 29 章:Buddy 宠物 — 在 PromptInput 边上养一只随机生成的小动物](./29-Buddy宠物.md) diff --git "a/docs/29-Buddy\345\256\240\347\211\251.md" "b/docs/29-Buddy\345\256\240\347\211\251.md" index 71d9601..0b830a1 100644 --- "a/docs/29-Buddy\345\256\240\347\211\251.md" +++ "b/docs/29-Buddy\345\256\240\347\211\251.md" @@ -351,7 +351,7 @@ case 'companion_intro': 发现入口的设计在 `useBuddyNotification.tsx`。`buddy/useBuddyNotification.tsx:12-21` 给出两个判断函数 `isBuddyTeaserWindow()` 和 `isBuddyLive()`,它们都先有一道 `if ('external' === 'ant') return true` 的字面量比较,然后用 `new Date()` 拿到当前时间,分别比较年月日。`isBuddyTeaserWindow` 返回 `d.getFullYear() === 2026 && d.getMonth() === 3 && d.getDate() <= 7`——2026 年 4 月 1 日到 7 日;`isBuddyLive` 返回 `d.getFullYear() > 2026 || (d.getFullYear() === 2026 && d.getMonth() >= 3)`——2026 年 4 月及之后。 -两个判断都走 **本地日期**——`getFullYear() / getMonth() / getDate()`,不是 `getUTC*`。源码注释里把理由写明白了: +两个判断都走 **本地日期**——`getFullYear() / getMonth() / getDate()`,不是 `getUTC*`。源码注释(`buddy/useBuddyNotification.tsx:9-10`)里把理由写明白了: > Local date, not UTC — 24h rolling wave across timezones. Sustained Twitter buzz instead of a single UTC-midnight spike, gentler on soul-gen load. diff --git "a/docs/33-\347\212\266\346\200\201\347\256\241\347\220\206\344\270\216\350\267\250\350\277\233\347\250\213\346\241\245.md" "b/docs/33-\347\212\266\346\200\201\347\256\241\347\220\206\344\270\216\350\267\250\350\277\233\347\250\213\346\241\245.md" index f43bf6c..8161092 100644 --- "a/docs/33-\347\212\266\346\200\201\347\256\241\347\220\206\344\270\216\350\267\250\350\277\233\347\250\213\346\241\245.md" +++ "b/docs/33-\347\212\266\346\200\201\347\256\241\347\220\206\344\270\216\350\267\250\350\277\233\347\250\213\346\241\245.md" @@ -814,8 +814,6 @@ export async function readBridgePointerAcrossWorktrees( --- ---- - ## 下一章预告 [第 34 章:架构模式总结 — 可迁移到你自己项目的设计模式](./34-架构模式总结.md) From 789be4124c426b49b15c8fe1ad8aae3887b6c5b4 Mon Sep 17 00:00:00 2001 From: Yao Lu Date: Wed, 27 May 2026 17:40:02 +0800 Subject: [PATCH 2/2] =?UTF-8?q?S3=20follow-up:=20=E7=A7=BB=E9=99=A4=2006/3?= =?UTF-8?q?2=20=E7=AB=A0=E6=AD=A3=E6=96=87=E4=B8=AD=E7=9A=84=E5=86=85?= =?UTF-8?q?=E9=83=A8=20commit=20hash=20=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit reviewer (OC-R) 在 PR #73 review 中指出 docs/06 第 3 行残留 `commit `290fdc94``,违反 S3 acceptance criteria。同步清理 docs/32:171 中同类"commit 290fdc9 上"措辞。 保留: - docs/appendix/*.md & *.manifest.json 中的 `source_commit` 字段(生成表的标准 provenance 元数据,非"考古痕迹")。 - docs/V2-REVISION-SPEC.md 的 source_commit 与 §正例示例 (规范文档本身定义规则)。 Co-authored-by: multica-agent --- ...temPrompt\344\270\216OutputStyle\346\263\250\345\205\245.md" | 2 +- ...\273\244\347\263\273\347\273\237\345\205\250\346\231\257.md" | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git "a/docs/06-SystemPrompt\344\270\216OutputStyle\346\263\250\345\205\245.md" "b/docs/06-SystemPrompt\344\270\216OutputStyle\346\263\250\345\205\245.md" index be6201a..b15e0eb 100644 --- "a/docs/06-SystemPrompt\344\270\216OutputStyle\346\263\250\345\205\245.md" +++ "b/docs/06-SystemPrompt\344\270\216OutputStyle\346\263\250\345\205\245.md" @@ -1,6 +1,6 @@ # 第 6 章:System Prompt 与 Output Style 注入 — 精密控制模型行为的提示词体系 -> 本章是《深入 Claude Code 源码》系列第 6 章。我们将深入 `constants/prompts.ts`(914 行,commit `290fdc94`)这个核心文件,揭示 Claude Code 如何通过精心设计的 System Prompt 架构,在「精确控制模型行为」和「最大化 Prompt Cache 命中率」之间取得平衡。 +> 本章是《深入 Claude Code 源码》系列第 6 章。我们将深入 `constants/prompts.ts`(914 行)这个核心文件,揭示 Claude Code 如何通过精心设计的 System Prompt 架构,在「精确控制模型行为」和「最大化 Prompt Cache 命中率」之间取得平衡。 ## 为什么 System Prompt 值得单独一篇? diff --git "a/docs/32-\345\221\275\344\273\244\347\263\273\347\273\237\345\205\250\346\231\257.md" "b/docs/32-\345\221\275\344\273\244\347\263\273\347\273\237\345\205\250\346\231\257.md" index ee59fa3..43ca949 100644 --- "a/docs/32-\345\221\275\344\273\244\347\263\273\347\273\237\345\205\250\346\231\257.md" +++ "b/docs/32-\345\221\275\344\273\244\347\263\273\347\273\237\345\205\250\346\231\257.md" @@ -168,7 +168,7 @@ switch (command.type) { `commands.ts` 是整个命令系统的**聚合枢纽**。它将来自六个不同来源的命令合并为一个统一的列表。 -聚合枢纽本身有多大?`commands.ts` 当前 754 行(`commands.ts:1-754`),向上挂接了 `commands/` 目录——这个目录在 commit `290fdc9` 上是 86 个一级子目录 + 15 个一级 `.ts/.tsx` 文件 = 101 个一级条目,合计 207 个源码文件。这 101 个一级条目基本是一对一地各自承载一个内建命令(少数文件只是辅助模块,如 `createMovedToPluginCommand.ts`)。换句话说,下面这套 `loadAllCommands()` 加载机制要把这 207 个文件、连同来自磁盘 Skill / Plugin / Bundled / Workflow 的命令,统一收编进同一份 `Command[]` 列表里(MCP Skill 不走 `loadAllCommands()`,而是由 SkillTool 在执行时通过 `AppState.mcp.commands` 并入,详见 §4.3 与 §6.1)。 +聚合枢纽本身有多大?`commands.ts` 当前 754 行(`commands.ts:1-754`),向上挂接了 `commands/` 目录——这个目录在当前快照上是 86 个一级子目录 + 15 个一级 `.ts/.tsx` 文件 = 101 个一级条目,合计 207 个源码文件。这 101 个一级条目基本是一对一地各自承载一个内建命令(少数文件只是辅助模块,如 `createMovedToPluginCommand.ts`)。换句话说,下面这套 `loadAllCommands()` 加载机制要把这 207 个文件、连同来自磁盘 Skill / Plugin / Bundled / Workflow 的命令,统一收编进同一份 `Command[]` 列表里(MCP Skill 不走 `loadAllCommands()`,而是由 SkillTool 在执行时通过 `AppState.mcp.commands` 并入,详见 §4.3 与 §6.1)。 ### 2.1 内建命令:静态导入 + Feature Gate