Skill Learning

improve-codebase-architecture

1. Bilingual SKILL.md

左右滑动可直接切换英文版与中文版;两种语言按段落自动对齐。英文中的蓝色虚线词语可点击查看解释。共标记 16 处。

入口 skill:improve-codebase-architecture左右滑动切换语言 · 段落位置自动对齐
# Improve Codebase Architecture
Surface architectural friction and propose **** — refactors that turn shallow modules into deep ones. The aim is testability and .
This command is _informed_ by the project's domain model and :
- Call the Skill tool with "codebase-design" for the architecture vocabulary (**module**, **interface**, **depth**, **seam**, **adapter**, **leverage**, **locality**) and its principles (the deletion test, "the interface is the test surface", "one adapter = hypothetical seam, two = real"). Use these terms exactly in every suggestion — "component," "service," "API," or "boundary." - The domain language in `CONTEXT.md` gives names to good seams; ADRs in `docs/adr/` record decisions this command .
## Process
### 1. Explore
**Scope before you scan — YAGNI.** Deepening a module pays off by making future changes to it easier, so the parts of the codebase that have recently changed. Decide *where* to look before you look:
- If the user named a direction — a module, a subsystem, a pain point — take it, and skip the inference below. - Otherwise, (`git log --oneline`) to find the codebase's — the files and areas that keep coming up — and let those paths pull your attention first. If the changes are scattered with no clear hot spot, .
Read the project's domain glossary (`CONTEXT.md`) and any ADRs in the area you're touching first.
Then spawn a sub-agent to walk the codebase. Don't follow rigid heuristics — explore organically and note where you experience friction:
- Where does understanding one concept require ? - Where are modules **shallow** — interface nearly as complex as the implementation? - Where have pure functions been extracted just for testability, but the real bugs hide in how they're called (no **locality**)? - Where do tightly-coupled modules leak across their seams? - Which parts of the codebase are untested, or hard to test through their current interface?
Apply the **deletion test** to anything you suspect is shallow: would deleting it concentrate complexity, or just move it? A "yes, concentrates" is .
### 2. Present candidates as an HTML report
Write a self-contained HTML file to the OS temp directory . Resolve the temp dir from `$TMPDIR`, falling back to `/tmp` (or `%TEMP%` on Windows), and write to `<tmpdir>/architecture-review-<timestamp>.html` so . Open it for the user — `xdg-open <path>` on Linux, `open <path>` on macOS, `start <path>` on Windows — and tell them the absolute path.
The report uses **Tailwind via CDN** for layout and styling, and **Mermaid via CDN** for diagrams where a graph/flow/sequence reliably communicates the structure. Mix Mermaid with hand-crafted CSS/SVG visuals — use Mermaid when relationships are graph-shaped (call graphs, dependencies, sequences), and hand-built divs/SVG when you want something more editorial (mass diagrams, cross-sections, collapse animations). Each candidate gets a **before/after visualisation**. Be visual.
For each candidate, render a card with:
- **Files** — which files/modules are involved - **Problem** — why the current architecture is causing friction - **Solution** — plain English description of what would change - **Benefits** — explained in terms of locality and leverage, and how tests would improve - **Before / After diagram** — side-by-side, custom-drawn, illustrating the shallowness and the deepening - **Recommendation strength** — one of `Strong`, `Worth exploring`, `Speculative`, rendered as a badge
End the report with a **Top recommendation** section: which candidate you'd tackle first and why.
**Use CONTEXT.md vocabulary for the domain, and the `/codebase-design` vocabulary for the architecture.** If `CONTEXT.md` defines "Order," talk about "the Order intake module" — not "the FooBarHandler," and not "the Order service."
**ADR conflicts**: if a candidate contradicts an existing ADR, only surface it when the friction is real enough to warrant revisiting the ADR. Mark it clearly in the card (e.g. a warning callout: _"contradicts ADR-0007 — but worth reopening because…"_). Don't list every theoretical refactor an ADR forbids.
See [HTML-REPORT.md](HTML-REPORT.md) for the full HTML scaffold, diagram patterns, and styling guidance.
Do NOT propose interfaces yet. After the file is written, ask the user: "Which of these would you like to explore?"
### 3. Grilling loop
Once the user picks a candidate, call the Skill tool with "grilling" to walk the decision tree with them — constraints, dependencies, the shape of the deepened module, , what tests survive.
Side effects happen inline as decisions crystallize — call the Skill tool with "domain-modeling" to keep the domain model current as you go:
- **Naming a deepened module after a concept not in `CONTEXT.md`?** Add the term to `CONTEXT.md`. Create the file lazily if it doesn't exist. - **Sharpening a fuzzy term during the conversation?** Update `CONTEXT.md` right there. - **User rejects the candidate with a ?** Offer an ADR, framed as: _"Want me to record this as an ADR so future architecture reviews don't re-suggest it?"_ Only offer when the reason would actually be needed by a future explorer to avoid re-suggesting the same thing — skip ephemeral reasons ("not worth it right now") and self-evident ones. - **Want to explore alternative interfaces for the deepened module?** Call the Skill tool with "codebase-design" and use its design-it-twice parallel sub-agent pattern.
# 改善代码库架构
揭示架构摩擦,并提出**深化机会(deepening opportunities)**——把浅模块重构为深模块。目标是提升可测试性与 AI 可导航性。
此命令会参考项目的领域模型,并建立在一套共享的设计词汇之上:
- 使用 Skill 工具调用 "codebase-design",获取架构词汇(**module**、**interface**、**depth**、**seam**、**adapter**、**leverage**、**locality**)及其原则(删除测试、"接口就是测试表面"、"一个适配器意味着假设性的接缝,两个才是真实接缝")。每条建议都必须准确使用这些术语——不要漂移到 "component"、"service"、"API" 或 "boundary"。 - `CONTEXT.md` 中的领域语言为优质接缝命名;`docs/adr/` 中的 ADR 记录此命令不应重新争论的决定。
## 流程
### 1. 探索
**先确定范围,再扫描——遵循 YAGNI。** 深化模块的回报在于让未来的改动更容易,因此要格外关注代码库中最近发生变化的部分。先决定去*哪里*看,再开始查看:
- 如果用户指定了方向——某个模块、子系统或痛点——就采用它,并跳过下面的推断。 - 否则,沿着足够长的一段提交历史回溯(`git log --oneline`),寻找代码库的热点——反复出现的文件和区域——让这些路径优先吸引你的注意。如果改动很分散,没有明显热点,就扩大搜索范围。
先阅读项目的领域术语表(`CONTEXT.md`),以及你将触及区域中的所有 ADR。
然后派生一个子代理遍历代码库。不要遵循僵硬的启发式规则——自然地探索,并记录你感受到摩擦的位置:
- 理解一个概念时,是否需要在许多小模块之间来回跳转? - 哪些模块是**浅的(shallow)**——接口几乎与实现一样复杂? - 哪些纯函数只是为了可测试性才被抽取,但真正的缺陷藏在它们的调用方式中(缺少 **locality**)? - 哪些紧密耦合的模块会跨越其接缝泄漏? - 代码库的哪些部分未经测试,或难以通过当前接口进行测试?
对任何你怀疑是浅模块的对象应用**删除测试(deletion test)**:删除它会集中复杂度,还是只会搬移复杂度?你想要的信号是“会,复杂度得到集中”。
### 2. 将候选方案呈现为 HTML 报告
向操作系统临时目录写入一个自包含 HTML 文件,确保仓库中不落入任何文件。通过 `$TMPDIR` 解析临时目录,若没有则回退到 `/tmp`(Windows 上为 `%TEMP%`),并写入 `<tmpdir>/architecture-review-<timestamp>.html`,让每次运行都生成新文件。为用户打开它——Linux 使用 `xdg-open <path>`,macOS 使用 `open <path>`,Windows 使用 `start <path>`——并告知绝对路径。
报告使用 **Tailwind CDN** 完成布局和样式,并在图、流程或时序能可靠表达结构时使用 **Mermaid CDN** 绘图。把 Mermaid 与手工 CSS/SVG 视觉效果混合使用——关系呈图结构时(调用图、依赖、时序)使用 Mermaid;想要更具编辑感的效果(质量图、剖面图、折叠动画)时使用手工 div/SVG。每个候选方案都要有一张**改造前/后可视化图**。要用视觉表达。
为每个候选方案渲染一张卡片,包含:
- **文件**——涉及哪些文件/模块 - **问题**——为什么当前架构会造成摩擦 - **方案**——用朴素英语说明将发生什么变化 - **收益**——以 locality 和 leverage 解释,并说明测试将如何改善 - **改造前 / 后图示**——并排、自定义绘制,展示浅薄状态与深化过程 - **推荐强度**——`Strong`、`Worth exploring`、`Speculative` 三者之一,以徽章呈现
报告末尾以**首要推荐(Top recommendation)**章节收尾:说明你会优先处理哪个候选方案,以及原因。
**领域部分使用 CONTEXT.md 的词汇,架构部分使用 `/codebase-design` 的词汇。** 如果 `CONTEXT.md` 定义了 "Order",就说 "the Order intake module"——不要说 "the FooBarHandler",也不要说 "the Order service"。
**ADR 冲突**:如果候选方案与现有 ADR 矛盾,只有当摩擦真实到值得重审 ADR 时才提出它。要在卡片中清楚标记(例如警告提示:_"与 ADR-0007 矛盾——但值得重新开启讨论,因为……"_)。不要罗列 ADR 禁止的每一个理论重构。
完整 HTML 脚手架、图示模式和样式指南见 [HTML-REPORT.md](HTML-REPORT.md)。
暂时**不要**提出接口方案。文件写好后,询问用户:"你想探索其中哪一个?"
### 3. 追问循环
用户选中候选方案后,使用 Skill 工具调用 "grilling",与用户一起走完决策树——约束、依赖、深化后模块的形状、接缝背后的内容,以及哪些测试得以保留。
随着决策逐渐明确,副作用会就地发生——使用 Skill 工具调用 "domain-modeling",在过程中持续更新领域模型:
- **深化后的模块以 `CONTEXT.md` 中尚不存在的概念命名?** 将该术语添加到 `CONTEXT.md`。如果文件不存在,则延迟到此刻再创建。 - **在对话中让模糊术语变得更精确?** 当场更新 `CONTEXT.md`。 - **用户以一个承重理由否决候选方案?** 主动提出记录 ADR,并这样表达:_"要我把它记录成 ADR,让未来的架构审查不再重复建议吗?"_ 只有当未来的探索者确实需要知道该理由以避免重复建议时才提出;跳过短期理由("现在不值得做")和不言自明的理由。 - **想探索深化后模块的其他接口方案?** 使用 Skill 工具调用 "codebase-design",采用其 design-it-twice 并行子代理模式。

