setup-matt-pocock-skills
用户调用P0 地基engineering
每个仓库跑一次的环境配置器:让后续工程技能知道工单在哪、标签怎么叫、领域文档放哪。
- 治什么病
- 硬契约缺失。
to-tickets 必须往特定工单系统投递、triage 必须打特定标签字符串;没有映射,产出是错的而不只是模糊。
- 配置三项
-
- 工单系统:GitHub(
gh CLI)/ GitLab(glab)/ 本地 Markdown(.scratch/<feature>/)/ 其他(Jira、Linear 等,用一段话描述即可)。
- 分诊标签词汇:五个规范角色(
needs-triage、needs-info、ready-for-agent、ready-for-human、wontfix)到真实标签字符串的映射。
- 领域文档布局:单上下文(根
CONTEXT.md + docs/adr/)或多上下文(根 CONTEXT-MAP.md 指向每个 context 的 CONTEXT.md)。
- 关键机制
-
- 先探索再问:
git remote -v、是否已存在 AGENTS.md/CLAUDE.md 及其 ## Agent skills 段、.scratch/、monorepo 信号、triage 是否安装。
- 一节一答,每题先给推荐答案,让人一个字接受。探索已定论的节直接跳过(没装
triage 就跳过 Section B;非 monorepo 就跳过 Section C 的多上下文询问)。
- 先展示草稿,让人改,再落盘。
- 永不在已有
CLAUDE.md 时新建 AGENTS.md(反之亦然);已有 ## Agent skills 段就原地更新,绝不追加重复。
- 输入 → 产出
仓库现状 + 你的选择 → docs/agents/issue-tracker.md、docs/agents/domain.md、docs/agents/triage-labels.md,以及写回根目录指令文件的 ## Agent skills 三段式指针块。
- 协作
- 被 to-spec / to-tickets / triage / code-review / wayfinder 当作硬前置;improve-codebase-architecture / tdd / diagnosing-bugs 是"软依赖"(
.agents/adr/0001 的分类)。
- 用法要点
- 它是提示驱动而非确定性脚本,会真的去读你的仓库。
docs/agents/*.md 之后可以直接手改,只有换工单系统才需要重跑。
grilling
模型调用P1 对齐原语productivity
整套体系里最重要的一块积木:无情访谈原语。把任何计划/决策/想法拷问到设计树的每一个分支都被关闭。
- 核心隐喻
- 设计树(design tree):每个决策都分叉出挂在它下面的决策。前沿(frontier)是所有前置条件已经落定的决策,也就是"现在就能问、不必猜测答案"的问题集合。
- 轮次机制
-
- 一轮 = 把整个前沿一次性问完,每题编号并附上推荐答案(
➡️),题与题之间用水平分隔线隔开。
- 用户的回答重塑树:落定的决策把前沿向外推,解锁原本依赖它的问题。
- 依赖本轮尚未回答之题的问题,属于下一轮,不在本轮。
- 前沿为空才算结束,且结束前不许据此行动,要等用户确认"已达成共识"。
- 职责分界
- 找事实是智能体的活,不是用户的。前沿里需要环境事实(文件系统、工具)的题,派子代理去查,绝不问用户;探索进行中不阻塞,只有下游的那几道题等它回报。拍板永远是用户的。
- 产出
- 一份已关闭的决策树 + 用户的共识确认。本身不落文档(落文档是
domain-modeling 的活)。
- 协作
- 被 grill-me / grill-with-docs / triage / wayfinder / improve-codebase-architecture / loop-me 调用,几乎总是与 domain-modeling 成对出现。
- 用法要点
- 直接裸用它的场合只有一个:你想要这场访谈,但不要外面那层包装。有工作目录就用
grill-with-docs,没有就用 grill-me。
grill-me
用户调用P1 对齐(无状态)productivity
全文只有一行:调用 Skill 工具执行 grilling。给没有工作目录的场合用:打磨计划、设计、一篇文章。
- 与兄弟的差别
- 它不在本地存任何东西,不建
CONTEXT.md,不留 ADR。grill-with-docs 跑的是同一场访谈,但会留下纸质痕迹,因此只要有仓库,后者严格更好。
- 典型场景
- 纯想法阶段、写作为主的任务、在没有 repo 的地方开会话。
- 协作
- 调用 grilling;与之相对的是 grill-with-docs(多调用一个 domain-modeling)。
grill-with-docs
用户调用P1 对齐(有状态)engineering
同样是七行正文:调用 Skill 工具两次,分别执行 grilling 与 domain-modeling。README 称它是全仓最受欢迎的技能,也是主链路的正式起点。
- 为什么它是默认起点
- 它是有状态的:学到的东西会留在
CONTEXT.md 与 ADR 里。ask-matt 的原话是"只要有.repo 留痕,它就是两者中更好的那个"。
- 双重收效
-
- 当场:访谈中的模糊词被就地 sharpen。
- 跨会话:这套术语一再复用,下一次会话开场就在一个更精简的语言上工作。
- 副产品红利
- README 举了一个真实例子(
course-video-manager 仓库的 CONTEXT.md):
之前:"当一个课程某节里的课时被变成 real(即在文件系统里获得位置)时会有问题"
之后:"materialization cascade 有问题"
concision pays off session after session。
- 协作
- 调用 grilling + domain-modeling;下游汇入 to-spec;research、to-questionnaire、improve-codebase-architecture 的产出都要先回到这里被消化。
domain-modeling
模型调用词汇底座engineering
主动构建与打磨项目的领域模型。注意它强调的是"主动":仅仅为了词汇去读一眼 CONTEXT.md 并不是这个技能,那只是任何技能都能做的一行式习惯。
- 五种动作
-
- 对照词汇表挑刺:"你的词汇表把 cancellation 定义为 X,但你似乎说的是 Y,哪个?"
- 磨快模糊措辞:"你说的 account,是 Customer 还是 User?这是两个东西。"
- 拿具体场景压测:自己发明边界场景,逼用户把概念边界说清。
- 与代码交叉验证:"你的代码整单取消 Order,但你刚说可以部分取消。哪个是对的?"
- 就地更新 CONTEXT.md:术语一落定就写,不攒批处理。
- 文档定位铁律
CONTEXT.md 必须完全没有实现细节。它不是 spec、不是草稿纸、不是实现决策的存放地,它只是一份词汇表。每条术语一两句话,只写"它是什么"不写"它做什么",并给出 _Avoid_: 同义词黑名单。
- ADR 三条件
- 三者全中才提议 ADR,缺一就跳过:① 难以反悔 ② 没有上下文会让人觉得奇怪 ③ 是真实取舍的结果。
ADR-FORMAT.md 的模板极简(标题 + 1-3 句),docs/adr/ 目录懒创建,编号取最大值 +1。
- 文件结构
- 根有
CONTEXT-MAP.md 即视为多上下文,各 context 下有自己的 CONTEXT.md 与 docs/adr/。都是懒创建:第一个术语落定才建 CONTEXT.md,第一个 ADR 需要时才建目录。
- 分工
CONTEXT.md 回答 what(这叫什么);ADR 回答 why(为什么不走另一条)。两者由 grill-with-docs / triage / wayfinder / improve-codebase-architecture 驱动更新。
wait-what
用户调用P1 纠偏productivity
一句话技能:"等等,我没跟上,换个说法"。智能体用你缺少的上下文、按 ASD-STE100 简化技术英语、并使用 CONTEXT.md 的统一语言,把刚才那段话重讲一遍。
- 定位
- 它是事后补救;治本的是
grill-with-docs(早期约定统一语言,行话根本就不会出现)。
- 用法
- 可以在任何技能运行过程中随时插入:偏转了就纠一下,不必中断流程。
- 细节
- 仓库若有多个上下文,需经
CONTEXT-MAP.md 找到正确的那一份 CONTEXT.md(这是从 CHANGELOG 里一个真实 bug 修出来的行为)。
research
模型调用P2 取证engineering
把阅读苦力外包给后台子代理:你去干活,它在后台读完一手源,留下一份带引用的 Markdown 文件。
- 关键约束
- 只认一手源(官方文档、源码、规范、第一方 API),不许引用别人的二手综述。每条论断都要追到持有它的那一份源。
- 落点
- 存到仓库里已有的同类笔记约定处;没有约定就放个合理位置并说明放哪了。
- 协作
- wayfinder 会把每个
research 票派一个后台子代理并行解决(且研究票是"每会话可解多个"的唯一例外);产出是喂给 grill-with-docs 的原料,不是替代理它思考。
- 用法要点
- 它是全程唯一"必须 async"的技能("Spin up a background agent so you keep working while it reads")。把它当同步工具用就丢掉了这个技能的一半价值。
to-questionnaire
用户调用P2 外部知识productivity
卡住你的东西不在你脑子里、也不在代码里,而在另一个人脑子里。它给那个人写一份可异步填写的问卷。
- 反转设计
- 拷问的是"这次发送",不是主题本身。普通的 grilling 拷问题目,而题目恰恰是你答不上来的那部分;所以它只问两件事:① 发给谁(角色/专长/与你的关系)② 你要拿回什么,然后把所有问题都瞄准这两者之间的缺口。
- 文档结构
- 目的 → From/To/回答用途 → 一段给陌生人定向的上下文 → 怎么答(截止 + 耗时,鼓励"I don't know")→ 按主题的
## 分组问题(最重要在前,异步意味着可能只有一次机会)→ 兜底的"还有别的吗"。每题单一意念、绝不复合,题下跟作答占位,必要时加一行 why this matters。
- 产出落点
to-questionnaire-<slug>.md,写进当前目录。
- 协作
- 它是 grill-me 的镜像(挖别人的脑子 vs 挖自己的);回收的答案是 grill-with-docs 或 to-spec 的原料。
wayfinder
用户调用P3 大规模规划高认知负载engineering
当想法大到一个会话装不下、且通往目的地的路还看不见时:把它画成工单系统上的一张共享地图,然后一次解决一张决策票,直到雾退、路现。
- 先命名目的地
- 到达感的形状决定一切:它可能是一份有待迭代的 spec、一个必须在开工前锁死的决定、或一次就地的数据迁移。目的地固定了范围,所以它是第一个被确定的东西。
- 只规划,不施工
- 每张票解决一个决定而非交付一件东西。"想直接开干的冲动,通常就是你已经走到地图边缘、该交接了的信号。"
- 地图结构
- 一个贴
wayfinder:map 标签的 issue 作为索引(不是仓储):Destination / Notes / Decisions so far(一行一条已关闭票的 gist + 链接)/Not yet specified(战争迷雾)/Out of scope。决定只存在一处(它自己的票),地图只捏出 gist 并链接。
- 四类票
-
- research(AFK):读一手源拿一个决定等着的事实。
- prototype(HITL):做个便宜的粗糙物件把保真度提上去。
- grilling(HITL):对话,默认款。永远同时调用
grilling 与 domain-modeling。
- task(HITL 或 AFK):在能做出决定之前必须先发生的手动事,它做而不是决定,价值在于解锁。
- HITL 铁律
- 人机票只能通过真人的实时交流解决。智能体绝不替人回答自己那一侧(一个自己回答自己问题的 grilling 代理就破坏了这条)。
- 战争迷雾
- 地图故意不完整。判断标准是"你现在能否把这个问句说清",而不是"你现在能否回答它":说得清就开票(哪怕被阻塞),说不清就留在迷雾里。绝不把雾预切成一张张票,它比票粗,一块雾以后可能毕业成几张票,也可能一张都不成。
- 范围 ≠ 清晰度
- 超出目的地的是out of scope(永不毕业,除非重画目的地);只有"朝着目的地但还不够清晰"的才是迷雾。两者进不同的段。
- 并发与认领
- 会话开工第一件事是把票分派给自己:开放且无人认领 = 未认领。阻塞优先用原生依赖(GitHub issue dependencies),因为这样前沿在人家 UI 里肉眼可见。无飞的票 = 前沿。每会话至多解决一张票(research 除外)。
- 交接纪律
- 地图清空后交到
/to-spec 把彼此关联的决定塌缩成可施工计划,再走 to-tickets。直接从地图跳到 implement 等于丢掉那些互相关联的细节。只有"这事最后真的小"才允许直跳。
- 表述纪律
- 对所有读者可见的东西只称其名(标题),不用裸 id/编号/slug。
#42, #43, #44 无法扫读;名字能。链接藏在名字里,而不是名字让位于链接。
- 用法要点
- 它是全仓认知负载最高的流。README 明说它为"不是一个已经范围清晰的特性"而准备。会话中若走到前沿却发现毫无迷雾,正确的动作是停止并问用户怎么走(你不需要地图)。
prototype
模型调用P4 设计验证engineering
一次性代码,回答一个问题。问题的形状决定产物的形状,选错分支整份原型报废。
- 分支一 LOGIC
- "这套状态机/业务逻辑用起来对吗?" → 单个可分享的 HTML 文件:自由操作按钮 + 分标签的引导式场景走查,能把状态机推到纸面上推不动的那些用例,且非开发者也能跑。核心是把逻辑写成一个纯模块(reducer / state machine / 纯函数集),页面只是一层薄壳,不许反向引用 DOM。干净之后这块逻辑可以直接抬进真代码。
- 分支二 UI
- "这东西该长什么样?" → 同一路由上 3-5 个截然不同的变体,用
?variant= 切换 + 底部浮动切换条(含左右箭头、键盘 ←/→ 且输入框聚焦时不拦截、生产构建下隐藏)。强烈优先"寄生在已有页面上"(子形态 A):空路由是个真空,每种变体孤立看都挺好。
- 共同六条
-
- 第一天起就标明是一次性的,放在会被用到的地方旁边,但名字能让人看出它不是生产代码。
- 启动零思考:一条命令,或双击一个 HTML。不要服务器、不要 bundler。
- 默认不持久化:持久性通常正是被检验的对象。
- 跳过打磨:不写测试、不做多余错误处理、不做抽象。
- 暴露状态:每次操作后把完整相关状态打/渲染出来。
- 做完要捕获:验证过的结论折进真代码,原型本身作为一手源提交到一次性分支(不进 main),并在实现 issue 上留上下文指针。main 只保留被验证的决策。
- 反模式
- 加测试(需要测试的原型已不是原型);接真库(除非问题就是持久化);做泛化;把逻辑和页面糊在一起;把 HTML 外壳推上生产。
- 协作
- 被 wayfinder 用作 prototype 票的执行体;产出的精炼片段可以写进 to-spec / to-tickets 的"实现决定"(这是唯一允许贴代码片段的场合,且须注明来自原型)。
to-spec
用户调用P5 规格化engineering
把当前对话变成一份 spec 发到工单系统。定义性约束:它不再访你一遍,只综合已经谈过的东西。
- 流程三步
-
- 探索仓库现状(若还没做),全程使用领域词汇,尊重相关 ADR。
- 画出接缝草稿:优先复用已有接缝,尽量取最高的那个,理想数量是 一个。然后与用户核对这些接缝是否符合预期。
- 按模板写 spec,发布,打
ready-for-agent 标签(无需再分诊)。
- 模板七段
- Problem Statement / Solution / User Stories(要求极长的编号列表) / Implementation Decisions / Testing Decisions / Out of Scope / Further Notes。
- 拒绝什么
- 不写具体文件路径与代码片断(stale fast)。唯一例外:原型产出了比散文更精确地编码了某个决定的片段(状态机、reducer、schema、类型形状),可内联进对应决定,注明来自原型,且只截富含决定的部分。
- Testing Decisions 要求
- 说明"什么样的测试是好测试"(只测外部行为)、要测哪些模块、以及代码库里的同类测试先例(prior art)。
- 协作
- 承接 grill-with-docs / wayfinder 的地图 / to-questionnaire 的回收;产出交给 to-tickets。
to-tickets
用户调用P6 任务编排engineering
把计划/spec/当前对话切成一组追踪弹(tracer bullet)垂直切片,每张票声明自己的阻塞边,然后投递到已配置的工单系统。
- 切片四规
-
- 每张切片是穿过每一层(schema、API、UI、测试)的窄而完整的路径,垂直而非水平。
- 完成的切片自己就能演示或验证。
- 尺寸限制为一个全新上下文窗口能装下。
- 任何预重构(prefactor)先行:"Make the change easy, then make the easy change."
- 宽重构例外
- 机械式改动(重命名一列、改一个共享符号的类型)炸开的是全库,没有哪个垂直切片能独自变绿。不要硬塞进追踪弹,改用 expand–contract:先 expand(新形式与旧形式并存,什么都不坏)→ 按爆炸半径分批 migrate(每批一张票,都阻塞于 expand,逐批保持 CI 绿)→ 最后 contract(删除旧形式,阻塞于所有 migrate 批)。连批次都无法单独变绿时,让它们共用一个集成分支,全部阻塞一张最终的 integrate-and-verify 票,绿只在那里承诺。
- 先拷问再落单
- 以编号列表呈现:标题 / 被谁阻塞 / 这张票交付什么端到端行为。然后问三件事:粒度对不对、阻塞边是否正确(只依赖真正门控它的票)、要不要合并或再拆。迭代到用户批准。
- 两种落点同一份内容
-
- 本地文件:
.scratch/<feature-slug>/issues/<NN>-<slug>.md,编号从 01 起按依赖顺序(阻塞者在前)。一票一文件,绝不合并成一份。
- 真工单系统:按依赖顺序逐个创建 issue(先创建阻塞者,才能引用真 id),优先用平台原生阻塞/子任务关系,否则在正文写
Blocked by。默认打 ready-for-agent(按构造它就能被 agent 直接抓)。
- 票体四要素
- What to build(从用户视角的端到端行为,不是逐层实现清单)/ Blocked by / Status / 验收标准复选框。
- 协作
- 承接 to-spec;产出被 implement 逐个消费。硬性纪律:绝不关闭或修改父 issue。
implement
用户调用P7 实现engineering
十五行正文,密度极高:按 spec 或票据施工。
- 五条规程
-
- 在预先约定的接缝上使用
/tdd(能用就用)。
- 定期跑类型检查。
- 定期跑单个测试文件。
- 结尾跑一次完整测试套件(注意"once at the end",不是反复全跑)。
- 用
/code-review 收尾,然后提交到当前分支。
- 上下文纪律
- 每个 ticket 一次全新上下文;票据之间
/clear。因为每张票是自包含的,上一张的上下文是可以丢弃的。
- 协作
- 内部驱动 tdd,收尾触发 code-review;消费 to-tickets 与 triage 的产出。
tdd
模型调用P7 红绿环engineering
红 → 绿循环。这个技能的真任务是让循环产出值得保留的测试:什么样的测试是好的、测试放在哪、有哪些反模式、循环的规矩。
- 好测试的定义
- 通过公共接口验证行为,不验证实现细节。代码可以全换,测试不该动。它能像规格书一样读:
user can checkout with valid cart,并且因为不关心内部结构而在重构中存活。
- 接缝前置
- 只在预先约定的接缝上测试。下笔第一条测试之前,先把"本次被测的接缝"写下来并与用户确认;未确认的接缝上一行测试都不许写。因为测不完所有东西,先约接缝才能让测试投入落在关键路径与复杂逻辑上。
- 三个反模式
-
- 实现耦合:mock 内部协作者、测私有方法、或走旁路验证(直接查库而不用接口)。识别信号:重构后测试挂了,但行为没变。
- 同义反复:断言按代码同样的方式重算期望值(如
expect(add(a,b)).toBe(a+b))。期望值必须来自独立的真源:已知的好字面量、一道算过的例题、spec。
- 水平切片:先把测试全写完再写实现。批量测试验证的是想象中的行为,测的是"形状"而非用户可见行为,并且在理解实现之前就锁死了测试结构。要垂直切片:一测试 → 一实现 → 重复。
- 循环三规
- 红在前。先写失败测试,只写刚好通过的代码,不预示未来测试、不加投机功能。一次一片。一接缝、一测试、一最小实现。重构不属于这个循环,它属于评审阶段。
- Mocking(附
mocking.md) - 只在系统边界 mock:外部 API、数据库(有时,优先真测试库)、时间/随机、文件系统(有时)。不 mock 自己的类、内部协作者、任何你自己能控制的东西。可 mock 性的两条设计法:依赖注入(传进来,不要在内部 new);SDK 式接口优于通用 fetcher(每个外部操作一个具体函数,mock 里才不需要条件分支)。
- 协作
- 被 implement 驱动;接口形状本身成疑时(多深、接缝在哪、暴露什么)取用 codebase-design 词汇。
codebase-design
模型调用架构词汇真源engineering
深层模块(deep module)词汇表:大量行为藏在小接口后面,放在干净的接缝上,并可从该接口测试。它是所有设计类技能的共享语言。
- 七个词(必须原样用)
-
- Module:任何有接口与实现的东西,刻意不区分尺度(函数、类、包、跨层切片)。禁用:unit / component / service。
- Interface:调用者为了正确使用模块必须知道的一切:类型签名,以及不变量、顺序约束、错误模式、必需配置、性能特征。禁用 API / signature(太窄)。
- Implementation vs Adapter:前者是内部的实体,后者是站在接缝上满足接口的角色(描述占什么位置,不是里面是什么)。
- Depth:接口处的杠杆率。深 = 小接口后藏大量行为;浅 = 接口几乎和实现一样复杂。
- Seam(Michael Feathers):不必就地编辑就能改变行为的地方,即模块接口所在的地点。接缝放哪是独立的设计决定。禁用 boundary(与 DDD 限界上下文撞车)。
- Leverage:调用者从深度得到什么(每单位要学的接口换来更多能力)。
- Locality:维护者从深度得到什么(变更、bug、知识与验证集中在一处,改一次到处生效)。
- 四条原则
-
- 深度是接口的属性,不是实现的属性。深模块内部可以由若干可 mock、可替换的小件组成,只是它们不属于接口。
- 删除测试:想象删掉它。复杂性随之消失 → 它是个透传;复杂性跑到 N 个调用者身上 → 它值这个价。
- 接口就是测试面。调用者与测试走同一条接缝。想越过接口去测,这模块多半形状不对。
- 一个适配器说明接缝是假想的,两个才是真的。除非确实有东西在它两边不同,不要引入接缝。
- DEEPENING:四类依赖
- ① 进程内(纯计算/内存态,永远可深,直接合并测试)② 本地可替换(有本地替身如 PGLite、内存文件系统,用替身跑,接缝在内部)③ 远程但自有(微服务/内部 API:在接缝定义 port,运输层作为 adapter 注入,测试用内存 adapter)④ 真正的外部(Stripe 之类,注入 port,测试给 mock adapter)。测试策略是替换而非叠加:浅模块上的旧单测在新深模块接口测试出现后应当删掉。
- DESIGN-IT-TWICE
- 出自 Ousterhout。先在 agents 面前写一份问题空间说明(约束、依赖类别、示意性草图),然后并行派 3+ 个子代理各给截然不同的设计约束(最小化接口 / 最大化灵活 / 优化最常见调用者 / 端口与适配器),每个产出接口 + 用法示例 + 接缝后藏了什么 + 依赖策略 + 权衡,然后按深度、局部性、接缝位置对比并给出有主见的推荐("用户要的是一个强判断,不是一张菜单")。
- 明确拒绝的框架
- 拒绝 Ousterhout 的"实现行数/接口行数"比值定义(会奖励注水);拒绝"接口 = TS 的 interface 关键字";拒绝 boundary。
- 协作
- improve-codebase-architecture、tdd、to-spec(接缝草稿)都讲这套语言。它是"供查阅的参考",不是要跑的会话。
code-review
模型调用P8 质量门禁engineering
对 HEAD 与一个固定点之间的 diff 做双轴评审:Standards(是否符合本仓库已成文的编码规范)与 Spec(是否忠实实现了来源 issue/spec)。两轴并行子代理,互不污染,然后聚合。
- Step 1 钉住固定点
- 用三点式
git diff <fixed-point>...HEAD(对比 merge-base),并取 git log <fixed-point>..HEAD --oneline。在派发子代理之前先用 git rev-parse 确认引用可解析且 diff 非空:坏引用或空 diff 应当在这里失败,而不是进到两个并行子代理里。
- Step 2 找 spec 源(有顺序)
- ① commit message 里的 issue 引用 → ② 用户作为参数传的路径 → ③
docs/、specs/、.scratch/ 下与分支名/特性匹配的文件 → ④ 都没有就问用户;用户说没有 spec,则 Spec 子代理跳过并报告"no spec available"。
- Step 3 找标准源 + 味道基线
- 仓库里任何记录"代码该怎么写"的文件(
CODING_STANDARDS.md、CONTRIBUTING.md)。在此之上,无条件附带 Fowler《重构》第 3 章的 12 条代码味道:神秘命名、重复代码、依恋情结、数据泥团、基本类型偏执、重复 switch、霰弹式修改、发散式变化、夸夸其谈通用性、消息链、中间人、被拒绝的遗赠。两条约束:仓库已写明的一律覆盖基线(它认可的东西不许再标);每条味道永远是一个判断而非硬违规(称作"possible Feature Envy")。工具已经强制的跳过。
- Step 4 并行两人
- Standards 子代理拿 diff 命令 + 提交列表 + 标准文件清单 + 全文粘贴的味道基线(它没有别的途径拿到)+ 简短 brief(400 词以内,区分硬违规与判断建议)。Spec 子代理拿 diff + spec 内容,报告三类事实:缺失/部分实现的需求、diff 里没人要的行为(范围蔓延)、看起来实现但疑似实现错了的需求,每条都引用 spec 原行。
- Step 5 聚合,并刻意不复排
- 两轴报告原样放在
## Standards 与 ## Spec 下。绝不合并或重新排序。结尾一行摘要:每轴发现总数 + 该轴内部最严重的一项;不在两轴之间选一个总冠军(那正是分离要防的复排)。
- 为什么非要两轴
- 因为两者可以分别通过/失败:符合全部规范但实现错了东西(Standards 过,Spec 挂);精确实现了需求却破坏了项目惯例(Spec 过,Standards 挂)。合起来报,其中一轴会掩盖另一轴。
diagnosing-bugs
模型调用P9 缺陷攻关engineering
给难 bug 与性能回归的一套纪律:造环 → 复现最小化 → 假设 → 插桩 → 修复+回归 → 清理。六个阶段,跳步要有显式理由。
- 先脱敏
- 技能会让你展示命令、输出与抓取的工件。每条秘密先写
<REDACTED>;优先构建依赖环境变量的环,让凭据留在环境里而不是出现在展示物里;抓来的工件带 auth header,只引信号所在的几行。(这是 CHANGELOG v1.2.3 里专门加的一段。)
- Phase 1:它就是全部
- "This is the skill." 有一个针对这只 bug 会变红的紧反馈环,你就一定会找到原因;二分、假设检验、插桩都只是消耗它。没有环,盯着代码看多久都救不了你。Be aggressive. Be creative. Refuse to give up.
- 十种造环方式
- 失败测试(触达 bug 的任意接缝)→ curl/HTTP 脚本 → CLI + 固定输入 diff 已知好快照 → 无头浏览器脚本(断言 DOM/console/network)→ 重放抓取的轨迹 → 一次性 harness(拉起系统最小子集)→ 属性/模糊测试(1000 随机输入找失败模式)→ 二分 harness(配合
git bisect run)→ 差分环(新旧版本/两份配置同时跑同输入 diff)→ HITL bash 脚本(最后手段,用 scripts/hitl-loop.template.sh 驱动人来跑)。
- 完成准则(四条全中才可进 Phase 2)
- 能说出一条命令(脚本路径/测试调用/curl),并且已经亲自跑过至少一次(展示调用与输出,脱敏后),它同时:能变红(驱动真实 bug 路径并断言用户的确切症状,不是"没报错")、确定性(非确定性 bug 则要求被钉住的高复现率)、快(秒级不是分钟级)、可由代理无人值守运行。
如果你发现自己在看懂环之前就开始读代码建理论,停下:直跳假设正是这个技能要防的那个失败。无红命令,无 Phase 2。
- 提高复现率
- 非确定性 bug 的目标不是干净复现,而是更高的复现率:循环触发 100 次、并行、加压、收窄时间窗、注入 sleep。50% 抖动的 bug 可调试,1% 不可。
- Phase 2 最小化
- 一次砍一个元素(输入、调用者、配置、数据、步骤),每次砍完重跑;直到剩余每个元素都是承重的(拿掉任何一个环就变绿)。价值:缩小 Phase 3 的假设空间,并直接成为 Phase 5 的干净回归测试。
- Phase 3 假设
- 先生成 3-5 条有序假设再测。单条生成会锚定在第一个看起来合理的想法上。每条必须可证伪并说出它的预测:如果 X 是原因,那么改动 Y 会让 bug 消失 / 改动 Z 会让它更糟。说不出预测的假设是"一个感觉",重写或丢弃。测试前把排序给用户看(常有领域知识瞬间重排,或知道哪些已排除);不阻塞,人不在就按自己的排序继续。
- Phase 4 插桩
- 每个探针必须映射到 Phase 3 的某条具体预测,一次只改一个变量。工具优先级:调试器/REPL 检视 > 边界处的定向日志 >>> 绝不"打日志然后 grep 一切"。每条调试日志打唯一前缀(如
[DEBUG-a4f2]):清理时一次 grep 收工,没标签的日志会活下来。性能回归是分支:日志通常无效,先建基线测量再二分,先测后修。
- Phase 5 先于 fix 写回归测试,但只在有正确的接缝时
- 正确接缝 = 测试能在调用点处行使真实的 bug 形态(多调用者才能触发却写成单调用者测试,就是假信心)。如果没有正确的接缝,那本身就是这份发现:代码库架构在阻止这只 bug 被锁死,记下来交给下一层(通常就是
improve-codebase-architecture)。
- Phase 6 清理清单
- 原始复现不再复现(重跑 Phase 1 环)/ 回归测试通过(或"无接缝"已被记录)/ 所有
[DEBUG-...] 已删(grep 前缀)/ 一次性原型已删或移入明确标记的调试位 / 把最终正确的那个假设写进 commit 或 PR message,让下一个调试者学到东西。
- 协作
- 解决不了缝合?握手给 improve-codebase-architecture。
resolving-merge-conflicts
模型调用P10 收口engineering
正在进行的 merge/rebase 冲突,逐 hunk 解决,然后把操作走完。
- 五步
-
- 看清当前状态:git 历史 + 冲突文件。
- 为每一侧找一手源:读 commit message、PR、原始 issue/票据,深挖每处改动为什么被做出来、原意图是什么。
- 逐 hunk 解决:尽量同时保全两侧意图;不可调和时取符合本次合并既定目标的那一侧并记下权衡。绝不发明新行为。
- 发现并运行项目的自动化检查,惯例是类型检查 → 测试 → 格式化,修掉合并破坏的东西。
- 完成这次 merge/rebase:暂存并提交;若是 rebase 则继续直到全部 commit 落完。
- 硬禁令
- 永不 --abort 冲突必须解决,不许回退。
- 用法要点
- 它站在所有流程之外,只在你已经身陷冲突时才摸它。
wizard
模型调用P11 只有人能做的步骤engineering
生成一个交互式 bash 脚本,牵着人走过那些只有人能做的步骤:开通基础设施、配凭据或 CI secrets、点一个陌生的第三方后台、跑一次性迁移或切换。
- 为什么它是模型调用
- CHANGELOG 写得很直白:因为模型调用,代理在撞上一堵只有人能过的墙的那一刻就能抬手够到它,而不是往聊天里吐一串编号指令然后指望你照做。代理能自己干的就该自己干,wizard 是给点击、审批和后台<|hy_place▁holder▁no▁813|>差事准备的。它的 description 特地写了一条反向触发:不必在智能体能独立完成的事上调用它。
- 模板分工
template.sh 里 STAGES 标记以上的是一个固定库:逐阶段进度、确认门、跨平台开 URL(含 WSL)、隐藏式密钥输入、幂等的 .env upsert、gh secret/gh variable 写入、收尾摘要。每个 wizard 都一模一样,且永不手工编辑这段库代码。技能本身的活只有两件:界定程序范围与撰写各个 stage。
- 四步
-
- 界定:先读仓库不求人。
.env*、README、docker-compose*、框架配置、以及 .github/workflows/ 里每一个 secrets.*/vars.* 引用都是一个脚本必须产出的值。
- 映射每段的旅程:开哪个 URL、点什么、值在哪显示、填进哪个变量(如"Dashboard → Developers → API keys → Reveal test key → copy")。不知道当前 UI 就明说并去查或问,绝不发明可能不存在的步骤。
- 撰写:按依赖顺序一步一个 stage;用
stage/say/step/open_url/ask/ask_secret/write_env/set_secret/set_var/pause/confirm。先开 URL 再问值、秘密必用 ask_secret、任何不可逆动作前 confirm、一 stage 一件事(会清屏,别让人滚动去找)。
- 验证与交付:
bash -n,有 shellcheck 就跑,chmod +x。不要自己端到端跑(它会开浏览器并阻塞等输入),改为静态比对:每个值都被捕获并落到 step 1 说的地方,每个 set_secret 名字与 CI 里的 secrets.* 引用逐字相符。
- 生命周期
- 默认用完即弃:写到 scratch 或
scripts/,干完删。只有当用户要一条可重复的搭建路径时才提交入库,并链到 README。
triage
用户调用P12 需求入口engineering
把工单系统上的 issue(以及外部 PR)推过一个配角优先的状态机:分类、验证、必要时拷问,最后写出可被上门代理直接消费的简报。
- 角色模型
- 两个类别角色:
bug / enhancement。五个状态角色:needs-triage / needs-info / ready-for-agent / ready-for-human / wontfix。每张单同时有且只有各一个。状态角色如果互相冲突,先停手标记出来,在动手之前先问 maintainer。
- PR 同机
- 若仓库把外部 PR 当请求面(由 tracker 配置的开关决定),PR 就是一份带代码的 issue,同样的角色、同样的机器。
ready-for-agent 表示"简报已附上,代理该对这份 diff 做下一步"。
- 透明度要求
- 每条发到工单系统的评论或 issue 必须以"本条由 AI 于分诊时生成"开头。
- 五个步骤
-
- 收集上下文:正文、评论、标签、作者、日期(PR 还含 diff),并解析既有分诊笔记以免重复提问。两项代码库检查:冗余(按领域概念而非措辞搜是否已实现)与先前拒绝(读
.out-of-scope/*.md)。
- 给出建议:类别 + 状态 + 理由 + 与请求相关的代码库摘要(含是否已实现),然后等指示。
- 验证主张(拷问之前):bug 按报告人步骤复现;PR 检出后跑相关测试确认 diff 真的做了它声称的事。报告"已确认/失败/信息不足"。被确认过的验证会让后续的 agent 简报强得多。
- 必要时拷问:同时调用
grilling 与 domain-modeling,一轮一轮把它拷打成型,同时就地 sharpen 术语并更新 CONTEXT.md/ADR。
- 落地结果:
ready-for-agent 贴 agent brief;ready-for-human 同结构但说明为何不能委派;needs-info 贴笔记(含"已确定的都记下来,别丢");wontfix 按三种原因分别处理。
- Agent Brief 是契约
- 四条原则:耐久性优于精确性(禁止文件路径与行号,描述接口/类型/行为契约,因为这张单可能躺几周)、行为性而非程序性(说系统该怎么表现,别说怎么实现)、完整可独立验证的验收标准、显式的范围边界(防代理镀金)。
- out-of-scope 知识库
.out-of-scope/*.md 一文件一概念(不是一文件一 issue)。只有被拒绝的功能请求(非 bug)才写入,用于机构记忆 + 去重;匹配看概念相似而非关键词("夜间主题"命中 dark-mode.md)。因"已实现"而关闭的绝不写入,那会污染去重检查。
- 快速越权
- 班长说"把 #42 挪到 ready-for-agent",就信任并直接执行(跳过拷问),但先确认要做的事(角色改动、评论、关闭)再动手。
- 协作
- 内部调用 grilling + domain-modeling;产出的 agent-ready 单被 implement 消费。纪律:
to-tickets 产出的票已经 agent-ready,不要再分诊它们。
handoff
用户调用P13 移交productivity
把当前对话压成一份可携带的手照样文档,让另一个代理能接着干。
- 六条约束
-
- 保存到操作系统的临时目录,不是当前工作区(避免脏你的仓库)。
- 必须含 "suggested skills" 段,点名下一个代理应该调用哪些技能。
- 不重复已存在于其他工件里的内容(spec、plan、ADR、issue、commit、diff):以路径或 URL 引用它们。
- 脱敏:API key、口令、个人身份信息。
- 有参数就把参数当作"下一个会话要干什么"的说明书,据此裁剪。
- 使用时机(很窄)
- 只在四种情况真需要它:换 harness(Claude→Codex)、换目录/仓库、交给同事、或在相位中途分岔一个副任务而不打乱主线。它买的东西叫可移植性:一个能旅行的文件。没有东西在旅行,就不需要它。
- 协作
- 同行还有一个 beta 兄弟 claude-handoff:不落文件,直接把摘要当作 prompt 拉起一个后台代理。
improve-codebase-architecture
用户调用P14 周期性维护engineering
定期给代码库做体检:扫出"变深的机会"(把浅模块变成深模块的重构候选),用一份可视化 HTML 报告呈现,然后对你挑中的那个进行拷问。
- Step 1 先定范围(YAGNI)
- 把一个模块变深的收益是"未来改它更容易",因此近期改动多的部位权重更高。用户没指方向就走一遍
git log --oneline 找热点(反复出现的文件与区域),让那些路径先牵走注意力;散得没有热点再撒大网。然后派子代理有机地走查并记录摩擦点:理解一个概念要在多少个小模块之间跳?哪里有浅模块(接口几乎和实现一样复杂)?哪些纯函数只是为了可测性被抽出来、而真 bug 藏在它们怎么被调用里(缺乏局部性)?紧耦合模块是否越接缝外漏?哪些部分不可测或难测?对疑似浅的一律施加删除测试。
- Step 2 可视化报告
- 写一份自包含 HTML 到操作系统临时目录(
$TMPDIR → /tmp → %TEMP%,文件名带时间戳以保证每次全新),然后替用户打开并告知绝对路径。每张候选卡包含:文件清单 / 痛点 / 方案 / 收益(必须用 locality 与 leverage 表述)/ 前后对比图示 / 推荐强度徽章(Strong 绿 / Worth exploring 琥珀 / Speculative 灰)。结尾要有 Top recommendation。
- 报告的语言纪律
- 领域词取自
CONTEXT.md,架构词取自 codebase-design。HTML-REPORT.md 甚至给出了禁用替换表:不许用 component/service/unit 代替 module,不许用 API/signature 代替 interface,不许用 boundary 代替 seam。收益 bullets 必须写成"locality: bug 集中到一个模块"这类,不许写"更易维护""代码更干净"。
- ADR 冲突
- 只有摩擦大到值得重开时才 propose,并明确标注 " contradict ADR-0007, but worth reopening because…"。不要罗列 ADR 禁止的所有理论重构。
- 此步的禁令
- 不要在这个时候提出接口。 写完就问:"你想探索哪个?"
- Step 3 拷问循环
- 用户挑中后调用
grilling 走决策树;副作用就地发生,调用 domain-modeling 保持领域模型最新:给深化的模块起名时用了词汇表外的新概念 → 加进 CONTEXT.md;用户带承重理由否决了一个候选 → 提议写 ADR(措辞:要不要把这个记成 ADR,免得以后的架构评审又提一遍?);想比较多种接口 → 用 codebase-design 的 design-it-twice 并行子代理。
- 诚实的边界
- README 亲手降温:"It is a survey, not a rescue." 在真正古老的代码库上它会找到真候选,但它不会替你解开那个泥团。
- 使用频率
- README 建议每隔几天跑一次;它产出的候选会成为一个新的想法,回到主链路的
/grill-with-docs。
writing-for-agents
模型调用P15 元层productivity
给代理写文档的写作学:技能、AGENTS.md/CLAUDE.md、以及任何靠指针抵达的文档。整套仓库的自我修养都写在这里。
- 上下文指针
- 一段"留在上下文里的引用",它说出上下文外的材料并编码了抵达它的条件。技能的 description 就是它。决定取用时机的是指针的措辞,不是它的目标。必达的材料配了软弱的措辞,就是一个方差 bug:先把措辞磨利,磨不利才考虑内联。指针要做两件事:说清材料是什么 + 列出应该触发取用的分支。每项攀爬...
- 两种预算
- 上下文负载:常驻材料对窗口的花费(AGENTS.md 的一行、一个技能 description)。认知负载:对人的花费(有哪些文档、何时够哪一个)。认知负载不是要最小化的成本,它是人类主体性的价格:在需要人的判断处花掉它,在不需要处移除它。
- 信息层级三级梯子
- ① 文件内步骤(主层:按序要做的动作)② 文件内参考(按需查阅;一堆平级规则完全可以共处一层,这不是坏味)③ 外披露参考(推到单独文件,由指针接管,指针触发才加载)。渐进披露是往下移的动作,主要不是为了省 token,而是为了保护这个层级:分支是最干净的披露测试,每个分支都要的东西内联,只有部分分支才走的藏到指针后。
- 完成准则两属性
- 清晰度(能否分辨做没做完):界限模糊会招引过早完成;可见的后续步骤(post-completion steps)提供拉力,准则的清晰度提供阻力。防御顺序:先磨利界限(局部且便宜),只有它本质上就糊且观察到抢跑,才用拆分序列把后续步骤藏起来(且必须跨越真实上下文边界,内联调用藏不住)。需求量(要求多少):"每个被修改的模型都要交代"比"产出一份变更清单"逼出更多苦力(legwork)。最强的准则是既可检查又穷尽的。
- 前置词(leading words)
- 模型预训练中已有的紧凑概念(lesson、fog of war、tracer bullets、tight、red)。重复的是 token 而不是句子,它积累分布式的定义,用最少的 token 锚住一大片行为,靠的是招用模型已有的先验。自造词招不到任何先验,你得用定义 token 付这笔钱,所以先借现成的词。它锚两次:正文里锚执行,指针里锚调用(同一个词活在你的 prompt、你的文档和你的代码里,代理会更可靠地把共享语言连到材料上)。
两个真实改例:"fast, deterministic, low-overhead" → tight;"a loop you believe in" → red(把模糊的门变成二值可观测状态)。
- 否定的失败模式
- 用禁止来掌舵会把被禁行为拖进上下文并让它更可得。不要想大象,于是只有大象。要正向提示目标行为(说"注释写成一行",而不是"别写长注释")。禁令只在无法正向表述的硬护栏下才配。
- 修剪
-
- 单一真源:重复会在梯子上把一个意思的地位抬到它不该在的层级。
- 环境也是真源(
package.json scripts、配置、目录布局、--help)。文档重述环境就是缓存:只有"查起来昂贵"时才值得。缓存代理查不到的东西:不成文惯例、选择背后的理由、配置不会招供的坑;一次命令一次文件的查找,留给环境,它不会过期。
- 相关性:逐行问它还负担着我们做的事吗。没有修剪纪律的默认宿命是沉积(sediment):陈旧层不断沉降,因为加东西显得安全、删东西显得冒险,直到你得钻透它们才能找到还活着的部分。
- no-op 狩猎:模型默认就会遵守的指令,付了负载却什么都没说。判据(相对默认是否改变行为)是相对模型而非相对读者的:两人争论一个句子是不是 no-op,其实是在争论默认值,去跑一遍文档而不是开会辩论。失败就删整句,不要从句子里删几个词。这条也就给前置词打了分:弱到打不过默认值的词(模型已经够彻底了还说"be thorough")就是 no-op,修法是换个更强的词(relentless),而不是换个技术。
- SKILL-MECHANICS
- 调用轴的经济学讲解:模型调用 = 永久上下文负载换可发现性;用户调用 = 零上下文负载付认知负载。以及两个用户调用技能共用的参考件应该放在技能系统之外的普通文件里(因为它们都没有 description,谁都够不到谁)。
teach
用户调用P15 学习productivity
有状态的长期教学:把当前目录当作一个教学工作区,跨会话教会用户一个概念或技能。
- 工作区骨架
MISSION.md(学这个的理由,所有教学的 grounding)/ RESOURCES.md(高信任资源清单)/ ./lessons/NNNN-*.html(主产物,一个自包含 HTML 教一件小事)/ ./reference/*.html(压缩后的速查件,会被反复回访)/ ./learning-records/NNNN-*.md(相当于学习领域的 ADR,用来推算最近发展区)/ ./assets/(可复用组件,共用样式表是每个工作区挣到的第一个组件)/ NOTES.md(偏好与工作笔记)。
- 三分法
- 知识(来自高质量高信任资源;绝不信任自己的参数化知识)、技能(通过高度相关的互动课获得)、智慧(来自与其他学习者/实践者的真实互动)。遇到像是要智慧的问题,默认姿势是先尝试回答,但最终委派给一个社区。
- 流利 vs 存储强度
- 流利(当场提取)会给出掌握的幻觉,存储强度(长期保持)才是真目标。用合意难度设计:提取练习、间隔、交错(仅技能练习)。
- 最近发展区(ZPD)
- 每节课都要做到"刚好难到":读 learning-records + 按 mission 推断,教落在 ZPD 里最相关的那件事。
- 课的要求
- 短(工作记忆很小)但给一个可积累的具体胜利;系于 mission;推荐一个最佳一手源去读或看;含有"有不懂就追问这个代理"的提醒(代理就是老师);尽量用 CLI 命令帮用户打开它。
- 知识 vs 技能的难度取向
- 获取知识时难度是敌人(吃掉理解所需的工作记忆);习得技能时难度是工具(费力提取才建得起存储强度)。反馈环越紧越好。
ask-matt
用户调用P15 路由engineering
"你记不住每个技能,那就问。" 一张覆盖全部用户可达技能的地图 + 路由表。CLAUDE.md 要求:任何技能增删改之后必须重读它并保持地图不撒谎。
- 它的世界观
- 一个flow 是穿过技能的一条路径。多数路主走在一条主链路上,两条入口匝道汇入它,其余是独立的或跑在下面的词汇层。
- 支路与占位
- 主链路第 2 步有一个 detour:当某个问题必须有可运行的答案(状态、业务逻辑、非看不可的 UI)时,两端都用
/handoff 架桥(原型活在自己的目录里,这正是 handoff 的用途):handoff 出去 → 在新会话跑 /prototype → handoff 回来并在原想法线程里引用它。
- 三重分类
- 主链路(grill-with-docs → to-spec → to-tickets → implement → code-review)、匝道(triage / diagnosing-bugs / wayfinder)、代码库健康(improve-codebase-architecture)、词汇底层(domain-modeling / codebase-design)、独立件(grill-me / grilling / resolving-merge-conflicts / prototype / research / to-questionnaire / wizard / wait-what / teach / writing-for-agents)。
- 先天限制
- 它只能暗示不能触发:用户调用技能没有 description,除了人手 typed 之外谁都够不到。这是 router 技能的结构性成本。