技能候选管理
一句话概括:把「零散重复的一次次操作」变成「有证据、有分数、有结论的候选清单」,再让清单里最硬的那几条晋升成为真正的技能。
核心原则和垃圾回收不同:这里绝不自动删除任何东西。候选可以沉睡、可以被驳回、可以降级,但每一次状态变化都要留下记录,且必须由人来拍板。
为什么需要它
技能目录天然是「只增不减」的:每次学到新东西就加一个 skill,从没有人回头看。三个月后你会发现三十多个技能里有一半从没被触发过,还有两个在做重复的事。
这个技能把「加技能」这件事从冲动变成流程——先落在候选池里攒证据,够硬了再晋升。
三个候选来源
判断一个候选是否成立,看它属于哪一类信号:
| 来源 | 典型表现 | 初判置信度 |
|---|---|---|
| 用户纠正 | 你做错了,用户明确说「应该这样」 | 0.7 |
| 错误修复 | 非显而易见地绕过一个坑,试了几次才对 | 0.6 |
| 重复流程 | 同一串步骤第三次出现,顺序稳定 | 0.5 |
「我觉得这个挺有用」不算信号。没有具体证据(哪一步、哪一天、哪句话)就不要登记。
候选项的字段
一个候选条目是一条最小化的记录,一次只描述一个触发点和一个动作:
id:短横线命名,例如prefer-append-only-logtrigger:什么时候会用到它,用一句话描述场景action:具体该怎么做,祈使句domain:归类标签,可选代码风格/测试/构建/调试/工作流/文档confidence:0.3 到 0.9 的小数evidence:证据列表,每条带上观察来源scope:项目(默认)或全局status:新登记/观察中/已采纳/已驳回/已晋升hits:被独立复现的次数
原子性是硬要求:一个候选只管一件事。发现一个候选里塞了三件事,说明它应该被拆成三个。
置信度怎么打分
置信度不是「你有多想做它」,而是「证据有多硬」:
- 0.3 起:只出现过一次,还可能是巧合
- 每多一次独立复现 +0.1:不同任务、不同天、同一个模式才算独立;同一任务里重复三遍只能算一次
- 用户明说要固化:直接 +0.2,这是最强的信号
- 有反例(按它做了反而更差):-0.2,并记录反例
- 上限 0.9:永远留 0.1 给不确定性。声称 1.0 的候选基本都是在自欺欺人。
晋升门槛:0.7 且 hits ≥ 3。低于这个线就继续在池子里放着,等待更多证据——不要因为「感觉差不多了」就提前动手。
详细的评分细则和历史案例见 references/候选评分卡.md。
四步工作流
第一步:登记
发现信号后立刻登记,别指望事后回忆。用下面的命令(脚本真实存在于本技能的 scripts/ 目录):
python scripts/candidate_cli.py add --id grep-before-edit --trigger "改写已有代码之前" --action "先用搜索确认所有调用点,再动手改" --domain 工作流 --evidence "用户在 2026-08-02 纠正过一次" --evidence "2026-09-11 同类任务复现" --confidence 0.6
命令行参数为 --id / --trigger / --action / --domain / --evidence / --confidence / --scope,其中 --evidence 可重复传入多次。数据默认写在当前目录的 candidates.json,用 --data 可以换位置。
第二步:累积
每次旧候选再次被印证,就补一条证据并提高分数:
python scripts/candidate_cli.py hit --id grep-before-edit --evidence "2026-09-18 又一次复现"
这一步最容易偷懒。请务必当场做——候选管理的全部价值都建立在「证据是当时记下来的」这个前提上,一周后补记的证据基本没有可信度。
第三步:评审
建议每月一次,或者每次大批量安装新技能之后追加一次。每次评审最多处理 20 条,宁可不完整也不要赶工:
python scripts/candidate_cli.py list --min 0.6
python scripts/candidate_cli.py review --id grep-before-edit --verdict 采纳 --note "可以晋升,和技能968题干里的流程一致"
--verdict 取值为 采纳 / 驳回 / 观察中 / 暂停。一条一次决策,禁止「全部批准」。「整批处理」会把这个流程变成走过场。
评审时优先挑这几类:① 和已有技能职责重叠的;② 置信度高但三个月没人执行过的(说明触发条件写得不对,不是技能没用);③ 从没被打过 hit 的僵尸候选。
> 注意「老」不等于「死」。季度结账、年度复盘这类技能可能半年才用一次,但到时候缺了它就得加班。年龄是信号,不是判决。
第四步:晋升
达到门槛的候选转成正式技能或者直接生成变更提案:
python scripts/candidate_cli.py promote --id grep-before-edit --target ../技能创建器
晋升只是把候选移交给「技能创建器」去真正编写,本技能到此为止。晋升后原候选标记 已晋升 并保留记录,不要在清单里删掉它——半年后你想知道「当初为什么建这个技能」时,只有这里能查到。
变更提案
改动一个已经上线在用的技能要走提案,不能直接改。原因很简单:一个被十条工作流依赖的技能,改坏了没人知道是谁的锅。
python scripts/candidate_cli.py propose --id grep-before-edit --change "把搜索范围从当前目录扩大到整个仓库" --risk 中
python scripts/candidate_cli.py proposals
python scripts/candidate_cli.py settle --proposal 3 --result 通过
提案要求写清三件事:改什么、为什么要改(附证据)、怎么回滚。缺任何一条就打回去重写。生产技能先复制一份快照到 _snapshot/<日期>/ 再动刀,硬改之前永远先留退路。
把技能编排成工作流
单个技能解决单点问题,工作流解决「一连串动作」。编排原则:
- 一个技能一个阶段,阶段之间靠明确的文件产物衔接,不靠上下文心领神会。上一个阶段必须落盘一个文件,下一个阶段读那个文件。
- 写清失败口径:某个阶段失败时是停下还是跳过?能跳过的必须写明跳过后后续阶段会不会缺输入。
- 标注每个阶段用哪个技能,并且注明「如果那个技能不存在,退化成什么人工步骤」。
- 别把整个工作流的细节塞进一个技能:如果某个阶段本身已经有独立技能了,直接引用它,不要复制它的正文。复制等于以后要维护两份。
一个工作流片段长这样:
阶段一 采集 用 技能候选管理/references/候选评分卡.md 的口径打分
阶段二 评审 人工确认 → 落盘 review-<日期>.md
阶段三 生成 调用 技能创建器 产出 SKILL.md 骨架
阶段四 校验 调用 技能脚手架 跑一遍 init 确认能落地
反模式
- 凭感觉登记:「这个应该挺有用」但举不出一次具体实例。删掉它。
- 批量批准:一次采纳十五条候选,等于没评审。
- 一次塞三个动作:候选必须原子,塞不下就拆。
- 拿「老」当「死」:季节性流程需要的是更好的触发描述,不是删除。
- 抹掉历史:晋升或驳回后把候选从清单里物理删除,等于烧掉自己的决策记录。
- 跨界 cleaned:别顺手去整理与技能候选无关的配置、缓存、源码目录,那些不属于本技能范围。
与其他技能的关系
技能创建器:本技能判定「值得做」之后,由它负责真正写出高质量的 SKILL.md。技能脚手架:判定「可以先搭个骨架试试水」时,由它一键生成目录结构。- 它俩都只负责「做」,「值不值得做」永远归本技能管。