/ Skills
[Skills-05] Maintaining Agent-Friendly Codebases: Deep Modules, Architecture, and Triage
Distilling codebase-design, architecture improvement, research, triage, and TypeScript module boundaries.
Agent 友好的代码库不是“文件越小越好”,而是关键行为集中、接口清楚、事实来源可靠、进入系统的工作已经被验证和分类。本篇覆盖五个围绕代码库健康度的 skill,其中 setup-ts-deep-modules 仍处于 in-progress。
1. codebase-design:深度是调用者获得的杠杆#
这个 skill 采用一套严格词汇,避免 component、service、API、boundary 在不同人嘴里不断漂移。
- Module:任何具有 interface 与 implementation 的东西,可以是函数、类、package 或跨层纵向切片;
- Interface:调用者正确使用 module 必须知道的一切,不只 type signature,还包括 invariant、顺序、错误和性能特征;
- Seam:可以替换行为而不在调用处修改代码的位置;
- Adapter:在 seam 上满足 interface 的具体角色;
- Depth:调用者每学习一单位 interface 能获得多少行为;
- Leverage:一个实现服务多个调用者和测试;
- Locality:变化、故障与知识集中在一个位置。
Deep module Shallow module
┌──────────────┐ ┌──────────────────────┐
│ small iface │ │ large, fussy iface │
├──────────────┤ ├──────────────────────┤
│ │ │ thin pass-through │
│ rich behavior│ └──────────────────────┘
│ │
└──────────────┘深度不是 implementation lines / interface lines 的比值,否则堆废代码反而能“变深”。它是调用杠杆。Deletion test 很直观:删掉 module 后,如果复杂度消失,它可能只是 middleman;如果复杂度重新散落到 N 个 caller,它就在提供价值。
1.1 Interface 同时是测试面#
好的 module 接受 dependency,而不是内部偷偷创建;返回 result,而不是只制造不可观察的 side effect;以更少方法和参数表达更多行为。
只有一个 adapter 时,seam 可能只是想象中的扩展点;出现第二个真实 adapter 后,变化才证明 seam 有价值。不要为“以后也许”引入 interface。
2. improve-codebase-architecture:寻找 deepening opportunity#
架构改进不是全仓库漫游式找茬。skill 先按 YAGNI 缩小扫描区域,优先最近频繁变化、持续制造摩擦的模块。
扫描结果写成视觉 HTML report。每个候选项包含涉及区域、当前 friction、改进方向、locality/leverage 收益、测试改善、before/after 图,以及 Strong / Worth exploring / Speculative 推荐等级。
此时只报告候选,不急着设计 interface。用户选中一个后,才通过 grilling 深入;需要多种 interface 时再调用 codebase-design 的 design-it-twice 方法。
如果候选违反现有 ADR,只有当真实摩擦足以值得重开决定时才展示,并清楚标注冲突。用户用有长期价值的理由拒绝候选时,可以把理由写成 ADR,防止下一次扫描重复建议。
3. research:每个事实追到第一方来源#
Research skill 很短,纪律却很强:
- 优先 official docs、source code、spec、first-party API;
- 每个重要 claim 都能追到拥有这个事实的 source;
- 结果写成单一、有引用的 Markdown,放进项目已有的研究目录;
- 研究作为 background work,不替代产品决策。
这与“让 Agent 凭参数知识写一段分析”不同。持久文件让后续 spec 或 wayfinder ticket 可以引用证据,也让信息随着依赖升级而重新审计。
4. triage:把原始请求变成可领取工作#
Triage 用两个正交维度标记 issue 或外部 PR:
- Category:
bug或enhancement; - State:
needs-triage、needs-info、ready-for-agent、ready-for-human、wontfix。
每项工作必须恰好有一个 category 和一个 state。状态冲突时先询问维护者,不能自行覆盖。
处理单个 issue 的流程是:
- 读完整 body、comments、labels 与相关代码;
- 搜索是否已经实现,并检查
.out-of-scope/是否有既往拒绝; - 向维护者给出 category/state 建议和依据;
- bug 先复现,PR 先验证 diff 声称的行为;
- 信息不足才进入 grilling;
- 输出 agent brief、human brief、needs-info notes 或 wontfix 记录。
Agent brief 描述行为、复现、验收和领域背景,不绑定很快失效的 file path。对于外部 PR,“PR 是带代码的 issue”:同样先判断请求是否成立,再决定 Agent 继续修改还是交给人 merge。
一个重要边界是:to-tickets 生成的 ticket 已经是 agent-ready,不应再次 triage。Triage 只处理未经加工的外部输入。
5. setup-ts-deep-modules:用工具强制 package 边界#
这个 in-progress skill 把 deep-module 原则落到 TypeScript monorepo。它使用 dependency-cruiser 建立约束:
- package 外部只能通过 entry point 导入;
- implementation 隐藏在子目录,禁止跨 package 深层 import;
- 测试也从公开 interface 驱动,而不是绕过 seam;
- 循环依赖和越层依赖由 CI 自动拒绝。
价值不只是“import 看起来整齐”。如果任意 caller 都能触碰内部文件,interface 就只是一份建议;工具化规则把 seam 变成可执行契约,也降低 Agent 为理解变化而遍历的文件数量。
迁移时需要先盘点 workspace layout、现有 entry points、测试路径和构建工具,再逐个 package 收紧。一次性开启所有限制,常会产生海量噪声,反而无法判断真正的设计问题。
6. 把健康度看成四个可维护面#
进入系统的工作 -> triage 验证、分类、写 brief
外部知识 -> research 固化证据
内部结构 -> codebase-design 定义深模块语言
持续治理 -> architecture scan 找机会,工具守住 seamAgent 提高了变化速度,也提高了熵增速度。维护代码库健康的目标不是多加规范,而是让请求、知识、接口和自动检查都拥有清晰的单一入口。