Lesson 0017 · Engineering · 只能人启动(user-invoked)· 流程课

improve-codebase-architecture:给代码库做体检的扫描仪

想象这个场景:一个项目写了三个月,功能都能跑,但你最近越来越常有一种感觉—— 想搞懂「下一个订单」这么一个概念,要在七八个小文件之间来回跳; 当初「为了好测」抽出来的一堆纯函数,真正的 bug 却藏在「谁在什么时候调用它们」里。 你说不上来哪里坏了,只知道代码在变软。这时候就该跑 improve-codebase-architecture:它把代码库扫一遍, 找出那些浅模块(接口和背后实现几乎一样复杂、只负责转发的那类模块), 把「值得加深」的候选做成一份可以在浏览器里看的 HTML 报告, 你挑一张卡片,它再逐条面试你、把设计决定落成字。 它是这套系统里的体检医生:只诊断、不动刀—— 报告写进系统临时目录而不进仓库,真正的重构交回主流程去做。 学完这节课,你能说清它的三段流程、每段会写/不会写什么、 它和 codebase-design 这台「设计工作台」的分工, 以及行为不对时该去改哪个文件的哪一段。

1. 它在整个系统里站在哪

0001 把 22 个已发布 skill 分成三层:配置层(跑一次性的初始设置)、 编排层(你手动启动的完整流程)、纪律层(被反复调用的基本功)。 improve-codebase-architecture编排层,是 user-invoked 的 (只能由人手动启动,AI 不会自己拿起它)。 但它不在「想法 → 交付」那条主流程上。ask-matt 给它单开了一类,叫 Codebase health(代码库保养):不是功能开发,是 upkeep(日常维护)—— 「有空的时候就跑一跑,让代码库保持适合 agent 操作的状态」。

它和主流程的关系是「供血」,不是「链条上的一环」:ask-matt 的原文说, 它找出 deepening opportunity(加深机会——把浅模块加深的重构候选), 你挑中一个,就等于产生了一个新想法(generates an idea), 可以拿着这个想法进主流程的 /grill-with-docs。 换句话说:主流程消耗想法,这个 skill 生产想法。

还有两个 skill 会把自己的「治不好」转交给它:

扫描仪 vs 工作台(全课最重要的一对分工) ask-matt 把这对分工写得很白:improve-codebase-architecture找候选的扫描仪(survey),codebase-design设计所选候选的工作台(bench)。 扫描仪负责「哪里疼」,工作台负责「怎么治」。 你已经知道要改哪个模块、只是缺词汇和方案 → 直接用 0005 讲的 codebase-design,跳过扫描; 你说不清哪里疼 → 先跑本 skill 体检。

地图:0001 的三层表与全表 · 路由规则:ask-matt/SKILL.md 的 Codebase health 一节 · 移交来源:diagnosing-bugs/SKILL.md 复盘段 · 配套词汇课:0005 codebase-design

2. 调用方式与触发场景

2.1 只能你手动启动

SKILL.md 的 frontmatter(文件头里的元数据区)写着 disable-model-invocation: true;同目录 agents/openai.yamlpolicy.allow_implicit_invocation: false。 两道闸门都关着,意思一致:AI 不会被允许自作主张地启动它。 docs 的说法最直白:「You invoke this by typing /improve-codebase-architecture — the agent won't reach for it on its own.」 (你输入这条斜杠命令来启动它——agent 自己不会伸手去拿它。)

frontmatter 里的 description 字段(这个字段是人和路由器看的简介)原文是: 「Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.」 (扫描代码库找加深机会,把它们呈现为一份可视化的 HTML 报告,然后对你挑中的那个做面试。) 这句话就是整个 skill 的三段式预告,第 3 节会逐段拆开。

2.2 什么时候该跑、什么时候不该跑