Entry SHA-256: 387f38d21367761c94d4b4dcea9e9d7d3e31f896c4decebf4984483e42125cfc

2. Why This Skill Is Clever

一句话核心机制

先用“近期变化 + 领域语言 + 删除测试”把架构扫描收窄为少量可信的模块深化候选,再用可视化报告把发现与设计决策隔开,最后只对用户选中的候选进入追问循环。

触发与边界

直接来源(Direct source): frontmatter 的 disable-model-invocation: true 表明这是一个由用户显式触发的 skill。它的入口任务是“扫描 → 报告 → 用户选择 → grilling”,不是直接改代码。原文还在报告生成后明确要求:Do NOT propose interfaces yet.

支撑上下文(Supporting context): agents/openai.yaml 用 allow_implicit_invocation: false 再次确认不能由模型隐式调用;配套 HTML-REPORT.md 只细化报告脚手架与图示模式,不改变入口流程。

解读(Interpretation): 当用户已经选定一个模块、只需要设计接口时,应直接进入 codebase-design,不必重新做全库扫描。若项目没有提交历史、CONTEXT.md 或 ADR,本 skill 仍可运行,但用于收窄范围和命名接缝的证据会更弱。

信息架构 / 执行顺序

  1. 先定扫描范围。 用户给方向就采用;否则从 git log --oneline 提取近期热点,没有热点再扩大范围。
  2. 先读已有语义约束。 CONTEXT.md 提供领域名词,相关 ADR 提供已经决定、不应随意重开的边界。
  3. 让子代理体验摩擦。 它不套固定规则,而是寻找跨模块跳转、浅接口、缺少 locality、接缝泄漏和难测区域。
  4. 用删除测试过滤。 只有删除浅模块会“集中复杂度”而非“搬移复杂度”的候选才值得继续。
  5. 先报告,不先设计。 候选被做成带改造前/后图示和强度徽章的 HTML 卡片,由用户决定探索哪一个。
  6. 选择后才进入决策循环。 grilling 澄清约束和接口形状;domain-modeling 同步更新领域词汇与必要 ADR;需要多接口方案时再调用 codebase-design。

