大多数人的 AI 编码方式是:打开编辑器,描述一个需求,AI 吐出代码,人肉检查。这是 AI 辅助——AI 是打字快的初级程序员,工程过程还是人的那套。
AI 原生的含义不同:整个软件工程过程——需求澄清、规格化、任务拆解、实现、测试、评审、演进——都围绕 AI 的特性重新设计。
mattpocock/skills 的作者 Matt Pocock 在仓库 README 里总结了他观察到的四个 AI 编码失败模式,这套技能集就是对着这四个失败模式设计的。理解它们,就理解了整条工作流的"所以然":
失败模式 #1:智能体做的不是我要的(misalignment)
"No-one knows exactly what they want" —— 《程序员修炼之道》
软件开发最常见的失败是供需错位:你以为开发懂了,看到成品才发现完全不是那么回事。AI 时代一模一样——你和智能体之间隔着一条沟通鸿沟。药方是 grilling(盘问式访谈):让智能体在动手之前,先把你追问到无处可逃。
失败模式 #2:智能体太啰嗦(没有共享语言)
"With a ubiquitous language, conversations among developers and expressions of the code are all derived from the same domain model." —— Eric Evans《领域驱动设计》
项目开始时,开发者和领域专家说的是两种语言。智能体被扔进项目时也一样,只能边猜边学,于是一句话能说清的事它用二十句。药方是一份共享术语表(CONTEXT.md)。它的好处不只是省字:变量、函数、文件命名全都跟着术语表走,代码库对智能体更好导航,它思考时烧的 Token 都更少。
失败模式 #3:代码不工作(没有反馈环)
"The rate of feedback is your speed limit." —— 《程序员修炼之道》
就算需求对齐了,智能体还是会产出垃圾——如果它得不到"代码跑起来到底对不对"的反馈,就是闭着眼睛飞。药方是反馈环:静态类型、自动化测试,尤其是 TDD 红绿循环——先写一个失败的测试,再让它通过,智能体的每一步都有即时反馈。
失败模式 #4:滚成泥石流(熵增加速)
"The best modules are deep." —— John Ousterhout《A Philosophy of Software Design》
智能体让写代码变快,也让软件熵增变快——代码库以前所未有的速度腐化。药方是真正关心代码设计:深模块、清晰的接缝、定期的架构走查。
换一个角度,从 AI 的客观特性出发,可以直接反推出工程过程必须长什么样:
| AI 的特性 | 对工程过程的要求 |
|---|---|
| 上下文窗口有限,塞满后质量衰减 | 任务必须切成"单个上下文能装下"的批次 |
| 每次会话开始时最"清醒" | 频繁开新会话,而不是一条会话干到底 |
| 不会主动追问,猜错了就错到底 | 需求阶段强制访谈,分歧在写代码前解决 |
| 产出无限、判断有限 | 人只做检查点决策,不做中间执行 |
| 记不住上一次的对话 | 共识必须落盘为文件,而不是留在脑子里 |
mattpocock/skills 就是围绕这两张表设计的。它的口号是 "skills for engineers who actually ship"——面向真正要交付软件的工程师。和 GSD、BMAD、Spec-Kit 这类"接管整个流程"的重型框架不同,它的设计取向是小、可改、可组合:每个技能是一份 Markdown 文档,你可以读、可以改、可以只取其中几个用。
两种安装方式,二选一,不要都装(否则每个技能会出现两遍):
# 方式一:Claude Code 官方插件市场(订阅式,自动更新,只读)
claude plugins install mattpocock-skills
# 方式二:skills.sh 安装器(把技能文件拷进你的仓库,可编辑、可魔改)
npx skills add mattpocock/skills
想长期定制自己团队的工作流,选方式二——技能落地为仓库里的普通文件,改完就是你自己团队的版本;想省心跟着作者更新,选方式一。
/setup-matt-pocock-skills
它会问你三件事,回答后生成仓库约定文件:
gh CLI)、GitLab、本地 Markdown 文件(.scratch/ 目录,适合个人项目),或其他(Jira/Linear,用一段话描述你的工作流即可)。needs-triage、needs-info、ready-for-agent、ready-for-human、wontfix。直接用默认值就好。CONTEXT.md + docs/adr/),monorepo 才需要多上下文布局。产出结构:
.
├── CLAUDE.md # 追加「## Agent skills」约定块
└── docs
└── agents
├── domain.md # 领域文档的布局与消费规则
├── issue-tracker.md # issue 在哪、怎么读写
└── triage-labels.md # 五个状态标签
这些文件是给智能体看的约定——后续每个技能启动时都会先读它们,知道"issue 写去哪、术语表在哪、状态标签叫什么"。之后想改约定,直接编辑 docs/agents/*.md 即可,不用重跑初始化。
这套技能集分两类,理解这个分类有助于后面看懂它们怎么互相调用:
/grill-with-docs、/to-spec、/to-tickets、/implement、/improve-codebase-architecture 等。/tdd、/code-review、/grilling、/domain-modeling、/codebase-design 等。规则是:用户触发的技能可以调用模型触发的技能,但反过来不行。所以你会看到 /implement 内部自动驱动 /tdd 和 /code-review,/grill-with-docs 内部自动驱动 /grilling 和 /domain-modeling——你只敲一条命令,纪律自动跟着来。
主流程是一条线:idea → ship。此外有三条"入口匝道":issue 堆积用 /triage、疑难杂症用 /diagnosing-bugs、大到看不清全貌的项目用 /wayfinder。本文聚焦主流程加上交付后的架构演进循环——这是 80% 的日常开发会走的路。
整条工作流的全貌——注意图里每一条边上的标注:每一环的产出物都是文件,下一环消费的是文件而不是对话记忆。这是整条工作流最重要的结构特征。
这套流程对上下文窗口的使用有明确纪律(来自 ask-matt 技能的 Context hygiene 规则):
/clear 也不要 /compact。/implement 开全新窗口。实现智能体冷启动,从 ticket 文件进场,再按 docs/agents/ 里的约定读 CONTEXT.md、相关 ADR 和 spec;它唯一看不到的是你 grill 时的对话——这正是共识必须落盘为文件(spec、tickets、术语表、ADR)的原因。纪律有一个例外出口:smart zone(黄金上下文区间)——大约是前 150k Token,模型还能清晰思考的区间。如果 grill 到一半发现事情比预想的大、会话逼近上限,不要硬撑:在阶段边界 /compact,或者升级路径补走 /to-spec。
在每个阶段边界上,你有五个选项:继续(continue)、/clear(清空)、/handoff(写成交接文档)、子智能体(派发任务拿回报告)、/compact(压缩续接,默认兜底)。记住结论就够了:单会话判断不是签生死状,中途可以改道。
grill-with-docs 解决的是失败模式 #1(供需错位)。它底层的 /grilling 技能把你的方案建模成一棵设计树:每个决策都分叉出挂在它下面的子决策。
举个例子。"要不要做语音播报"没拍板之前,"播报是按每个键触发还是按结果触发"就没法问——它依赖前一个答案,只能挂在树的深处等;一旦"要做语音播报"落定,它就被解锁,进入"现在就能问"的那一圈。frontier 就是这一圈:所有前置条件已敲定、不用猜就能问的决策的集合。后面 4.4 的实战里你能看到它真实的样子:第一轮问功能范围,第二轮才轮到"语音播报粒度与读法"。
访谈按轮次推进。每一轮,智能体把 frontier 上的所有决策一次性全部抛出,每个问题附带它自己的推荐答案,然后停下来等你回答。你的答案落定后,frontier 向外推进,解锁下一轮问题。终止条件是 frontier 清空:设计树的每个分支都走过,没有任何"默默假设"残留。
这个机制里有两个关键分工:
其他访谈类技能把会话留在你脑子里;grill-with-docs 把文件留在磁盘上——它内部同时驱动 /domain-modeling 技能:
CONTEXT.md(领域术语表),而不是访谈结束批量补交;三道闸门缺任何一道,就不写 ADR——这个克制很重要,后面演进循环里会看到它的效果。CONTEXT.md 有严格的纯度要求:只放领域术语与共识,不放任何实现细节——它不是 spec、不是草稿本,只是词汇表。
/mattpocock-skills:grill-with-docs 给老人开发一款计算器 macOS 原生应用。
发起后,你的工作量极小:每轮看 frontier 上的全部问题(不设固定个数,实战里一轮大约 5~7 个),每个都带推荐答案,回答"都按推荐"即可,或者针对某几条给出不同选择。访谈结束的标志是:智能体宣布 frontier 已清空,给出完整共识总结,请你确认。在它给出总结、你确认之前,它不会动手写任何代码。
中途有两个改道口:
/prototype,用一次性原型代码回答这个问题,再回到访谈;/compact,或升级走多会话路径。「长辈计算器」的访谈共四轮 27 问,我四轮都只回了三个字:"都按推荐"。
每一轮结束,智能体当场重写 CONTEXT.md。看一个真实条目——"砍掉记忆功能"这个取舍落地成这样:
不做记忆功能(M+/M− 等)——历史记录已覆盖"之前算的数字想再用"的场景,记忆键的隐式状态对老人是纯负担。
注意它不只记录了决策,还记录了理由。三个月后任何人(或任何智能体)读到这里,都不需要重新争论一遍。这就是共享语言的复利。
四轮结束后智能体给出共识总结,最后一句话是:
请确认:以上理解是否与你心目中的产品一致? 确认后我就开始动手搭建工程和实现。如有任何一条想改,现在说是最便宜的时机。
"现在说是最便宜的时机"——这句话就是整个环节的存在意义。
访谈完成后按规模分岔:
/implement(内部驱动 TDD 和 code-review),不落 spec。此时盘问结论还活在当前上下文窗口里,再写 spec 等于把模型已经知道的东西序列化一遍再读回来,纯属搬运。但注意这不等于"零存档"——CONTEXT.md 和 ADR 在访谈过程中已经落盘了。/to-spec → /to-tickets → 逐票 /implement。一句话记住:"为什么这么做"永远落盘(ADR + 术语表);"具体做什么"只在需要跨窗口传递时才落盘(spec + tickets)。
/to-spec 的技能说明里有句话极其重要:"no interview, just synthesis"——不做访谈,只综合你们已经讨论过的内容。思考在 grill 阶段已经完成,spec 的职责是把盘问结论压缩成一份能跨窗口传递的文档。
它存在的唯一理由是对抗上下文丢失:/implement 是在新窗口冷启动的,看不到你 grill 时的任何讨论。所以多会话构建必须把思考固化成可携带的制品。
这也解释了 spec 模板里一条看似奇怪的禁令:不许写具体文件路径和代码片段——它们过时得太快。spec 是易腐的执行计划,写的是决策和行为,不是实现快照。
to-spec 最不传统的地方是它的写入顺序:动笔写 spec 之前,先和你确认测试接缝。
Seam(接缝)是 Michael Feathers(《修改代码的艺术》)的术语:一个无需在那个位置编辑代码就能改变行为的地点。对测试来说,接缝就是"测试从外部观察系统的位置"。
确认接缝的三条原则(来自技能原文):
这一步的价值在于:架构决策(哪里是深模块、哪里是薄壳)在写代码之前就以"可测试性"的形式被双方锁定,而不是实现到一半才想起"这玩意儿怎么测"。
/mattpocock-skills:to-spec
智能体先提出接缝方案请你确认,确认后写出完整 spec,发布到初始化时约定的 tracker(本地模式是 .scratch/<feature-slug>/spec.md),并标记 Status: ready-for-agent。
spec 的固定六段结构:
| 段落 | 内容 |
|---|---|
| Problem Statement | 用户视角的问题 |
| Solution | 用户视角的解决方案 |
| User Stories | 编号用户故事长清单,格式「作为 <角色>,我想 <功能>,以便 <收益>」,要写到穷尽 |
| Implementation Decisions | 模块划分、接口、架构决策——不含文件路径和代码 |
| Testing Decisions | 什么是好测试、测哪些模块、测试先例 |
| Out of Scope | 明确排除什么 |
「长辈计算器」是全新代码库,没有既有接缝,智能体提议在最高层设两个:
接缝 1:计算引擎——纯逻辑状态机。测试从"用户按键"这个最高点进,断言"屏幕显示什么、历史里多了什么",完全不碰内部实现。
接缝 2:中文数字朗读转换——纯函数,规则最复杂、最容易出错,独立成接缝。
不在接缝上的:SwiftUI 界面、配色、语音实际播放——这些手工验证。理由:接缝越少越好。
我确认后,spec 落盘:36 条用户故事按"基本计算 / 看得清 / 听得见 / 错得起 / 回看核对 / 键盘与其他"六组组织;实现决策写明"两个深模块 + SwiftUI 薄壳";Out of Scope 明确排除 10 项(记忆功能、科学计算、运算优先级、结果复制、历史持久化、按键音效……)。
Out of Scope 这一段常常被忽视,但它在后面的评审环节会发挥真实作用——第八节你会看到。
这是最容易误解的一环。spec 里的 36 条用户故事描述的是"系统该有什么行为";/to-tickets 拆的是实现批次——一张 ticket 会打包多条相关的故事。
“曳光弹”(Tracer Bullet)是软件工程中一个非常经典的隐喻,最早由《程序员修炼之道》(The Pragmatic Programmer)一书提出。它指的是在开发过程中,先实现一个完整的、可运行的功能路径(即“曳光弹”),然后再逐步完善和扩展其他功能。这个方法强调快速迭代和持续交付,确保每个阶段都有可验证的成果,从而降低风险并提高开发效率。
拆票遵循 tracer-bullet(曳光弹)原则,四条规则:
每张票还要声明自己的 blocking edges(阻塞边):哪些票必须先完成它才能开工。没有阻塞的票可以立即动工,已完工票解锁的票构成新的 frontier。
(例外情况:波及全库的宽重构——改一个列名牵动几千个调用点那种——不硬塞进曳光弹,改用 expand–contract 三段式:先并存、分批迁移、最后删除。日常开发很少用到,知道有这个出口即可。)
这套流程里,手工介入次数 ≈ ticket 数量:拆票确认 1 次 + 每张票启动 1 次。而且这是设计意图,不是缺点:
/mattpocock-skills:to-tickets
智能体给出拆票草案后,会反问你三个问题:粒度合适吗?阻塞边对吗?有想合并或再拆的吗?——又一个低成本确认点。你确认后,它把每张票写成独立文件:
.scratch/elder-calculator/issues/
├── 01-project-scaffolding.md
├── 02-digit-input-display.md
└── ... (每票一文件,编号按依赖顺序)
单票模板极简:What to build(用户视角的端到端行为)、Blocked by、Status: ready-for-agent、验收清单。同样不写文件路径和代码片段。
「长辈计算器」被拆成 12 张票:
| # | Ticket | Blocked by |
|---|---|---|
| 01 | 工程脚手架 | 无 ✅ 可立即开始 |
| 02 | 数字输入与大屏显示 | 01 |
| 03 | 四则运算与等号 | 02 |
| 04 | 小数、正负号、百分比 | 03 |
| 05 | 退格与分级清除 | 02(可与 03 并行) |
| 06 | 错误与边界 | 04 |
| 07 | 中文数字朗读转换模块 | 01(可与主干并行) |
| 08 | 语音播报接入 | 07, 03 |
| 09 | 计算历史 | 03 |
| 10 | 设置面板与高对比双主题 | 08 |
| 11 | 键盘输入 | 06 |
| 12 | 窗口行为与应用收尾 | 09, 10, 11 |
注意几张票的切法:一张"四则运算与等号"票(03)打包了链式语义、运算符替换、重复等号等十几条故事——因为它们是同一个状态机的同一层逻辑;而"中文朗读转换"(07)单独成票——它是独立的纯逻辑模块,且能和主干并行。这就是垂直切片和水平分层的区别。
/implement 内部首先驱动 /tdd 技能。TDD 在这里的角色不是"测试信仰",而是失败模式 #3 的药方:红→绿循环让智能体的每一步都有即时、客观的反馈。
技能对"什么是好测试"有严格定义:通过公开接口验证行为,不碰实现细节。代码可以整个重写,测试不该动——一条好测试读起来像规格书:"用户可以用有效购物车结账",它活过任何重构,因为它不关心内部结构。
三个反模式被点名禁止:
expect(add(a,b)).toBe(a+b)),永远通过、永远抓不到 bug。期望值必须来自独立的真相源:已知正确的字面量、手工演算的样例、spec;还有两条循环纪律:红灯在绿灯之前(不许预写实现);重构不属于红绿循环——它归后面的 code-review 阶段。
最重要的一条:只在预先约定的接缝上写测试。接缝在 to-spec 阶段已经双方确认过,没有确认的接缝不写测试——这是测试火力集中在关键路径上、而不是撒胡椒面的机制。
/mattpocock-skills:implement .scratch/elder-calculator/issues/03-arithmetic-equals.md
⚠️ 坑:/implement 必须显式传入单个 ticket 文件路径。不带参数裸跑 /mattpocock-skills:implement,它会尝试执行所有 tickets——多票并存时尤其危险。
一张票的内部流程(全自动,无需人介入):
/code-review 双轴评审;/code-review 把评审拆成两条轴,用并行子智能体分别执行——互不污染对方的上下文,然后并排报告:
为什么必须分轴?因为一轴的通过不能掩盖另一轴的失败:代码可能完全符合规范但做错了事(Standards 过、Spec 挂);也可能完全做对了事但破坏了项目约定(Spec 过、Standards 挂)。合并报告会让一类问题被另一类冲淡。
TDD 阶段——4 个红→绿切片:基本加法与完整算式 → 四则与链式执行 → 运算符替换/出结果开新笔/重复等号 → 结果格式化(10 位有效数字、去尾零、千分位)。最终 23 个引擎行为测试全绿,全部只经 press / displayState 断言外部行为。
评审阶段——两条轴的表现正好演示了设计的意图:
| 评审轴 | 实战结果 |
|---|---|
| Spec 轴 | 发现真实偏差:算式行中的数字未带千分位(CONTEXT.md 明确要求)→ 补测试修复 ✅;另注明"12 + ="静默无反应是 spec 未定义行为,记录在案留待 ticket 06,而不是当场拍脑袋决定 |
| Standards 轴 | 两项轻量重构被采纳(消除数据泥团、橙色按钮去重);一项 Primitive Obsession 建议暂不做——现有实现已被 23 个测试钉住,留待 ticket 09 再评估 |
最关键的细节是评审意见的处理方式:Spec 轴发现的是"和共识的偏差",必须修;Standards 轴给的是"判断性建议",可以基于测试覆盖情况有理有据地拒绝。AI 评审不再是无差别的意见倾泻,而是有优先级的工程判断。
收尾:两个提交落到 main(cc2f124 feat: 四则运算与等号(ticket 03)、c098cda chore: 勾选 ticket 03 验收项),issue 文件验收项逐条勾选。
交付不是终点。智能体加速写代码也加速熵增(失败模式 #4),所以这套工作流有一条专门的演进循环。建议每隔几天就在代码库上跑一次架构走查。
交付 12 张票后,先做一次全量评审:
/mattpocock-skills:code-review 64f0c0a
64f0c0a 是固定点(基点)——评审审的不是整个代码库,而是 git diff <基点>...HEAD 这个差异。基点的选择直接决定审查范围:
f241e09 chore: setup 配置
64f0c0a docs: spec + 12 张 ticket ← ★ 基点:spec 定格,实现未开始
bda3dd3 feat: 工程脚手架(ticket 01)
… tickets 02–12 …
c9bd0b5 chore: HEAD
选 64f0c0a 的理由:这一刻 spec 和 tickets 已写好、一行实现代码都还没写,从它往后的 diff 正好覆盖全部实现,不多不少。基点太早,diff 混入无关旧代码,报告充满噪音;基点太晚,部分实现被漏审。技能要求基点错误要在源头就失败,而不是等两个子智能体跑出垃圾报告才发现。
全量评审的实战产出:
注意这两类发现恰好对应 spec 里 Out of Scope 和 Implementation Decisions 的价值——当时白纸黑字写下的边界,现在成了审判的标尺。
/mattpocock-skills:improve-codebase-architecture
所以然:深模块词汇表。这个技能建立在一套精确的架构词汇上(来自 /codebase-design,它要求所有建议严格使用这些术语,不许漂移成 "component""service""API"):
| 术语 | 定义 |
|---|---|
| Module(模块) | 任何有接口和实现的东西,刻意尺度无关:函数、类、包都算 |
| Interface(接口) | 调用方正确使用模块必须知道的一切:类型签名,还有不变式、顺序约束、错误模式、性能特征 |
| Depth(深度) | 接口处的杠杆率:少量接口背后压着大量行为 = 深;接口和实现一样复杂 = 浅 |
| Seam(接缝) | 模块接口所在的位置;接缝放哪是独立的设计决策 |
| Adapter(适配器) | 在接缝处满足接口的具体东西,描述角色而非内容 |
| Leverage(杠杆) | 深度给调用方的好处:学一份接口,获得 N 处能力 |
| Locality(局部性) | 深度给维护者的好处:修改、bug、知识、验证集中在一处 |
三条核心判断原则:
怎么做。智能体先扫 git 历史找热点(最近常改的地方值得优先深化),再派子智能体走查代码库,产出一份可视化 HTML 报告(写进系统临时目录,不污染仓库):每个候选项一张卡片——涉及文件、问题、方案、before/after 对比图、强度分级。报告看完,你挑一个候选,它用 grilling 流程陪你把决策走完。
实战:四个候选与一个最大结论。「长辈计算器」的走查报告给出四个候选:
| # | 候选 | 强度 |
|---|---|---|
| 1 | 播报词决策与语音合成器分层——错误优先、每键播报词这些适老化核心规则锁在与 AVSpeechSynthesizer 硬耦合的模块里,零测试覆盖 | Strong |
| 2 | 数值规范口径收敛——"10 位有效数字"在引擎和语音格式化器各实现一遍,靠注释对齐 | Worth exploring |
| 3 | 运算符表述集中——符号/语义在 Engine 目录,播报用词在 Speech 目录,一个概念被切开 | Worth exploring |
| 4 | 错误态改为 DisplayState 显式 case | Speculative |
报告里的最大结论值得抄下来:
这个项目的计算与朗读转换两侧已经够深,唯一的结构性短板在语音播报的"决策/硬件"不分层——它恰好是产品的核心卖点,却是唯一没有测试接缝的行为规则集中地。
我选了候选 1、2、3,进入 grilling。又是熟悉的节奏:三轮 13 问,每问附推荐答案,我三次"都按推荐"。
但真正的价值在过程中——访谈本身就是持续发现机制。智能体在追问前重读了相关代码,挖出两个走查报告都没抓到的实锤:
%.10g 产出 "9.999999999e+23",逐字符映射把 e、+ 吞成"零"——今天就会念出"九点九九九…零二三"。这就是为什么这套流程不厌其烦地访谈:每一轮追问都迫使智能体把代码事实重新核实一遍,猜测在这个过程中被事实替换。
13 项决策尘埃落定后,用 ADR 三道闸门检验,只有 2 项够格:
| 决策 | 检验 |
|---|---|
| 语音数值口径对齐屏幕(超范围念固定提示语) | ✅ 三条全中:未来读者会疑惑"为什么语音不念精确大数",可能把它"修"回发散状态 |
| 播报词决策与语音合成分层 | ✅ 三条全中:未来会有人图省事把合成器直接内联回去 |
其余 11 项(双守卫、假适配器位置、目录选择……)因为"易逆转、不意外"全部跳过——三道闸门的克制让 ADR 保持信噪比。
两份 ADR 各自记录了被否决的备选方案和否决理由。价值在下次架构走查时兑现:"要不要让语音念精确值""要不要把合成器内联回去"这类问题永远不会再被重新提议。
决策树变成两张新 ticket(13 数值规范文本、14 播报词决策分层),走熟悉的 TDD 流程落地。注意这里没有再过一次 /grill-with-docs:决策访谈已经在架构走查内部做完了,直接回到拆票环节即可——图 1 的回流箭头画的是候选还没被访谈过的标准路线。结果:
| 提交 | 内容 |
|---|---|
c8fb22b docs | ADR-0001、ADR-0002、CONTEXT.md 新增两个术语 |
a076f7f feat (ticket 13) | NumericText 统一数值口径;修掉 e-notation 念错、1e13–1e16 发散两个存量 bug |
32e375b refactor (ticket 14) | SpeechScript 纯函数决策模块、SpeechSynthesizing 接缝 + 双适配器 |
测试从 66 个增长到 76 个,全绿。过程中还有一处诚实更正被记录在案:走查阶段判断"万亿节单位可删",实现前复核发现万亿级整数结果真实可达,予以保留——分析错了就改,记录里写明。
两张票最后都标记 ready-for-human:大数播报和整体听感留给我手工验收。自动化测试管行为,人的感官管体验,边界清晰。
走完两个循环,提炼六条信条。即使你不用这套技能集,这些原则也成立:
1. 共识的所有权在文件系统,不在对话。人在访谈中说过的话可以忘,写进 CONTEXT.md 的一句都不能丢。每次会话切换、每个新智能体接手,都是从文件冷启动,零记忆丢失。
2. spec 和 tickets 是跨会话的通信协议,不是流程的仪式感。单会话能做完的事,ADR 和术语表已经留下了该留的东西;要跨窗口传递时,才需要 spec 和 tickets 这两个序列化格式。
3. 接缝越少越好,且在写代码前锁定。测试接缝是架构决策的可测试化表达。理想数量是一个。
4. 评审分轴:偏离共识必修,改进建议可拒。Spec 轴守护"做对了事",Standards 轴守护"事做得好",分开报告,互不稀释。
5. 频繁人工介入是特性,不是缺点。每张票之间的检查点让你能亲手点点看;每张票的新会话让智能体永远清醒。人的介入全部发生在决策点,而不是执行点。
6. ADR 防翻案:被否决的备选也要写下来。记录"为什么不这么做"和记录"为什么这么做"同样重要——它让未来的走查不重复提议,让三个月后的自己不重新争论。
「长辈计算器」全程的量化记录:
| 环节 | 数量 |
|---|---|
| 需求访谈 | 4 轮 27 问,人只回答了 4 次(全是"都按推荐"+ 确认) |
| 领域术语表 | CONTEXT.md 持续演进,17 个术语条目(含取舍理由) |
| spec | 1 份,36 条用户故事,10 项 Out of Scope |
| tickets | 12 + 2 张,每张含依赖声明与验收清单 |
| 行为测试 | 76 个,全部经公开接口断言 |
| ADR | 2 份(13 项决策过三道闸门筛选) |
| 评审发现 | 千分位偏差、口径偏差、设计流水线衔接缺失、2 项 scope creep、2 个存量播报 bug |
| 人的介入 | 全部在决策点:访谈确认、接缝确认、拆票确认、每票启动、架构候选挑选、ADR 确认、最终人工验收 |
推广不等于吹捧,实战中暴露的问题如实记录:
1. /implement 的调用方式有坑。不带参数会尝试执行所有 tickets,必须显式传入单个 issue 文件路径。
2. 工具链噪音需要人有判断力。实现过程中 SourceKit 持续报错,但 xcodebuild 实际编译通过——智能体正确识别了这是"缓存噪音"。反过来,如果它判断错了,"测试全绿"就建立在幻觉上。人的检查点价值正在于此。
3. spec 不可能完备。"12 + ="(没输右操作数就按等号)是 spec 没覆盖的行为。正确处理是"静默无反应 + 记录在案、留待错误态 ticket"——显式记录"已知未定义行为",比假装 spec 完备重要。
4. 规模适配。这套流程的重型仪式(四轮访谈、十几张票、双轴评审)对中等复杂度项目刚好。一个 200 行的脚本用它是杀鸡用牛刀;一个超大系统需要在 to-tickets 之上加 /wayfinder 级别的路线规划。但"访谈落盘 → 接缝先行 → 曳光弹切票 → 每票新上下文"这四条原则是规模无关的。
5. 架构走查是体检不是抢救。作者的原话:在真正老旧的代码库上它能找到真候选,但不会替你解开那团泥。它的最佳用法是从项目早期就定期跑,让泥石流不发生。
如果你想在团队里推广这套工作流,我建议的路径:
第一步:选一个中等复杂度的真实项目。不是 demo(没有真实约束,流程的价值显现不出来),也不是核心系统(试错成本太高)。一个两周量级、有真实用户的新功能或独立小工具最合适。
第二步:先走通构建循环。安装、初始化、grill、to-spec、to-tickets、逐票 implement。走一两张票感受一下"每票新会话"的节奏,觉得介入太烦再考虑合并票——不要一开始就打折扣。
第三步:补上仓库自己的标准文档。Standards 轴需要"成文的仓库标准"可审。团队跑顺之后,把编码规范沉淀成 CODING_STANDARDS.md 或 CLAUDE.md 的章节,评审的 Standards 轴才有牙齿。
第四步:交付后启动演进循环。全量 code-review 定基线,定期跑 improve-codebase-architecture,让架构走查成为团队节拍的一部分(作者建议每隔几天一次)。
第五步:把技能变成团队自己的。如果用的是 npx skills add 安装方式,技能就是仓库里的普通 Markdown 文件——按团队的习惯改它:你们的术语、你们的评审侧重、你们的 ticket 模板。这套东西的设计取向本来就是 "hack around with them, make them your own"。
这次实践给我最大的冲击不是"AI 写代码有多快",而是工程过程本身被重新定义了:
人在这条流水线里的角色,从"写代码的人"变成了共识的仲裁者和方向的把关人。这才是"AI 原生"的含义:不是 AI 替人干活,而是把工程过程改造成人和 AI 各自做最擅长的事。