docs 给的定位是 periodic maintenance(周期性保养): 每隔几天跑一次,或者每当代码库开始给你那种感觉—— 「理解一个概念要在太多小模块之间跳来跳去」。 它读现有架构,提出该在哪里加深。 它不是流程链上必须过的一站:主流程不会在任何一步自动需要它。

情境 该用 improve-codebase-architecture 更该去哪
隔了几天没体检,或代码「变软」:一个概念要跳很多小文件才能看懂 (这正是它设计的触发场景)
已经明确知道要重构哪个模块,只需要设计词汇和接口方案 不该(跳过一个你已经知道答案的扫描是浪费) codebase-design(0005):词汇 + design-it-twice
修完一个难缠的 bug,复盘发现根子是没有好接缝能锁住它 (diagnosing-bugs 正式移交过来的入口) 先由 diagnosing-bugs 完成修复和复盘
分拣 issue 时发现一堆毛病背后是同一笔架构债 该(0001 全表里 triage 的出口之一) 分拣本身仍归 triage
脑子里有个新功能想法,想把它磨清楚再开工 不该(它读的是现有代码,不聊新想法) grill-with-docs(0003),主流程第一步
想让 AI 自动定期给仓库做架构扫描 做不到(它被刻意设计成只能人启动) 你每隔几天自己跑一趟;路由问题问 ask-matt

权威原文: skills/engineering/improve-codebase-architecture/SKILL.md 的 frontmatter · agents/openai.yaml · 人读文档: docs/engineering/improve-codebase-architecture.mdaihero.dev/skills-improve-codebase-architecture

3. 三段式流程总览:先装上词汇再开工

SKILL.md 的 Process 一节把整个 skill 排成三步。 先把全貌摆出来,后面三节再逐段放大:

  /improve-codebase-architecture
              │
              ▼
  ① Explore(探索)
     先定范围(用户指方向,否则翻 git log 找热点)
     → 派 Explore 子代理有机地走代码库
     → 对可疑浅模块套删除测试
              │
              ▼
  ② HTML report(报告)
     写 <临时目录>/architecture-review-<timestamp>.html
     (Tailwind + Mermaid 都走 CDN,不进仓库)
     → 每张候选卡片:文件/问题/方案/收益/前后对比图/强度徽章
     → 结尾给出 Top recommendation
     → 停!问你:「想探索哪一个?」(明确禁止在此刻设计接口)
              │
              ▼
  ③ Grilling loop(面试循环)
     对你挑中的候选跑 /grilling 决策树
     → 边面试边跑 /domain-modeling 落字:
       新术语进 CONTEXT.md · 有分量的否决理由提议记 ADR
     → 想看几种接口方案 → 回 /codebase-design 跑 design-it-twice

在第一步开始之前,SKILL.md 开篇先做了两件事——这是理解整个 skill 的钥匙:

  1. 装上架构词汇。原文指令:运行 /codebase-design skill, 拿到架构词汇(module、interface、depth、seam、adapter、leverage、locality) 和它的原则(删除测试、「接口就是测试面」、「一个 adapter = 假想的接缝,两个 = 真接缝」)。 并且要求:每条建议里严格使用这些词,不许滑向 component、service、API、boundary。 0005 讲过,这叫 prose 调用(在 skill 正文里用一句自然语言把另一个 model-invoked skill 拉进来)。
  2. 装上领域词汇和既往决定。目标项目 CONTEXT.md 里的领域语言 「给好的接缝提供了名字」;docs/adr/ 里的 ADR (Architecture Decision Record,架构决策记录——把不可逆的决定连同理由写下来的文档) 记录着这条命令不应该重新争论的决定。
为什么开头要先「装词汇」 这份报告的所有卡片都用两套词写成:架构名词来自 codebase-design,领域名词来自项目的 CONTEXT.md。效果是卡片读起来像 「deepen the Order intake module」(加深 Order 的 intake 模块), 而不是「refactor the FooBarHandler」(重构某个实现类的名字),也不是 「the Order service」(service 是被禁用的近义词)。 用词统一不是洁癖:只有候选卡片和后续的面试、spec、测试说同一套话, 这条「扫描 → 面试 → 落地」的传送带才不会在接缝处掉件。