这条链路把不确定性分成三类依次处理:去哪看、什么值得做、选中后怎么做。每一步都有停止点,避免全库扫描直接滑成未经同意的重构。

最巧妙的设计点

  1. “Scope before you scan — YAGNI.” — 在探索之前先优化注意力分配。
    直接来源: 最近频繁变化的路径获得更高权重,用户指定的方向优先于自动推断。
    解读: 架构改进的收益来自未来变化;把注意力放在活跃代码上,比对整个仓库平均用力更可能兑现收益。

  2. “Use these terms exactly” — 用受控词汇约束分析输出。
    直接来源: 建议必须使用 module、interface、depth、seam、adapter、leverage、locality,且明确禁止漂移到近似词。
    解读: 术语约束不是文风要求,而是一种轻量 schema:它让不同候选可以比较,也减少“service”“boundary”等词悄悄改变设计含义。

  3. “Apply the deletion test” — 把抽象美学变成反事实判据。
    直接来源: 删除候选模块后,复杂度必须被集中,而不是简单搬家。
    解读: 这避免把“文件更少”误判成“模块更深”;测试关注的是隐藏复杂度的能力,而不是代码形状。

  4. “Each candidate gets a before/after visualisation.” — 把架构差异变成可审阅证据。
    直接来源: 每张卡片都要列文件、问题、方案、收益、前后图示和推荐强度。
    支撑上下文: HTML-REPORT.md 进一步给出调用图、剖面图、质量图和折叠图等图示模式。
    解读: 报告不是装饰性输出;统一卡片字段和前后对照迫使扫描结果回答“哪里浅、如何变深、收益是什么”。

  5. “Do NOT propose interfaces yet.” — 在用户选择前冻结高成本设计。
    直接来源: 报告完成后必须停下并询问用户要探索哪一个候选。
    解读: 这是关键的人机审批门。代理可以低成本扩散候选,但不能在用户尚未选择时把上下文和时间投入任一方案。

  6. “load-bearing reason” — 只把持久反对理由写入组织记忆。
    直接来源: 用户若以承重理由否决候选,才建议记录 ADR;短期或不言自明的理由应跳过。
    解读: 这在“避免未来重复建议”和“避免 ADR 噪声”之间建立了明确阈值,也让拒绝本身成为下一次扫描的输入。

