MoreRSS

site iconColobu | 鸟窝 晁岳攀修改

rpcx作者,出版《深入理解Go并发编程》等,中科大,先后在清华同方、Motorola、Comcast、新浪等公司工作。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Colobu | 鸟窝 晁岳攀的 RSS 预览

我把775篇收藏塞进4MB向量库:一个比Karpathy Wiki更能"翻箱底"的RAG skill

2026-06-29 22:25:37

<p>我把 775 篇收藏的文章塞进一个 4MB 的向量库,然后问它:&quot;我都收藏过哪些关于 loop engineering 的资料?&quot;三秒钟,它把散在六七篇文章里的观点拼成一段答案,每条都带出处。</p><img src="/2026/06/29/chao-rag-wiki-personal-knowledge-base/image-20260629054807094.png" class=""><p>这不是什么 SaaS 产品,是我自己写的一个 skill,叫 <code>chao-rag-wiki</code>。今天聊聊它,顺便聊聊它背后那个问题:知识库越攒越大,你到底怎么&quot;读&quot;它?</p><p>得先从 Karpathy 的一个想法说起。</p><hr><span id="more"></span><h2 id="一、Karpathy-的-LLM-Wiki-:让-AI-替你维护知识库"><a href="#一、Karpathy-的-LLM-Wiki-:让-AI-替你维护知识库" class="headerlink" title="一、Karpathy 的&quot;LLM Wiki&quot;:让 AI 替你维护知识库"></a>一、Karpathy 的&quot;LLM Wiki&quot;:让 AI 替你维护知识库</h2><p>起点是 Andrej Karpathy 抛出的一句话:</p><blockquote><p>&quot;The LLM writes and maintains the wiki; the human reads and asks questions.&quot;<br>(LLM 负责写和维护 wiki,人类负责读和提问。)</p></blockquote><p>有人把这句话做成了一个 skill —— <code>karpathy-llm-wiki</code>。玩法是这样:</p><p>你有两个目录。<code>raw/</code> 放原始素材,只读、永不修改——收藏的推文、文章、论文都丢这里。<code>wiki/</code> 放编译后的知识文章,AI 全权打理。</p><p>每往 <code>raw/</code> 加一篇新素材,AI 就把它&quot;编译&quot;进 wiki:判断这篇属于哪个已有主题,跟某篇是同一个核心论点就合并进去、更新段落,全新概念就新建一篇,顺便检查跟已有内容有没有冲突、有就标出来。最后维护一个 <code>wiki/index.md</code> 全局索引,每篇一行——链接、摘要、更新日期。</p><p>你查询的时候(&quot;我知道哪些关于 X 的东西?&quot;),AI 先读 index.md 定位到相关文章,打开那几篇,再综合作答。</p><p>这个设计很优雅,本质是用 AI 把碎片素材沉淀成结构化的知识资产,而且会随时间复利增长。读起来像一本你自己的、不断长大的百科全书。</p><p>但它有个隐含前提:素材得先被&quot;编译&quot;进 wiki,才搜得到。下面这个 skill,想绕开的就是这件事。</p><hr><h2 id="二、chao-rag-wiki:不编译,直接检索"><a href="#二、chao-rag-wiki:不编译,直接检索" class="headerlink" title="二、chao-rag-wiki:不编译,直接检索"></a>二、chao-rag-wiki:不编译,直接检索</h2><p>我借了 <code>karpathy-llm-wiki</code> 的&quot;raw&#x2F; 只读&quot;哲学,但把后半段换成了 RAG(检索增强生成)。</p><p>一句话说清区别:<strong>karpathy-llm-wiki 是先把书写好再去翻书;chao-rag-wiki 是书原样不动,但给每一页都建了语义索引,随问随搜。</strong></p><img src="/2026/06/29/chao-rag-wiki-personal-knowledge-base/image-20260629054948985.png" class=""><p>技术栈是这么几块拼的:</p><p><strong>1. 向量检索用 <a href="https://github.com/RyanCodrai/turbovec">turbovec</a>。</strong> Google Research 的 TurboQuant 算法的 Rust 实现,能把向量压 16 倍还几乎不掉精度——上一篇我专门拆过。我的 775 篇切成 9089 个 chunk(去重后),整个索引才 4.8MB,常驻内存毫无压力。</p><p><strong>2. 嵌入默认使用千帆的 bge-large-zh(1024 维),但接口跟 provider 无关。</strong> 想换 OpenAI、Voyage 或本地模型都行,只改环境变量,不动代码。key 全走环境变量,绝不硬编码。</p><p><strong>3. 混合检索(Hybrid RAG),这是关键。</strong> 同时跑两路:稠密向量检索管语义,知道&quot;自我迭代&quot;和&quot;循环&quot;是一回事;BM25 关键词检索管字面,能精确命中 <code>rotate_writer.go</code> 这种代码标识符、人名、专有词。两路结果用 RRF(Reciprocal Rank Fusion,倒数排名融合)合并。语义检索擅长&quot;意思对但用词不同&quot;,关键词检索擅长&quot;就要这个词&quot;,融合之后两头都不漏。</p><img src="/2026/06/29/chao-rag-wiki-personal-knowledge-base/image-20260629055149668.png" class=""><p><strong>4. 可选的 LLM 重排(rerank)。</strong> 检索快但粗,再拉一个 LLM 当&quot;相关性裁判&quot;给候选打分重排,精度优先时加 <code>--rerank</code> 就行。</p><img src="/2026/06/29/chao-rag-wiki-personal-knowledge-base/image-20260629055320393.png" class=""><p><strong>5. 建索引时按 chunk 文本哈希去重。</strong> <code>raw/</code> 里同一段内容存了多份副本的话,只留一份进库,免得副本在结果里挤名额——我这 775 篇就压掉了 706 个重复 chunk。</p><img src="/2026/06/29/chao-rag-wiki-personal-knowledge-base/image-20260629055449657.png" class=""><h3 id="优缺点摆出来"><a href="#优缺点摆出来" class="headerlink" title="优缺点摆出来"></a>优缺点摆出来</h3><p>先说好的:</p><ul><li><p>零编译延迟。新素材丢进 <code>raw/</code>,跑一句增量索引就搜得到,不用 AI 逐篇消化。而且增量索引按内容哈希只处理新增和改动的文件,没变化就几秒退出。</p></li><li><p>召回更全。它检索的是原始全文的每个片段。哪怕某个话题你压根没想过给它单独建篇文章,只要素材里提过,就搜得到。</p></li><li><p>混合检索加重排加去重,对中英混排、专有名词、长尾问题都更稳。同一段内容在 <code>raw/</code> 里有多份副本,建索引时按 chunk 文本哈希自动合并,结果不会被副本占名额——但保留&quot;另见 N 份副本&quot;的来源信息,去重不丢信息。</p></li></ul><p>再说差的,这些恰好是 <code>karpathy-llm-wiki</code> 的强项:</p><ul><li><p>它没有知识沉淀,给你的是原文片段拼盘,不是一篇消化过、把内部矛盾理顺了的文章。<code>karpathy-llm-wiki</code> 那边的 wiki 文章是真正的二次创作,读起来成体系。</p></li><li><p>它只能精确去重。逐字相同的副本能干净合并,但&quot;同一篇、有细微编辑差异&quot;的近似重复就认不出来了——那得上 MinHash 或 SimHash,复杂得多。</p></li><li><p>它依赖在线 embedding,查询要联网(或者本地部署的大模型)、有 API 成本(BM25 那一路不用)。</p></li></ul><p>说白了,<code>karpathy-llm-wiki</code> 重&quot;沉淀&quot;,<code>chao-rag-wiki</code> 重&quot;召回&quot;。前者像精心整理的笔记本,后者像一个全文搜索引擎。</p><hr><h2 id="三、实战对比:两个查询"><a href="#三、实战对比:两个查询" class="headerlink" title="三、实战对比:两个查询"></a>三、实战对比:两个查询</h2><p>光说不练假把式。同样两个问题,两个 skill 各跑一遍。</p><p>自从 Karpathy的llm-wiki理念提出来之后,我收集资料的时候特意使用Obsidian web clipper进行收集,最近几个月也收集了700多篇资料,也在Hermes中建立了llm-wiki,这次我使用<code>chao-rag-wiki</code> 建立了RAG索引,让我们比较一下这两个skill搜索资料的效果。</p><h3 id="查询一:-loop-engineering"><a href="#查询一:-loop-engineering" class="headerlink" title="查询一:&quot;loop engineering&quot;"></a>查询一:&quot;loop engineering&quot;</h3><p><code>chao-rag-wiki</code>(hybrid + rerank)召回了散在多篇原文里的片段:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">[1] rerank=8.0 PART 2: WHAT LOOP ENGINEERING ACTUALLY IS</span><br><span class="line"> articles/...Loops What Every AI Engineer Needs to Know in 2026.md</span><br><span class="line">[2] rerank=7.0 工程化的三个层次</span><br><span class="line"> articles/...深度拆解:AI 智能体 Harness 的构造.md</span><br><span class="line">[3] rerank=7.0 Most Developers Do Not Need Agent Loops Yet</span><br><span class="line">[4] rerank=7.0 Agent Harness 拆解:AI Agent 真正的工程底座</span><br><span class="line">[5] rerank=6.0 &gt; I don&#x27;t talk to an agent anymore, I talk to a loop</span><br></pre></td></tr></table></figure><p>它直接定位到讲 loop engineering 五阶段(DISCOVER→PLAN→EXECUTE→VERIFY→ITERATE)的原文段落,连&quot;大多数开发者其实还不需要 loop&quot;这种唱反调的视角也捞了出来——因为那篇文章确实在我素材里。</p><img src="/2026/06/29/chao-rag-wiki-personal-knowledge-base/image-20260629060619850.png" class=""><p><code>karpathy-llm-wiki</code> 呢?它在 <code>wiki/index.md</code> 里一搜就命中一篇编译好的文章:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">| Loop Engineering: 从提示 Agent 到设计循环 | 2026 年 6 月爆发的 AI 编程</span><br><span class="line"> 新范式:五个原语(Automations/Worktrees/Skills/Connectors/Sub-agents)</span><br><span class="line"> +状态记忆,四条件测试,最小可行 Loop,刹车配置与四种死法 | 2026-06-24 |</span><br></pre></td></tr></table></figure><p>打开是一份消化整合过的结构化笔记:核心定义、Boris Cherny 的三阶段演化、五个必需品表格、引用了 8 个来源,读起来一气呵成。</p><p>这一局 <code>karpathy-llm-wiki</code> 赢在成品质量。loop engineering 是热门话题,我早让它编译过一篇。<code>chao-rag-wiki</code> 给的是原料,它给的是成菜。</p><h3 id="查询二:-grill-skill"><a href="#查询二:-grill-skill" class="headerlink" title="查询二:&quot;grill skill&quot;"></a>查询二:&quot;grill skill&quot;</h3><p>这局反过来了。</p><p><code>chao-rag-wiki</code>(hybrid + rerank):</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">[1] rerank/score Mattpocock Skills 系统:AI Agent 的能力单元 › SKILL.md 的文件结构</span><br><span class="line"> sources/AI时代的程序员/02 Mattpocock Skills系统.md</span><br><span class="line">[2] Productivity Skills</span><br><span class="line"> sources/AI时代的程序员/《AI时代的软件工程》-图书大纲.md</span><br><span class="line">[3] skill_manage 操作分发 (+1 dup copies)</span><br><span class="line"> articles/2026-04-12 -Hermes Agent 源码解析.md</span><br><span class="line">[5] Productivity —— grill-me / caveman / handoff...</span><br><span class="line"> articles/...mattpocock skills Skills for Real Engineers.md › #1: The Agent Didn&#x27;t Do What I Want</span><br></pre></td></tr></table></figure><p>干净命中 mattpocock 技能库里 <code>grill-me</code>、<code>grill-with-docs</code> 的介绍——&quot;写代码前先让 AI 反过来拷问你&quot;。注意第 3 条后面那个 <code>(+1 dup copies)</code>:去重把那篇的副本合并成一条、留了来源标记,没让重复内容占掉好几个名额。</p><p><code>karpathy-llm-wiki</code> 呢?我去 <code>wiki/index.md</code> 里搜 &quot;grill&quot;、&quot;mattpocock&quot;、&quot;拷问&quot;……</p><p>一条都没有。</p><p>不是说我素材里没有 grill 相关内容——有,好几篇正文都提了 <code>/grill-me</code>。问题是这个话题从没被单独编译成一篇 wiki 文章,index.md 里就没它的入口。按 karpathy-wiki &quot;先读 index 再定位文章&quot;的路子,它要么直接漏掉这个查询,要么只能模糊地甩你一篇泛泛的&quot;agent skills 框架&quot;。</p><p>这一局 <code>chao-rag-wiki</code> 完胜。它检索全文,根本不在乎你立没立过条目。</p><hr><h2 id="四、所以到底用哪个?"><a href="#四、所以到底用哪个?" class="headerlink" title="四、所以到底用哪个?"></a>四、所以到底用哪个?</h2><p>两个查询跑下来,结论挺清楚:它俩不是替代关系,是互补关系。</p><table><thead><tr><th></th><th>karpathy-llm-wiki</th><th>chao-rag-wiki</th></tr></thead><tbody><tr><td>核心机制</td><td>AI 编译素材成文章</td><td>RAG 全文语义检索</td></tr><tr><td>查询方式</td><td>读 index → 定位文章</td><td>向量+BM25 混合检索+重排</td></tr><tr><td>强项</td><td>热门话题、成体系的沉淀</td><td>全量召回、长尾话题、专有名词</td></tr><tr><td>弱项</td><td>没编译过的话题会漏</td><td>给原料而非成品、只能精确去重</td></tr><tr><td>延迟</td><td>编译慢、查询快</td><td>索引快、查询需联网</td></tr><tr><td>想读一篇消化好的总结,问 <code>karpathy-llm-wiki</code>;想确认&quot;我到底收藏过啥&quot;、找长尾、找冷门词,用 <code>chao-rag-wiki</code>。</td><td></td><td></td></tr></tbody></table><p>我现在就是这么用的:<code>chao-rag-wiki</code> 当全文搜索引擎兜底召回,<code>karpathy-llm-wiki</code> 当精编笔记本沉淀热点。一个保证不漏,一个保证好读。</p><hr><h2 id="五、把它接进-Obsidian:从-看到-到-可搜"><a href="#五、把它接进-Obsidian:从-看到-到-可搜" class="headerlink" title="五、把它接进 Obsidian:从&quot;看到&quot;到&quot;可搜&quot;"></a>五、把它接进 Obsidian:从&quot;看到&quot;到&quot;可搜&quot;</h2><p>前面讲的都是 skill 本身。可知识库要真转起来,得先解决一个更前面的问题:素材怎么进来?总不能每篇手动复制粘贴。</p><p>我这套链路全自动,分三段。</p><h3 id="第一段:Web-Clipper-抓取,落到-raw"><a href="#第一段:Web-Clipper-抓取,落到-raw" class="headerlink" title="第一段:Web Clipper 抓取,落到 raw/"></a>第一段:Web Clipper 抓取,落到 <code>raw/</code></h3><p><a href="https://obsidian.md/clipper">Obsidian Web Clipper</a> 是官方的浏览器插件,Chrome、Edge、Firefox 都有。看到一篇好文章、一条推文,点一下插件图标,它就把正文提取成干净的 Markdown,存进你的 Obsidian vault。</p><p>它能配模板和保存路径,这是关键。我把模板的目标文件夹设成 vault 里的 <code>raw/articles/</code>,文件名用 <code>&#123;&#123;date&#125;&#125; -&#123;&#123;author&#125;&#125;-&#123;&#123;title&#125;&#125;</code>,再让它自动带上来源 URL、抓取日期这些 frontmatter。于是浏览中随手一点,文章就躺进了 <code>raw/</code>——正好是两个 skill 都约定&quot;只读、不改&quot;的那个源目录。我那 775 篇,基本就是这么攒的。</p><h3 id="第二段:定时任务自动索引"><a href="#第二段:定时任务自动索引" class="headerlink" title="第二段:定时任务自动索引"></a>第二段:定时任务自动索引</h3><p>素材进来了,但还没&quot;可搜&quot;。这步交给定时任务——<code>raw/</code> 每天在长,那就让索引每天自己追上:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># crontab:每天凌晨 3:07 增量索引(错峰,别卡整点)</span></span><br><span class="line">7 3 * * * <span class="built_in">cd</span> ~/Obsidian-Vault &amp;&amp; \</span><br><span class="line"> ~/.claude/skills/chao-rag-wiki/.venv/bin/python \</span><br><span class="line"> ~/.claude/skills/chao-rag-wiki/scripts/build_rag.py --raw raw --out .rag --update</span><br></pre></td></tr></table></figure><p>前面说了,<code>--update</code> 按内容哈希只处理新增和改动的文件,没变化就几秒退出、零 API 调用,所以天天跑也不浪费。Web Clipper 当天剪的新文章,第二天一早就进了向量库。</p><p>karpathy-llm-wiki 那一路同理,挂个任务把当天 <code>raw/</code> 的新文件编译进 wiki 沉淀下来就行。两条管道并行:chao-rag 让每篇立刻可搜,karpathy-wiki 把值得沉淀的编成文章。</p><p>实际上是在我的Mac mini m2上的Hermes中配置了定时任务,每天凌晨调用这个skill进行索引处理。</p><img src="/2026/06/29/chao-rag-wiki-personal-knowledge-base/image-20260629055738407.png" class=""><h3 id="第三段:随时调用-skill-搜索"><a href="#第三段:随时调用-skill-搜索" class="headerlink" title="第三段:随时调用 skill 搜索"></a>第三段:随时调用 skill 搜索</h3><p>闭环这就成了。想找东西,直接在 Claude Code 里调:</p><ul><li><code>/chao-rag-wiki 找出关于 X 的资料</code>——全文混合检索,长尾、冷门词都捞得到;</li><li><code>/karpathy-llm-wiki 我都知道哪些关于 X 的东西</code>——读编译好的精编文章。</li></ul><p>整条链路连起来就是:浏览时点一下 Web Clipper,文章落进 <code>raw/</code>,定时任务自动索引,想搜时一句话调 skill。你只管&quot;看到好东西点一下&quot;和&quot;有问题问一句&quot;,中间的剪藏、入库、索引全自动。Karpathy 那句&quot;人类负责读和提问&quot;,落地大概就是这个样子。</p><hr><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p><code>chao-rag-wiki</code> 已经开源,一行命令装上:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx skills add smallnest/chao-rag-wiki</span><br></pre></td></tr></table></figure><p>配好一个 embedding 的 key(默认千帆,也支持 OpenAI、Voyage 或任意 OpenAI 兼容网关),素材丢进 <code>raw/</code>,跑一句 build 就能开问。再按第五节配好 Web Clipper 模板和定时任务,整个知识库就自己转起来了。</p><blockquote><p>最后留个彩蛋:写这篇时,&quot;两个 skill 各跑两个查询、对比结果&quot;那一步,就是 chao-rag-wiki 自己检索出来的。它检索自己被讨论的素材,多少有点自产自销。RAG 的尽头,没准就是让知识库学会自我介绍。</p></blockquote>

Go 语言技能:AI 时代的 Go 开发工具链

2026-06-28 18:00:00

