9arm-skills:让 AI 编程助手按流程干活的合约式 Skills
posts posts 2026-05-21T11:50:00+08:009arm-skills 是一组可执行的合约式 Skills,把调试、复盘、审查、向上沟通写成 AI 必须遵守的触发时机、执行顺序与退出条件,让编程助手在证据不足时停下来而不是硬凑答案技术笔记Claude, Skills, 开发工具9arm-skills:让 AI 编程助手按流程干活的合约式 Skills
AI 编程助手给的建议常常「听起来对但差点意思」:模型能力够了,缺的是让它在证据不足时停下来的约束。9arm-skills 就是为补上这个差距做的——把项目里最需要纪律保障的四件事(调试、复盘、审查、向上沟通)分别编码成技能(Skill),每个技能都是一份规定了触发时机、执行顺序和退出条件的可执行合约,AI 必须照办,否则就停下来。
一、缺的不是能力,是约束
AI 助手说:「建议把这段逻辑抽成一个独立函数,提高复用性。」
它说得没错。函数确实可以抽。但你的团队有自己的一套做法:哪些逻辑该抽、抽到哪个模块、命名前缀跟什么对齐——这些隐性知识,通用 AI 模型不知道。你拿到的是一句不会错但也不太有用的建议。
再把场景放大一点。你刚修了一个折磨两天的 bug,想让 AI 帮你写复盘文档。它洋洋洒洒给你三段话,看起来结构完整,但仔细一读:没有复现步骤,没有根因追溯链,没有验证方案——写的是一篇「叙事散文」,不是一份工程师之间传递判断的工程记录。
通用模型默认给「最可能有帮助的回答」,但工程流程需要它在证据不足时拒绝回答。9arm-skills(GitHub: thananon/9arm-skills,2026 年 9 月 14 日 3187 Stars)把「拒绝条件」写进了技能的触发逻辑里。
仓库的主体是 skills/ 目录,技能按 bucket 分组。截至撰写时的快照,实际只有三个 bucket——engineering/、productivity/、misc/(misc 暂空),共 6 个技能;README 里规划的 personal/、in-progress/、deprecated/ 尚未落地。本文只拆其中最需要纪律保障的 4 个——debug-mantra、post-mortem、scrutinize、management-talk;另外两个(qwen-agent 把琐碎任务委托给便宜的 Qwen 子代理、qwenchance 管理长任务的上下文预算)不在本文范围。
二、一张图看懂四技能的分工
四个技能覆盖两条主线——一条面向工程执行(工程师对工程师),一条面向信息传递(工程师对组织)。
两条线有明确的交接点:post-mortem 产出的是面向工程师的工程真相,如果你需要给 VP 或 PM 看,把这份产出交给 management-talk——它负责把函数名、文件路径、commit SHA 翻译成领导层能用来做决策的语言。post-mortem 不删代码标识符,management-talk 不编造事实、不替用户往 Slack 或邮件渠道发帖——两个技能各自守住自己的边界。
三、四个技能的完整拆解
下面逐一展开每个技能「管什么、怎么执行、在什么条件下拒绝执行」。
debug-mantra:调试四念处
这是整个技能库中最「硬」的一个——它规定了一条调试纪律,并要求 AI 在每个调试 session 开始时逐字复述,然后按序执行。
四步执行链:
复现(Reproduce reliably) — 在提出任何修复假设之前,必须拿到一个可运行的复现脚本。如果是 flaky(偶发性 bug),先把复现率从 1% 提到 50% 以上——循环触发、加并发压力、注入 sleep 缩小时间窗口。50% 的 flaky 可以调试,1% 的不行。完全没有复现 → 停下来,明确告知用户,不准跳到假设阶段。
调试器使用示例(LLDB):
# 启动调试器并附加到进程 lldb --attach-pid <PID> # 在可疑函数设置断点 (lldb) breakpoint set --name tadaLaunchPrepare # 运行到断点 (lldb) continue # 检查变量值 (lldb) frame variable # 单步执行 (lldb) step追踪失败路径(Know the fail path) — 三条路径按优先级递进:在调试器里设断点 → 源追踪加配置开关枚举 → 代码内埋点(printf/log,每个探针带唯一前缀方便后续
grep清理)。只有当上一级确实走不通时才升级手段。日志埋点示例:
// 在关键路径添加带唯一前缀的日志 #define DBG_PREFIX "[DBG-7af3]" void tadaLaunchPrepare(scheduler_t *scheduler, launch_plan_t *plan) { log_info("%s Entering tadaLaunchPrepare, numStreams=%d", DBG_PREFIX, scheduler->numStreams); if (scheduler->numStreams == 1 && !plan->persistent) { log_warn("%s Fast path triggered, may skip sync", DBG_PREFIX); } }证伪假设(Falsify the hypothesis) — 提出 3-5 个按可能性排序的假设,先跑证伪实验。能存活下来的假设才值得继续。只追一个假设会锚定在第一个看起来合理的想法上。
运行账本长什么样——下面三行取自第四节的 GPU 挂起 bug 案例(内容与仓库自带 worked example 一致,完整流转见第四节):
假设 实验 观察 账本结论 kernel 启动顺序 调试器断点检查入队 kernel 正确入队 排除 scratch 缓冲区初始化竞态 [DBG-7af3]埋点打印指针与事件时间戳kernel 发布先于 IPC publish 完成 确认 门控验证 强制 numStreams = 2bug 消失 锁定门控 交叉验证每一条线索(Every run is a breadcrumb) — 维护一份运行账本(ledger):每次实验改了哪个变量、观察到什么、排除了什么。新假设必须与账本中所有历史记录一致。不一致 → 假设有问题,修正或丢弃。
触发时机:/debug-mantra 命令;用户报告 bug、说「坏了/报错了/不行」;用户粘贴 stack trace 或 error log。
关键约束:除非用户明确说「跳过口诀」,AI 必须在第一条回复里逐字背诵四步口诀,然后按序执行。这是技能强行加在 AI 行为上的闸门。
post-mortem:工程复盘的及格线
这个技能划了一条硬线:没有可靠复现、已知根因、已验证修复的情况下,拒绝起草复盘文档。
这跟大多数人的直觉相反。我们习惯让 AI「帮忙写个复盘」,但它不知道你的 bug 到底修好了没有,也不知道你所谓的「根因」是确认过的机制还是一厢情愿的假设。post-mortem 直接把门槛写进触发逻辑里——四个必要条件缺一不可:
- 存在可靠复现(不是「有时候会崩」)
- 根因已知(机制确认,不是假设)
- 修复已落地(有 PR 或 commit 指针)
- 修复已验证(原始复现通过、客户负载通过)
如果缺了任何一项,它会列出缺什么然后停下来——而不是凑一篇看着像复盘的「推测性叙事」。
还有两条不在这四个条件里的拒绝线:客户可见的故障要单独的事故报告(时间线、影响范围、通信记录),post-mortem 只管 bug 修复记录,遇到会先提示确认再动手;琐碎修复(typo、一眼看懂的单行改动)PR 描述就是记录,不值得凑九段结构。
复盘文档结构(4 个必填段 + 5 个条件段,编号即源文件顺序):
| 段 | 类型 | 内容要求 |
|---|---|---|
| 1. Summary | 必填 | 一句话:什么坏了 / 什么修好了 / JIRA + PR + Owner |
| 2. Symptom | 条件 | 实际见到的错误输出、日志、性能数字 |
| 3. Root cause | 必填 | 全链路机制追溯,保留所有代码标识符(函数名、文件路径、struct 字段)——这是整个文档最贵的一段 |
| 4. Why it produced the symptom | 条件 | 把根因和症状之间的因果链走通——bug 在 tadaLaunchPrepare 里,但客户看到的是几小时后训练挂起 |
| 5. Fix | 必填 | 改了什么,为什么能治根因而非掩盖症状;如有失败的修法尝试,点名并解释错在哪里 |
| 6. How it was found | 条件 | 调试路径:什么工具、哪些假设被否掉、哪一次实验定案 |
| 7. Why it slipped through | 条件 | CI 盲区 / 潜在代码被后续改动激活 / 之前的修复掩盖了症状 / Review 遗漏 |
| 8. Validation | 必填 | 怎么验证的,诚实标注只测了哪些配置——「在 Llama-2-70B / 8 GPU / DeepSpeed 验证通过,未在其他负载重测」比暗示全覆盖有用得多 |
| 9. Action items | 条件 | 具体到人 + ticket + PR 的后续动作 |
两个关键区别:
- 这是工程师对工程师的文档。函数名、struct 字段、commit SHA、行号——全部保留。六个月后的你要靠
grep回到现场,不是靠读叙事散文。 - 它为
management-talk提供源材料。把这份工程文档交给management-talk,后者负责翻译成给 VP 看的版本。
scrutinize:外部视角的端到端审查
scrutinize 做一件代码评审里最难自动化的事:先问「这个改动该不该存在」,再查「它到底干了什么」。
大多数 AI 代码审查只读 diff,然后给你一堆风格建议。scrutinize 的四步 workflow 顺序不可跳过:
Step 1 — 意图(Intent):用一句话描述这个改动的目标。如果连目标都说不清楚,直接停在这里。然后必须问:有没有更简单或更小的方法达到同样目的?考虑方案包括:不做(问题是真实存在的吗?)、用已有的机制而非新增 surface(暴露面)、更小的改动解决 90% 的问题、在另一个层面解决(配置而非代码、框架而非应用、编译期而非运行时)。只有用户明确说「不要质疑范围」,这一步才被豁免。
Step 2 — 追踪(Trace):从入口点出发,沿真实调用链通读,包含 diff 两侧未被修改的代码。bug 往往藏在 diff 和周边代码的交界处。
Step 3 — 验证(Verify):对每个声称的行为,显式回答「我走了一遍代码路径,实际发生了 X,所以这个声称成立/不成立」。同时检查什么输入/状态会打破它、它悄悄改了什么(性能语义、错误语义、对外契约)、测试是否真的覆盖了所追踪的路径。
Step 4 — 报告(Report):按 blocker → major → nit 排列,每个发现包含四件事:一句话发现(带 file:line 引用)、后果、证据、建议改动。结尾给一句话判决:ship / fix-then-ship / rework / reject。
输出不谈「这个 PR 看起来不错」。每条发现带引用。没有发现就说清楚你追了哪些路径、检查了哪些边界。
输出格式示意(分级与字段结构按 SKILL.md,内容为虚构):
## Review Report: PR #1234
### Blocker
- `src/auth.ts:45` — 移除 null check 后,`getUser()` 可在未认证状态下调用
- 后果:攻击者无需 token 即可拉取任意用户资料
- 证据:测试 `auth-none-user` 在 PR 合入后通过(按原语义应失败)
- 建议:恢复 null check,或补认证守卫
### Major
- `src/session.ts:112` — session 生命周期与文档不一致
- 后果:文档说 30 分钟无活动过期,实现是 24 小时(`session-manager.ts:89` 的 `MAX_IDLE_TIME`)
- 证据:常量定义与全部引用点
- 建议:代码与文档任选一侧对齐
### Nit
- `src/utils.ts:233` — `deepClone` 无调用方
- 建议:删除,或留注释说明保留原因
**判决**:fix-then-ship — Blocker 修复后可合入management-talk:工程事实的语境转换
management-talk 解决的问题很具体:工程师写的 bug 分析在 VP 眼里是一堆不认识的名词,而直接删掉所有技术细节又会让信息失真。它在中间做了一层精准翻译。
翻译规则:
| 处理方式 | 对象 | 原因 |
|---|---|---|
| 保留 | 产品名、框架名、团队组件名、JIRA Key、PR 编号、客户/负载标识 | 这些是工程和领导层之间的交叉索引 |
| 删除 | 函数名、文件路径、struct 字段、commit SHA、代码表达式、环境变量名 | 对目标受众不可操作 |
| 翻译 | 机制描述 → 一两句平实的因果关系 | 「kernel 读到 scratchBuf == NULL」→「GPU 从未初始化的缓冲区读取数据并永久等待一个永远到不了的信号」 |
还有一条容易被忽略的规则:不要过度删除。它面向的是「懂工程的管理层」——race condition(竞态)、synchronization(同步)、fast-path(快速路径)、workaround(临时方案)这类概念级词汇他们读得懂,直接保留;把「竞态」软化成「时序问题」反而显得居高临下。删除只发生在「函数名、文件路径、SHA」这一层,不碰「这个概念存在且重要」这一层。
然后根据发布渠道二次塑形:
| 渠道 | 规则 |
|---|---|
| JIRA 评论 | 完整结构化块,粗体段标签易扫描 |
| Slack | 一条消息:粗体 TL;DR + 2-4 子弹 + 一个内链,不超过 80 词 |
| 异步站会 | 1-3 行:[状态] [事项]。负责人。下一步。 |
| 邮件 | TL;DR 即标题,正文用流动段落代替粗体标签 |
| 会议发言要点 | 子弹列表,每项最多一小句,按发言顺序排列 |
management-talk 还显式声明了它不做什么:不编造事实(工程源说「根因未知」,改写就是「根因未知」,不会为了叙事完整把猜测升格为结论)、不删 JIRA Key/PR 编号(删了就断了交叉索引)、不替用户推测负责人(源材料没写就去问,不翻 git blame 猜)、连 JIRA 发帖都要用户确认后才执行,Slack、邮件等一切非 JIRA 渠道则一律只交草稿。它产出的是状态更新,不是建议——想让管理层「优先处理这个」,得另起一份建议文档。
management-talk 输出示例(Slack 草稿,内容为虚构,项目名与第四节案例一致):
**Tada 通信库在 dumbModel LLM-7B 微调时挂起**【已修复待合并】(JIRA-12345)
- 通信快速路径跳过同步 → GPU 读未初始化内存 → 挂起。潜在数月。
- 负责人:Alex,PR #5751 审查中。
- 临时方案:关闭 IPC 注册。JIRA 评论的完整版与站会版本见第四节流转案例。
四、一个完整的流转案例
以下案例为虚构示意:Tada 通信库、dumbModel 等项目名与代码标识符均为虚构,仅用于演示四个技能的配合流程。skill 自带的 worked example 也使用了同一套名字,机制一致。
假设你接手了一个 GPU 训练挂起的 bug。
1. debug-mantra 接管调试 session
CI 报 Tada 通信库在 8-GPU LLM-7B 微调时 eval 阶段永久挂起,无报错、无超时——busy-spin(忙等待)在 tadaKernel_AllReduce_f32_RING。
AI 被 debug-mantra 约束,第一条回复先逐字背诵四步口诀,然后开始:
- Step 1:把「8-GPU 偶尔挂」收敛为 2-GPU 子集上确定性的 30s 复现脚本
- Step 2:调试器 attach → 发现 kernel 正确入队,排除启动顺序假设 → 源追踪发现
tadaLaunchPrepare存在一个单流快速路径的门控 → 埋点[DBG-7af3]显示 kernel 发布先于deviceStream的 IPC publish 完成 - Step 3:按口诀排出多个排序假设,逐个先跑证伪实验——第一个假设(kernel 启动顺序)被调试器推翻:断点显示 kernel 正确入队;第二个假设(scratch 缓冲区初始化竞态)被
[DBG-7af3]埋点日志确认 - Step 4:关键实验——强制
numStreams = 2,bug 消失。根因锁定:单流快速路径跳过了跨流同步事件
2. 修完后,post-mortem 起草复盘
修复落地(PR #5751:移除不安全的快速路径 + 收紧设备端 null check),验证通过(3 次 2 小时连续跑 + 6 小时浸泡跑 + tada-tests 套件全绿)。
四个必要条件全部满足,post-mortem 开始起草。文档包含:
- 根因全链路:
tadaLaunchPrepare门控条件scheduler->numStreams == 1 && !plan->persistent→ 跳过launchStream与deviceStream的跨流事件 →scratchBuf在 kernel 可见时为NULL→ 解引用野指针 → ring ready-flag 读到垃圾内存 → 永久自旋 - 症状与根因的因果链:挂起在 ring waitloop(调用栈最后一帧),实际 bug 在 launch-prep(几帧之前)。跳过的同步是静默的,直到 dumbModel 的 reduce-scatter pattern(规约-分散模式)在每次 eval step 精确触发门控
- 失败的修复尝试:PR #5612 在 IPC publish 后加了主机端防御检查,在部分路径掩盖了症状但没有消除底层竞态——这次也一并回退
- 怎么漏出去的:单流快速路径 3 月加入时假设 dumbModel 总走多流路径。5 月 dumbModel launcher 把 eval step 坍缩为单流——条件翻转。CI 没有覆盖单流 + IPC + scratch buffer 的组合矩阵
3. management-talk 翻译给管理层
把 post-mortem 的工程事实交给 management-talk,同一个 bug,按渠道出三份:
JIRA 评论版本(最完整):
Status: Fixed pending merge. Bug found, fix validated, PR up for review.
Impact: LLM-7B fine-tuning on 8 GPUs would hang every time it tried to evaluate the model — blocking the entire workload. Affects customers using dumbModel.
What broke: Our GPU communication library (Tada) skipped an internal synchronization step under a specific configuration that dumbModel happens to trigger. The GPUs ended up reading from an uninitialized buffer and got stuck waiting for a signal that would never arrive. The unsafe shortcut had been in the code for months but wasn’t reached by any real workload until now.
A previous fix attempt added a defensive check that hid the symptom in some paths but left the underlying race in place. This new fix removes the unsafe shortcut entirely and tightens the safety check on the device side.
Owner: Alex (Tada team). PR org/platform#5751.
Next steps: code review → merge. Customers hitting this today can disable IPC registration as a temporary workaround.
Slack 版本就是上一节那份草稿——同一诊断,砍掉「为什么现在才暴露」和「失败的修复尝试」,控制在 80 词以内。
站会版本(1-3 行,动词开头):
Fixed Tada hang on dumbModel LLM-7B (JIRA-12345). Alex’s PR #5751 in review. Workaround posted in the ticket; backport to v7.2 next.
三个渠道内容完全一致:状态、负责人、下一步。JIRA 全都要,Slack 只留能扫读的,站会一句话说完。任何一份里都找不到 scratchBuf 和 tadaLaunchPrepare。
4. scrutinize 审查修复 PR
scrutinize 从意图开始:移除不安全快速路径 + 收紧设备端 null check → 目标成立 → 但有没有更简单的方式?→ 已有代码库中不存在更轻量的替代 → 通过。然后端到端追踪代码路径:tadaLaunchPrepare → tadaLaunchKernel → tadaLaunchFinish → 检查移除后 numStreams == 1 的流量是否正确走常规路径 → 验证 null check 的位置在解引用之前而非之后。
四个技能在这个流程里各自卡住了 AI 默认会跳过的环节——debug-mantra 拒绝在没复现时推进,post-mortem 拒绝在缺必要输入时动笔,scrutinize 拒绝跳过「这个改动该不该存在」的追问。
五、这套设计的工程逻辑
这套设计为什么管用?下面几条直接来自 SKILL.md 文件里的工程决策。
拒绝条件写在触发逻辑里
把上面同一个 bug 放到没有约束的 AI 编程助手面前,行为路径会明显不同。
调试阶段。AI 看到报错后大概率直接给出三个修复假设,跳过复现脚本。你拿到的是「看起来都合理」的候选答案,但没有任何一个被证伪过——第一个看起来最合理的假设往往就被采纳,根因是不是它没人知道。
复盘阶段。修完之后让 AI 写复盘,它会基于你提供的片段信息生成一篇结构完整的文档:有 Summary、有 Root cause、有 Action items。但 Root cause 段写的是「可能是 X 导致的」而不是「确认是 X 导致的」,Validation 段会写「建议补充测试」而不是「在 Llama-2-70B / 8 GPU / DeepSpeed 验证通过,未在其他负载重测」。文档读起来流畅,但六个月后你 grep 不到任何能定位现场的代码标识符。
审查阶段。AI 读完 diff 给出 5 条风格建议和 2 条「考虑抽取函数」的意见,跳过了「这个快速路径该不该存在」这一步。null check 加在了解引用之后,没人发现。
向上沟通。你把工程文档原文贴给 VP,VP 在站会上问「这个 tadaKernel 是什么」,没人答得上来。
这些差异来自约束的缺失——AI 做了它默认会做的事,但工程流程需要它在证据不足时停下来。9arm-skills 把拒绝条件写进触发逻辑:debug-mantra 的退出条件是「没有可靠复现就停下来」,post-mortem 的退出条件是「四个必要输入缺一不可」,scrutinize 的 Step 1 是「先问这个改动该不该存在」。
AI 一直在变聪明,但你不想它在你还没确认根因时就替你写了一份看起来很有道理的复盘——好看,但错,而且因为好看所以更难被识别为错。
代码标识符是回溯入口
post-mortem 和 management-talk 最关键的默契在这里:前者保留所有代码标识符(函数名、struct 字段、文件路径、commit SHA),后者把同一份事实翻译成管理层能读的语言。
两份文档各自的版本就是各自的真相。复盘文档里的 tadaLaunchPrepare 是六个月后 git log --grep 的回溯点;管理层 Slack 里的「skipped synchronization in the comms fast-path」是 VP 在站会上向 PM 转述的一句判断。各自完整,不需要互相迁就。
实验空间与发布门槛分治
9arm-skills 的 bucket 划分是一套治理模型的雏形。README 把六个目录分成两组:engineering/、productivity/、misc/ 对外暴露;personal/(跟个人配置绑定)、in-progress/(草稿空间)、deprecated/(退出通道)不对外。这条边界不靠自觉,仓库里有两道机制在执行它:
- 双重索引:仓库的
CLAUDE.md把规则写成指令——对外三个 bucket 里的每个技能,必须同时登记进 README 引用清单和.claude-plugin/plugin.json(Claude Code 的插件清单);私有 bucket 里的技能,两处都不得出现。草稿就算写完了,没进索引就没有入口。 - 链接过滤:
link-skills.sh建软链时用find显式排除deprecated/、in-progress/、personal/三个路径,脚本层面再挡一道。
目前仓库实际只落了对外那组(misc 暂空),三个私有目录还没有实体。这套「草稿不入列、废弃有出口」的分层,才是你自己搭技能库时真正值得抄的设计。
上述目录结构基于撰写时的仓库快照,技能增减与归类以仓库 README 当前版本为准。
六、适用与不适用
9arm-skills 对「已经在按流程走的团队」加成最明显。如果你们已经有一套调试纪律、复盘规范、代码审查惯例,那把这个库拿过来改写成团队的版本,AI 就能直接继承这些判断。
推荐的采用顺序:
先装
debug-mantra,跑一周。把四步口诀打卡变成肌肉记忆,感受 AI 在「拒绝跳到假设」这件事上的行为变化。 验收信号:当 AI 在你贴出 stack trace 后第一条回复是逐字背诵四步口诀而不是直接给修复假设,且至少有一次它要求你先提供复现脚本再继续——这一步就跑通了。再装
post-mortem。每次修完 bug 后让 AI 按那 9 段结构起草复盘——你立刻能看出哪些信息你在修 bug 过程中实际上没有收集。 验收信号:至少有一次 post-mortem 因为缺「可靠复现」或「根因确认」而拒绝起草,并明确列出缺什么——这说明门槛在生效。再装
scrutinize和management-talk。这两个是锦上添花——审查流程和向上沟通在团队规模扩大后才变成高频需求。 验收信号:scrutinize至少在一次 PR 审查中质疑了改动本身的必要性(而不只是给风格建议);management-talk产出的 Slack 草稿里没有函数名和 commit SHA,但 JIRA Key 还在。
什么时候不必用:
- 项目还处在快速原型阶段,流程本身就是每周在变的东西。这时候让 AI 跟着硬约束反而不如自由探索高效。
- 单人项目,没有「团队隐性知识」需要传递。你不需要
management-talk翻译给 VP,也不需要scrutinize模拟一个外部审查者的视角。 - 主要用 AI 做一次性脚本生成而非持续 coding session。技能的触发条件建立在「AI 始终活跃在 session 中」这个前提上。
安装方式:仓库推荐 npx skills add thananon/9arm-skills(对任意 agent 都可用);作者自己的开发循环用 ./scripts/link-skills.sh 把每个 shippable 技能软链接到 ~/.claude/skills/。
如果你要构建自己的技能库:
9arm-skills 的目录结构和安装机制本身就是一套可复用的骨架。从自建的 in-progress/ 目录起手写你的第一个技能,用 SKILL.md 的 YAML frontmatter(name + description)声明元数据,在正文中规定触发时机、执行顺序和退出条件。写完后移到 engineering/ 或 productivity/,跑 link-skills.sh,你的 AI session 就能多一条可执行约束。
七、局限性
9arm-skills 本身有明确的适用范围。
仓库近乎个人作品。截至撰写时的快照,仓库只有 4 次提交、每个技能只有一个 SKILL.md 文件,贡献者除作者 Thananon(Arm)外,还有 claude(以 Co-Author 身份出现在全部 4 次提交里)与 narze(Manassarn「Noom」Manoonchai,1 次贡献)。它本质上是一套「把一两个人的工程纪律固化成技能」的范本,不是开箱即用的成品库——拿来当骨架改写可以,原样照单全收不建议。
技能质量绑定作者经验。debug-mantra 的四步口诀是作者自己在工程实践中验证过的调试方法论。如果你的团队的调试习惯不同——比如你们靠 bisect 定位而非调试器——那这个技能就需要改写,而不是照搬。
技能本体只是提示词,没有配套脚本。六个技能的实体全是 SKILL.md——GitHub 把仓库语言标成 Shell,只是因为 scripts/ 下两个 Shell 脚本(link-skills.sh 做软链安装,list-skills.sh 列出技能清单)。这意味着所有执行都发生在 AI 的会话里,没有任何可执行代码兜底:AI 若不遵守合约,仓库层面没有机制能拦住它。需要复杂预处理的场景(比如解析 AST 再做代码审查)得自己写配套工具,SKILL.md 只能指挥 AI 去调用它。
文化耦合。四个技能都假设你的团队有工程师自主推动流程的文化。如果团队习惯是主管分配任务、工程师执行,那 scrutinize 的「先问这个改动该不该存在」这一步可能跟实际决策权归属不一致。
约束强制力依赖宿主工具。SKILL.md 本质是 Markdown 加 YAML frontmatter,这套格式原生面向 Claude Code 的 .claude/skills 机制。其他 AI 编程助手是否能严格遵守「没复现就停下」这类退出条件,取决于它是否提供类似 skills 的显式调用机制。你可以把 SKILL.md 内容拷过去当项目级自定义指令用,但强制力会比在 Claude Code 里弱。
八、收束
开头那个场景里,AI 给的建议「听起来对但差点意思」,差的是一组约束——告诉它在什么时候执行哪个流程、在什么条件下停下来。
9arm-skills 把这些约束写成了 AI 必须照办的合约。修完 bug 让 AI 起草复盘时,它会先列出缺哪些必要输入——让你立刻知道还缺什么,比拿到一篇流畅但 grep 不到任何代码标识符的「叙事散文」有用。调试、复盘、审查三个环节都有类似的约束在起作用。
如果打算上手,先做一件事:把你团队现在最没纪律保障的那个环节(多半是修完 bug 到写复盘之间)写成一份 AI 必须遵守的合约,第一行写退出条件——「没有可靠复现就不起草」。
项目地址:thananon/9arm-skills
资料口径说明
本文的判断和结论来自以下来源,存在明确的局限性:
主要来源:9arm-skills 仓库(GitHub: thananon/9arm-skills)的公开文档和 SKILL.md 源码。这些材料代表了作者 Thananon Patinyasakdikul(Arm)的个人实践经验,不代表通用真理。
技术准确性边界:本文提到的技能设计(debug-mantra、post-mortem、scrutinize、management-talk)是基于作者个人项目经验。不同团队的调试纪律、复盘格式、代码审查标准和沟通需求可能不同,需要根据团队实际情况调整触发时机、执行顺序和退出条件。
适用性边界:9arm-skills 面向的是「需要纪律保障的编码流程」,对于自由探索、原型开发、一次性脚本等场景,这套约束可能过度。
未覆盖话题:本文不讨论 Claude Code 的安装配置、其他 AI 编程助手(Cursor、GitHub Copilot 等)的对比评测、多模态编程等话题。
版本与时效性:本文初稿基于 2026 年 6 月中旬的仓库快照撰写(
qwen-agent、qwenchance于 2026-06-15 并入后共 6 技能);2026-09-14 修订时通过 GitHub API 复核了仓库结构、提交历史与四个核心 SKILL.md 的内容,Stars 数字为当日 API 返回的 3187。9arm-skills 仍在持续迭代,后续新增技能或调整以仓库最新版本为准。
参与讨论
使用 GitHub 登录。欢迎补充事实、异议与实践。
讨论暂时无法加载。