出处:SKILL.md 开篇两段与 Process 一节 · 词汇的唯一权威:codebase-design/SKILL.md · 词汇课:0005

4. 第 1 步 Explore:先定范围,再找浅点

4.1 YAGNI:先决定去哪看,再去看

这一步的标题是 「Scope before you scan — YAGNI」。 YAGNI 是 "You Aren't Gonna Need It"(你不会需要它)的缩写, 在这里的意思是:别把整个仓库平铺着扫一遍——扫描本身也有成本,要把注意力花在值当的地方。 背后的账算得很清楚:加深一个模块的回报,是让未来对它的改动更容易; 所以最近一直在改动的代码,权重最高。

情况 怎么做 依据(SKILL.md 原文要点)
用户给了方向:某个模块、某个子系统、某个痛点 直接采用这个方向,跳过下面的推断 「If the user named a direction — take it, and skip the inference below.」
用户没给方向 往回翻一大段提交历史(git log --oneline),找出 hot spot(热点——反复出现在提交里的文件和区域),让这些路径优先吸引注意力 「walk back a good stretch of the commit history … let those paths pull your attention first」
提交很散,看不出热点 把网放宽(widen the net) 「If the changes are scattered with no clear hot spot, widen the net.」

范围定了之后、扫描开始之前,还要先读两样东西:目标项目的 CONTEXT.md (领域词汇表)和扫描区域相关的 ADR。 前者让报告能说业务语言,后者防止把已经拍板不许动的决定又当候选端出来。

4.2 派 Explore 子代理,有机地走代码库