防失败机制与 trade-off

原文明确的不变量:

防失败价值: 这些规则分别防止扫描失焦、术语漂移、工作区污染、泛泛建议、过早设计、重复争论和 ADR 膨胀。尤其是“报告后暂停”,把一次自主分析变成可撤销、可选择的决策支持,而不是不可逆的代码修改。

权衡与可移植性风险:

可迁移原则

  1. 先路由注意力,再启动昂贵分析。 用户方向优先;否则用行为证据选择热点。
  2. 给抽象判断配反事实测试。 不要只问“看起来更整洁吗”,要问删除后复杂度去哪了。
  3. 把探索输出做成同构决策卡。 固定证据字段,才能比较不同候选。
  4. 在扩散与收敛之间放人工选择门。 代理可以生成选项,但不能替用户选择高成本方向。
  5. 只持久化未来真正需要的理由。 组织记忆应阻止重复错误,而不是记录所有临时偏好。

今日实践题

假设最近 30 次提交都集中在支付流程,但你发现一个多年未动、测试极少的权限模块:你会怎样写出扫描范围规则,既保持“近期变化优先”,又给这个高风险遗留区一个不破坏 YAGNI 的进入条件?

Evidence note

Source & provenance
Repository path
skills/engineering/improve-codebase-architecture/SKILL.md
Generated
2026-08-17 08:23 Asia/Shanghai
Upstream commit
068b6e0c62393147daf03530149cdce209c93da8
Source
View on GitHub