<blockquote><p>&quot;Clear is better than clever.&quot;<br>清晰胜于聪明。<br>—— Rob Pike, Go Proverbs</p></blockquote><p>第 23 章把重构讲完了。嗅坏味道、套 Fowler 手法、小步施工、每步测试,这套东西对 Java、Python、Go 一视同仁。但真到 Go 上手你会发现,Fowler 的目录够不着 Go 的好几层脾气。一段能跑的 Go 代码,可能还停在 Go 1.10 的写法,不地道;可能并发原语用错了,race detector 一开就红,不安全;也可能分配没控住,cache line 在 false sharing,不快。这些坏味道扫不出来,是 Go 二十年攒下来、只有老手才摸得到的门道。</p><p>门道都散在各处。Dave Cheney 的高性能工作坊讲一套,dgryski 的 go-perfbook 讲一套,《Go 并发编程实战》讲一套,Go 团队的 modernize 分析又讲一套,再加上无数生产事故换来的风格约定。以前你得一本书一本书读、一个 pprof 一个 pprof 啃。现在有人把这些蒸成一个 Skill,Agent 调一下就能用。</p><p>本章介绍五个 Go 专属的 Skill,正好覆盖 Go 工程的四个面:现代化(<code>/modern-go</code>)、性能(<code>chao-go-perf</code>)、并发(<code>chao-go-sync</code>)、风格(<code>go-style-guide</code>),外加一个把这几样打包、还顺带做了效果评估的全家桶(<code>cc-skills-golang</code>)。前三个是本书作者 smallnest 写的,对,写这本书的人和写这些 Skill 的人是同一个;后两个分别来自 madflojo(Benjamin Cane)和 samber。</p><span id="more"></span><h2 id="24-1-为什么-Go-需要专属技能"><a href="#24-1-为什么-Go-需要专属技能" class="headerlink" title="24.1 为什么 Go 需要专属技能"></a>24.1 为什么 Go 需要专属技能</h2><p>第 1 章立过本书的旗:从 Prompt-Driven 到 Skill-Driven。Prompt 临时,Skill 持久;Skill 等于可复用的方法论加结构化的知识加标准化的输入输出。这话对什么语言都成立,但 Go 尤其该说一遍,因为它有三样东西让通用 Agent 特别容易翻车。</p><p>一是 Go 的地道写法绑版本。同一件事,Go 1.10 和 Go 1.22 的标准答案不一样。循环找切片里有没有某个元素,1.10 要手写 for 循环,1.21 一行 <code>slices.Contains</code> 搞定;求最小值,1.20 要 if-else,1.21 有内置 <code>min</code>。Agent 训练数据里两种写法都有,随手给你写哪种全看运气。代码是能跑,可能是个十年前的化石。</p><p>二是 Go 的并发坑深,而且静默。一个 <code>map</code> 并发读写不会马上崩,要等压力上来、等到生产环境的某个深夜才 panic。一个 <code>sync.Mutex</code> 被复制了,<code>go vet</code> 查得出,Agent 不会主动跑。goroutine 泄漏更无声无息,程序能跑,内存曲线却悄悄爬坡。这些坑 Fowler 的坏味道目录里一个都没有。</p><p>三是 Go 的性能是测出来的,不是猜出来的。Dave Cheney 那句「You can&#39;t optimize what you don&#39;t measure」是 Go 性能圈的宪法。可 Agent 的默认行为恰恰是猜,看一眼代码凭直觉说「这里用 sync.Pool 优化一下」,既没 benchmark 也没 pprof。猜对的概率比你想的低。</p><p>三样合起来指向一个结论:Go 的资深经验得编码进 Skill,才能被 Agent 可靠复用。这不算锦上添花,是这门语言逼出来的刚需。下面五个 Skill,就是这件事的五个侧面。</p><p><img src="/images/image-20260627085111146.png"></p><h2 id="24-2-五个-Skill-一览"><a href="#24-2-五个-Skill-一览" class="headerlink" title="24.2 五个 Skill 一览"></a>24.2 五个 Skill 一览</h2><p>先给一张全景图,免得后面绕晕。</p><table><thead><tr><th>Skill</th><th>作者</th><th>定位</th><th>覆盖面</th><th>Stars(2026&#x2F;06)</th></tr></thead><tbody><tr><td><code>/modern-go</code></td><td>smallnest</td><td>Go 代码现代化</td><td>35 条 gofix 风格规则,Go 1.0→1.26+</td><td>goal-workflow 套件内</td></tr><tr><td><code>chao-go-perf</code></td><td>smallnest</td><td>Go 性能分析专家</td><td>CPU&#x2F;内存&#x2F;GC&#x2F;编译器&#x2F;缓存&#x2F;并发,含 PGO</td><td>~40</td></tr><tr><td><code>chao-go-sync</code></td><td>smallnest</td><td>Go 并发编程专家</td><td>全部 sync 原语 + 13+ 模式 + 分布式</td><td>~37</td></tr><tr><td><code>go-style-guide</code></td><td>madflojo (Benjamin Cane)</td><td>固执己见的 Go 工程契约</td><td>包设计&#x2F;接口&#x2F;错误&#x2F;日志&#x2F;布局&#x2F;测试</td><td>~35</td></tr><tr><td><code>cc-skills-golang</code></td><td>samber</td><td>生产级 Go Skills 全家桶</td><td>28+ 原子 Skill,跨工具,带评估</td><td>~2300</td></tr></tbody></table><p>五个 Skill 的分工可以这样理解:<code>/modern-go</code> 管「代码是不是用了新版本的写法」,<code>go-style-guide</code> 管「代码符不符合工程契约」,<code>chao-go-sync</code> 管「并发安不安全」,<code>chao-go-perf</code> 管「跑得快不快」,<code>cc-skills-golang</code> 把这四件事各做一份,外加交叉引用和效果评估。前四个是专精一件的单点 Skill,最后一个是面面俱到的体系。</p><p>顺带说一句 <code>cc-skills-golang</code> 的体量,两千多 stars,是本章里唯一算得上「大项目」的。它的特别之处不在多,在于拿数据证明了 Skill 真的有用。这个留到 24.7 节细讲。</p><p><img src="/images/image-20260627085255642.png"></p><p>下面逐一展开。</p><h2 id="24-3-modern-go:让老代码跟上新版本"><a href="#24-3-modern-go:让老代码跟上新版本" class="headerlink" title="24.3 &#x2F;modern-go:让老代码跟上新版本"></a>24.3 &#x2F;modern-go:让老代码跟上新版本</h2><p><code>/modern-go</code> 在第 8 章作为 Goal Workflow 的 Bonus Skill 露过一面,第 23 章也提过它和 <code>/refactor</code>、<code>/smell</code> 一样是「保持代码库健康」的邻居。这里展开讲它的机制。(介绍页:<a href="https://goal.rpcx.io/index_cn.html#step-modern-go">https://goal.rpcx.io/index_cn.html#step-modern-go</a> )</p><p>我自己写它,是因为 goscapy 这种库要长期维护,go.mod 里的版本会一点点往前挪,可代码还停在五年前写它时的写法。靠人记得每条 <code>time.Since</code> 替换、记得 <code>interface{}</code> 该换成 <code>any</code>,不现实。<code>go fix</code> 官方工具又只覆盖一小部分。于是把 Go 团队 modernize 分析能找到的转换规则、加上社区常用的,凑成一份带版本门控的 Skill,让 Agent 替我盯着。它的定位很纯粹,像 <code>go fix</code> 一样,把老写法自动改成新版本的地道写法。装一行:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx skills add smallnest/goal-workflow --skill modern-go</span><br></pre></td></tr></table></figure><p>触发可以直接打 <code>/modern-go</code>,或说「现代化」「modernize」「gofix」。</p><p><img src="/images/image-20260627085439804.png"></p><h3 id="24-3-1-35-条版本门控的转换规则"><a href="#24-3-1-35-条版本门控的转换规则" class="headerlink" title="24.3.1 35 条版本门控的转换规则"></a>24.3.1 35 条版本门控的转换规则</h3><p>Skill 内置 35 条转换规则,每条带一个版本门控,只在项目的 Go 版本够格时才启用。规则从 Go 1.0 一路排到 1.26+,挑几个有代表性的:</p><table><thead><tr><th>Go 版本</th><th>老写法</th><th>新写法</th></tr></thead><tbody><tr><td>1.0+</td><td><code>time.Now().Sub(start)</code></td><td><code>time.Since(start)</code></td></tr><tr><td>1.13+</td><td><code>err == io.EOF</code></td><td><code>errors.Is(err, io.EOF)</code></td></tr><tr><td>1.18+</td><td><code>interface{}</code></td><td><code>any</code></td></tr><tr><td>1.18+</td><td><code>strings.Index</code> + 手动切片</td><td><code>strings.Cut</code></td></tr><tr><td>1.19+</td><td><code>atomic.StoreInt32(&amp;v, 1)</code></td><td><code>var v atomic.Int32; v.Store(1)</code></td></tr><tr><td>1.20+</td><td><code>fmt.Errorf(&quot;...: %w: %w&quot;, e1, e2)</code></td><td><code>errors.Join(...)</code></td></tr><tr><td>1.21+</td><td>手写 for 循环找元素</td><td><code>slices.Contains</code></td></tr><tr><td>1.21+</td><td><code>if a&lt;b {v=a} else {v=b}</code></td><td><code>v = min(a, b)</code></td></tr><tr><td>1.21+</td><td><code>var once sync.Once; once.Do(...)</code></td><td><code>sync.OnceFunc(...)</code></td></tr><tr><td>1.22+</td><td><code>for i := 0; i &lt; n; i++</code></td><td><code>for i := range n</code></td></tr></tbody></table><p>每条规则都配 before&#x2F;after 代码对照,机械、可执行。这正是 Go 团队 modernize 分析能被 Agent 接住的地方。</p><h3 id="24-3-2-安全保护:读-go-mod,绝不越级"><a href="#24-3-2-安全保护:读-go-mod,绝不越级" class="headerlink" title="24.3.2 安全保护:读 go.mod,绝不越级"></a>24.3.2 安全保护:读 go.mod,绝不越级</h3><p>真正关键的不是这 35 条规则,是它怎么决定该用哪条。流程很死板:</p><ol><li>先读 <code>go.mod</code> 里的 <code>go</code> 指令,拿到项目声明的 Go 版本;</li><li>扫描目标范围内所有 <code>.go</code> 文件(排除 <code>vendor/</code>、<code>.git/</code>、<code>testdata/</code>);</li><li>对每个文件,只应用版本 ≤ 项目版本的规则,从老到新依次套;</li><li>最后打印一份改了什么、跳过了什么的汇总。</li></ol><p>铁律只有一条,但很硬:绝不应用需要比项目声明版本更高的规则。项目还停在 Go 1.20,就不会给你塞 1.21 的 <code>min</code> 和 <code>slices</code>,塞了编译不过。这条把「现代化」和「改坏」之间的边界钉死了。</p><p>这条保护和第 23 章 <code>/refactor</code> 的五阶段协议是同一种思路:把人最容易手滑的地方改成 Agent 必须遵守的护栏,这里是「图新」而越级升级。人升级 Go 时常犯的错,比如把目标版本改高了却忘了改 <code>go.mod</code>,或者用了新 API 却没加 import,<code>/modern-go</code> 用版本门控和 requires importing 的提示一条条堵上。</p><h3 id="24-3-3-实演:一段老代码怎么被现代化"><a href="#24-3-3-实演:一段老代码怎么被现代化" class="headerlink" title="24.3.3 实演:一段老代码怎么被现代化"></a>24.3.3 实演:一段老代码怎么被现代化</h3><p>光看规则表没感觉,跑一段。假设 <code>go.mod</code> 写的是 <code>go 1.21</code>,项目里有这么个函数,写法停在 Go 1.13:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">parseHeader</span><span class="params">(buf []<span class="type">byte</span>)</span></span> (key, val <span class="type">string</span>, ok <span class="type">bool</span>) &#123;</span><br><span class="line"> <span class="keyword">if</span> i := bytes.Index(buf, []<span class="type">byte</span>(<span class="string">&quot;=&quot;</span>)); i &gt;= <span class="number">0</span> &#123;</span><br><span class="line"> key = <span class="type">string</span>(buf[:i])</span><br><span class="line"> val = <span class="type">string</span>(buf[i+<span class="number">1</span>:])</span><br><span class="line"> ok = <span class="literal">true</span></span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> cache atomic.Value</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">getConfig</span><span class="params">()</span></span> *Config &#123;</span><br><span class="line"> cache.Store(&amp;Config&#123;&#125;)</span><br><span class="line"> <span class="keyword">return</span> cache.Load().(*Config)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>/modern-go</code> 进来先读 <code>go.mod</code>,拿到 1.21 这个版本上限,然后从老到新逐条套能用的规则。对上面这段,它会动三处:</p><ul><li><code>bytes.Index</code> 加手动切片 → 1.20+ 的 <code>bytes.Cut</code>(1.21 够格);</li><li><code>atomic.Value</code> 加类型断言 → 1.19+ 的 <code>atomic.Pointer[T]</code>;</li><li>顺手把 import 补上。</li></ul><p>出来是这样:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">parseHeader</span><span class="params">(buf []<span class="type">byte</span>)</span></span> (key, val <span class="type">string</span>, ok <span class="type">bool</span>) &#123;</span><br><span class="line"> before, after, found := bytes.Cut(buf, []<span class="type">byte</span>(<span class="string">&quot;=&quot;</span>))</span><br><span class="line"> <span class="keyword">if</span> found &#123;</span><br><span class="line"> key, val, ok = <span class="type">string</span>(before), <span class="type">string</span>(after), <span class="literal">true</span></span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> cache atomic.Pointer[Config]</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">getConfig</span><span class="params">()</span></span> *Config &#123;</span><br><span class="line"> cache.Store(&amp;Config&#123;&#125;)</span><br><span class="line"> <span class="keyword">return</span> cache.Load()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>注意它没碰 1.22 的 range-over-int,项目是 1.21,那条规则被门控挡掉了。这是版本门控真正干活的样子:该改的改,不该碰的一行不动。要是谁手贱把 go.mod 提到 1.22,再跑一遍,那个 for 循环才会被改成 <code>for i := range n</code>。</p><h2 id="24-4-chao-go-perf:把-Dave-Cheney-的工作坊装进-Skill"><a href="#24-4-chao-go-perf:把-Dave-Cheney-的工作坊装进-Skill" class="headerlink" title="24.4 chao-go-perf:把 Dave Cheney 的工作坊装进 Skill"></a>24.4 chao-go-perf:把 Dave Cheney 的工作坊装进 Skill</h2><p><code>/modern-go</code> 解决「写法老不老」,<code>chao-go-perf</code> 解决「跑得快不快」。我写它,是因为 rpcx、goscapy 这种库对性能敏感,可每次让 Agent 帮忙优化,它张口就是「这里加个 sync.Pool」,没 benchmark、没 pprof,纯靠猜。猜错是常态。Go 性能圈其实有现成的规矩,Dave Cheney 和 dgryski 讲过很多遍,第一条都是「先测量」。这些规矩散在讲义和书里,Agent 不会自动遵守,那就把它们蒸成一个 Skill,逼它先拿数据再说话。它把 Go 性能圈几本「圣经」装进来:</p><ul><li>Dave Cheney 的 High Performance Go Workshop(GopherCon 2019)</li><li>dgryski 的 go-perfbook(中文版)</li><li>Effective Go</li><li>Go 101 的 Optimizations 101</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx skills add smallnest/chao-go-perf</span><br></pre></td></tr></table></figure><h3 id="24-4-1-黄金法则:先测量,再优化"><a href="#24-4-1-黄金法则:先测量,再优化" class="headerlink" title="24.4.1 黄金法则:先测量,再优化"></a>24.4.1 黄金法则:先测量,再优化</h3><p><code>chao-go-perf</code> 开篇就把 Dave Cheney 和 go-perfbook 的两句话钉在墙上:</p><blockquote><p>&quot;You can&#39;t optimize what you don&#39;t measure. Always benchmark before and after.&quot;<br>—— Dave Cheney</p><p>不要猜测性能瓶颈。用数据说话。先测量,再优化,最后验证。<br>—— go-perfbook</p></blockquote><p>由此引出五条黄金法则:先测量再优化、Benchmark 驱动、了解编译器、内存是瓶颈、优化最热路径。这五条不是建议,是 Skill 的工作前提,和第 16 章 agent-skills 的验证门禁、第 23 章 <code>/refactor</code> 的安全协议同源:Agent 得先有证据(benchmark、pprof)才能动优化。这一条直接把 Agent 最爱的毛病禁了,看一眼代码就凭直觉「优化」。</p><p><img src="/images/image-20260627085649794.png"></p><h3 id="24-4-2-三套分析框架:CPU-内存-并发"><a href="#24-4-2-三套分析框架:CPU-内存-并发" class="headerlink" title="24.4.2 三套分析框架:CPU &#x2F; 内存 &#x2F; 并发"></a>24.4.2 三套分析框架:CPU &#x2F; 内存 &#x2F; 并发</h3><p>Skill 给出三套可机械执行的分析框架,每套都是「命令 → 看什么 → 判断什么」:</p><table><thead><tr><th>维度</th><th>生成 profile</th><th>看什么</th><th>典型病因</th></tr></thead><tbody><tr><td>CPU</td><td><code>go test -bench -cpuprofile</code></td><td>火焰图最热函数</td><td>内联失败、不必要计算、算法复杂度</td></tr><tr><td>内存</td><td><code>go test -bench -memprofile</code> + <code>-gcflags=&quot;-m&quot;</code></td><td>alloc_space 热点、逃逸分析</td><td>slice 未预分配、[]byte↔string 转换、接口装箱</td></tr><tr><td>并发</td><td><code>go test -race</code> + <code>runtime/trace</code> + mutex profile</td><td>锁等待、调度</td><td>锁粒度过大、false sharing、channel vs mutex 选错</td></tr></tbody></table><p>这套框架把性能优化从「拍脑袋改代码」变成「先定位瓶颈在哪一层,再用对应工具验证」。AI 时代尤其用得上,Agent 吐的代码经常埋着 N+1 分配、循环内排序这类量小看不出、上了量才爆的坑,<code>chao-go-perf</code> 的内存框架一眼能扫出来。</p><h3 id="24-4-3-覆盖面与参考资料"><a href="#24-4-3-覆盖面与参考资料" class="headerlink" title="24.4.3 覆盖面与参考资料"></a>24.4.3 覆盖面与参考资料</h3><p>Skill 还配 8 份参考资料,按需加载:benchmarking、memory-optimization、cpu-optimization、cache-optimization、concurrency-perf、pgo、tooling、version-changes。其中两块是 Go 圈的硬骨头:PGO(Profile-Guided Optimization)的完整工作流,和 Go 1.12 到 1.27 的关键性能变更(哪个版本改了 GC、哪个版本改了调度器,升级时要留意什么)。CPU 缓存那块也讲得细,cache line 对齐、false sharing 检测、AoS 对 SoA 的数据局部性取舍,这些资深 Go 工程师才碰得到,Agent 默认不会主动想。</p><h3 id="24-4-4-实演:先看-benchmark,再谈优化"><a href="#24-4-4-实演:先看-benchmark,再谈优化" class="headerlink" title="24.4.4 实演:先看 benchmark,再谈优化"></a>24.4.4 实演:先看 benchmark,再谈优化</h3><p>按 Skill 的规矩,它不会直接给优化方案,第一句话是问数据。你喂给它一段有锁竞争的计数器:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Counter <span class="keyword">struct</span> &#123;</span><br><span class="line"> mu sync.Mutex</span><br><span class="line"> n <span class="type">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Counter)</span></span> Inc() &#123;</span><br><span class="line"> c.mu.Lock()</span><br><span class="line"> c.n++</span><br><span class="line"> c.mu.Unlock()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>说「这个 Inc 在高并发下慢,优化一下」。<code>chao-go-perf</code> 不会立刻说「换 atomic」,它会先走 Step 1 的分类和 Step 2 的框架,让你先出证据:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">问题分类:并发竞争(吞吐量不随 CPU 增加)</span><br><span class="line">诊断步骤:</span><br><span class="line">1. go test -bench=. -cpuprofile=cpu.out</span><br><span class="line">2. go tool pprof -http=:8080 cpu.out → 看 mutex 热点</span><br><span class="line">3. go test -race → 确认无数据竞争</span><br><span class="line">4. 看锁竞争:临界区只有一个 n++,纯计数</span><br></pre></td></tr></table></figure><p>证据到位(profile 显示锁等待占大头),它才进锁选择决策树。Skill 里那张决策图长这样:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">是否只需要保护简单整数/布尔/指针?</span><br><span class="line"> └── Yes → atomic 操作</span><br><span class="line"> └── No → 读写比例?</span><br><span class="line"> ├── 几乎全读 (&gt; 90%) → sync.RWMutex</span><br><span class="line"> ├── 读写均衡 → sync.Mutex</span><br><span class="line"> └── 偶尔写入一次 → sync.Once / sync.Map</span><br></pre></td></tr></table></figure><p><code>n</code> 是个整数,<code>Inc</code> 只做自增,正好走第一条分支,给方案:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Counter <span class="keyword">struct</span> &#123;</span><br><span class="line"> n atomic.Int64</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Counter)</span></span> Inc() &#123;</span><br><span class="line"> c.n.Add(<span class="number">1</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>并附一串近似量级让你心里有数:atomic 约 1-2 ns&#x2F;op,无竞争 Mutex 15-30 ns&#x2F;op,channel 50-200 ns&#x2F;op。最后还不忘补一句:优化前后的 benchmark 都得跑,用 benchstat 验证。这套流程才是 Skill 想要的样子,先量、再分类、最后给方案,每一步都有数据兜着,而不是上来就 sync.Pool。</p><h2 id="24-5-chao-go-sync:并发是-Go-的灵魂,也是最容易翻车的地方"><a href="#24-5-chao-go-sync:并发是-Go-的灵魂,也是最容易翻车的地方" class="headerlink" title="24.5 chao-go-sync:并发是 Go 的灵魂,也是最容易翻车的地方"></a>24.5 chao-go-sync:并发是 Go 的灵魂,也是最容易翻车的地方</h2><p>Go 的并发是它的招牌,也是它最容易出事的地方。<code>chao-go-sync</code> 基于《Go 并发编程实战》一书,把 Go 并发的全套知识,从标准库原语到分布式同步,装进一个 Skill。这本书是我写的,写它的时候把踩过的坑、用过的第三方库、做过的分布式同步方案整理了一遍。写完发现,这些内容正好是 Agent 写并发代码最缺的那块。它知道 <code>sync.Mutex</code> 怎么用,但不知道哪里会复制、哪里会重入死锁、什么时候该上分片锁。于是把书的内容蒸成 Skill,让 Agent 调一下就能拿到一整本书的判断力。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx skills add smallnest/chao-go-sync</span><br></pre></td></tr></table></figure><h3 id="24-5-1-覆盖面:从-stdlib-到-etcd"><a href="#24-5-1-覆盖面:从-stdlib-到-etcd" class="headerlink" title="24.5.1 覆盖面:从 stdlib 到 etcd"></a>24.5.1 覆盖面:从 stdlib 到 etcd</h3><p><code>chao-go-sync</code> 的覆盖面是五个 Skill 里最广的,横跨四个层次:</p><table><thead><tr><th>层次</th><th>内容</th></tr></thead><tbody><tr><td>标准库原语</td><td>Mutex、RWMutex、WaitGroup、Cond、Once、Pool、sync.Map、atomic、channel、context、synctest</td></tr><tr><td>官方扩展</td><td>信号量、SingleFlight、ErrGroup、限流器</td></tr><tr><td>第三方库</td><td>CyclicBarrier、断路器(sony&#x2F;gobreaker)、Worker Pool(panjf2000&#x2F;ants)、sourcegraph&#x2F;conc、各类限流库</td></tr><tr><td>分布式同步</td><td>基于 etcd 的 Leader 选举、分布式锁、分布式队列&#x2F;屏障、STM</td></tr></tbody></table><p>外加 13+ 种并发模式(半异步半同步、Reactor、Proactor、Per-CPU、活动对象……)和四个经典问题(哲学家就餐四种解法、理发师问题、水工厂、Fizz Buzz)。这个体量,基本上是把一本并发书搬进了 Skill。</p><h3 id="24-5-2-Bug-诊断框架:五个必查项"><a href="#24-5-2-Bug-诊断框架:五个必查项" class="headerlink" title="24.5.2 Bug 诊断框架:五个必查项"></a>24.5.2 Bug 诊断框架:五个必查项</h3><p>并发 Bug 最难的是定位。Skill 给了一套诊断框架,收到并发问题先过这五条:</p><ul><li>有没有数据竞争?(<code>-race</code> 输出)</li><li>锁的获取&#x2F;释放顺序对不对?(防死锁)</li><li>有没有锁重入?(Go 的 Mutex 不可重入,这是 Java 转 Go 最常踩的坑)</li><li>有没有复制 sync 原语?(<code>go vet</code> 能查,Agent 不会主动跑)</li><li>WaitGroup 计数匹不匹配?goroutine 有没有泄漏?(Go 1.26+ 运行时自动检测)</li></ul><p>这五条本身就是一份并发代码审查清单。<code>go-style-guide</code> 里也有一份并发 reference,但深度不在一个量级,<code>go-style-guide</code> 讲怎么用对,<code>chao-go-sync</code> 讲出了问题怎么查、怎么治、还有哪些更高级的替代。</p><h3 id="24-5-3-实演:两个静默-Bug,诊断框架一眼揪出"><a href="#24-5-3-实演:两个静默-Bug,诊断框架一眼揪出" class="headerlink" title="24.5.3 实演:两个静默 Bug,诊断框架一眼揪出"></a>24.5.3 实演:两个静默 Bug,诊断框架一眼揪出</h3><p>并发 Bug 最阴的地方在于不崩。喂给它两段看着没毛病的代码,让它审。</p><p>第一段,忘记 Unlock。多分支 return,有一条路径漏了 Unlock,程序不会立刻死,锁会泄漏,到某个时刻所有 goroutine 卡住:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(f *Foo)</span></span> Bar() &#123;</span><br><span class="line"> f.mu.Lock()</span><br><span class="line"> <span class="keyword">if</span> f.count &lt; <span class="number">1000</span> &#123;</span><br><span class="line"> f.count += <span class="number">3</span></span><br><span class="line"> <span class="keyword">return</span> <span class="comment">// 漏了 Unlock</span></span><br><span class="line"> &#125;</span><br><span class="line"> f.count++</span><br><span class="line"> f.mu.Unlock()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>第二段,锁重入死锁。从 Java 转来的人最容易写,Go 的 Mutex 不可重入,<code>Bar</code> 里再 <code>Lock</code> 直接死锁:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *T)</span></span> Foo() &#123;</span><br><span class="line"> t.mu.Lock()</span><br><span class="line"> <span class="keyword">defer</span> t.mu.Unlock()</span><br><span class="line"> t.Bar() <span class="comment">// Bar 内部又 Lock</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *T)</span></span> Bar() &#123;</span><br><span class="line"> t.mu.Lock() <span class="comment">// 死锁</span></span><br><span class="line"> <span class="keyword">defer</span> t.mu.Unlock()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>chao-go-sync</code> 的诊断框架对这两段走的路径不一样。第一段它先问「锁的获取&#x2F;释放配不配对」,发现 <code>Lock</code> 后有分支提前 return 却没 <code>defer Unlock</code>,直接指出该用 <code>defer</code> 兜底;第二段它走的是「有没有锁重入」那条,点明 Go Mutex 不可重入,给的解法是重构,别让 <code>Foo</code> 持着锁调 <code>Bar</code>,要么把 <code>Bar</code> 拆成不加锁的内部方法 <code>barLocked</code>,由 <code>Foo</code> 在持锁状态下调。两个 Bug 都不是 race detector 能报的(race detector 只管数据竞争),靠的是 Skill 里那份「五必查」清单的经验。这就是它比通用 Agent 多出来的一层:知道去哪几个固定位置找问题。</p><h3 id="24-5-4-性能优化与版本迁移"><a href="#24-5-4-性能优化与版本迁移" class="headerlink" title="24.5.4 性能优化与版本迁移"></a>24.5.4 性能优化与版本迁移</h3><p>诊断之外,<code>chao-go-sync</code> 还给了一份锁选择决策:什么场景该用 RWMutex 替代 Mutex,什么场景该上分片锁、sync.Map、atomic,什么场景干脆 lock-free。它也覆盖 Go 1.20 到 1.27 的 sync 包变更,比如 <code>sync.OnceValue</code>&#x2F;<code>OnceFunc</code>(1.21)、运行时 goroutine 泄漏检测(1.26)这些新东西,旧代码该不该迁移、怎么迁移。这跟 <code>/modern-go</code> 互补,<code>/modern-go</code> 管通用 API 的现代化,<code>chao-go-sync</code> 专管并发原语。</p><h2 id="24-6-go-style-guide:一份固执己见的-Go-工程契约"><a href="#24-6-go-style-guide:一份固执己见的-Go-工程契约" class="headerlink" title="24.6 go-style-guide:一份固执己见的 Go 工程契约"></a>24.6 go-style-guide:一份固执己见的 Go 工程契约</h2><p>前三个 Skill 偏「术」,现代化、性能、并发都是具体技术。<code>go-style-guide</code> 偏「道」,管的是 Go 代码的工程契约:包怎么设计、接口怎么定、错误怎么传、日志怎么打。作者是 madflojo(Benjamin Cane)。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx skills add -g -y madflojo/go-style-agent-skill</span><br></pre></td></tr></table></figure><p>它最显眼的标签是 README 里那句 &quot;Opinionated by design&quot;,刻意固执己见。它明确说,这不是通用、官方的 Go 风格指南,是个人偏好,要的是真实代码库里的一致性、可维护性和生产可用性。紧接着一句很关键:「如果你仓库已经有自己的约定,那些约定通常优先。」这一句把固执己见和尊重本地两边都顾上了,Skill 给默认值,但不覆盖既有规矩。</p><h3 id="24-6-1-十条-TL-DR"><a href="#24-6-1-十条-TL-DR" class="headerlink" title="24.6.1 十条 TL;DR"></a>24.6.1 十条 TL;DR</h3><p>Skill 用十条 TL;DR 浓缩了整套契约,挑几条最硬的。测试优先设计,先注入依赖、保持逻辑纯,再谈别的。Config 进、具体 struct 出,构造器吃 Config,显式校验和默认值。错误是契约,用 sentinel error 做持久分支判断,其余的用 <code>%w</code> 或 <code>errors.Join</code> 包裹。包要可复用,不藏全局变量、不藏默认日志、不搞意外副作用。标准库优先,第三方包必须靠「有意义、维护良好、被广泛采用」挣一席之地。accept interfaces, return structs,接口通常由消费者定义。覆盖率是信号不是证明,测边界和误用路径,别只测 happy path。声称性能提升前先 benchmark 热路径,并发代码跑 <code>-race</code>。</p><p>这些条款和 <code>chao-go-perf</code> 的「先测量再优化」、<code>chao-go-sync</code> 的并发安全说的是一回事,只是 <code>go-style-guide</code> 站在工程视角把它们串起来。</p><h3 id="24-6-2-执行协议:六步,先看仓库再动手"><a href="#24-6-2-执行协议:六步,先看仓库再动手" class="headerlink" title="24.6.2 执行协议:六步,先看仓库再动手"></a>24.6.2 执行协议:六步,先看仓库再动手</h3><p><code>go-style-guide</code> 不只是规则清单,它还有一份六步执行协议,规定 Skill 干活时的顺序:</p><ol><li>先看仓库:读现有包布局、构造器、测试、错误约定,再提新 API;</li><li>先定契约:包边界、Config 形状、返回类型、sentinel error、依赖缝隙、context&#x2F;关停预期,写代码前先定;</li><li>尽早写测试:表格驱动单测起步,输入密集的加 fuzz,性能敏感的加 benchmark;</li><li>最小可维护改动:沿用仓库既有布局,<code>main.go</code> 保持薄,没明确边界别引入新抽象;</li><li>跑收尾检查:<code>gofmt</code>&#x2F;<code>goimports</code>、相关 <code>go test</code>、并发跑 <code>-race</code>、声称性能就跑 benchmark;</li><li>验证面向人的契约:函数签名、Config 形状、错误行为、文档注释,和代码一样重要。</li></ol><p>这六步和第 16 章 agent-skills 的 Define→Plan→Build→Verify→Review→Simplify→Ship 是一个谱系,都是把资深工程师不会跳过的步骤固化成 Agent 必走的流程。配 10 份 reference(CONFIG、INTERFACES、ERRORS、LOGGING、DOCUMENTATION、LAYOUT、BENCHMARKS、TESTING、CONCURRENCY、REVIEW-CHECKLIST)按需加载,也就是第 2 章讲的渐进式信息披露。</p><h2 id="24-7-cc-skills-golang:拿数据说话的全家桶"><a href="#24-7-cc-skills-golang:拿数据说话的全家桶" class="headerlink" title="24.7 cc-skills-golang:拿数据说话的全家桶"></a>24.7 cc-skills-golang:拿数据说话的全家桶</h2><p>前四个 Skill 各管一面,<code>cc-skills-golang</code> 是把它们全做了一份、还做了交叉引用和效果评估的体系。作者 samber(samber&#x2F;lo 的作者,Go 圈老熟人),两千多 stars,是本章体量最大的项目。</p><p>它的态度写在 README 最显眼的地方:</p><blockquote><p>Bootstrapped with Claude Code by distilling my Go project commits. <strong>Edited, tested, reviewed and reworked by a human.</strong><br><strong>No AI slop here.</strong> AI-made skills are useless.</p></blockquote><p>先用 Claude Code 把自己 Go 项目的提交蒸馏成 Skill 草稿,再由人编辑、测试、审查、返工。最后那句「No AI slop here. AI-made skills are useless.」是整个项目的主张:AI 生成的 Skill 没人把关就是废纸,人审过的才是 Skill。这跟本书第 2 章 Matt Pocock 的「real engineering, not vibe coding」、第 12 章的 maker-checker 分离是一个调子。</p><h3 id="24-7-1-28-原子-Skill,交叉引用"><a href="#24-7-1-28-原子-Skill,交叉引用" class="headerlink" title="24.7.1 28+ 原子 Skill,交叉引用"></a>24.7.1 28+ 原子 Skill,交叉引用</h3><p><code>cc-skills-golang</code> 把 Go 工程拆成 28+ 个原子、可交叉引用的 Skill,分四大类加一批框架&#x2F;库 Skill:</p><table><thead><tr><th>大类</th><th>代表 Skill</th></tr></thead><tbody><tr><td>代码质量</td><td>code-style、naming、error-handling、safety、security、structs-interfaces、documentation、lint</td></tr><tr><td>架构与设计</td><td>concurrency、context、data-structures、database、dependency-injection、design-patterns、modernize</td></tr><tr><td>QA 与性能</td><td>testing、benchmark、performance、observability、troubleshooting</td></tr><tr><td>项目搭建</td><td>cli、continuous-integration、project-layout、popular-libraries、stay-updated、dependency-management</td></tr><tr><td>框架&#x2F;库</td><td>grpc、graphql、google-wire、uber-dig&#x2F;fx、spf13-cobra&#x2F;viper、samber-lo&#x2F;mo&#x2F;ro&#x2F;do&#x2F;hot&#x2F;slog&#x2F;oops、testify</td></tr></tbody></table><p>注意里面的 <code>modernize</code>、<code>performance</code>、<code>concurrency</code>、<code>code-style</code>,和前四个 Skill 的职责正面重叠。samber 的处理方式是让 Skill 之间互相引用。比如错误处理影响日志的规则,就放在 <code>error-handling</code> 里,由 <code>observability</code> 引用,不各写一份。README 特意提醒,只装一部分会得到片面、可能不一致的视图,最好整套一起装。这套「原子 Skill 加交叉引用」的做法,和第 2 章的「小而可组合」、第 16 章的「24 个 Skill 覆盖完整生命周期」思路一样,只是规模更大。</p><h3 id="24-7-2-用数据说话:Skill-到底有没有用"><a href="#24-7-2-用数据说话:Skill-到底有没有用" class="headerlink" title="24.7.2 用数据说话:Skill 到底有没有用"></a>24.7.2 用数据说话:Skill 到底有没有用</h3><p><code>cc-skills-golang</code> 有一点别的前四个 Skill 都没有:它给 Skill 跑了评估,拿出了量化效果。</p><p><img src="/images/image-20260627085843606.png"></p><p>samber 给每个 Skill 跑了一套评估(evals),对比「装了 Skill」和「没装 Skill」时 Agent 的通过率,并算出「错误率下降幅度」(Error rate gap)。先看总账:</p><table><thead><tr><th></th><th>装了 Skill</th><th>没装 Skill</th><th>差距</th></tr></thead><tbody><tr><td>总体</td><td>3315&#x2F;3395(98%)</td><td>1915&#x2F;3395(56%)</td><td><strong>+41 个百分点</strong></td></tr></tbody></table><p>装了 Skill,Agent 通过率从 56% 跳到 98%。本书前面一直在主张 Skill 有用,到这里才头一回有硬数。再看单项,挑几个降幅最猛的:</p><table><thead><tr><th>Skill</th><th>错误率下降</th></tr></thead><tbody><tr><td><code>golang-modernize</code></td><td>-61%</td></tr><tr><td><code>golang-continuous-integration</code></td><td>-59%</td></tr><tr><td><code>golang-safety</code></td><td>-58%</td></tr><tr><td><code>golang-dependency-management</code></td><td>-54%</td></tr><tr><td><code>golang-documentation</code></td><td>-53%</td></tr><tr><td><code>golang-benchmark</code></td><td>-50%</td></tr></tbody></table><p><code>modernize</code> 降 61%,<code>safety</code> 降 58%,正好对应本章 <code>/modern-go</code>(现代化)和并发安全这两个最容易出错的领域,说明这些地方最需要 Skill 兜底。框架&#x2F;库类里 <code>golang-samber-do</code>(依赖注入)最夸张,降 81%。这些数字替本书从第 1 章念到现在的「Skill 是 AI 软件工程的基石」补上了证据。</p><h3 id="24-7-3-token-预算:把渐进式信息披露做成了账"><a href="#24-7-3-token-预算:把渐进式信息披露做成了账" class="headerlink" title="24.7.3 token 预算:把渐进式信息披露做成了账"></a>24.7.3 token 预算:把渐进式信息披露做成了账</h3><p><code>cc-skills-golang</code> 还把第 2 章的渐进式信息披露做成了明账。每个 Skill 都标三档 token 权重:<code>description</code>(frontmatter 里的描述,常驻上下文,用于触发)、<code>SKILL.md</code>(触发后才加载的全文)、<code>Directory</code>(SKILL.md 加所有 reference)。比如 <code>golang-code-style</code> 是 115 &#x2F; 2069 &#x2F; 2685 token,<code>golang-security</code> 是 84 &#x2F; 3036 &#x2F; 21472 token。也就是说 security 这个 Skill 平时只占 84 token 趴在上下文里等触发,真用上了才把两万多 token 的全量知识加载进来。这比把所有规则一股脑塞进系统提示省得多。</p><h2 id="24-8-五个-Skill-怎么配合"><a href="#24-8-五个-Skill-怎么配合" class="headerlink" title="24.8 五个 Skill 怎么配合"></a>24.8 五个 Skill 怎么配合</h2><p>五个 Skill 有重叠,怎么选?给一张决策表:</p><table><thead><tr><th>你要解决的问题</th><th>首选 Skill</th><th>备选</th></tr></thead><tbody><tr><td>老代码升级到新 Go 写法</td><td><code>/modern-go</code></td><td>cc-skills-golang 的 <code>golang-modernize</code></td></tr><tr><td>代码慢、要优化</td><td><code>chao-go-perf</code></td><td>cc-skills-golang 的 <code>golang-performance</code>&#x2F;<code>benchmark</code></td></tr><tr><td>并发 Bug 或并发设计</td><td><code>chao-go-sync</code></td><td>cc-skills-golang 的 <code>golang-concurrency</code></td></tr><tr><td>包设计、接口、错误契约</td><td><code>go-style-guide</code></td><td>cc-skills-golang 的 <code>golang-code-style</code> 等</td></tr><tr><td>想要一站式、且要效果有数据</td><td><code>cc-skills-golang</code>(整套)</td><td>——</td></tr></tbody></table><p>一个务实的组合:日常拿 <code>cc-skills-golang</code> 当底座(覆盖全、有评估、交叉引用),遇到性能和并发这两个深水区,再挂上 <code>chao-go-perf</code> 和 <code>chao-go-sync</code>,这两个的深度 samber 的全家桶比不了,一个搬了 Dave Cheney 工作坊,一个搬了整本并发书。<code>/modern-go</code> 嵌在 Goal Workflow 里,做提交前的现代化体检。<code>go-style-guide</code> 适合团队对齐工程契约时当起点。</p><p>重叠不可怕。<code>cc-skills-golang</code> 的 <code>golang-modernize</code> 和 <code>/modern-go</code> 规则高度相似,但 <code>/modern-go</code> 多了「读 go.mod、版本门控」这层保护;<code>golang-performance</code> 和 <code>chao-go-perf</code> 都讲 pprof,但后者多了一整本 go-perfbook 的方法论。重叠的地方正好见高下,比较着选就行。</p><h2 id="24-9-与全书方法论的对接"><a href="#24-9-与全书方法论的对接" class="headerlink" title="24.9 与全书方法论的对接"></a>24.9 与全书方法论的对接</h2><ul><li>第 2 章 Skills:这五个 Skill 是「原子 Skill」在 Go 领域的展开。<code>cc-skills-golang</code> 的 28+ 原子 Skill 加交叉引用,是「小而可组合」的体系级样本;<code>go-style-guide</code> 的 10 份 reference 按需加载,是渐进式信息披露的典型实现。</li><li>第 8 章 Goal Workflow:<code>/modern-go</code> 是 Goal Workflow 套件的 Bonus Skill,和 <code>/refactor</code>、<code>/smell</code> 同属代码库健康维护工具链。</li><li>第 16 章 agent-skills:<code>chao-go-perf</code> 的「先测量再优化」、<code>go-style-guide</code> 的六步执行协议,都是 agent-skills 验证门禁和反合理化表的同类,把 Agent 最爱跳过的步骤(不 benchmark 就优化、不看仓库就动手)钉成必须走的流程。</li><li>第 20 章 Anthropic 官方插件:官方插件注入领域知识和工程工作流,这五个 Go Skill 是社区版的 Go 领域知识插件,把 Go 二十年的门道封装成任何 Agent Skills 兼容工具都能用的能力。</li><li>第 23 章 重构:<code>/modern-go</code> 和 <code>/refactor</code>、<code>/smell</code> 是邻居,<code>/smell</code> 扫病灶,<code>/refactor</code> 套 Fowler 手法治,<code>/modern-go</code> 管版本现代化,三者一起维护代码库健康。</li></ul><h2 id="24-10-本章小结"><a href="#24-10-本章小结" class="headerlink" title="24.10 本章小结"></a>24.10 本章小结</h2><p>Go 这门语言表面小,门道深。地道写法绑版本,并发坑静默,性能靠测量,通用 Agent 写出的 Go 经常是能跑但不地道、不安全、不快。本章五个 Skill 把 Go 二十年的资深经验编码成 Agent 能可靠复用的能力:<code>/modern-go</code> 管现代化(35 条版本门控规则),<code>chao-go-perf</code> 管性能(先测量再优化),<code>chao-go-sync</code> 管并发(从 stdlib 到 etcd),<code>go-style-guide</code> 管工程契约(固执己见但尊重本地),<code>cc-skills-golang</code> 把这几样各做一份还顺带做了评估。<code>cc-skills-golang</code> 那张「装了 Skill 98%、没装 56%」的评估表,是本书到现在最硬的一块证据,给「Skill 是 AI 软件工程的基石」这句话补了数。</p><p>第 22 章读懂代码,第 23 章改好代码,这一章用 Go 专属技能把 Go 代码写地道、写安全、写快。但这些 Skill 解决的都还是「写」和「改」,代码写完了,谁来证明它真的对?下一章的 autoreview 和 Crabbox 接的就是这一棒,一个做自动化代码审查,一个在远程沙箱里真跑一遍验证。</p>