真正走代码的不是主 agent 硬啃,而是用 Agent 工具派出 subagent_type=Explore子代理 (subagent:主 agent 派出去独立干活的工作者;Explore 是一种只读的代码库探索代理)。 SKILL.md 特意交代:不要按死板的启发式走 (don't follow rigid heuristics),要「有机地」探索,记下你作为读者亲身感到的 friction(摩擦——读代码时硌手的地方)。 原文给了五个探测问题:

  1. 哪里理解一个概念需要在很多小模块之间来回跳?
  2. 哪些模块是浅的——接口几乎和实现一样复杂?
  3. 哪里有「只是为了可测性才抽出来的纯函数」,而真正的 bug 藏在「怎么调用它们」里(没有 locality——局部性,即变更和知识没有集中在一处)?
  4. 哪些紧耦合的模块在跨接缝泄漏?
  5. 哪些部分没有测试,或者没法通过当前接口测试?

4.3 删除测试:候选的入场券

对每一个可疑的浅模块,套用 deletion test(删除测试,0005 第 4 节讲过): 想象把这个模块整个删掉,复杂度是被集中到一个小接口后面, 还是只是搬了个家(散回到 N 个调用者身上或别处)? 原文写得明白:「A "yes, concentrates" is the signal you want.」 (「是的,会集中」才是你要的信号。) docs 把这道门槛的意义点透了:不是每个候选都配拿一张卡片—— 只有过了删除测试的才入选,正是这道过滤让报告不至于退化成「泛泛的清理建议」 (generic cleanup advice)。

出处:SKILL.md Process §1 · 删除测试的定义:codebase-design/SKILL.md · 「过滤掉泛泛建议」的说法:docs/engineering/improve-codebase-architecture.md

5. 第 2 步 HTML 报告:写进临时目录的候选卡片

5.1 写到哪里、怎么打开

探索结果不落进仓库一个字,而是写成一份自包含的 HTML 文件,放进操作系统的临时目录:

为什么坚持「临时目录」 这是刻意的副作用设计:体检是高频动作(每隔几天一次),如果每份报告都进仓库, 仓库很快堆满过期的诊断书。临时目录的意思是——报告是一次性阅读材料, 看完、挑完卡片,它的使命就结束了;真正要留下来的东西(术语、决策) 在第 3 步经 domain-modeling 落进 CONTEXT.md 和 ADR。

5.2 技术底座与卡片字段

报告用 Tailwind via CDN 做布局和样式,用 Mermaid via CDN 画图 (CDN 是内容分发网络——HTML 里一个 <script> 标签从公网把库拉下来,不用安装任何东西; Mermaid 是一个把文本描述渲染成流程图/时序图的库)。 但原文也叮嘱:别什么都用 Mermaid,要混用手绘的 CSS/SVG 图—— 图的关系感强(调用图、依赖、时序)时用 Mermaid; 想要更「editorial」(杂志插画感)的东西——体量图、剖面图、折叠动画——就手搓 div 和 SVG。 每个候选给一张 before/after 可视化(加深前 vs 加深后的对比图)。「Be visual.」(要视觉化。)

卡片字段 写的是什么
Files 涉及哪些文件/模块
Problem 当前架构为什么造成摩擦
Solution 用平实英语描述会改变什么(注意:描述方向,不设计接口——见 5.4 的禁令)
Benefits 用 locality 和 leverage 解释收益,并说明测试会如何变好
Before / After diagram 并排、定制的图,左边画出浅的样子,右边画出加深后的样子
Recommendation strength 三档徽章(badge)之一:Strong(强推荐)、Worth exploring(值得探索)、Speculative(推测性)

报告最后以 Top recommendation(首选推荐)一节收尾: 如果是你,会先动手哪一张卡片,为什么。 扫描仪交卷时必须有立场,不是甩给用户一份没有排序的清单。

5.3 用词纪律与 ADR 冲突

第 3 节讲过的词汇要求在报告里强制执行:领域词用 CONTEXT.md 的, 架构词用 codebase-design 的。卡片说「the Order intake module」, 不说「FooBarHandler」,也不说「the Order service」。

如果某个候选和现有 ADR 矛盾,处理规则是: 只有当摩擦真实到值得重开这份 ADR 时才摆上卡片, 并且要在卡片上明确标注——原文给的样式是一个警告框: 「contradicts ADR-0007 — but worth reopening because…」(与 ADR-0007 冲突,但值得重开,因为……)。 反面的禁令同样明确:不要把 ADR 禁止的理论上存在的重构全部列出来。 ADR 是既往决定的记录,扫描仪的职责不是批量翻旧案。

5.4 报告写完后的两个「停」

Do NOT propose interfaces yet. SKILL.md 用独立一句明文禁止:此刻不要提出接口设计。 报告只回答「哪里浅、为什么值得加深」,不回答「新接口长什么样」—— 接口设计是第 3 步面试、以及 design-it-twice 的事。 提前画接口,等于替你做了还没被面试过的决定。

第二个「停」:文件写完、打开之后,问用户一句 「Which of these would you like to explore?」(你想探索哪一个?), 然后停下来等。不自动进入第 3 步——挑哪张卡片是用户的决定,不是扫描仪的。

出处:SKILL.md Process §2 · 脚手架与图示细节:HTML-REPORT.md

6. HTML-REPORT.md:报告的格式法典

SKILL.md 第 2 步末尾把「怎么把报告画好」整体委托给了同目录的 HTML-REPORT.md:完整的 HTML 脚手架、图示模式、样式指引都在那里。 这个 sibling 文件(和 SKILL.md 同目录的配套文件)是微调报告长相的唯一入口, 值得逐节认识。

6.1 脚手架与页头

脚手架是一个普通 HTML5 文件:先引 Tailwind 的 CDN 脚本, 再以 ES module 方式引 Mermaid 11 并初始化(主题 neutral、安全级别 loose), 外加一小段自定义样式层,专门补 Tailwind 盖不住的东西——比如虚线接缝、手绘感箭头、深模块的深色渐变。 页头只放三样:仓库名、日期、一段紧凑的图例 (实线框 = 模块,虚线 = 接缝,红箭头 = 泄漏,粗黑框 = 深模块)。 没有介绍段落——开门见山,直接进候选卡片。

6.2 卡片规则:图承重,文字稀疏

每个候选是一个 <article>。规则可以压缩成一句: 图承担重量,文字稀疏平实,词汇表里的词直接拿来用、不加客套。 具体要求:

格式法典里最硬的一句话 「No paragraphs of explanation. If the diagram needs a paragraph to be understood, redraw the diagram.」(不写解释段落。如果一张图需要一个段落才能看懂,把图重画。) 报告是给你 30 秒建立直觉的,不是给你读论文的。

6.3 五种图示模式

模式 什么时候用 长什么样
Mermaid graph(主力) 要说「X 调 Y 调 Z,看看这团乱」时;依赖图、调用流。时序图适合「before:6 次往返;after:1 次」这类对比 flowchart/graph 代码块,外面包一层 Tailwind 卡片免得突兀;用 classDef 把泄漏的边染红、深模块染深色
手绘盒子加箭头 Mermaid 的自动布局和你打架时;尤其当 after 图想要「一个粗边框深模块、内部零件灰掉」的分量感——Mermaid 画不出那种重量 模块是带边框和标签的 div,箭头是绝对定位的内联 SVG 线条
Cross-section(剖面图) 适合「层状的浅」:一次调用要穿过多少层 横向色带堆叠。before:6 个什么都不做的薄层;after:1 条写着合并后职责的厚带
Mass diagram(体量图) 适合「接口和实现一样宽」这类浅 每个模块画两个矩形:一个表示接口面积,一个表示实现体量。before:两个矩形几乎一样高(浅);after:接口矩形矮、实现矩形高(深)
Call-graph collapse(调用图折叠) 适合展示「一树调用收进一个模块」 before:嵌套盒子画出的调用树;after:同一棵树折叠成一个盒子,变成内部调用的部分在盒子里淡出显示

原文还要求混着用:别让每张图长得一样——多样性本身就是目的之一。

6.4 样式与语气

样式指引的关键词是 editorial, not corporate-dashboard (杂志感,不是公司仪表盘感):留白大方,标题可以用衬线字体,颜色克制—— 一个强调色(翠绿或靛蓝)+ 红色专给泄漏 + 琥珀色专给警告。 图保持 320px 左右高,好让 before/after 不用滚动就能并排放下。 图里的模块标签用 text-xs uppercase tracking-wider, 让它们读起来像图纸标注而不是界面按钮。 整份报告只有两个脚本(Tailwind CDN 和 Mermaid 的 ESM 引入),其余全静态。

语气(Tone)一节就是 0005 那张词汇表的执法版: Use exactly(严格只用):module、interface、implementation、depth、deep、shallow、seam、adapter、leverage、locality。 Never substitute(永不替换):component/service/unit 不许顶替 module, API/signature 不许顶替 interface,boundary 不许顶替 seam, layer/wrapper 在指 module 时不许用。 Wins 子弹必须用词汇表里的词命名收益—— 可以写「locality: bugs concentrate in one module」, 不许写「easier to maintain」「cleaner code」, 因为那些词不在词汇表里,挣不到自己的位置。 原文最后一条:不 hedging(不闪烁其词)、不 throat-clearing(不绕弯开场)、 能写成子弹就别写成句子,能砍掉的子弹就砍掉。

出处:HTML-REPORT.md 全文(Scaffold / Candidate card / Diagram patterns / Style guidance / Tone 各节)

7. 第 3 步 Grilling loop:边面试边落字

你挑了一张卡片之后,skill 跑 /grilling—— 0003 讲过的那条面试基本功: 沿决策树(decision tree,一串相互依赖的待定决定)一个分支一个分支往下走, 一次只问一个问题、每个问题都附上推荐答案,能自己查到的事实不问你, 但决定全部留给你做。 在这里,决策树的具体题目由 SKILL.md 点名: 约束、依赖、加深后模块的形状、接缝后面藏什么、哪些测试活下来

7.1 四条内联副作用分支(本课的核心考点)

面试不是干聊。SKILL.md 的原话是 「Side effects happen inline as decisions crystallize」 (副作用随着决定结晶而内联发生)——边面试边运行 /domain-modeling, 让领域模型保持最新。原文列了四种触发情形:

面试中发生了什么 skill 该做什么 落点
给加深后的模块起名,名字是一个 CONTEXT.md 里还没有的概念 把这个新术语加进 CONTEXT.md;文件还不存在就现建(create the file lazily——用到才建) 目标项目的 CONTEXT.md
对话中把一个原本模糊的词磨清楚了 当场更新 CONTEXT.md,不拖到面试结束 目标项目的 CONTEXT.md
用户否决了这个候选,而且给了一个有分量(load-bearing)的理由 主动提议记一份 ADR,原文话术:「Want me to record this as an ADR so future architecture reviews don't re-suggest it?」(要不要我把这个理由记成 ADR,免得以后的架构评审再把它端出来?) 目标项目的 docs/adr/
想给加深后的模块看几种不同的接口方案 运行 /codebase-design,走它的 design-it-twice 并行子代理模式(0005 第 9 节) 对话里(比较与推荐;落地交给后续流程)
ADR 提议的门槛 不是每次「不做」都配拿一份 ADR。原文限定:只有当这个理由是未来探索者真正需要、 能避免他们重复推荐同一个候选时,才提议记 ADR。 两类理由明确跳过:转瞬即逝的(ephemeral,比如「现在不值得做」——下个季度可能就值得了) 和不言自明的(self-evident)。ADR 是写给未来扫描仪的「此路已审」标记,不是情绪垃圾桶。

7.2 这段面试和主流程是什么关系

ask-matt 说:挑中一个候选 = 产生了一个想法,可以拿进主流程的 /grill-with-docs。而 SKILL.md 内部其实已经跑过了 /grilling + /domain-modeling——这正是 grill-with-docs 的两个组成部分(0003:grill-with-docs = grilling 面试 + 文档留痕)。 所以准确的图景是:面试在架构会话内部完成,结晶出的决定进入 CONTEXT.md 和 ADR;之后这个「想法」按主流程继续走—— 写进 spec、拆成票、再实现(第 10 节展开)。 这个 skill 自始至终不替你重构代码

出处:SKILL.md Process §3 · 面试基本功:grilling/SKILL.md0003 · 落字纪律:domain-modeling/SKILL.md0004 · 「产生想法进主流程」:ask-matt/SKILL.md Codebase health 一节

8. 依赖关系图:它拉谁进来、谁把它拉进来

            被拉进来(它依赖谁)                    improve-codebase-architecture
  ┌───────────────────────────────┐                      ▲
  │ /codebase-design  词汇+原则    │                      │ 谁把它拉进来(谁依赖它)
  │   开头装词;design-it-twice   │        ┌─────────────┼─────────────────┐
  │ /grilling       面试决策树     │        │             │                 │
  │ /domain-modeling 落字          │   diagnosing-bugs  triage         ask-matt
  │ Explore 子代理    走代码库     │   复盘移交:没好    架构债        Codebase health
  │ CONTEXT.md / docs/adr 先读     │   接缝锁不住 bug   路由           路由入口
  └───────────────────────────────┘
                          │
                          ▼ 产出
        临时 HTML 报告 → 挑卡片 → 面试 → CONTEXT.md / ADR 更新
                          │
                          ▼ 再交给
        主流程:grill-with-docs 已成形 → to-spec → to-tickets → implement(+tdd)
Skill / 文件 什么时候被拉进来 拉进来干什么
codebase-design 流程开头(装词汇);面试中想看多种接口方案时(design-it-twice) 提供 module/interface/depth/seam/adapter/leverage/locality 词汇和删除测试等原则;提供并行接口设计模式
grilling 第 3 步,用户挑中候选后 沿决策树逐题面试:约束、依赖、模块形状、接缝后藏什么、哪些测试活下来
domain-modeling 第 3 步全程内联 新术语进 CONTEXT.md、模糊词当场磨清、有分量的否决理由提议记 ADR
Explore 子代理 第 1 步 只读地有机探索代码库,记录摩擦点
diagnosing-bugs (反向)它复盘后移交给你本 skill 当 bug 的根子是「没有好接缝」,带着具体情况来这里做体检
ask-matt (反向)路由层 把「代码库保养」的意图路由到本 skill;把它和 codebase-design 的「扫描仪 vs 工作台」分工写进地图

依赖声明集中在 SKILL.md 开篇与各步的「Run the /… skill」句子 · 反向入口:diagnosing-bugs/SKILL.mdask-matt/SKILL.md

9. 副作用清单:会写/改什么

动作 写/改什么 说明
第 1 步 Explore 什么都不写 Explore 子代理只读;git log 也是只读操作
第 2 步报告 操作系统临时目录里的一份新 HTML:<tmpdir>/architecture-review-<timestamp>.html 明确「nothing lands in the repo」(仓库里一个字都不落);每次运行一份新文件
第 3 步面试:新术语 / 磨清的词 目标项目的 CONTEXT.md(可能现建) /domain-modeling 落笔,不是本 skill 直接写
第 3 步面试:有分量的否决理由 可能新增一份 ADR 到目标项目的 docs/adr/ 先提议、你同意才写;转瞬即逝和不言自明的理由跳过
整个流程 不碰业务代码、不写 issue tracker 真正的重构交回主流程(to-spec / to-tickets / implement);它和 to-tickets、triage 不同,全程不动工单

0001 的全表对这条 skill 的定性就三句话,可以当口诀背: 「临时目录里的一份 HTML 报告(不进仓库);讨论后可更新 CONTEXT/ADR;不直接大改业务代码。」

出处:SKILL.md §2(临时目录段)与 §3(四条分支) · 总表定性:0001

10. 用完之后接什么

  1. 挑了卡片、面试走完 → 结晶的决定已经在 CONTEXT.md / ADR 里。 这个想法按主流程继续:进 to-spec 把模块、接口、测试决策写成 spec (0009),再 to-tickets 拆票(0010)、implement 内部驱动 tdd 逐票实现(0011、0012)。 ask-matt 的说法:扫描产生想法,设计工作台是 codebase-design,落地走主流程。
  2. 面试中跑了 design-it-twice → 采纳推荐方案(或混合体)→ 接口决定写进 spec;如果这个接口决定不可逆,记一份 ADR → 实现时 tdd 只在约定的接缝上写测试。
  3. 否决了候选且理由有分量 → ADR 落字。 这份 ADR 的价值在下一次体检兑现:第 1 步会先读 ADR, 未来的扫描仪看到它就不会再把这个候选端上来。
  4. 只是体检、一张卡片都没挑 → 报告留在临时目录,关掉浏览器标签页就行。 仓库零变化,这也是一次健康的运行——体检本来就不必每次都查出病。

11. 行为不对时,去改哪个文件的哪一段

症状 先查(并在这里改) 不要误改
扫描整库平铺、不偏向最近改动的代码 SKILL.md Process §1「Scope before you scan」一段:git log 找热点、热点不明就放宽 HTML-REPORT.md(它只管报告长相,管不到扫描策略)
报告/对话里冒出 component、service、API、boundary SKILL.md 开篇的词汇段 + HTML-REPORT.md 的 Tone 一节(Use exactly / Never substitute 两张清单) codebase-design/SKILL.md 的 Glossary——词汇的唯一权威在那,但这里是「借词执法」,先改执法段
报告阶段就给出接口设计 SKILL.md §2 的「Do NOT propose interfaces yet.」一句 卡片字段清单(字段没错,是越界)
卡片缺字段、徽章乱标、没有 Top recommendation SKILL.md §2 的卡片字段清单 + HTML-REPORT.md 的 Candidate card 一节(含徽章配色与依赖类别标签) 图示模式一节(图好不好看是另一件事)
图全靠文字解释、段落连篇 HTML-REPORT.md「If the diagram needs a paragraph…redraw the diagram」+ 五种图示模式 删除测试的措辞(那是候选筛选,不是排版)
报告被写进了仓库目录 SKILL.md §2 的临时目录解析段($TMPDIR → /tmp → %TEMP%) 脚手架 HTML(写哪和怎么写是两段文字)
面试时新术语没进 CONTEXT.md,或什么否决都提议记 ADR SKILL.md §3 的四条分支(含 ADR 提议的门槛) domain-modeling/SKILL.md 的 ADR 格式(格式没错,是触发条件错了)
AI 自作主张启动了这个 skill SKILL.md frontmatter 的 disable-model-invocation: trueagents/openai.yamlpolicy.allow_implicit_invocation: false——两道闸门都该是关的 description 字段(它是简介,不是闸门;改它拦不住调用)

12. 检索练习

先别往回翻,凭记忆答。选项长度刻意对齐,版式不泄题。答错回正文对应节核对。

自测(立即反馈)

1. 谁能启动 improve-codebase-architecture?
2. 架构评审报告默认写到哪里?
3. 一个候选要过哪道门槛,才配拿到报告卡片?
4. 用户没指方向时,扫描范围怎么定?
5. 报告阶段被明文禁止做的一件事是?
6. 用户以有分量的理由否决了候选,skill 应该?
7. 卡片上 Recommendation strength 徽章有哪三档?
8. 面试中想比较几种接口方案,该跑什么?
额外提取练习(无选项) 合上本页,默写三段流程:每段的名字、产物、以及各自的「停」(扫描前必先定范围; 报告后禁止设计接口、停下问用户挑哪张)。 再默写报告卡片的六个字段和三档强度徽章。 最后默写面试阶段的四条内联副作用分支——尤其「什么样的否决理由才配提议记 ADR」。 写完对照第 3、5、7 节。

13. 下一课与一手材料

本课主一手材料(请打开原文读,不要只背本页摘要):

速查页(本课同步): reference/improve-codebase-architecture.html

导航: 上一课 0016 wayfinder (另一条「交付物不是代码」的重型流程:它产出决策,本课产出候选卡片)。 总览仍回 0001 系统地图; 词汇地板见 0005 codebase-design0004 domain-modeling; 面试编排见 0003; 移交入口见 0015 diagnosing-bugs0014 triage; 落地去 0009 to-spec0010 to-tickets0011 implement

建议下一课(0018): 0018 resolving-merge-conflicts。 交接点很实在:架构加深的想法一旦落地成票、几张票并行推进 implement,同一个被加深的模块几乎必然被多人(或多个 agent 会话)同时碰, 合并冲突就跟着来——那时候用得上它。

老师就在会话里。 对本课任何一个边界有疑问——比如「热点翻多长的 git log 才算 good stretch」、 「load-bearing 理由和 ephemeral 理由的灰色地带」、 「面试已经在内部跑过 grilling 了,还要不要再走 grill-with-docs」——直接在对话里问。 回答会回到 SKILL.md / HTML-REPORT.md / ask-matt 的原文,不会临场编造。 做完检索练习后,回复「练习结果 / 哪里卡住 / 开 0018 或先补 0005」,我们安排下一课。