重构:AI 时代的代码进化

2026-06-28 17:30:00

<blockquote><p>「Any fool can write code that a computer can understand. Good programmers write code that humans can understand.」<br>任何傻瓜都能写出计算机能看懂的代码。好程序员写的是人能看懂的代码。<br>—— Martin Fowler</p></blockquote><p>第 22 章解决了「人怎么读懂 AI 写的代码」,用 UML 把代码画成图。</p><p>读懂之后呢?你打开 AI 生成的代码,能跑,但是一团乱麻:一个方法三百行,一个类管了八件事,同样的逻辑复制了五遍。这时候怎么办?</p><p>重构。</p><p>这件事本身不新鲜,Martin Fowler 1999 年就把它写成了一本书。变的是执行者。以前是人对着那本书一处一处手动改,现在是 AI 对着同一本书的目录自动改,人退到后面审查 diff。</p><span id="more"></span><p><img src="/images/image-20260626094732641.png"></p><p>本章分两半。前半讲重构的理论根基:什么是重构、技术债是怎么回事、什么时候该重构、Fowler 编了哪些坏味道和手法。这部分主要参考 Fowler 的《重构》,以及把这本书做成在线可检索版本的 <a href="https://refactoring.guru/refactoring">refactoring.guru</a>。后半讲 goal workflow 套件里的两个 Skill:<code>/refactor</code>(介绍页:<a href="https://goal.rpcx.io/index_cn.html#step-refactor">https://goal.rpcx.io/index_cn.html#step-refactor</a> )把 Fowler 第 2 版的整个目录封进了一个 AI Agent 能直接调用的能力里;<code>/smell</code>(介绍页:<a href="https://goal.rpcx.io/index_cn.html#step-smell">https://goal.rpcx.io/index_cn.html#step-smell</a> )则在它前面一步,负责扫出整个代码库到底哪里有问题。一个诊断,一个治疗。</p><h2 id="23-1-什么是重构,什么是技术债"><a href="#23-1-什么是重构,什么是技术债" class="headerlink" title="23.1 什么是重构,什么是技术债"></a>23.1 什么是重构,什么是技术债</h2><p>重构(refactoring)是在不改变外部行为的前提下改善代码内部结构。说白了,把一团乱麻(dirty code)整理成清爽的代码(clean code),但程序对外的表现一字不变。</p><ul><li><strong>脏代码</strong>是经验不足,再加上 deadline、管理混乱、开发途中走捷径,几样凑一起的产物。</li><li><strong>整洁代码</strong>易读、易懂、易维护,它让开发变得可预测。你大概知道改一处要花多久,而不是每次都掉进未知的坑。</li></ul><p>代码为什么会从整洁滑向肮脏?Ward Cunningham 的<strong>技术债</strong>这个说法解释得很到位。走捷径、跳过测试,就像找银行贷款:眼下买东西是快了,但要付利息。你不光还本金,还得还利息;利息攒够了,甚至会超过你的全部收入,永远还不清。代码也一样。不写测试能暂时提速,可它每天都在拖你后腿,直到哪天你补上测试,把债还掉。</p><p><img src="/images/image-20260626095233920.png"></p><p>refactoring.guru 列了一串技术债的成因。这些在 AI 时代值得重读,因为大多被放大了:</p><ul><li><strong>业务压力</strong>:功能没做完就得上线,于是补丁和权宜之计堆上去,盖住没收尾的部分。</li><li><strong>看不到后果</strong>:管理层不知道技术债有「利息」,债越欠越多、开发越来越慢,于是舍不得给重构留时间。</li><li><strong>强耦合没人管</strong>:项目变成一块铁板而不是一堆独立模块,动一处牵全身。</li><li><strong>缺测试</strong>:没有即时反馈,人就敢用又快又险的 workaround。最坏的情况是没测试直接上线,可能给几千个客户发出一封诡异的测试邮件,也可能直接把数据库清空。</li><li><strong>缺文档、缺沟通</strong>:新人上手慢;关键的人一走,开发就停摆。</li><li><strong>长期多分支并行</strong>:隔离的改动越多,合并时积下的债越大。</li><li><strong>重构一拖再拖</strong>:需求一直变,旧代码总有显得笨重的一天;可程序员每天还在往旧代码上接新代码,所以拖得越久,将来要返工的依赖就越多。</li></ul><p>「缺测试」和「重构一拖再拖」这两条在 AI 时代尤其要命。Agent 几分钟就能吐出几千行代码,没有特征测试兜底、没有及时整理,技术债的本金和利息会以人类时代见不到的速度滚起来。第 12 章讲 GSD Core 时提过的「反合理化表」,对抗的正是「以后再重构」「先跳过测试」这类自欺。它其实就是技术债成因的制度化解药。</p><h2 id="23-2-何时重构:三次法则"><a href="#23-2-何时重构:三次法则" class="headerlink" title="23.2 何时重构:三次法则"></a>23.2 何时重构:三次法则</h2><p>Fowler 的经验法则很简洁——<strong>三次法则(Rule of Three)</strong>:</p><ol><li><strong>第一次</strong>做某件事,直接做完。</li><li><strong>第二次</strong>做类似的事,心里别扭也照旧重复一遍。</li><li><strong>第三次</strong>再碰到同类的事,开始重构。</li></ol><p>第一次重复忍着,第三次出现就动手。除此之外还有三个天然时机:</p><ul><li><strong>加功能时</strong>:重构能帮你读懂别人的代码。面对一坨脏代码,先重构再加,整洁的代码好改得多。这一改不只方便你,也方便后面接手的人。</li><li><strong>修 bug 时</strong>:bug 跟现实里的虫子一样,专挑代码最暗最脏的角落待着。把代码清干净,错误几乎会自己冒出来。</li><li><strong>代码评审时</strong>:这往往是代码公开前最后一次整理的机会。最好跟作者结对来做,简单问题当场修掉,复杂的估个时间再说。</li></ul><h2 id="23-3-如何重构:正确的姿势"><a href="#23-3-如何重构:正确的姿势" class="headerlink" title="23.3 如何重构:正确的姿势"></a>23.3 如何重构:正确的姿势</h2><p>重构是一连串小改动,每一步让代码好一点,同时让程序始终能跑。refactoring.guru 的「做对了」清单只有三条,却是整套方法论的核心:</p><ul><li><strong>代码必须变干净。</strong> 重构完还是一团乱,那这一小时就白花了。这种事多半发生在你丢掉「小步改」、把一大堆重构混进一次大改动的时候。尤其赶 deadline 的时候,很容易把自己绕晕。</li><li><strong>重构期间不写新功能。</strong> 别把重构和加特性搅在一起,至少在单个 commit 里把两件事分开。</li><li><strong>重构后所有已有测试都得过。</strong> 测试挂了只有两种可能:要么你改错了,修就是;要么你的测试太底层了,比如去测了类的私有方法,这种情况是测试的锅,该把它重写成更高层、BDD 风格的测试。</li></ul><p>记住这三条。后半 <code>/refactor</code> Skill 的安全协议,基本就是把它们逐条机械化了一遍。</p><h2 id="23-4-Fowler-的目录:坏味道与手法"><a href="#23-4-Fowler-的目录:坏味道与手法" class="headerlink" title="23.4 Fowler 的目录:坏味道与手法"></a>23.4 Fowler 的目录:坏味道与手法</h2><p>refactoring.guru 把 Fowler 书里的内容编成了两张能检索的目录:</p><ul><li>**代码坏味道(Code Smells)**是问题的征兆,好发现,但它可能只是更深层问题露出的一角。</li><li>**重构手法(Refactoring Techniques)**是具体的改法。每种手法都有得有失,所以每次重构都该有明确的动机,谨慎施用。</li></ul><p>手法分六大类:组合方法(Composing Methods)、在对象间搬移特性(Moving Features Between Objects)、组织数据(Organizing Data)、简化条件表达式(Simplifying Conditional Expressions)、简化方法调用(Simplifying Method Calls)、处理泛化关系(Dealing with Generalization)。</p><p>整个流程是「症状到处方」:你先嗅到味道,比如「过长方法」或者「Feature Envy」,目录再告诉你该用哪几种手法去治。这套映射关系明确、能机械执行,也正是 AI Agent 接得住的地方。</p><h2 id="23-5-refactor:把-Fowler-的书变成一个-Skill"><a href="#23-5-refactor:把-Fowler-的书变成一个-Skill" class="headerlink" title="23.5 &#x2F;refactor:把 Fowler 的书变成一个 Skill"></a>23.5 &#x2F;refactor:把 Fowler 的书变成一个 Skill</h2><p>理论讲完,看看 <a href="https://goal.rpcx.io/index.html">goal workflow 套件</a>里的 <code>/refactor</code> 是怎么把这本书落成一个能调用的能力的。</p><p><code>/refactor</code> 基于 Fowler《重构》第 2 版的完整目录:识别坏味道,套用验证过的手法,在不动外部行为的前提下把代码改清爽。它在 goal workflow 主闭环(第 8 章)之外,是个 Bonus 技能。安装一行就够:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx skills add smallnest/goal-workflow --skill refactor</span><br></pre></td></tr></table></figure><p>触发可以直接打 <code>/refactor</code>,也可以用自然语言或术语:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">重构:重构 UserManager 类,它太大了</span><br><span class="line">code smell:这个函数有 Feature Envy,修复它</span><br><span class="line">extract method:把这个长方法拆分成更小的函数</span><br></pre></td></tr></table></figure><h3 id="23-5-1-22-种坏味道(五大类别)"><a href="#23-5-1-22-种坏味道(五大类别)" class="headerlink" title="23.5.1 22 种坏味道(五大类别)"></a>23.5.1 22 种坏味道(五大类别)</h3><p>Skill 内置 22 种代码坏味道,按五大类组织,每种都关联到对应的重构手法:</p><table><thead><tr><th>类别</th><th>坏味道</th><th>主要重构手法</th></tr></thead><tbody><tr><td><strong>臃肿类</strong></td><td>过长方法</td><td>Extract Method, Replace Temp with Query</td></tr><tr><td></td><td>过大的类</td><td>Extract Class, Extract Subclass</td></tr><tr><td></td><td>基本类型偏执</td><td>Replace Data Value with Object</td></tr><tr><td></td><td>过长参数列表</td><td>Introduce Parameter Object</td></tr><tr><td></td><td>数据泥团</td><td>Extract Class</td></tr><tr><td><strong>OO 滥用类</strong></td><td>Switch 语句</td><td>Replace Conditional with Polymorphism</td></tr><tr><td></td><td>临时字段</td><td>Extract Class, Introduce Null Object</td></tr><tr><td></td><td>被拒绝的遗赠</td><td>Replace Inheritance with Delegation</td></tr><tr><td></td><td>异曲同工的类</td><td>Rename Method, Extract Superclass</td></tr><tr><td><strong>变更阻碍类</strong></td><td>发散式变化</td><td>Extract Class</td></tr><tr><td></td><td>霰弹式修改</td><td>Move Method, Move Field</td></tr><tr><td></td><td>平行继承体系</td><td>Move Method, Move Field</td></tr><tr><td><strong>冗余类</strong></td><td>注释(代码本应自说明)</td><td>Extract Method, Rename Variable</td></tr><tr><td></td><td>重复代码</td><td>Extract Method, Pull Up Method</td></tr><tr><td></td><td>冗赘类</td><td>Inline Class, Collapse Hierarchy</td></tr><tr><td></td><td>纯数据类</td><td>Move Method, Encapsulate Field</td></tr><tr><td></td><td>死代码</td><td>删除(Git 历史有记录)</td></tr><tr><td></td><td>夸夸其谈未来性</td><td>Inline Class, Remove Parameter</td></tr><tr><td><strong>耦合类</strong></td><td>依恋情节</td><td>Move Method</td></tr><tr><td></td><td>狎昵关系</td><td>Move Method, Move Field</td></tr><tr><td></td><td>消息链</td><td>Hide Delegate</td></tr><tr><td></td><td>中间人</td><td>Remove Middle Man</td></tr><tr><td></td><td>不完美的库类</td><td>Introduce Foreign Method</td></tr></tbody></table><h3 id="23-5-2-40-种重构手法(六大类)"><a href="#23-5-2-40-种重构手法(六大类)" class="headerlink" title="23.5.2 40+ 种重构手法(六大类)"></a>23.5.2 40+ 种重构手法(六大类)</h3><p><img src="/images/image-20260626095835777.png"></p><p>每种手法都附带机械步骤(mechanics)和 before&#x2F;after 对比示例,这正是 refactoring.guru 那张目录的 AI 可执行版:</p><table><thead><tr><th>类别</th><th>手法数</th><th>代表性手法</th></tr></thead><tbody><tr><td>组合方法</td><td>9</td><td>Extract Method, Inline Method, Extract Variable, Replace Temp with Query, Substitute Algorithm</td></tr><tr><td>移动特性</td><td>7</td><td>Move Method, Move Field, Extract Class, Inline Class, Hide Delegate</td></tr><tr><td>组织数据</td><td>13</td><td>Replace Data Value with Object, Encapsulate Field, Replace Type Code with Subclasses, Replace Magic Number</td></tr><tr><td>简化条件</td><td>8</td><td>Decompose Conditional, Guard Clauses, Replace Conditional with Polymorphism, Introduce Null Object</td></tr><tr><td>方法调用</td><td>13</td><td>Rename Method, Separate Query from Modifier, Introduce Parameter Object, Replace Error Code with Exception</td></tr><tr><td>泛化</td><td>9</td><td>Pull Up Method, Push Down Method, Extract Interface, Form Template Method, Replace Inheritance with Delegation</td></tr></tbody></table><h3 id="23-5-3-五阶段安全协议:把「做对了」清单制度化"><a href="#23-5-3-五阶段安全协议:把「做对了」清单制度化" class="headerlink" title="23.5.3 五阶段安全协议:把「做对了」清单制度化"></a>23.5.3 五阶段安全协议:把「做对了」清单制度化</h3><p><code>/refactor</code> 真正关键的设计不是目录,而是<strong>安全协议</strong>。它把 23.3 节那三条清单变成了 Agent 必须照办的执行护栏:</p><ul><li><strong>准备阶段</strong>:写特征测试(characterization test),提交当前状态,开一个重构分支。</li><li><strong>每一步</strong>:一次只改一处,编译过,测试全过,提交。</li><li><strong>验证阶段</strong>:测试全过,手动冒烟测一遍,自己审 diff,最后提交。</li><li><strong>铁律</strong>:不动外部行为,不夹带功能改动,每一步都有测试兜底。</li></ul><p>对着 Fowler 的三条清单看,正好一一对上:「代码必须变干净」对应自审 diff,「不写新功能」对应不夹带功能改动,「测试必须全过」对应每步测试加特征测试兜底。</p><p>AI 时代的价值就在这。人在 deadline 底下,难免偷偷给自己找台阶,「这块以后再重构」「这次先跳过测试」。Agent 被钉死在协议上,没这个空子可钻。重构的纪律,从「靠人自觉」变成了「靠机器强制」。</p><h3 id="23-5-4-语言专属指南"><a href="#23-5-4-语言专属指南" class="headerlink" title="23.5.4 语言专属指南"></a>23.5.4 语言专属指南</h3><p>Skill 还针对主流语言给出特化建议:</p><table><thead><tr><th>语言</th><th>核心建议</th></tr></thead><tbody><tr><td>Java</td><td>final 局部变量、IDE 自动重构、Records、Sealed Classes</td></tr><tr><td>TypeScript</td><td>解构减少参数、const 优先、Union Types 替代类型码、<code>?.</code> 消除 null 检查</td></tr><tr><td>Python</td><td>Type Hints、dataclasses、<code>@property</code>、Context Managers</td></tr><tr><td>Go</td><td>小接口、命名返回值、表格驱动测试、early returns 消除嵌套</td></tr><tr><td>Rust</td><td>Result&#x2F;Option 替代错误码和 null、Pattern Matching、From trait、Derive macros</td></tr></tbody></table><h3 id="23-5-5-在工作流中的位置"><a href="#23-5-5-在工作流中的位置" class="headerlink" title="23.5.5 在工作流中的位置"></a>23.5.5 在工作流中的位置</h3><p><code>/refactor</code> 不单干,它跟两个邻居配合,其中最重要的是下一节要单独讲的 <code>/smell</code>;另外 <code>/modern-go</code>(35+ 条 gofix 风格规则)跟它一样,都是用来保持代码库健康的工具。还有 <code>/review-it</code>——它的审查原则里写得很清楚:「Reject noise,拒绝不切实际的边界情况、投机性风险、过度重构」。这跟 <code>/refactor</code> 安全协议里「小修复优先」是一个意思——重构不是越多越好,闻到坏味道才动手。</p><h2 id="23-6-smell:先诊断,再开刀"><a href="#23-6-smell:先诊断,再开刀" class="headerlink" title="23.6 &#x2F;smell:先诊断,再开刀"></a>23.6 &#x2F;smell:先诊断,再开刀</h2><p><code>/refactor</code> 解决的是&quot;知道哪里该改、怎么改&quot;。但更常见的困境在前一步:面对一个 AI 攒出来的几万行代码库,你不知道该从哪下手。哪个模块烂得最厉害?是架构错了,还是只有某个函数太长?先动哪块?</p><p><code>/smell</code> 回答的就是这个。它跟 <code>/refactor</code> 同级,分工是:<code>/smell</code> 诊断,扫出代码库的病灶并排优先级;<code>/refactor</code> 治疗,照 Fowler 手法一处处修。一个出报告,一个动手术。</p><p>安装:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx skills add smallnest/goal-workflow --skill smell</span><br></pre></td></tr></table></figure><p>触发同样可以直接打 <code>/smell</code>,或用自然语言:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">代码坏味道检测:找出代码坏味道</span><br><span class="line">架构审计:检测架构反模式</span><br><span class="line">复杂度扫描:分析代码复杂度</span><br></pre></td></tr></table></figure><h3 id="23-6-1-比-Fowler-更宽的视野:8-大类-50-坏味道"><a href="#23-6-1-比-Fowler-更宽的视野:8-大类-50-坏味道" class="headerlink" title="23.6.1 比 Fowler 更宽的视野:8 大类 50+ 坏味道"></a>23.6.1 比 Fowler 更宽的视野:8 大类 50+ 坏味道</h3><p>这里要留意 <code>/smell</code> 和 <code>/refactor</code> 在覆盖面上的区别。<code>/refactor</code> 盯的是 Fowler 那 22 种坏味道,基本都在函数和类这个尺度。<code>/smell</code> 往上抬了一层,把架构和复杂度也算进来,一共 8 大类、50+ 种:</p><table><thead><tr><th>类别</th><th>示例</th></tr></thead><tbody><tr><td>架构</td><td>大泥球、分布式单体、贫血模型、CQRS 滥用、层边界违反</td></tr><tr><td>耦合</td><td>循环依赖、内容耦合、公共耦合(全局状态)、印记耦合</td></tr><tr><td>内聚</td><td>上帝对象、霰弹式修改、依恋情结、数据泥团</td></tr><tr><td>设计</td><td>抽象泄露、静态粘连、服务定位器滥用、SOLID 违反</td></tr><tr><td>代码</td><td>重复代码、长方法、基本类型偏执、魔数、死代码</td></tr><tr><td>测试</td><td>零测试覆盖、测试-实现耦合、不稳定测试</td></tr><tr><td>命名</td><td>模糊命名、命名不一致</td></tr><tr><td>复杂度</td><td>嵌套循环 (O(n²))、N+1 查询、重复线性扫描、循环内排序、渲染重复计算</td></tr></tbody></table><p>最后两类,「测试」和「复杂度」,是 Fowler 的坏味道目录里没有的,而它们在 AI 时代恰好用得上。AI 生成的代码经常零测试覆盖,也经常埋着 N+1 查询、循环内排序这类一眼看不出、上了量才爆的性能坑。这些 <code>/smell</code> 能一并扫出来。</p><h3 id="23-6-2-输出:一份带优先级的重构路线图"><a href="#23-6-2-输出:一份带优先级的重构路线图" class="headerlink" title="23.6.2 输出:一份带优先级的重构路线图"></a>23.6.2 输出:一份带优先级的重构路线图</h3><p><code>/smell</code> 不只是列问题,它产出一份结构化的 Markdown 报告:</p><ul><li>执行摘要和整体健康评估</li><li>检测到的架构风格,对比它&quot;应该是&quot;的风格</li><li>按严重级别分类的发现:严重 &#x2F; 警告 &#x2F; 建议</li><li>依赖图分析和模块健康评分卡</li><li>8 大类坏味道的分布统计</li><li>一份重构路线图,分成「立即可做 &#x2F; 短期 &#x2F; 长期」</li></ul><p>最有价值的是最后那份路线图。它直接回答了开头那个问题:该先动哪块。你可以让它只跑「仅严重」模式做快速体检,也可以把范围缩到某个模块,或者只扫最近改动的文件。</p><h3 id="23-6-3-两个-Skill-怎么配合"><a href="#23-6-3-两个-Skill-怎么配合" class="headerlink" title="23.6.3 两个 Skill 怎么配合"></a>23.6.3 两个 Skill 怎么配合</h3><p><img src="/images/image-20260626100640873.png"></p><p>把 <code>/smell</code> 和 <code>/refactor</code> 串起来,就是一条完整的&quot;健康维护&quot;链路:</p><ol><li><strong><code>/smell</code> 出报告</strong>:定位病灶,排好优先级,知道先改哪、后改哪。</li><li><strong><code>/refactor</code> 逐条施工</strong>:针对报告里的具体坏味道,套 Fowler 手法,走五阶段安全协议,每步提交。</li><li>改完再跑一遍 <code>/smell</code>,看健康评分有没有真的涨上去。</li></ol><p>这正好呼应了 23.3 节那条铁律,「代码必须变干净」。<code>/smell</code> 的健康评分让&quot;变干净&quot;这件事从主观感受变成了可量化的前后对比:重构前一个分,重构后一个分,涨了才算没白干。</p><h2 id="23-7-小结"><a href="#23-7-小结" class="headerlink" title="23.7 小结"></a>23.7 小结</h2><p>重构的方法论二十年没怎么变:嗅坏味道、对着手法目录、小步施工、每步测试、不夹带功能。AI 时代变的只有一件事,把 Fowler 那本书从「人读的参考书」变成了「Agent 执行的 Skill」,再用安全协议把人最容易偷的懒,改成机器必须遵守的护栏。goal workflow 把这件事拆成两个 Skill:<code>/smell</code> 诊断,扫出整个代码库的病灶并排好优先级;<code>/refactor</code> 治疗,照着 Fowler 手法一处处修。先体检,再开刀,改完再体检,这就是 AI 时代维护代码库健康的闭环。</p><p>第 22 章用 UML 让你读懂 AI 写的代码,这一章用重构让你改好 AI 写的代码。读懂是前提,改好是落点。两件事合起来,才是「你可以外包思考,但不能外包理解」这句话在工程上真正站住脚的样子。</p>

UML 新用途:让 AI 理解你生成的代码

2026-06-28 17:00:00

<blockquote><p>「A picture is worth a thousand words. A diagram is worth ten thousand lines of code.」<br>一图胜千言。一张图胜万行代码。</p></blockquote><p>第 13 章解决了一个问题:AI 写代码容易,读代码难。Understand-Anything 用知识图谱<strong>让 AI 理解现有代码</strong>。</p><p>反过来——代码写完了,作为人类<strong>你怎么理解它</strong>?毕竟,线上出了故障你还等着你背锅呢。</p><p>我前一段看到一句箴言:&quot;𝐲𝐨𝐮 𝐜𝐚𝐧 𝐨𝐮𝐭𝐬𝐨𝐮𝐫𝐜𝐞 𝐲𝐨𝐮𝐫 𝐭𝐡𝐢𝐧𝐤𝐢𝐧𝐠, 𝐛𝐮𝐭 𝐲𝐨𝐮 𝐜𝐚𝐧𝐧𝐨𝐭 𝐨𝐮𝐭𝐬𝐨𝐮𝐫𝐜𝐞 𝐲𝐨𝐮𝐫 𝐮𝐧𝐝𝐞𝐫𝐬𝐭𝐚𝐧𝐝𝐢𝐧𝐠&quot;, 翻译过来就是&quot;你可以外包你的思考(给AI),但是你不能外包你的理解&quot;。 这句话被 Andrej Karpathy 多次引用,以至于大家认为是他说的,其实是kache说的:</p><p><img src="/images/image-20260604094614868.png"></p><p>这句话非常有哲理。Dex Horthy 在 2025 AI Engineer 大会上独立提出了:&quot;Don&#39;t outsource the thinking&quot; &#x2F; &quot;AI cannot replace thinking, it can only amplify the thinking you have done.&quot;,但是今年你看, AI已经外包了我们的思考,你只需说出的你需求,智能体就能帮助你生生成你要的程序,但是 AI 没有办法帮我们理解啊。</p><p>我最近就遇到了这样的困惑:我通过goal workflow很快的实现了一个大模型训推任务智能诊断系统,全是AI帮我生成的,但是在联调的前一个星期,我心虚了。</p><p>因为我知道,联调和上线的时候,必然有一些问题,比如当时的设计有些模糊的地方,设计上有gap, 实现上也难免有bug。如果我对生成的代码不熟悉,联调的时候出故障我都不知道啥原因咋修复,可能当时还得重新捋代码才能慢慢找根因,太影响联调的同学了。未来上线以后出现问题,想快速修复就更不可能了。</p><p>所以我专门花了两天时间,建了几个卡片,就为了学习代码理解代码。</p><p>那我是通过什么方式去理解AI生成的代码的呢?</p><p>答案藏在一个用了二十多年的老工具里:UML。区别只有一点:以前的 UML 是人画给团队的,现在是 AI 画给你的。十四种图,从类结构到部署拓扑,从序列交互到状态变迁。AI 生成代码,AI 再画图解释代码——你读图就够了。</p><p>为此,我专门创建了一个Skill,用来生成UML的十四种代码和架构图、流程图以及泳道图。此skill的介绍:<a href="https://goal.rpcx.io/index_cn.html#step-diagram%EF%BC%8C">https://goal.rpcx.io/index_cn.html#step-diagram,</a> 也集成到了goal workflow套件中了。</p><p>本章分两部分:第一部分过一遍 UML 十四种正式图形,外加三种 UML 规范没有但实际很常用的图。第二部分介绍 insight-diagram——一个在 goal.rpcx.io 上发布的 Skill,给任意代码库自动生成全套 UML 图、架构图和流程图。</p><span id="more"></span><h2 id="14-1-UML-简史:从三剑客到-OMG-标准"><a href="#14-1-UML-简史:从三剑客到-OMG-标准" class="headerlink" title="14.1 UML 简史:从三剑客到 OMG 标准"></a>14.1 UML 简史:从三剑客到 OMG 标准</h2><p>1994 年,Grady Booch 和 Jim Rumbaugh 在 Rational Software 相遇。Booch 有他的 Booch Method,Rumbaugh 有他的 OMT(Object Modeling Technique)。两种方法符号体系不同,画出来的图互不认识。</p><p>1995 年,Ivar Jacobson 加入,带来他的 OOSE(Object-Oriented Software Engineering)方法。三人被称为「三剑客」(Three Amigos),目标:统一面向对象建模的符号体系,让所有软件工程师用同一套语言画图。</p><p>1997 年,OMG(Object Management Group)采纳 UML 1.0。2005 年,UML 2.0 图形种类从 9 种扩展到 13 种。最新版本 UML 2.5.1(2017 年)定义了 14 种图,分为两大类:</p><ul><li><strong>结构性图形(Structure Diagrams)</strong>:描述系统的静态结构——有哪些组件、怎么组织的。</li><li><strong>行为性图形(Behavior Diagrams)</strong>:描述系统的动态行为——怎么运行、怎么交互。</li></ul><p>AI 时代之前,UML 的命运比较尴尬。敏捷宣言之后,很多人觉得「重文档轻代码」不靠谱,UML 跟着被冷落了。但有一个事实没变:代码由 AI 大量生成之后,人类比以往更需要可视化理解工具。UML 重新有了用武之地——角色从「先画图再写代码」的前置仪式,变成了「AI 写代码,你读图」的后置理解工具。</p><h2 id="14-2-结构性图形(Structure-Diagrams):系统长什么样"><a href="#14-2-结构性图形(Structure-Diagrams):系统长什么样" class="headerlink" title="14.2 结构性图形(Structure Diagrams):系统长什么样"></a>14.2 结构性图形(Structure Diagrams):系统长什么样</h2><p>结构性图形回答「系统由什么组成」——类、对象、组件、包、部署节点。它们是系统的静态 X 光片。</p><h3 id="14-2-1-类图(Class-Diagram)"><a href="#14-2-1-类图(Class-Diagram)" class="headerlink" title="14.2.1 类图(Class Diagram)"></a>14.2.1 类图(Class Diagram)</h3><p>最常用的 UML 图。展示系统中的类、接口、协作以及它们之间的关系。</p><p><strong>画什么:</strong></p><ul><li>类名、属性、方法——每个类一个矩形框,分成三格</li><li>关系类型:泛化(继承,空心三角箭头)、实现(虚线空心三角)、关联(实线)、聚合(空心菱形,整体-部分弱关系)、组合(实心菱形,整体-部分强关系,同生命周期)、依赖(虚线箭头)</li></ul><p><strong>什么时候用:</strong> 看项目的领域模型。agent-wrapper 项目的 <code>Agent</code>、<code>Task</code>、<code>Tool</code>、<code>Message</code> 等核心类型及其继承和组合关系。</p><p><strong>AI 时代的价值:</strong> AI 生成 50 个类之后,类图让你一眼看清谁继承了谁、谁组合了谁——不用在 50 个文件之间反复横跳。</p><h3 id="14-2-2-对象图(Object-Diagram)"><a href="#14-2-2-对象图(Object-Diagram)" class="headerlink" title="14.2.2 对象图(Object Diagram)"></a>14.2.2 对象图(Object Diagram)</h3><p>类图的运行时快照。展示特定时刻的对象实例及其属性值和链接关系。</p><p><strong>画什么:</strong></p><ul><li>对象名:类名(加下划线标注)、属性的具体值、实例间的链接</li><li>比如 <code>agent1: Agent { name=&quot;code-generator&quot;, model=&quot;claude-4&quot; }</code> 连接到 <code>task42: Task { status=&quot;running&quot; }</code></li></ul><p><strong>什么时候用:</strong> 调试时的内存快照。复杂对象图在某个时刻的状态——帮助看清递归结构、循环引用、单例模式的具体实例分布。</p><h3 id="14-2-3-组件图(Component-Diagram)"><a href="#14-2-3-组件图(Component-Diagram)" class="headerlink" title="14.2.3 组件图(Component Diagram)"></a>14.2.3 组件图(Component Diagram)</h3><p>比类图高一层——展示软件架构中可替换的模块化组件及其接口。</p><p><strong>画什么:</strong></p><ul><li>组件(矩形,带 <code>&lt;&lt;component&gt;&gt;</code> 标识)、提供的接口(棒棒糖符号)、需要的接口(插座符号)</li><li>组件间通过接口的依赖关系</li></ul><p><strong>什么时候用:</strong> 理解微服务架构或模块化系统中组件之间的契约关系。agent-wrapper 中 <code>LLM Provider</code> 组件提供 <code>chat()</code> 接口,<code>Agent Runtime</code> 组件消费这个接口。</p><h3 id="14-2-4-部署图(Deployment-Diagram)"><a href="#14-2-4-部署图(Deployment-Diagram)" class="headerlink" title="14.2.4 部署图(Deployment Diagram)"></a>14.2.4 部署图(Deployment Diagram)</h3><p>把软件映射到硬件。展示运行时处理节点及驻留在节点上的构件。</p><p><strong>画什么:</strong></p><ul><li>节点(三维立方体):服务器、容器、设备</li><li>构件(矩形):部署在节点上的软件模块</li><li>通信路径:节点间的网络连接,可标注协议(HTTP&#x2F;REST、gRPC、消息队列)</li></ul><p><strong>什么时候用:</strong> 理解生产环境的物理拓扑。agent-wrapper 的部署:User&#39;s Machine 节点运行 CLI,Cloud VM 节点运行 Agent Runtime,外部节点 Anthropic API。</p><h3 id="14-2-5-包图(Package-Diagram)"><a href="#14-2-5-包图(Package-Diagram)" class="headerlink" title="14.2.5 包图(Package Diagram)"></a>14.2.5 包图(Package Diagram)</h3><p>按逻辑分组组织模型元素。包可以嵌套,包之间有依赖和导入关系。</p><p><strong>画什么:</strong></p><ul><li>包(文件夹图标或带标签的矩形框)、包间的依赖箭头、包的嵌套层次</li><li>体现分层架构:<code>domain/</code> → <code>application/</code> → <code>infrastructure/</code> → <code>presentation/</code></li></ul><p><strong>什么时候用:</strong> 大项目的模块组织概览。agent-wrapper 中 <code>core/</code> 包、<code>tools/</code> 包、<code>plugins/</code> 包、<code>cli/</code> 包的依赖方向。</p><h3 id="14-2-6-复合结构图(Composite-Structure-Diagram)"><a href="#14-2-6-复合结构图(Composite-Structure-Diagram)" class="headerlink" title="14.2.6 复合结构图(Composite Structure Diagram)"></a>14.2.6 复合结构图(Composite Structure Diagram)</h3><p>深入一个类的内部。展示类的部件(Part)、端口(Port)、连接器(Connector)以及它们之间的协作。</p><p><strong>画什么:</strong></p><ul><li>部件(类内部的组件实例)、端口(小方块,部件与外界的交互点)、连接器(部件间的连线)</li><li>比类图更微观——类图展示「哪些类」,复合结构图展示「这个类内部由哪些部分构成」</li></ul><p><strong>什么时候用:</strong> 理解复杂模式(如 Observer、Visitor)的运行时内部结构。agent-wrapper 中 <code>AgentLoop</code> 类的内部:<code>Planner</code> 部件 → <code>Executor</code> 部件 → <code>Verifier</code> 部件,通过端口相互连接。</p><h3 id="14-2-7-剖面图(Profile-Diagram)"><a href="#14-2-7-剖面图(Profile-Diagram)" class="headerlink" title="14.2.7 剖面图(Profile Diagram)"></a>14.2.7 剖面图(Profile Diagram)</h3><p>UML 的扩展机制。定义特定领域或平台的方言——自定义构造型(Stereotype)、标签值(Tagged Value)、约束(Constraint)。</p><p><strong>画什么:</strong></p><ul><li><code>&lt;&lt;stereotype&gt;&gt;</code> 定义、用构造型标注的元类扩展</li><li>比如定义一个 <code>&lt;&lt;microservice&gt;&gt;</code> 构造型,标注 <code>language</code>、<code>port</code>、<code>healthCheck</code> 等标签值</li></ul><p><strong>什么时候用:</strong> 当 UML 需要说团队自己的术语时。agent-wrapper 项目可以定义 <code>&lt;&lt;skill&gt;&gt;</code>、<code>&lt;&lt;tool&gt;&gt;</code>、<code>&lt;&lt;hook&gt;&gt;</code> 等自定义构造型。</p><h2 id="14-3-行为性图形(Behavior-Diagrams):系统怎么运行"><a href="#14-3-行为性图形(Behavior-Diagrams):系统怎么运行" class="headerlink" title="14.3 行为性图形(Behavior Diagrams):系统怎么运行"></a>14.3 行为性图形(Behavior Diagrams):系统怎么运行</h2><p>行为性图形回答「系统怎么工作」——流程、交互、状态变迁。它们是系统的动态录像。</p><h3 id="14-3-1-用例图(Use-Case-Diagram)"><a href="#14-3-1-用例图(Use-Case-Diagram)" class="headerlink" title="14.3.1 用例图(Use Case Diagram)"></a>14.3.1 用例图(Use Case Diagram)</h3><p>从用户视角展示系统能做什么。外行最容易看懂的 UML 图。</p><p><strong>画什么:</strong></p><ul><li>参与者(火柴人图标):人、外部系统、定时器</li><li>用例(椭圆):系统提供的功能</li><li>关系:<code>&lt;&lt;include&gt;&gt;</code>(必须包含)、<code>&lt;&lt;extend&gt;&gt;</code>(可选扩展)、泛化(参与者或用例的继承)</li></ul><p><strong>什么时候用:</strong> 和产品经理对齐需求。agent-wrapper 的用例:用户 → 「创建 Agent」、用户 → 「配置 Skill」、用户 → 「启动自主循环」、外部 API → 「响应 Tool Call」。</p><h3 id="14-3-2-活动图(Activity-Diagram)"><a href="#14-3-2-活动图(Activity-Diagram)" class="headerlink" title="14.3.2 活动图(Activity Diagram)"></a>14.3.2 活动图(Activity Diagram)</h3><p>增强版流程图。展示从活动到活动的控制流,支持并发分支和合并。</p><p><strong>画什么:</strong></p><ul><li>活动节点(圆角矩形)、决策节点(菱形)、fork&#x2F;join(粗横线)、泳道(可选)</li><li>开始节点(实心圆)→ 活动序列 → 结束节点(实心圆+外圈)</li></ul><p><strong>什么时候用:</strong> 描述一个流程的多分支执行路径。agent-wrapper 中 Goal 命令的执行流程:解析 Goal → 生成 Plan → fork(并行执行 Sub-goals)→ join(汇总结果)→ 验证 → 输出。</p><h3 id="14-3-3-状态机图(State-Machine-Diagram)"><a href="#14-3-3-状态机图(State-Machine-Diagram)" class="headerlink" title="14.3.3 状态机图(State Machine Diagram)"></a>14.3.3 状态机图(State Machine Diagram)</h3><p>跟踪一个对象从生到死的完整生命周期——中间经历了哪些状态,什么事件触发了状态变迁。</p><p><strong>画什么:</strong></p><ul><li>状态(圆角矩形,可包含 entry&#x2F;do&#x2F;exit 动作)、转移(箭头上标注「事件[守卫]&#x2F;动作」)</li><li>初始伪状态(实心圆)、终止状态(实心圆+外圈)</li></ul><p><strong>什么时候用:</strong> 理解有复杂生命周期的对象。agent-wrapper 中 <code>Task</code> 对象的状态机:pending → queued → running → (completed | failed | cancelled),每个转移上标注触发事件。</p><h3 id="14-3-4-序列图(Sequence-Diagram)"><a href="#14-3-4-序列图(Sequence-Diagram)" class="headerlink" title="14.3.4 序列图(Sequence Diagram)"></a>14.3.4 序列图(Sequence Diagram)</h3><p>最常用的交互图。按时间顺序展示对象间的消息交换——谁先调谁、传什么参数、返回什么。</p><p><strong>画什么:</strong></p><ul><li>生命线(纵向虚线,代表对象的时间线)、激活条(生命线上的矩形,代表对象正在执行)</li><li>消息(水平箭头):同步调用(实心箭头)、异步消息(开放箭头)、返回(虚线箭头)</li></ul><p><strong>什么时候用:</strong> 理解一个具体场景的完整调用链。agent-wrapper 中「创建并运行一个 Agent」的完整交互序列:CLI → AgentFactory.create() → Agent.run() → LLMProvider.chat() → ToolRegistry.execute() → 返回结果 → CLI 输出。</p><h3 id="14-3-5-通信图(Communication-Diagram)"><a href="#14-3-5-通信图(Communication-Diagram)" class="headerlink" title="14.3.5 通信图(Communication Diagram)"></a>14.3.5 通信图(Communication Diagram)</h3><p>和序列图共享同一批信息,视角不同。序列图强调时间顺序(从上到下),通信图强调对象间的组织关系(空间布局)。</p><p><strong>画什么:</strong></p><ul><li>对象(矩形节点)、链接(对象间的连线)、消息(连线上标注序号和箭头方向)</li><li>消息编号(1, 2, 3...)表示时间顺序,嵌套用 1.1, 1.2...</li></ul><p><strong>什么时候用:</strong> 关注「在某个时刻,哪些对象在互相通信」时——对象间的链接结构成为重点,时间线退居次要。</p><h3 id="14-3-6-定时图(Timing-Diagram)"><a href="#14-3-6-定时图(Timing-Diagram)" class="headerlink" title="14.3.6 定时图(Timing Diagram)"></a>14.3.6 定时图(Timing Diagram)</h3><p>展示对象状态随时间的变化曲线,含精确的时间约束。</p><p><strong>画什么:</strong></p><ul><li>时间轴(横向,精确刻度)、状态线(折线,展示每个对象的状态变化)、持续时间约束 <code>{duration &lt; 500ms}</code></li><li>适合实时系统、嵌入式系统和性能关键路径</li></ul><p><strong>什么时候用:</strong> 性能分析和实时约束验证。agent-wrapper 中 Tool Call 的超时机制:<code>execute_tool()</code> 必须在 30s 内完成,否则触发重试——定时图展示这四个阶段的时间约束。</p><h3 id="14-3-7-交互概览图(Interaction-Overview-Diagram)"><a href="#14-3-7-交互概览图(Interaction-Overview-Diagram)" class="headerlink" title="14.3.7 交互概览图(Interaction Overview Diagram)"></a>14.3.7 交互概览图(Interaction Overview Diagram)</h3><p>活动图和序列图的混合体。用活动图的控制流框架,每个节点可以嵌入一个交互片段(序列图、通信图、定时图或其他交互概览图)。</p><p><strong>画什么:</strong></p><ul><li>框架是活动图(决策节点、fork&#x2F;join、开始&#x2F;结束)</li><li>节点内部嵌入 <code>sd</code>(序列图)等交互片段</li></ul><p><strong>什么时候用:</strong> 复杂流程的宏观概览——不展示每次函数调用的细节,而是展示「这个流程分几大阶段,每个阶段内部发生了什么交互」。agent-wrapper 完整运行流程:初始化(序列图)→ 规划(序列图)→ 执行循环(交互概览图)→ 完成(序列图)。</p><h2 id="14-4-超越-UML:三种实用的非-UML-图"><a href="#14-4-超越-UML:三种实用的非-UML-图" class="headerlink" title="14.4 超越 UML:三种实用的非 UML 图"></a>14.4 超越 UML:三种实用的非 UML 图</h2><p>上面 14 种是 UML 2.5 标准定义的。真实软件工程中,有三种图不在 UML 规范里,但使用频率比很多 UML 图更高。</p><h3 id="14-4-1-系统架构图(Architecture-Diagram)"><a href="#14-4-1-系统架构图(Architecture-Diagram)" class="headerlink" title="14.4.1 系统架构图(Architecture Diagram)"></a>14.4.1 系统架构图(Architecture Diagram)</h3><p>比组件图更自由。展示系统的顶层组件、外部依赖以及数据流方向。不遵守 UML 严格的符号约束——方块、圆圈、数据库图标、云图标都可以用,含义清晰即可。</p><p><strong>什么时候用:</strong> 任何项目的第一个图。项目经理、新成员、外部评审者——所有人都从架构图开始理解系统。</p><h3 id="14-4-2-流程图(Flowchart)"><a href="#14-4-2-流程图(Flowchart)" class="headerlink" title="14.4.2 流程图(Flowchart)"></a>14.4.2 流程图(Flowchart)</h3><p>比活动图更简单。没有 fork&#x2F;join 的并发语义,没有泳道的组织维度——只有开始、结束、处理步骤、判断分支。它就是画在白板上的那种图。</p><p><strong>什么时候用:</strong> 描述算法逻辑、业务流程或决策树。不追求 UML 的完备语义,追求最大可读性。</p><h3 id="14-4-3-泳道图(Swimlane-Diagram)"><a href="#14-4-3-泳道图(Swimlane-Diagram)" class="headerlink" title="14.4.3 泳道图(Swimlane Diagram)"></a>14.4.3 泳道图(Swimlane Diagram)</h3><p>流程图 + 角色分工。把流程步骤按「谁负责」分配到不同的泳道里,跨泳道的箭头表示交互和交接。</p><p><strong>什么时候用:</strong> 跨团队协作流程。agent-wrapper 中用户、Agent Runtime、LLM Provider、Tool Registry 四个泳道的完整交互流程。</p><h2 id="14-5-UML-在-AI-时代的三个用途"><a href="#14-5-UML-在-AI-时代的三个用途" class="headerlink" title="14.5 UML 在 AI 时代的三个用途"></a>14.5 UML 在 AI 时代的三个用途</h2><p>AI 生成代码之后,UML 的角色从「前置设计工具」变成了「后置理解工具」。三个具体用途:</p><p><strong>用途一:代码理解的可视化层。</strong> 第 13 章的 Understand-Anything 产出知识图谱——文件、函数、类的节点和边。UML 把这些节点组织成有意义的模式——类图把散落的类型组织成领域模型,序列图把函数调用链组织成交互故事。知识图谱是原材料,UML 是成品。</p><p><strong>用途二:AI 生成代码的质量验证。</strong> AI 生成了 2000 行代码。你怎么知道架构没被写烂?生成一张类图——继承链有没有循环引用一目了然。生成一张包图——依赖方向有没有违反 Clean Architecture 的箭头规则。UML 就是 AI 代码的架构 X 光。</p><p><strong>用途三:团队沟通的通用语言。</strong> 不同的人看同一段 AI 代码,脑子里画的图可能完全不一样。UML 给了一套标准化的可视化符号,所有人坐下来看同一张图,对「这段代码长什么样」的理解不会差太远。</p><h2 id="14-6-insight-diagram:一键生成全套-UML-图的-Skill"><a href="#14-6-insight-diagram:一键生成全套-UML-图的-Skill" class="headerlink" title="14.6 insight-diagram:一键生成全套 UML 图的 Skill"></a>14.6 insight-diagram:一键生成全套 UML 图的 Skill</h2><p>前面聊了 17 种图。一个中等规模的项目,手工画完,单位是天。</p><p>insight-diagram 在 <a href="https://goal.rpcx.io/index_cn.html#step-diagram">goal.rpcx.io</a> 上发布,给任意代码库自动生成全套 UML 图、架构图和流程图。不需要你懂 UML——告诉它项目在哪,它分析代码库、让你选图表类型,然后一张张生成。</p><p><img src="/images/image-20260604090531683.png"></p><h3 id="14-6-1-核心理念:代码分析-→-图表选择-→-逐个生成"><a href="#14-6-1-核心理念:代码分析-→-图表选择-→-逐个生成" class="headerlink" title="14.6.1 核心理念:代码分析 → 图表选择 → 逐个生成"></a>14.6.1 核心理念:代码分析 → 图表选择 → 逐个生成</h3><p>四个步骤:</p><p><strong>步骤 1 — 分析代码库。</strong> Skill 读取项目的 <code>CLAUDE.md</code>(项目概览)、各子目录的 <code>CLAUDE.md</code>(模块细节),用 Glob 扫描源码文件结构,用 Grep 搜索关键模式(接口定义、函数签名、依赖注入)。提炼出组件清单、依赖关系图、核心类型、业务流程和部署拓扑。</p><p><strong>步骤 2 — 选择图表。</strong> 多选菜单,17 种图表分四组展示:结构性图形(类图、对象图、组件图、部署图、包图、复合结构图、剖面图)、行为性图形(用例图、活动图、状态机图)、交互图(序列图、通信图、定时图、交互概览图)、实用非 UML(系统架构图、流程图、泳道图)。默认推荐:architecture + sequence + flowchart。</p><p><strong>步骤 3 — 逐个生成。</strong> 每个图表的生成流程:</p><ol><li><strong>先读示例。</strong> Skill 内置 13 个示例 HTML 文件,每种图表类型一个。生成前从示例中提取布局策略(节点间距、分组方式、箭头走向)、节点样式层级(核心节点高亮、普通节点实线边框、可选节点虚线边框)、标注风格(阶段标签、Legend 图例、卡片摘要)和信息密度。</li><li><strong>整理元素和关系。</strong> 根据步骤 1 的分析结果,确定元素和关系。类图:10-15 个核心类型。序列图:2-5 个核心交互场景。每个图有明确关注重点,不追求全量覆盖。</li><li><strong>调用 architecture-diagram skill 渲染。</strong> 使用 Anthropic Claude 视觉风格(暖白背景 <code>#FAF9F6</code>、terracotta&#x2F;sage&#x2F;plum&#x2F;rose 配色、Inter 字体),输出 HTML+SVG。所有元素不得遮盖——箭头在节点下方、间距充足(垂直 ≥40px,水平 ≥30px)、文字不溢出。元素过多则拆分子图或缩小元素。</li><li><strong>保存到 <code>docs/</code> 目录。</strong> 文件命名如 <code>docs/architecture.html</code>、<code>docs/class.html</code>、<code>docs/sequence.html</code>。</li></ol><p><strong>步骤 4 — 报告。</strong> 全部生成完成后输出文件列表和每张图的简要描述。</p><h3 id="14-6-2-图表生成顺序:从宏观到微观"><a href="#14-6-2-图表生成顺序:从宏观到微观" class="headerlink" title="14.6.2 图表生成顺序:从宏观到微观"></a>14.6.2 图表生成顺序:从宏观到微观</h3><p>生成顺序是固定的,不是随机的:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">architecture → component → deployment → package → composite-structure →</span><br><span class="line">profile → class → object → usecase → flowchart → activity → state-machine →</span><br><span class="line">swimlane → sequence → communication → timing → interaction-overview</span><br></pre></td></tr></table></figure><p>从架构图开始,逐步深入到组件、部署、包结构、类的内部结构,再到行为层面的用例、流程、状态、交互。每一步都踩在上一步提取的信息上——生成类图的时候,架构图和组件图已经把系统的主要模块和边界画出来了。</p><h3 id="14-6-3-关键设计决策"><a href="#14-6-3-关键设计决策" class="headerlink" title="14.6.3 关键设计决策"></a>14.6.3 关键设计决策</h3><p><strong>示例驱动,而非提示词驱动。</strong> Skill 不给 LLM 一段「画类图的提示词」——给示例 HTML 文件。LLM 从示例中提取布局模式、色彩方案、节点样式,用自己的内容替换。LLM 做「模仿已有模板然后替换内容」这件事远比做「根据纯文本描述从零生成视觉设计」靠谱。</p><p><strong>专用渲染 Skill 分离。</strong> insight-diagram 不做渲染——它调用 <code>/architecture-diagram</code>(另一个 Skill)生成 HTML+SVG。职责分离:insight-diagram 负责「分析代码、选择图表、整理元素」,architecture-diagram 负责「把元素渲染为 HTML+SVG」。这是 Skill 系统中的组合模式——一个 Skill 依赖另一个 Skill。</p><p><strong>防遮盖规则。</strong> SVG 元素不得互相遮盖。箭头绘制在节点下方(SVG 中先画箭头再画节点)。节点间最小间距 40px(垂直)、30px(水平)。文字不超出节点边界——超长截断或换行。这些规则在生成时强制检查,确保产出图表可直接用于文档和演示,跳过人工微调步骤。</p><p><strong>语言无关。</strong> 支持 Go、Python、TypeScript、Java、Rust 等主流语言。分析代码库使用 Glob + Grep + Read——不依赖语言特定解析器,对所有语言有基本覆盖。需要精确提取「所有类和它们的方法签名」的类图时,建议与 Understand-Anything(第 13 章)组合使用——Understand-Anything 提供精确的结构数据,insight-diagram 负责可视化。</p><h3 id="14-6-4-与-Understand-Anything-的配合"><a href="#14-6-4-与-Understand-Anything-的配合" class="headerlink" title="14.6.4 与 Understand-Anything 的配合"></a>14.6.4 与 Understand-Anything 的配合</h3><p>第 13 章和本章是互补关系:</p><table><thead><tr><th>维度</th><th>Understand-Anything</th><th>insight-diagram</th></tr></thead><tbody><tr><td>产出</td><td>知识图谱(JSON)</td><td>UML&#x2F;架构&#x2F;流程 图(HTML+SVG)</td></tr><tr><td>精度</td><td>确定性(Tree-sitter 解析)</td><td>LLM 推断(基于代码阅读)</td></tr><tr><td>用途</td><td>Agent 查询、影响分析、导航</td><td>人类阅读、文档、演示</td></tr><tr><td>目标读者</td><td>AI Agent</td><td>人类团队</td></tr><tr><td>更新方式</td><td>增量(commit hook 触发)</td><td>按需(手动触发重新生成)</td></tr></tbody></table><p>最佳实践:Understand-Anything 产出的知识图谱提供精确的组件清单和依赖关系,insight-diagram 把信息可视化为标准 UML 图形。确定性的结构数据 + LLM 的视觉表达——和 Understand-Anything 的 Tree-sitter + LLM 混合架构是同一设计哲学。</p><h3 id="14-6-5-在-agent-wrapper-上实战"><a href="#14-6-5-在-agent-wrapper-上实战" class="headerlink" title="14.6.5 在 agent-wrapper 上实战"></a>14.6.5 在 agent-wrapper 上实战</h3><p>实际上只生成了架构图、流程图和几个UML图就已经可以充分理解AI生成的代码了,这里我生成了所有的图片,主要是为了让你了解生成的各个图形的效果 。我更多会看架构图、流程图、类图、序列图、泳道图等。</p><p>有些生成的图形连线有些错误,图形有些重叠,你可以给智能体指出错误,让它修复,生成完美的图形。下面有些图生成的不是很完美,我也贴出来了,没有进一步优化。</p><p>agent-wrapper(<code>/Users/smallnest/ai/agent-wrapper</code>)是 Go 语言实现的 AI Agent 包装框架,核心功能包括 Agent 生命周期管理、Skill 注册与调度、Tool 调用链、LLM Provider 抽象和多轮对话状态机。项目包含 20+ 个 Go 源文件,分布在 <code>core/</code>、<code>tools/</code>、<code>plugins/</code>、<code>cli/</code> 等包中。</p><p>使用 insight-diagram 生成全套图表的过程:</p><ol><li><strong>调用 Skill。</strong> <code>/insight-diagram</code>,Skill 读取 <code>CLAUDE.md</code>、扫描源码结构、提取组件和接口。</li><li><strong>选择图表。</strong> 默认推荐三张图(architecture + sequence + flowchart),覆盖「系统怎么组织的、关键交互怎么发生、主流程怎么走」。</li><li><strong>逐个生成。</strong> Skill 依次读取对应示例、整理元素、调用 architecture-diagram 渲染、保存到 <code>docs/</code>。</li><li><strong>人工补充。</strong> 生成的图表作为基础版本,微调后补充到项目文档。</li></ol><h4 id="agent-wrapper-系统架构图(Architecture-Diagram)"><a href="#agent-wrapper-系统架构图(Architecture-Diagram)" class="headerlink" title="agent-wrapper 系统架构图(Architecture Diagram)"></a>agent-wrapper 系统架构图(Architecture Diagram)</h4><p><img src="/images/image-20260604091042656.png"></p><p>这张图把 agent-wrapper 的顶层结构摊开了。上边调用方(Go 代码或 CLI),中间是核心——Registry 管理 8 个 Provider、Orchestrator 驱动多轮对话循环、process 包管理子进程生命周期。下边 8 个 Agent CLI 进程(claude、codex、pi、opencode 等),每个独立子进程,通过 stdin&#x2F;stdout 与 wrapper 通信。</p><h4 id="agent-wrapper-类图(Class-Diagram)"><a href="#agent-wrapper-类图(Class-Diagram)" class="headerlink" title="agent-wrapper 类图(Class Diagram)"></a>agent-wrapper 类图(Class Diagram)</h4><p><img src="/images/image-20260604093527716.png"></p><p>五个核心类型。<code>Agent</code> 是顶层接口,只有 <code>Run()</code> — 接收 <code>RunInput</code>,输出 <code>&lt;-chan Event</code>。<code>Orchestrator</code> 持有 <code>Agent</code>,加 <code>ApprovalHandler</code>、<code>BudgetHandler</code>、<code>ContextCompressor</code> 三个钩子。<code>Registry</code> 用 <code>sync.RWMutex</code> 保护 map。<code>RunInput</code> 的 <code>SessionID</code>、<code>MaxTurns</code>、<code>OutputFormat</code> 决定每次调用的行为。<code>Event</code> 五种类型(TextDelta&#x2F;ToolCall&#x2F;ToolResult&#x2F;TurnEnd&#x2F;Error)覆盖 agent CLI 的所有输出。</p><h4 id="agent-wrapper-对象图(Object-Diagram)"><a href="#agent-wrapper-对象图(Object-Diagram)" class="headerlink" title="agent-wrapper 对象图(Object Diagram)"></a>agent-wrapper 对象图(Object Diagram)</h4><p><img src="/images/image-20260604094235636.png"></p><p>「用 Claude Code provider 创建并运行一个 Agent」那一瞬间的内存快照。<code>Registry</code> 里注册了 8 个 provider,<code>Get(&quot;claude-code&quot;)</code> 返回 <code>ClaudeCodeAgent</code> 实例。<code>Orchestrator</code> 持有这个 agent,默认 <code>ChainedCompressor</code>(SlidingWindow + Summary),3 次重试。<code>RunInput</code> 带着 prompt &quot;重构这个文件&quot;、<code>MaxTurns=10</code>、<code>OutputFormat=stream</code>。</p><h4 id="agent-wrapper-组件图(Component-Diagram)"><a href="#agent-wrapper-组件图(Component-Diagram)" class="headerlink" title="agent-wrapper 组件图(Component Diagram)"></a>agent-wrapper 组件图(Component Diagram)</h4><p><img src="/images/image-20260604095935699.png"></p><p>组件之间的契约关系。<code>Registry</code> 对外提供 <code>Register(name, Factory)</code> 和 <code>Get(name) Agent</code> 两个接口(棒棒糖),各 provider 包作为组件注册进来。<code>Orchestrator</code> 消费 <code>Agent</code> 接口,同时插 <code>ApprovalHandler</code> 和 <code>BudgetHandler</code> 两个插座。底层 <code>process.AgentProcess</code> 封装 <code>os/exec.Cmd</code>,提供 stdin&#x2F;stdout&#x2F;stderr 管道和优雅关闭(SIGTERM → 5s → SIGKILL)。</p><h4 id="agent-wrapper-部署图(Deployment-Diagram)"><a href="#agent-wrapper-部署图(Deployment-Diagram)" class="headerlink" title="agent-wrapper 部署图(Deployment Diagram)"></a>agent-wrapper 部署图(Deployment Diagram)</h4><p><img src="/images/image-20260604100230653.png"></p><p>代码到物理节点的映射。用户机器运行 CLI(<code>cmd/agent-wrapper</code> 二进制), 运行 <code>Orchestrator.Run()</code>,启动 claude&#x2F;codex 等子进程。外部节点三个:Anthropic API(claude 后端)、OpenAI API(codex 后端)、Moonshot API(kimi-code 后端)。CLI → Orchestrator 是本地函数调用,Orchestrator → Agent CLI 是子进程 stdio,Agent CLI → 外部 API 是 HTTPS。</p><h4 id="agent-wrapper-包图(Package-Diagram)"><a href="#agent-wrapper-包图(Package-Diagram)" class="headerlink" title="agent-wrapper 包图(Package Diagram)"></a>agent-wrapper 包图(Package Diagram)</h4><p><img src="/images/image-20260604100303916.png"></p><p>顶层 <code>agentwrapper</code> 包入口,依赖 <code>types</code>、<code>harness</code>、<code>process</code>。<code>types/</code> 在最底层——<code>Agent</code> 接口、<code>Event</code>、<code>Message</code>、<code>RunInput</code>,所有其他包都依赖它。<code>harness/</code> 提供可插拔组件:<code>ApprovalHandler</code>、<code>BudgetHandler</code>、<code>ContextCompressor</code>。<code>process/</code> 封装子进程管理。<code>provider/</code> 是独立子树——八个包各自实现 <code>Agent</code> 接口。箭头方向符合 Clean Architecture:外层依赖内层,内层不依赖外层。</p><h4 id="agent-wrapper-复合结构图(Composite-Structure-Diagram)"><a href="#agent-wrapper-复合结构图(Composite-Structure-Diagram)" class="headerlink" title="agent-wrapper 复合结构图(Composite Structure Diagram)"></a>agent-wrapper 复合结构图(Composite Structure Diagram)</h4><p><img src="/images/image-20260604100505711.png"></p><p><code>Orchestrator</code> 的内部结构。四个 Parts:<code>Agent</code>(子进程驱动)、<code>ApprovalHandler</code>(工具审批)、<code>BudgetHandler</code>(token 预算)、<code>ContextCompressor</code>(上下文压缩重试)。<code>Run()</code> 通过 <code>runAgentWithRetry()</code> 端口调 Agent,Event Channel 经审批和预算检查后从 <code>out</code> 端口输出。关键:<code>agent.Run</code> 失败 → <code>IsContextLengthExceeded(err)</code> → <code>compressor.Compress()</code> → 重试最多 <code>maxRetries</code> 次(默认 3)。</p><h4 id="agent-wrapper-剖面图(Profile-Diagram)"><a href="#agent-wrapper-剖面图(Profile-Diagram)" class="headerlink" title="agent-wrapper 剖面图(Profile Diagram)"></a>agent-wrapper 剖面图(Profile Diagram)</h4><p><img src="/images/image-20260604101714963.png"></p><p>为 agent-wrapper 定义的三个自定义 Stereotype。<code>&lt;&lt;Provider&gt;&gt;</code>——实现 Agent 接口的子进程驱动类,含 <code>binary</code>、<code>protocol</code> 标签值。<code>&lt;&lt;Handler&gt;&gt;</code>——可插拔运行时钩子,含 <code>hook_point</code>、<code>is_async</code> 标签。<code>&lt;&lt;Event&gt;&gt;</code>——统一事件类型,含 <code>direction</code> 标签。在 <code>agent.go</code> 里写 <code>// @stereotype Provider binary=claude protocol=stream-json</code>,生成类图时自动识别特殊样式。</p><h4 id="agent-wrapper-流程图(Flowchart)"><a href="#agent-wrapper-流程图(Flowchart)" class="headerlink" title="agent-wrapper 流程图(Flowchart)"></a>agent-wrapper 流程图(Flowchart)</h4><p><img src="/images/image-20260604102024902.png"></p><p>从输入到输出的完整决策树。<code>Registry.Get(provider)</code> → 查表 → 未找到返回 <code>ErrNotRegistered</code>。找到则创建 Agent → <code>NewOrchestrator</code> 配 Approval&#x2F;Budget&#x2F;Compressor&#x2F;Retries。<code>orch.Run()</code> → 校验 prompt → <code>runAgentWithRetry()</code> 启子进程 → Scanner 解析 NDJSON → 每条事件过审批(allow&#x2F;deny&#x2F;abort)→ 过预算 → 输出。TurnEnd 检查 <code>stop_reason</code>,Context 超限触发压缩重试。</p><h4 id="agent-wrapper-用例图(Use-Case-Diagram)"><a href="#agent-wrapper-用例图(Use-Case-Diagram)" class="headerlink" title="agent-wrapper 用例图(Use Case Diagram)"></a>agent-wrapper 用例图(Use Case Diagram)</h4><p><img src="/images/image-20260604101840972.png"></p><p>这个图画的不清晰。</p><h4 id="agent-wrapper-活动图(Activity-Diagram)"><a href="#agent-wrapper-活动图(Activity-Diagram)" class="headerlink" title="agent-wrapper 活动图(Activity Diagram)"></a>agent-wrapper 活动图(Activity Diagram)</h4><p><img src="/images/image-20260604102238637.png"></p><p><code>Orchestrator.Run()</code> 的并发控制流。起始 → Fork 两条。主循环:eventCh 接收 → 分发审批&#x2F;预算&#x2F;转发 → TextDelta 直接转,ToolCall 走审批,TurnEnd 走预算。子进程监控:goroutine 监听 <code>ctx.Done()</code> → <code>terminate()</code>(SIGTERM → 5s → SIGKILL)。退出时 Join → <code>close(out)</code>。</p><h4 id="agent-wrapper-状态机图(State-Machine-Diagram)"><a href="#agent-wrapper-状态机图(State-Machine-Diagram)" class="headerlink" title="agent-wrapper 状态机图(State Machine Diagram)"></a>agent-wrapper 状态机图(State Machine Diagram)</h4><p><img src="/images/image-20260604102405183.png"></p><p><code>AgentProcess</code> 生命周期。<code>Idle</code> → <code>cmd.Start()</code> → <code>Running</code>。Running + <code>cmd.Wait()</code> → <code>Exited</code>(异常记 ExitCode)。Running + ctx 取消 → <code>Terminating</code> → SIGTERM → 5s 后 SIGKILL → <code>Killed</code>。<code>sync.Once</code> 保证 terminate 只跑一次。</p><h4 id="agent-wrapper-序列图(Sequence-Diagram)"><a href="#agent-wrapper-序列图(Sequence-Diagram)" class="headerlink" title="agent-wrapper 序列图(Sequence Diagram)"></a>agent-wrapper 序列图(Sequence Diagram)</h4><p><img src="/images/image-20260604102512785.png"></p><p><code>Orchestrator.RunSync()</code> 的时间线。<code>CLI</code> → <code>Registry.Get(&quot;claude-code&quot;)</code> → 返回 <code>ClaudeCodeAgent</code> → <code>NewOrchestrator</code> → <code>orch.RunSync()</code> → <code>agent.Run()</code> → <code>StartProcess()</code> 启动子进程 → NDJSON 到 stdout → Scanner 解析 → 首条 event 带 <code>session_id</code> → 逐条回 Orchestrator → TurnEnd → <code>RunResult{Text, Usage, SessionID}</code>。agent-wrapper 最核心调用链。</p><h4 id="agent-wrapper-通信图(Communication-Diagram)"><a href="#agent-wrapper-通信图(Communication-Diagram)" class="headerlink" title="agent-wrapper 通信图(Communication Diagram)"></a>agent-wrapper 通信图(Communication Diagram)</h4><p><img src="/images/image-20260604102722921.png"></p><p>同一批信息,视角换成「谁在跟谁通信」。<code>CLI</code>→<code>Registry</code>(1:Get)→<code>Orchestrator</code>(2:NewOrchestrator, 3:RunSync)→<code>ClaudeCodeAgent</code>(4:Run)→<code>AgentProcess</code>(5:Start)→<code>Anthropic API</code>(6:HTTPS)。反馈路径:API→Process→Scanner→Agent→Orchestrator channel→CLI。强调拓扑,不强调时间线。</p><p>图画的不好。</p><h4 id="agent-wrapper-定时图(Timing-Diagram)"><a href="#agent-wrapper-定时图(Timing-Diagram)" class="headerlink" title="agent-wrapper 定时图(Timing Diagram)"></a>agent-wrapper 定时图(Timing Diagram)</h4><p><img src="/images/image-20260604103316021.png"></p><p><code>Orchestrator.RunSync()</code> 的时间约束(ms)。0ms 开始,2ms Agent.Run,5ms Process running,10ms 流式输出,12ms API 请求,50ms TurnEnd,55ms 返回。约束:tool_call ≤ 30s、SIGTERM→SIGKILL &#x3D; 5s。检查长对话超时边界。</p><h4 id="agent-wrapper-交互概览图(Interaction-Overview-Diagram)"><a href="#agent-wrapper-交互概览图(Interaction-Overview-Diagram)" class="headerlink" title="agent-wrapper 交互概览图(Interaction Overview Diagram)"></a>agent-wrapper 交互概览图(Interaction Overview Diagram)</h4><p><img src="/images/image-20260604103110823.png"></p><p>活动图框架嵌入三个交互场景。判断「output format?」→ 三条分支:<code>stream</code>(sd OutputStream,实时输出)、<code>json</code>(sd OutputJSON,<code>Marshal(RunResult)</code> 单条)、<code>stream-json</code>(sd OutputStreamJSON,NDJSON 逐行)。汇聚到 exit。不展开细节,一眼看清分流逻辑。</p><h4 id="agent-wrapper-泳道图(Swimlane-Diagram)"><a href="#agent-wrapper-泳道图(Swimlane-Diagram)" class="headerlink" title="agent-wrapper 泳道图(Swimlane Diagram)"></a>agent-wrapper 泳道图(Swimlane Diagram)</h4><p><img src="/images/image-20260604102857112.png"></p><p>四泳道:User&#x2F;CLI、Orchestrator、Agent&#x2F;Provider、External LLM API。User:Registry.Get → RunInput → RunSync&#x2F;消费 events。Orchestrator:校验 prompt → runAgentWithRetry → processEvent(审批+预算)→ collect result。Agent:startSubprocess → parseNDJSON → emit events → wait exit。API:receive → generate → return tokens&#x2F;tool_calls。跨泳道标注协议:<code>via interface</code>、<code>via pipe</code>、<code>via HTTPS</code>。</p><h2 id="14-7-本章小结"><a href="#14-7-本章小结" class="headerlink" title="14.7 本章小结"></a>14.7 本章小结</h2><p>UML 十四种图加上三种实用扩展,覆盖软件系统的两个核心维度:结构(系统长什么样)和行为(系统怎么运行)。AI 开始生成代码之后,UML 从「前置设计工具」变成了「后置理解工具」——AI 写代码,图让人看得懂。</p><p>insight-diagram 把画图自动化了。一个 Skill,四步(分析代码 → 选择图表 → 逐图生成 → 报告),17 种图表。示例驱动的生成策略锁住了风格,防遮盖规则保证了产出直接能用。跟 Understand-Anything 配合,就是「确定性结构 + LLM 可视化」的完整链路。</p><p>本章为 agent-wrapper 预留的图表占位区,后续用 insight-diagram 生成全套图表后补充实际图片。</p><p>第 12 到 14 章连续过了三组 AI 编码辅助工具:官方插件、代码知识图谱、UML 可视化。下一章进代码重构——代码写完了,怎么让 AI 帮你把它改好。</p>

Understand-Anything:代码知识图谱

2026-06-28 16:30:00

<blockquote><p>&quot;The goal isn&#39;t a graph that wows you with how complex your codebase is — it&#39;s a graph that quietly teaches you how every piece fits together.&quot;<br>目标不是一张让你惊叹「代码库真复杂」的图——是一张默默教你每个部分如何协作的图。</p><p>——Yuxiang Lin, Understand-Anything 作者, 2026 年</p></blockquote><p>Skills 拆能力。Spec 写合约。Ralph Loop 循环到对。gstack 角色覆盖。Goal Workflow 串流水线。autoresearch 全自动闭环。官方插件注入领域知识。每一章都在回答同一件事:让 AI 写出更好的代码。</p><p>本章不教 AI 写代码——教 AI 读懂已有的代码。</p><p>Understand-Anything 是目前「代码理解」方向上最成熟的开源项目:48.4K Stars,15 个 AI Agent 平台支持,最新版本 v2.7.3。作者 Yuxiang Lin。装上之后,Agent 不再靠 grep 和逐文件阅读理解代码库——先查知识图谱。</p><p><img src="/images/image-20260601161740269.png"></p><span id="more"></span><h2 id="13-1-问题:AI-不理解你的代码"><a href="#13-1-问题:AI-不理解你的代码" class="headerlink" title="13.1 问题:AI 不理解你的代码"></a>13.1 问题:AI 不理解你的代码</h2><p>AI 写代码很快。读代码是另一回事。</p><p>当你对 Claude Code 说「在这个功能里加上暗黑模式」,Agent 需要自己找出哪些文件跟主题相关、哪些组件需要适配、CSS 变量在哪里定义、有没有已有的主题切换逻辑。它用 grep 搜关键词,用 Read 逐文件阅读——每次一个文件,每次消耗上下文窗口。五万行的代码库,靠 grep + Read 理解全貌,几十轮对话。每轮烧 token,每轮都可能漏掉关键依赖。</p><p>Agent 不记昨天读过什么。你昨天问了「这个项目的认证逻辑在哪里」,今天再问,它从头搜。Understand-Anything 提前做了这件事。Agent 再来问,直接查知识图谱。</p><h2 id="13-2-核心概念:代码-→-知识图谱"><a href="#13-2-核心概念:代码-→-知识图谱" class="headerlink" title="13.2 核心概念:代码 → 知识图谱"></a>13.2 核心概念:代码 → 知识图谱</h2><p>把代码库变成知识图谱。每个文件、每个函数、每个类是一个节点。import 关系、调用关系、继承关系是边。节点上挂 LLM 生成的摘要和标签,边上标依赖方向。</p><p>这张图有了之后:</p><ul><li><strong>快速定位。</strong> 搜索语义,不是搜索关键词。「认证逻辑在哪里?」——知识图谱返回 <code>src/auth/</code> 模块及它依赖的 <code>src/middleware/session.ts</code>。</li><li><strong>影响分析。</strong> 改了 <code>UserModel</code>,知识图谱展示哪些文件 import 了它、哪些函数调用了它的方法。</li><li><strong>新人上手。</strong> 新成员 Clone 仓库后跑一次 <code>/understand</code>,再用 <code>/understand-onboard</code> 产出按依赖顺序的阅读指南——先看 domain 层,再看 service 层,最后看 API 层。</li></ul><h2 id="13-3-Tree-sitter-LLM:确定性骨架,语义血肉"><a href="#13-3-Tree-sitter-LLM:确定性骨架,语义血肉" class="headerlink" title="13.3 Tree-sitter + LLM:确定性骨架,语义血肉"></a>13.3 Tree-sitter + LLM:确定性骨架,语义血肉</h2><p>Understand-Anything 的架构做了明确分工。</p><p><strong>Tree-sitter</strong> 负责结构解析。把源代码解析成语法树,提取确定性事实:哪些文件 export 了哪些符号、import 来自哪个模块、函数调用了哪些函数、类继承自哪个类。同一份代码,Tree-sitter 每次输出完全相同——零随机性,零幻觉。这些结构事实在扫描阶段预解析成 <code>importMap</code>,文件分析 Agent 直接从 <code>importMap</code> 读取,不重新推导。Tree-sitter 还驱动增量更新——文件内容变了,fingerprint 定位变更范围。</p><p><strong>LLM</strong> 负责语义判断。读入 Tree-sitter 产出的结构和原始源码,产出解析器做不到的事:每个节点的人类可读摘要、语义标签、架构层分类、业务域映射、引导式学习路径。Tree-sitter 确定「这文件导出了什么」,LLM 判断「这个文件是做什么的、属于哪一层、和哪些业务流程相关」。</p><p>分开的好处:结构解析不消耗 token、不膨胀、不摇摆。语义理解只在需要判断「含义」的地方才调 LLM。两侧产出可独立验证——结构结果和 import 语句逐条对账,语义结果人工抽查。</p><h2 id="13-4-安装与配置"><a href="#13-4-安装与配置" class="headerlink" title="13.4 安装与配置"></a>13.4 安装与配置</h2><h3 id="13-4-1-平台支持"><a href="#13-4-1-平台支持" class="headerlink" title="13.4.1 平台支持"></a>13.4.1 平台支持</h3><p>Understand-Anything 支持 15 个 AI Agent 平台。核心引擎是同一套 TypeScript 代码,不同平台只是斜杠命令注册方式不同。</p><table><thead><tr><th>平台</th><th>安装方式</th></tr></thead><tbody><tr><td>Claude Code</td><td>Plugin Marketplace 原生安装</td></tr><tr><td>Codex</td><td><code>install.sh codex</code></td></tr><tr><td>OpenCode</td><td><code>install.sh opencode</code></td></tr><tr><td>OpenClaw</td><td><code>install.sh openclaw</code></td></tr><tr><td>Antigravity CLI</td><td><code>install.sh antigravity</code></td></tr><tr><td>Gemini CLI</td><td><code>install.sh gemini</code></td></tr><tr><td>Pi Agent</td><td><code>install.sh pi</code></td></tr><tr><td>Vibe CLI</td><td><code>install.sh vibe</code></td></tr><tr><td>Hermes</td><td><code>install.sh hermes</code></td></tr><tr><td>Cline</td><td><code>install.sh cline</code></td></tr><tr><td>KIMI CLI</td><td><code>install.sh kimi</code></td></tr><tr><td>Trae</td><td><code>install.sh trae</code></td></tr><tr><td>Cursor</td><td>自动发现 <code>.cursor-plugin/plugin.json</code></td></tr><tr><td>VS Code + Copilot</td><td>自动发现 <code>.copilot-plugin/plugin.json</code>(v1.108+)</td></tr><tr><td>Copilot CLI</td><td><code>copilot plugin install</code></td></tr></tbody></table><h3 id="13-4-2-Claude-Code-安装(推荐)"><a href="#13-4-2-Claude-Code-安装(推荐)" class="headerlink" title="13.4.2 Claude Code 安装(推荐)"></a>13.4.2 Claude Code 安装(推荐)</h3><p>最简路径——Claude Code 内置 Plugin Marketplace:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/plugin marketplace add Lum1104/Understand-Anything</span><br><span class="line">/plugin install understand-anything</span><br></pre></td></tr></table></figure><p>第一条命令添加插件市场源,第二条安装插件。安装后 <code>/understand</code> 等命令全局可用。</p><h3 id="13-4-3-一行命令安装(其他平台)"><a href="#13-4-3-一行命令安装(其他平台)" class="headerlink" title="13.4.3 一行命令安装(其他平台)"></a>13.4.3 一行命令安装(其他平台)</h3><p>macOS&#x2F;Linux:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -fsSL https://raw.githubusercontent.com/Lum1104/Understand-Anything/main/install.sh | bash</span><br></pre></td></tr></table></figure><p>指定平台:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -fsSL https://raw.githubusercontent.com/Lum1104/Understand-Anything/main/install.sh | bash -s codex</span><br></pre></td></tr></table></figure><p>Windows(PowerShell):</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">iwr</span> <span class="literal">-useb</span> https://raw.githubusercontent.com/Lum1104/Understand<span class="literal">-Anything</span>/main/install.ps1 | <span class="built_in">iex</span></span><br></pre></td></tr></table></figure><p>安装脚本做的事:Clone 仓库到 <code>~/.understand-anything/repo</code>,创建平台特定的符号链接,注册斜杠命令。重启 AI Agent 后生效。</p><h3 id="13-4-4-更新与卸载"><a href="#13-4-4-更新与卸载" class="headerlink" title="13.4.4 更新与卸载"></a>13.4.4 更新与卸载</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">./install.sh --update <span class="comment"># 更新到最新版本</span></span><br><span class="line">./install.sh --uninstall codex <span class="comment"># 卸载指定平台</span></span><br></pre></td></tr></table></figure><h2 id="13-5-五到七个专门的-Agent-流水线"><a href="#13-5-五到七个专门的-Agent-流水线" class="headerlink" title="13.5 五到七个专门的 Agent 流水线"></a>13.5 五到七个专门的 Agent 流水线</h2><p>运行 <code>/understand</code>,背后是五个专门 Agent 按序执行。</p><table><thead><tr><th>Agent</th><th>角色</th><th>技术</th></tr></thead><tbody><tr><td><code>project-scanner</code></td><td>扫描项目,发现文件,检测语言和框架</td><td>Tree-sitter + 文件系统</td></tr><tr><td><code>file-analyzer</code></td><td>从每个文件提取函数、类、导入,生成图节点和边</td><td>Tree-sitter + importMap</td></tr><tr><td><code>architecture-analyzer</code></td><td>识别架构层(API、Service、Data、UI、Utility)</td><td>LLM</td></tr><tr><td><code>tour-builder</code></td><td>生成按依赖排序的学习路径</td><td>LLM</td></tr><tr><td><code>graph-reviewer</code></td><td>验证图完整性、引用完整性</td><td>默认内联(确定性检查),<code>--review</code> 切换到 LLM 全面审查</td></tr></tbody></table><p>五个是基础流水线。<code>/understand-domain</code> 追加第六个 Agent——<code>domain-analyzer</code>,从代码中提取业务域、流程、步骤。<code>/understand-knowledge</code> 追加第七个 Agent——<code>article-analyzer</code>,处理 Karpathy-pattern LLM Wiki 文章,提取实体、声明和隐含关系。</p><p>文件分析 Agent 并发运行——最多 5 个并行,每批 20-30 个文件。LLM 调用的延迟被并行掩盖,大项目的分析时间主要由最长的那批文件决定,而不是文件总数。</p><p>增量更新模式(<code>--auto-update</code> 或 commit hook):只重新分析变更的文件。Tree-sitter 的 fingerprint 检测哪些文件变了,只跑这几个文件的 file-analyzer,其他节点和边不动。小型 commit 的图更新秒级完成。</p><h2 id="13-6-知识图谱的七种用途"><a href="#13-6-知识图谱的七种用途" class="headerlink" title="13.6 知识图谱的七种用途"></a>13.6 知识图谱的七种用途</h2><h3 id="13-6-1-交互式浏览:-understand-dashboard"><a href="#13-6-1-交互式浏览:-understand-dashboard" class="headerlink" title="13.6.1 交互式浏览:/understand-dashboard"></a>13.6.1 交互式浏览:<code>/understand-dashboard</code></h3><p>产出的知识图谱可以导入交互式 Web Dashboard。每个节点可点击——点击文件节点,展示 LLM 摘要、导出的符号、依赖来源和去向。点击类节点,展示方法列表和继承链。节点按架构层颜色编码——API 层蓝色,Service 层绿色,Data 层橙色,UI 层紫色,Utility 层灰色。Dashboard 支持角色自适应 UI——初级开发者、PM、高级用户看到不同粒度的信息。</p><h3 id="13-6-2-语义搜索:-understand-chat"><a href="#13-6-2-语义搜索:-understand-chat" class="headerlink" title="13.6.2 语义搜索:/understand-chat"></a>13.6.2 语义搜索:<code>/understand-chat</code></h3><p>搜索语义,不是关键词。「哪些模块处理用户认证?」——知识图谱中匹配到 <code>src/auth/login.ts</code>(摘要:「处理邮箱+密码登录」)、<code>src/middleware/session.ts</code>(摘要:「会话管理和 token 验证」)、<code>src/models/User.ts</code>(摘要:「用户数据模型和密码哈希」)。Agent 不仅告诉你在哪里,还能解释它们之间的协作关系。</p><h3 id="13-6-3-影响分析:-understand-diff"><a href="#13-6-3-影响分析:-understand-diff" class="headerlink" title="13.6.3 影响分析:/understand-diff"></a>13.6.3 影响分析:<code>/understand-diff</code></h3><p>改代码前先跑。告诉你在当前 diff 中,你改了哪些文件、每个被改文件影响了哪些下游依赖、哪些影响是「可能破坏」的、哪些是「需要测试」的。这是「在你把改动推出去之前,先让 AI 告诉你这一改会引发什么连锁反应」。</p><h3 id="13-6-4-新人引导:-understand-onboard"><a href="#13-6-4-新人引导:-understand-onboard" class="headerlink" title="13.6.4 新人引导:/understand-onboard"></a>13.6.4 新人引导:<code>/understand-onboard</code></h3><p>自动生成项目上手文档——按依赖顺序,而不是文件名字母顺序。最底层的模块先讲,依赖它们的模块后讲。路径上附 LLM 摘要——「这个文件提供日期格式化、字符串转义和 UUID 生成,被项目中 17 个其他文件调用」。</p><h3 id="13-6-5-业务域提取:-understand-domain"><a href="#13-6-5-业务域提取:-understand-domain" class="headerlink" title="13.6.5 业务域提取:/understand-domain"></a>13.6.5 业务域提取:<code>/understand-domain</code></h3><p>切换到业务视图。代码层的知识图谱展示技术结构——文件、函数、类。<code>/understand-domain</code> 提取业务结构——域、流程、步骤。一个电商项目,技术结构是 <code>src/orders/</code> 目录下的文件。业务结构是「下单流程:购物车验证 → 地址校验 → 库存锁定 → 支付 → 订单确认」。</p><h3 id="13-6-6-知识库分析:-understand-knowledge"><a href="#13-6-6-知识库分析:-understand-knowledge" class="headerlink" title="13.6.6 知识库分析:/understand-knowledge"></a>13.6.6 知识库分析:<code>/understand-knowledge</code></h3><p>Understand-Anything 处理的不仅是代码。它对 Karpathy-pattern LLM Wiki 有专门支持——纯 Markdown 文件 + <code>index.md</code> wikilinks 组织的个人知识库。<code>/understand-knowledge</code> 读取 Wiki 目录,确定性解析器提取 wikilinks 和分类,LLM 发现隐含关系、提取实体,生成力导向图。</p><h3 id="13-6-7-深度解释:-understand-explain"><a href="#13-6-7-深度解释:-understand-explain" class="headerlink" title="13.6.7 深度解释:/understand-explain"></a>13.6.7 深度解释:<code>/understand-explain</code></h3><p>对单个文件或函数做深度分析。「这个函数是做什么的,为什么这样设计,有什么性能考虑,有哪些调用方?」——不是给你代码注释的翻译,是给你这段代码存在的原因。</p><h2 id="13-7-知识图谱的共享与版本控制"><a href="#13-7-知识图谱的共享与版本控制" class="headerlink" title="13.7 知识图谱的共享与版本控制"></a>13.7 知识图谱的共享与版本控制</h2><p>知识图谱产出 JSON 文件——<code>.understand-anything/knowledge-graph.json</code>。因为是 JSON,可以 Git。commit 一次,团队其他人 Clone 后直接拿到图,不需要重跑分析流水线。</p><p><code>.gitignore</code> 按以下规则配置:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">.understand-anything/intermediate/ ← 中间文件,不提交</span><br><span class="line">.understand-anything/diff-overlay.json ← 本地临时文件,不提交</span><br></pre></td></tr></table></figure><p><code>.understand-anything/</code> 下其余文件全部提交。大型项目(图文件 10MB+)用 Git LFS 管理:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git lfs install</span><br><span class="line">git lfs track <span class="string">&quot;.understand-anything/*.json&quot;</span></span><br><span class="line">git add .gitattributes .understand-anything/</span><br></pre></td></tr></table></figure><p>commit 图的成本是一份 JSON 文件。收益是整个团队省掉重复的分析时间。</p><h2 id="13-8-实战:用-Understand-Anything-理解-goscapy"><a href="#13-8-实战:用-Understand-Anything-理解-goscapy" class="headerlink" title="13.8 实战:用 Understand-Anything 理解 goscapy"></a>13.8 实战:用 Understand-Anything 理解 goscapy</h2><p>goscapy 是一个纯 Go 网络协议库,12 个子包,200+ 个 <code>.go</code> 源文件。核心包包括 <code>layers</code>(以太网&#x2F;IP&#x2F;TCP&#x2F;UDP&#x2F;ARP&#x2F;ICMP&#x2F;IPv6&#x2F;ICMPv6&#x2F;NDP 等协议层实现)、<code>packet</code>(数据包序列化&#x2F;反序列化核心接口)、<code>pcap</code>(抓包)、<code>sendrecv</code>(收发)、<code>sniff</code>(嗅探)、<code>route</code>(路由表)、<code>reassembly</code>(TCP 流重组)、<code>arping</code>(ARP 发现)、<code>fields</code>(协议字段注册表)、<code>goscapy</code>(高层快捷 API)。examples&#x2F; 下有 20 个示例程序,覆盖从以太网帧构造到 TCP SYN 扫描的完整场景。</p><p>这种规模的 Go 项目,新人想理解架构,通常要从 <code>go doc</code> 开始,然后逐包读 <code>types.go</code> 找接口定义,再追踪 <code>layers/</code> 里的具体实现。一个下午至少耗掉。</p><p>用 Understand-Anything,几分钟。</p><p><strong>第一步:Claude Code 中安装并运行。</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">/plugin marketplace add Lum1104/Understand-Anything</span><br><span class="line">/plugin install understand-anything</span><br><span class="line">/understand --language zh</span><br></pre></td></tr></table></figure><p>Agent 做的事:</p><ol><li>Tree-sitter 扫描 <code>pkg/</code> 下所有 <code>.go</code> 文件,30 多个文件分析 Agent 并发提取每个包导出的函数、类型、接口;</li><li><code>architecture-analyzer</code> 识别出 goscapy 的层次结构<ol><li><code>packet/</code> 是核心接口层(<code>Layer</code>、<code>Packet</code>、<code>SerializeBuffer</code>),</li><li><code>layers/</code> 是协议实现层(依赖 <code>packet/</code> 的接口),</li><li><code>pcap/</code>、<code>sendrecv/</code>、<code>sniff/</code> 是 I&#x2F;O 层(依赖 <code>layers/</code> 和 <code>packet/</code>),</li><li><code>goscapy/</code> 是门面层(聚合所有下层能力)。</li></ol></li></ol><p><img src="/images/image-20260601150911572.png"></p><p>分析了将近一小时,分析完成,自动打开网页:</p><p><img src="/images/image-20260601155012187.png"></p><p>总之,眼花缭乱,需要你花点时间熟悉它的界面,以及你能不能从中获取帮助。</p><p><strong>第二步:查构建器链。</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/understand-chat goscapy 中一个 TCP SYN 包是怎么构建的?</span><br></pre></td></tr></table></figure><p>Agent 查知识图谱,返回链路:<code>goscapy.NewPacket()</code> → <code>packet.NewPacketInfo()</code> 创建空数据包 → <code>layers.EthernetType.Build()</code> 加 Ethernet 头 → <code>layers.IPv4Type.Build()</code> 加 IP 头 → <code>layers.TCPType.Build()</code> 加 TCP 头(SYN flag)→ <code>packet.Serialize()</code> 序列化为字节流。每个 <code>Build()</code> 调用在知识图谱中用边标注,Agent 知道接口定义在 <code>packet/layer.go:15</code> 的 <code>LayerBuilder</code> 接口,TCP 实现在 <code>layers/tcp.go:200</code> 的 <code>Build()</code> 方法。</p><p>不靠 grep 搜 <code>Build</code>(200 个文件里至少有 40 个匹配)。不靠逐文件跟踪调用链。知识图谱一条边一条边走过。</p><p><img src="/images/image-20260601155809044.png"></p><p><strong>第三步:影响分析。</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/understand-diff</span><br></pre></td></tr></table></figure><p>你改动了 <code>packet/layer.go</code> 的 <code>Layer</code> 接口定义(加了新方法)。知识图谱标记影响面:<code>layers/</code> 下所有协议层都实现了这个接口——<code>ethernet.go</code>、<code>ipv4.go</code>、<code>tcp.go</code>、<code>udp.go</code>、<code>arp.go</code>、<code>icmp.go</code>、<code>ipv6.go</code>、<code>icmpv6.go</code>、<code>ndp.go</code>、<code>vlan.go</code>、<code>gre.go</code>,加上 <code>pcap/</code>、<code>sendrecv/</code> 中引用 <code>Layer</code> 类型的函数。12 个文件受影响,需要逐文件补新方法实现。</p><p><strong>第四步:新人上手。</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/understand-onboard</span><br></pre></td></tr></table></figure><p>产出一份按依赖顺序的阅读路径:第一步读 <code>packet/layer.go</code>(核心接口:<code>Layer</code>、<code>Packet</code>、<code>LayerBuilder</code>)→ 第二步读 <code>packet/serialize.go</code>(序列化原理)→ 第三步读 <code>layers/ethernet.go</code>(最简单的协议层实现)→ 第四步读 <code>layers/ipv4.go</code>(理解 options 和 fragmentation 处理)→ 第五步读 <code>layers/tcp.go</code>(理解 flag、checksum、状态机)→ 最后读 <code>goscapy/goscapy.go</code>(高层 API 封装)。每一个节点上都标注了关键的类型定义和核心方法,附 LLM 生成的中文摘要。</p><p>四个步骤,从安装到影响分析到新人阅读路径,200 个文件的 Go 项目全貌几分钟就通了。直接对 Claude Code 说「帮我理解这个项目」,Agent 靠 grep 猜结构。有知识图谱作骨架,是两套完全不同的东西。</p><p><img src="/images/image-20260601160059128.png"></p><h2 id="13-9-支持的语言与本地化"><a href="#13-9-支持的语言与本地化" class="headerlink" title="13.9 支持的语言与本地化"></a>13.9 支持的语言与本地化</h2><p>Tree-sitter 覆盖了主流编程语言——TypeScript、JavaScript、Python、Go、Rust、Java、C、C++、Ruby、PHP、Swift、Kotlin。语言检测自动完成,不需要配置。</p><p><code>/understand --language zh</code> 将输出切换为中文——节点摘要、Dashboard UI 标签、引导式学习路径。支持 <code>en</code>(默认)、<code>zh</code>、<code>zh-TW</code>、<code>ja</code>、<code>ko</code>、<code>ru</code>。</p><p>对中文开发者团队来说,中文知识图谱不仅降低阅读门槛,也让非技术角色(PM、设计师、运营)能读懂代码库的结构。</p><h2 id="13-10-适用边界"><a href="#13-10-适用边界" class="headerlink" title="13.10 适用边界"></a>13.10 适用边界</h2><p>最适合:五人以上的团队项目(知识图谱 commit 后新人上手速度翻倍)、长期维护的代码库(架构演进时可追踪模块间依赖变化)、跨语言项目(Tree-sitter 多语言解析让跨语言依赖关系可追溯)、频繁改动的核心模块(每次 commit 后增量更新,保持知识图谱最新)。</p><p>不适合:个人小项目(&lt; 20 个文件,手动翻比生成知识图谱快)、单文件脚本、极度频繁变更的早期原型(代码结构一天三变,图的维护成本高于收益)。</p><h2 id="13-11-与前后章节的关系"><a href="#13-11-与前后章节的关系" class="headerlink" title="13.11 与前后章节的关系"></a>13.11 与前后章节的关系</h2><p>与第 2 章 Skills:Understand-Anything 本身是 Skill 包——通过 Plugin Marketplace 或 <code>install.sh</code> 安装、注册为 <code>/</code> 命令、Markdown + TypeScript 混合实现。这是 Pocock 的「一个 Markdown 文件定义一种行为」哲学在代码理解领域的体现。</p><p>与第 12 章官方插件:和 code-review、feature-dev 同类——都是通过 <code>/plugin</code> 或 <code>/plugin marketplace</code> 安装的插件。Understand-Anything 填补了官方插件未覆盖的缺口:代码理解。</p><p>与第 3 章 SDD:写增量规格需要知道哪些模块会被影响、哪些行为必须保持。知识图谱能显式回答这两个问题——让规格更有依据。</p><p>与第 5 章 gstack、第 7 章 autoresearch:多 Agent 流水线的架构共享同样的思路——不同 Agent 负责不同维度。Understand-Anything 的 Agent 是功能化分工——<code>project-scanner</code> 扫描、<code>file-analyzer</code> 提取、<code>architecture-analyzer</code> 分层。</p><p>与第 8 章 Goal Workflow:<code>/to-issues</code> 和 <code>/review-it</code> 能从知识图谱中获取代码结构信息,减少 grep + Read 的轮次。Understand-Anything 可以是 Goal Workflow 流水线的一层基础设施。</p><h2 id="13-12-本章小结"><a href="#13-12-本章小结" class="headerlink" title="13.12 本章小结"></a>13.12 本章小结</h2><p>Understand-Anything 是全书唯一聚焦「代码理解」而非「代码生成」的一章。AI 写好代码的前提是理解代码——而理解正是多数 AI 编码工具最薄弱的环节。grep + Read 能走通,但 token 成本高、遗漏概率大、缺乏记忆。</p><p>Understand-Anything 用 Tree-sitter + LLM 混合架构回答了这个问题——确定性的事归 Tree-sitter(imports、exports、调用链、继承),语义的事归 LLM(摘要、标签、架构分层、学习路径)。一次分析产出的 JSON 知识图谱可以 commit 到 Git,全团队共享。Dashboard 给人看,Chat 给 Agent 查,Diff 在改动前预警影响面。</p><p>在 goscapy 这个 200 文件 Go 项目上的实战说明了这个方案的可行性——几分钟内从安装到新人上手路径,覆盖了「这个项目怎么组织」「一个包怎么构建」「改了接口会影响多少文件」三个最常见的代码理解问题。</p><p>下一章讲 UML 在 AI 时代的新用途——当 AI 能生成 UML,当 UML 能反过来教我们理解 AI 生成的代码。</p>

Anthropic 官方插件:AI Agent 的领域知识插件

2026-06-28 16:00:00

<blockquote><p>&quot;The decisive result came not from the model alone, but from the harness around it.&quot;<br>决定成败的不仅是模型本身,更是其配套的外围系统。</p><p>——Anthropic Harness Engineering Team</p></blockquote><p>第 2 章讲了 Skills 系统——Matt Pocock 的工程哲学:一个 Markdown 文件定义一种行为,小而可组合。第 6 章讲了 superpowers——社区级 Skills 库,十四个 Skill 覆盖十四个场景。</p><p>Anthropic 自己为 Claude Code 开发了 13 个官方插件。截至 2026 年 5 月,全部放在 Claude Code 仓库的 <code>plugins/</code> 目录下。和社区 Skills 不同,这些插件是 Anthropic 工程师为 Claude Code 构建的第一方工具——通过 <code>/plugin</code> 安装,深度集成到 hooks、agents、skills 三层基础设施中。</p><p><strong>安装。</strong> 所有 13 个插件通过同一命令安装:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/plugin install code-review</span><br></pre></td></tr></table></figure><p><code>/plugin install &lt;name&gt;</code> 从 Anthropic 官方源拉取插件,注册斜杠命令、hooks 和 Agent。<code>/plugin marketplace add</code> 可添加第三方源。安装后插件在 <code>~/.claude/plugins/</code> 下,可手动编辑配置。</p><span id="more"></span><h2 id="12-1-为什么需要领域知识插件"><a href="#12-1-为什么需要领域知识插件" class="headerlink" title="12.1 为什么需要领域知识插件"></a>12.1 为什么需要领域知识插件</h2><p>Skill 是原子能力——&quot;做 TDD&quot;&quot;做代码审查&quot;&quot;对齐需求&quot;。Skill 告诉你 Agent 能做什么。</p><p>但 Skill 不回答另一个问题:<strong>Agent 应该知道什么。</strong></p><p>一个没有领域知识的编码 Agent 等同于一个刚入职的工程师。它会写代码,但不知道你的项目在用 JWT 还是 Cookie 做认证、SQL 用 Postgres 还是 MySQL、错误处理是抛异常还是返回 Result。它只能靠 grep 猜。</p><p>CLAUDE.md 是补这个缺口的基础设施——项目上下文在会话启动时自动注入(第 10 章的 SessionStart hook)。但 CLAUDE.md 是静态文件。它不会主动扫描你的代码库、不会对比你的编码规范、不会在 PR 合并前自动跑审查规则。</p><p>领域知识插件让 CLAUDE.md 里的规矩活起来。code-review 插件读你的 CLAUDE.md,对照每一条规范检查 PR 改动。feature-dev 插件读你的代码库架构,基于已有模式生成三个备选方案。security-guidance 插件在你编辑任何文件时静默监控 9 个安全风险大类。</p><p>十三个插件,做的都是同一件事:把静态的领域知识变成执行时的动态检查。</p><h2 id="12-2-十三个官方插件全景"><a href="#12-2-十三个官方插件全景" class="headerlink" title="12.2 十三个官方插件全景"></a>12.2 十三个官方插件全景</h2><p>Claude Code 的 <code>plugins/</code> 目录下目前有 13 个插件,通过 <code>/plugin</code> 命令管理。每个插件都由 <code>.claude-plugin/plugin.json</code> 定义元数据,由 commands(斜杠命令)、agents(专门 Agent)、skills(技能)、hooks(事件钩子)四种机制组合构成。</p><p><img src="/images/image-20260531232015980.png"></p><table><thead><tr><th>插件</th><th>命令</th><th>核心机制</th><th>定位</th></tr></thead><tbody><tr><td><strong>code-review</strong></td><td><code>/code-review</code></td><td>4 个并行 Agent + 0-100 信心评分</td><td>PR 自动审查</td></tr><tr><td><strong>feature-dev</strong></td><td><code>/feature-dev</code></td><td>7 阶段引导 + 3 个专门 Agent</td><td>功能开发全流程</td></tr><tr><td><strong>pr-review-toolkit</strong></td><td><code>/pr-review-toolkit:review-pr</code></td><td>6 个可组合审查 Agent</td><td>细粒度 PR 审查</td></tr><tr><td><strong>commit-commands</strong></td><td><code>/commit</code>, <code>/commit-push-pr</code></td><td>Git 工作流自动化</td><td>提交&#x2F;推送&#x2F;创建 PR</td></tr><tr><td><strong>hookify</strong></td><td><code>/hookify</code></td><td>对话分析 → hook 生成</td><td>行为护栏自动创建</td></tr><tr><td><strong>security-guidance</strong></td><td>PreToolUse hook(自动)</td><td>9 类安全规则实时监控</td><td>静默安全守护</td></tr><tr><td><strong>ralph-wiggum</strong></td><td><code>/ralph-loop</code></td><td>Stop hook 拦截退出</td><td>自主循环开发</td></tr><tr><td><strong>plugin-dev</strong></td><td><code>/plugin-dev:create-plugin</code></td><td>8 阶段引导 + AI 辅助</td><td>插件开发工具包</td></tr><tr><td><strong>frontend-design</strong></td><td>自动触发 Skill</td><td>设计指南注入</td><td>前端界面设计</td></tr><tr><td><strong>agent-sdk-dev</strong></td><td><code>/new-sdk-app</code></td><td>项目脚手架 + 2 验证 Agent</td><td>Agent SDK 开发</td></tr><tr><td><strong>claude-opus-4-5-migration</strong></td><td>自动触发 Skill</td><td>代码&#x2F;prompt 自动迁移</td><td>模型版本迁移</td></tr><tr><td><strong>explanatory-output-style</strong></td><td>SessionStart hook(自动)</td><td>教育性上下文注入</td><td>理解实现选择</td></tr><tr><td><strong>learning-output-style</strong></td><td>SessionStart hook(自动)</td><td>决策点互动提问</td><td>交互式学习</td></tr></tbody></table><p>插件之间可组合。feature-dev 走完七个 Phase,code-review 在合入前扫一遍 PR。security-guidance 全程静默运行——Agent 执行危险操作前才被感知。</p><h2 id="12-3-code-review:本地-diff-审查"><a href="#12-3-code-review:本地-diff-审查" class="headerlink" title="12.3 &#x2F;code-review:本地 diff 审查"></a>12.3 &#x2F;code-review:本地 diff 审查</h2><p><code>/code-review</code> 由 Boris Cherny(Claude Code 的创建者)开发。在 Claude Code 会话中直接审查当前 diff。</p><p><img src="/images/image-20260531232526789.png"></p><p>用法:</p><ul><li><code>/code-review</code> — 审查当前 diff,报告正确性 bug 和代码效率、简化机会。无需安装 GitHub App,在任何 Claude Code 会话中都能运行</li><li><code>/code-review --comment</code> — 将发现作为内联 PR 评论发布</li><li><code>/code-review --fix</code> — 审查后自动将修复应用到工作树</li><li><code>/code-review ultra --fix</code> — 云端运行 deeper ultrareview,结果返回后应用修复</li></ul><p>降低 effort level 返回更少但更高可信度的发现;<code>high</code> 到 <code>max</code> 覆盖更广,可能返回不确定的发现。不传 effort 参数时使用会话当前的 effort。可传路径或 PR 引用审查特定目标。</p><p>v2.1.147 之前命令名为 <code>/simplify</code>(默认应用修复)。v2.1.154 起 <code>/simplify</code> 改为仅做清理审查——只应用修复,不找 bug。之前用 <code>/simplify</code> 做 bug 查找的脚本应切换到 <code>/code-review --fix</code>。</p><p><strong>自定义审查行为。</strong> 两个文件控制审查器的行为。</p><p><code>CLAUDE.md</code> — 项目共享指令。审查器读它作为项目上下文,把新增违规标为 nit。双向生效:如果 PR 改了代码导致 <code>CLAUDE.md</code> 陈述过时,审查器也会标记。</p><p><code>REVIEW.md</code> — 根目录的审查专用覆盖文件,注入到审查管道中每个 Agent 的系统提示中,优先级最高。纯明文指令。典型用途:重新定义哪些问题算 Important 级别、限制 Nit 发现数量上限、跳过特定路径(生成代码、锁文件、vendored 依赖)、添加仓库特定检查(&quot;新 API 路由必须有集成测试&quot;)、设置验证门槛(行为声明需 <code>file:line</code> 源码引用)、控制重审收敛(首审后只报 Important 级发现)、调整摘要格式。</p><p>审查结果包含每条 issue 的 GitHub 永久链接——完整 SHA + <code>#L</code> 行号范围。</p><h2 id="12-4-feature-dev:7-阶段引导开发"><a href="#12-4-feature-dev:7-阶段引导开发" class="headerlink" title="12.4 feature-dev:7 阶段引导开发"></a>12.4 feature-dev:7 阶段引导开发</h2><p><code>/feature-dev</code> 把一个功能从想法带到代码合并,分成七个阶段。插件作者是 Sid Bidasaria(Anthropic 工程师)。</p><p><img src="/images/image-20260531233037492.png"></p><p><strong>Phase 1:需求澄清。</strong> 对模糊需求提问。&quot;你想解决什么问题?&quot;&quot;有什么约束?&quot;确认理解后再进入下一步。</p><p><strong>Phase 2:代码库探索。</strong> 启动 2-3 个专门 Agent(<code>code-explorer</code>)并行探索不同维度——类似功能如何实现、相关区域架构、现有模式。每个 Agent 返回入口点(精确到 <code>文件:行号</code>)、执行路径、关键组件、架构洞察和建议阅读的文件清单。Claude 阅读所有标注文件,生成全面摘要。</p><p><strong>Phase 3:澄清问题。</strong> 结合代码库发现和需求,列出不明确的部分:边界条件、错误处理、集成点、向后兼容性、性能需求。关键规则:<strong>回答全部问题之前不得进入设计阶段。</strong></p><p><strong>Phase 4:架构设计。</strong> 启动 2-3 个专门 Agent(<code>code-architect</code>),每个走不同侧重:</p><ul><li><strong>最小改动方案</strong>——最大化重用已有代码,最小化文件变更</li><li><strong>干净架构方案</strong>——关注可维护性和抽象优雅度</li><li><strong>务实平衡方案</strong>——速度和质量折中</li></ul><p>每个方案附详细取舍分析。Claude 给出推荐意见和原因,最终选哪个由你决定。</p><p><strong>Phase 5:实现。</strong> 等你明确选择方案后,才开始写代码。严格遵循项目已有的命名、风格、模块边界惯例。每一步更新 todo 列表。</p><p><strong>Phase 6:质量审查。</strong> 启动 3 个专门 Agent(<code>code-reviewer</code>)并行检查:简洁性&#x2F;DRY&#x2F;优雅度、Bug&#x2F;正确性、惯例遵守&#x2F;抽象设计。高优先级问题(信心 75-100)和中等问题(信心 50-74)分别列出,每个附精确的 <code>文件:行号</code> 引用和 CLAUDE.md 规范引用。所有测试通过后才允许进入下一步。</p><p><strong>Phase 7:总结。</strong> 文档化:构建了什么、关键决策是什么、修改了哪些文件、建议的后续步骤。</p><p>七个阶段把&quot;开发功能&quot;从&quot;一段 prompt + AI 出代码&quot;变成了结构化的工程流程。第 4 章 Ralph Loop 的核心洞察——AI 说做完了不等于真的做完了——在 feature-dev 里体现为每个可能出问题的节点都设了等待点。需求摸清之前不设计。方案选定之前不实现。审查通过之前不总结。</p><h2 id="12-5-pr-review-toolkit:六维度细粒度审查"><a href="#12-5-pr-review-toolkit:六维度细粒度审查" class="headerlink" title="12.5 pr-review-toolkit:六维度细粒度审查"></a>12.5 pr-review-toolkit:六维度细粒度审查</h2><p>pr-review-toolkit 是可组合 PR 审查工具箱。和 code-review 的&quot;给一个综合分数&quot;不同,它做的是&quot;挑出你最关心的一两个维度,深度查&quot;。</p><p><code>/pr-review-toolkit:review-pr</code> 支持七个可选开关:<code>--comments</code>(审查 comment 质量)、<code>--tests</code>(审查测试覆盖)、<code>--errors</code>(审查错误处理)、<code>--types</code>(审查类型设计)、<code>--code</code>(审查代码质量)、<code>--simplify</code>(审查简化机会)、<code>--all</code>(全维度)。</p><p>每个开关背后是一个专门 Agent——comment-analyzer、pr-test-analyzer、silent-failure-hunter(找静默失败)、type-design-analyzer、code-reviewer、code-simplifier。</p><p>和 code-review 的关系:code-review 是常规武器——每个 PR 自动跑,4 个 Agent 快速扫一遍。pr-review-toolkit 是特种工具——关键 PR 或安全敏感代码,选一两个最关心的维度深度审查。</p><h2 id="12-6-security-guidance:9-类安全规则静默守护"><a href="#12-6-security-guidance:9-类安全规则静默守护" class="headerlink" title="12.6 security-guidance:9 类安全规则静默守护"></a>12.6 security-guidance:9 类安全规则静默守护</h2><p>security-guidance 是唯一不需要手动触发的插件。安装后在 PreToolUse hook 上注册 9 条安全规则,在 Agent 编辑文件时静默检查:命令注入、XSS 注入、eval 使用、危险的 HTML 构造、pickle 反序列化、os.system 调用、SQL 注入、硬编码密钥、不安全随机数生成。</p><p>Agent 每次执行 Edit&#x2F;Write&#x2F;Bash 操作前,PreToolUse hook 比对这 9 条规则。匹配到危险模式时,hook 在 Agent 上下文中注入安全提醒——用引导而非强制。</p><p>hookify 是 security-guidance 的补充。security-guidance 的规则是 Anthropic 预定义的通用安全模式。hookify 从你自己的对话中学习特定的风险模式——conversation-analyzer Agent 扫描你和 Agent 的交互历史,自动生成对应的 hook 规则。</p><h2 id="12-7-其他插件"><a href="#12-7-其他插件" class="headerlink" title="12.7 其他插件"></a>12.7 其他插件</h2><p><strong>frontend-design。</strong> 自动触发 Skill,在前端工作时激活。引导 Agent 避开均匀间距、对称布局、标准配色的&quot;AI 风&quot;界面,注入设计约束:大胆排版、有意图的色彩、微交互、非对称布局。和第 5 章 gstack 的 <code>/plan-design-review</code> 目标一致——抵抗 AI Slop。</p><p><strong>explanatory-output-style 和 learning-output-style。</strong> 通过 SessionStart hook 注入教育性上下文。前者为每个实现选择解释原因,后者在关键决策点提问、鼓励手写 5-10 行代码。</p><p><strong>commit-commands。</strong> 三个 Git 快捷命令:<code>/commit</code>(生成 conventional commit 消息并提交)、<code>/commit-push-pr</code>(推送并创建 PR)、<code>/clean_gone</code>(清理远端已删除的本地分支)。</p><p><strong>agent-sdk-dev 和 plugin-dev。</strong> Agent 开发者工具:<code>/new-sdk-app</code> 创建 Agent SDK 项目脚手架,<code>/plugin-dev:create-plugin</code> 用 8 阶段工作流辅助插件创建。</p><p><strong>claude-opus-4-5-migration。</strong> 自动处理从旧模型迁移到 Opus 4.5 的代码和 prompt 变更。</p><h2 id="12-8-插件的共同设计模式"><a href="#12-8-插件的共同设计模式" class="headerlink" title="12.8 插件的共同设计模式"></a>12.8 插件的共同设计模式</h2><p><img src="/images/image-20260531233736843.png"></p><p>十三个插件有几条共性:</p><p><strong>专用 Agent 并行审查。</strong> code-review 用 4 个并行 Agent,feature-dev 在不同阶段启动 2-3 个探索 Agent 和 3 个审查 Agent,pr-review-toolkit 用 6 个独立审查 Agent。和第 7 章 autoresearch 的多 Agent 轮转审查逻辑一致——一个 Agent 看不到的东西,换个角度就能看到。包括Claude Code推出的Teams、dynamic workflows的理念一样,充分利用多 Agent 的特性。</p><p><strong>信心评分过滤。</strong> code-review 的 0-100 评分 + 80 阈值是降噪策略。pr-review-toolkit 的 Agent 也使用类似的信心分类(高&#x2F;中优先级)。&quot;宁愿漏掉一个真问题,不要让十个假问题淹没一个真问题&quot;——给 Agent 用的审查系统需要这个取舍,因为人对噪音的容忍度远低于 Agent。</p><p><strong>结构化阶段门控。</strong> feature-dev 的 7 个 Phase 之间设有明确等待点——Phase 3 的回答、Phase 4 的方案选择、Phase 6 的问题处理。和第 5 章 gstack 的 PreToolUse hook 强制门控本质相同。</p><p><strong>hook + Agent 双引擎。</strong> security-guidance 完全靠 PreToolUse hook 触发,explanatory-output-style 和 learning-output-style 通过 SessionStart hook 加载,hookify 从对话分析自动生成 hook 规则。第 10 章的 Harness Engineering 在这里是最直接的基层——hook 是插件行为的基础设施。</p><h2 id="12-9-与全书方法论的对接"><a href="#12-9-与全书方法论的对接" class="headerlink" title="12.9 与全书方法论的对接"></a>12.9 与全书方法论的对接</h2><table><thead><tr><th>全书方法论</th><th>在官方插件中的体现</th></tr></thead><tbody><tr><td>Skills 系统(第 2 章)</td><td>frontend-design、claude-opus-4-5-migration 是 Skill 的官方实现</td></tr><tr><td>Ralph Loop(第 4 章)</td><td>ralph-wiggum 是 Stop hook 循环的第一方实现</td></tr><tr><td>gstack(第 5 章)</td><td>feature-dev 的 7 阶段门控对应 gstack Sprint;frontend-design 的 AI Slop 检测对应 <code>/plan-design-review</code></td></tr><tr><td>Harness Engineering(第 10 章)</td><td>security-guidance 的 PreToolUse hook、hookify 的自动 hook 生成</td></tr><tr><td>Goal Workflow(第 8 章)</td><td>feature-dev + commit-commands 组合对应 Goal Workflow 的流水线</td></tr><tr><td>autoresearch(第 7 章)</td><td>code-review 的 4 Agent 并行审查 + 信心评分对应多 Agent 交叉审查</td></tr></tbody></table><h2 id="12-10-本章小结"><a href="#12-10-本章小结" class="headerlink" title="12.10 本章小结"></a>12.10 本章小结</h2><p>Anthropic 的十三个官方插件是 Claude Code 的工具级&quot;出厂配置&quot;。</p><p>从使用角度看这些插件的角色:code-review(每个 PR 该跑,4 Agent 并行 + 80 分阈值过滤噪音)、feature-dev(需求模糊时用,7 阶段引导不允许在不确定状态下写代码)、pr-review-toolkit(需要盯特定维度时用——安全性、类型设计、静默失败)、security-guidance(该装完就忘掉它——静默守护,不需要手动跑)、commit-commands(日常 git 机械操作的自动化)。</p><p>共性设计模式——专用 Agent 多视角审查、高信心阈值过滤噪音、结构化阶段门控、hook 驱动的自动触发——第 2 章的 Skills、第 4 章的 Ralph Loop、第 5 章的 gstack、第 7 章的 autoresearch、第 10 章的 Harness Engineering 都能在这些插件中找到一一对应的工程实现。</p>