cm-fix — 缺陷修复小闭环
SkillDev toolsUse when the user says "fix this reproducible bug" or asks to fix code based on a failing report. Runs red-light testing, root-cause localization, minimal fix, independent review, and regression; for unconfirmed issues use cm-test first, and hand new features or architectural redesigns to cm-prd.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the cm-fix — 缺陷修复小闭环 skill
What this skill tells your AI
The instructions your AI receives, as published by kingxiaozhe/cm-workflow in skills/cm-fix/SKILL.md and read by ahel’s review.
执行前读取 ../../runtime/project-context.md、../../runtime/orchestration.md、
../../runtime/review.md、../../runtime/model-efficiency.md 与
../../runtime/logging.md。Codex 入口为 $cm-fix;Claude Code 跨平台入口为
/cm-fix,macOS/Linux 另有历史别名 /cm:fix。
每个缺陷开始/恢复时按 ../../runtime/project-learning.md 重读项目根 AGENTS.md,
筛选相关教训辅助复现与定位;同一合同约束收尾写回,不以旧经验代替本次证据。
用户明确要求外部专家,或为本次修复开启 AUTO 时,仍必须先完成第 1 步本地复现,
再按 ../../runtime/external-expert.md 执行 ../external-expert/SKILL.md 的任务
路由。代码、修复、测试和审查保持 LOCAL;只有竞争根因或高风险事实查证可路由到
CONSULT/VERIFY。外部假设必须回到本地证伪;咨询记录不能代替 2.5 或第 5 步独立
审查。
用法:$cm-fix {specs路径} {代码项目路径} 缺陷描述(现象/报错/截图均可)
JS 只读准入
在读取项目内容、解析角色、写 run_start、运行复现命令或创建档案前,先确认本轮包含非空缺陷
描述,但不要把描述正文拼进 shell;随后执行:
node "{CM_WORKFLOW_ROOT}/scripts/cm-fix-entry.mjs" \
--skill-dir "{CM_WORKFLOW_ROOT}/skills/cm-fix" --project "{CODE_PROJECT}" \
[--specs "{SPECS_DIR}"] --defect-present
没有 specs 的裸项目省略 --specs。缺少描述时不传 --defect-present,入口返回
blocked / defect_required 后只向用户补要描述。只有 ready / reproduce 才进入下方既有闭环;
它不提前声称缺陷可复现、不可复现或属于设计问题,只声明复现失败仍走 observation、确认设计
问题仍转 $cm-prd --change。返回的角色、日志和 Learning 均为 pending,执行/写入权限为 false;
入口不运行命令、不调用 provider/browser/外部专家、不创建日志/测试/档案,也不替代七步流程。
执行入口选择
准入通过后,具备当前会话双向进程通道、分离的 specs/代码根、命令式复现与测试配置时,
读取 references/js-host.md,使用既有 cm-fix-host.mjs 执行;Codex/Claude 共用同一 owner。
下文七步仍是业务要求,但 JS 分支的日志、交接、Review 发布及完成全部交给 owner,
不得再手工执行对应写入步骤。只读准入的 ready 不是执行、外发或完成许可。
裸项目、无自动测试/纯视觉替代、父 N6 运行衔接等尚未接通 JS 的场景,要明确报告缺口; 不得宣称已完成 JS 迁移。只有用户明确选择既有非 JS 流程且尚未创建 JS 运行时,才执行 下文手工流程;JS 已启动后遇到阻断,不得切换旁路、换身份或双写状态。
以下手工流程中,两个路径校验通过后调用统一写入器记录 run_start;暂停/续跑沿用同一
.cm-run.json,本次缺陷闭环或观测闭环退出时写 run_done。不得直接拼 JSON。
项目角色路由
从代码项目根解析 coder、tester、reviewer(命令、参数和日志字段见
runtime/workflow-routing.md)。coder 只作为最小修复的请求路由元数据,tester
负责防护网/回归,reviewer 只描述独立审查候选通道;declared-adapter 必须记录为
未观测适配器,不能伪造调用或绕过本地执行与独立审查。resolver 返回非零或配置错误
时立即 BLOCKED,不得复现、修改或写入缺陷档案;配置不存在时保持当前默认行为。
managed-adapter 按 runtime/model-efficiency.md 返回文本建议并自动记录真实 usage;
复现、修复落盘、测试和独立审查仍由本地流程执行。
角色调用按 runtime/model-efficiency.md 只传当前缺陷的复现证据、根因范围、修复
diff、回归结果和对应规则;不重复投喂整仓、完整历史日志或其他缺陷上下文。失败输出
保留首个可行动错误与证据路径,防护网、独立审查和回归要求不因精简而变化。
修 bug 专用的轻量闭环——不走 N1–N8 全链(那是 feature 流程),也不许脱离工作流裸改(裸改没防护网没审查,修一个坏三个)。
多缺陷输入:先对全部缺陷做第 1-2 步(复现+定位),按根因聚类——同根缺陷合并为一次修复(多个失败测试、一次改动、档案互链),修复顺序按严重度排,不按输入顺序。不聚类的代价:三个现象一个根因跑三个闭环,且第一个修复落地后,后两个的复现步骤可能已失效(第 1 步卡死)。
转交进场(消费上游落盘物,不改上游流程):缺陷描述可附上游档案引用——$cm-test 的只读测试报告、$cm-refactor 档案的未修缺陷清单、N6 业务走查报告的偏差项、观测闭环的半份档案(按 slug 在 fixes/ 检索)。带引用进场的缺陷,第 1 步采信上游已有证据(位置/现象/日志原文),仍须实际复现一次核实,但不从零摸排。
$cm-ai 全局规则在本流程内同等生效:灾难级与节点显式卡点暂停、多方案自主决策留痕、状态落盘(node 写 FIX)、运行日志照记、独立审查按 runtime/review.md 执行。
修改代码前预检 fresh 独立审查通道;无可用通道时暂停修复,已有改动保持待审。
当前支持 Codex 子代理/隔离 CLI;未验证的 Claude-native 适配不能改名冒充 Codex。
跨边界证据(条件触发):缺陷涉及跨进程/跨服务、异步队列或流、路由目标、缓存/状态不一致或时序偶现时,读取 references/cross-boundary-debugging.md;它只补定位证据,不新增入口、状态或完成标准。普通可复现缺陷不补表,仍走以下七步。
闭环七步(每个缺陷)
1. 复现(不能复现的 bug 不许修)
- 按描述复现:实际操作/运行一次,拿到失败证据(报错原文、错误截图、错误返回值);证据要用严格裁判——宽容裁判会把坏产物蒙混成功(实跑:补丁类缺陷 GNU patch 的 fuzz 容错险些吞掉复现,换 git apply --check 才拿到硬证据)
- 未复现先做复现探索:主动构造输入值(边界/空/超长/非法编码)、前置状态(空数据/脏数据/并发写入中间态)、时序(先后顺序/失焦与点击/异步未完成)、环境(版本/区域设置/权限/离线)、规模(单条/大量)场景;每次只改一个维度,记录「场景 → 结果」,沿用既有授权,不扩执行权限。
- 探索最多 3 个场景或 15 分钟(先到为准);命中即进第 2 步定位,该场景脚本/步骤作为第 3 步红灯测试骨架。到上限仍未复现 → 不猜着修,才走观测闭环(偶现 bug 专用,两段式):
① 先判断是否命中跨边界证据条件;命中时按参考先列“边 → 预期证据 → 实际证据”,再在可疑路径加最小观测点(日志/埋点——观测点本身按最小改动+审查纪律入库,观测点不是修复尝试)
② 缺陷档案先落半份,状态记
观测中,列出已试场景,说明观测点为何这样埋,写清"等什么证据(哪个日志出现什么内容)" ③ 本次命令正常收口退出,不挂着等——运行日志记run_done,detail 写「观测中:等{什么证据}」;状态文件 state 复位,不留悬挂的 running ④ 证据到手后再次运行$cm-fix附上证据,按 slug 定位fixes/下的半份档案,从第 2 步定位续跑,档案续写、状态改修复中,运行日志记resume(detail 注证据摘要) ——"我改了点东西你再试试"依然被禁止
2. 定位(先找根因,不是找改哪行能让现象消失)
- 按
../codebase-context/references/writeback.md确定项目地图及本次文档范围;有地图先读相关链路与影响映射,项目指定架构文档同样适用 - 无地图 → 从失败点向上追调用链,找到根因层(现象在 UI,根因可能在数据层)
- 命中跨边界证据条件 → 将调用链、每条边的最小证据、最后正常边与首个失败边写入缺陷档案;同时写“假设 → 支持证据 → 反证试验 → 结果”,一次只检验一个假设。日志与试验必须本地且脱敏,不自动联网、不外发日志、不安装依赖、不重启服务、不清理缓存。
- 输出一句话根因结论 + 波及面清单(本次修改会牵连哪些模块)——写进缺陷档案(第 7 步)
2.5 根因与修法对抗确认(条件触发;根因错误是本流程最贵的错误,必须在防护网之前拦)
任一客观条件命中才触发(简单缺陷零负担,判断依据同"门槛是客观项不是判断题"):波及面 ≥3 个模块 / 根因层与现象层不同层 / 观测闭环续跑的缺陷 / 拟走升级出口。
- 把根因结论 + 复现证据 + 波及面清单 + **拟采用修法(含放弃的备选)**交给新上下文的独立审查者;命中跨边界证据条件时一并交调用链、最后正常边、首个失败边和已完成的反证试验。提示词要义:「假设这个根因判断是错的,找出更深层的解释;再审修法:治本还是治症?有没有更小的改动?会不会引入新耦合?」。通道与降级规则同 N4
- 仅 1 轮:推翻 → 回第 2 步重定位;分歧 → 交人裁决;通过 → 进第 3 步
- 凭证落
{SPECS_DIR}/.reviews/fix-{slug}-cause-r1.md——命名带cause是有意的:不落入第 5 步fix-{slug}-r*.md的匹配域,两个卡点各自独立,根因凭证不会误满足 diff 审查卡点
3. 防护网(先让 bug 有测试,再修)
- 写一个能复现此 bug 的失败测试(红)——它是"修好了"的客观定义,也是永久回归资产;红的原始输出落进档案(第 5 步审查要核对红证据,从未红过的测试转绿是空话)
- 项目有存量测试 → 先跑一遍记录基线(修完对照,防止修 A 坏 B)
- JS owner:首轮补测走原 test-author;保留原红灯和存量基线。最终审查要求补测时,按
references/test-extension.md在第二轮登记扩充,修复回调仍不得改测试。 - 写不了自动化测试的形态(如纯视觉)→ 截图/录屏留"修前"证据
4. 修复(最小改动)
- 只改根因层,禁止顺手重构(N3 同款纪律:看不惯的代码记 LESSONS 待触发备忘,事后走
$cm-refactor,不在修 bug 时动) - 修法有多个方案 → 自主决策选最优,
decision事件留痕 - 升级出口:定位发现是设计缺陷/需要跨模块大改 → 停止硬修,先通过第 2.5 步根因审查。JS 返回
design_change_required后,有redTest就沿原测试编写/红测入口取得真实失败;意外通过或失败原因不符照常阻断。红测确认后进入escalation_required,不跑基线、修复、回归或最终实现审查。 - 已建资产不弃:失败测试留在仓库;档案状态记
升级立项,列出根因、影响范围、诊断方案、根因审查凭证、测试路径和红证据路径,建议用$cm-prd --change立项,以新方案使该测试变绿为验收。非视觉运行未配置redTest时直接进入升级归档,并明写没有失败测试及原因;视觉运行必须配置视觉redTest(testFiles:[]),先走视觉红测核验真实修前载体再升级,不冒充自动红测。 - JS 可先
publish_dossier,再用获准的finish写run_done / escalation / escalated并关闭 owner;中断后在原运行重开收口,冲突则阻断。重开后的escalated是终态,completionEligible始终为 false,不记 task_done 或修复完成指标;立项建议不自动创建变更项目。
5. 审查(独立审查同 N4)
-
修后按
../cm-test/references/unit-coverage.md检查已授权修复范围的增量单测覆盖率, 核对正常/异常/边界及相邻场景并重跑,纳入下面的同一份 handoff;原失败测试红绿证据必须保留。 普通流程在审前补足授权测试;JS owner 若第一轮最终审查要求补测,按references/test-extension.md登记测试编写和实跑结果, 再走第二轮修复、回归与独立审查;不在 owner 外修改测试或重建原红灯、基线。 -
先按
../codebase-context/references/writeback.md完成地图评估与必要回写;无地图建本次局部地图,有地图只更新受影响章节。普通流程记 handoff evidence,JS 复用已绑定的 plan、修后文件与 Review;改动纳入摘要与独立审查,不能等第 7 步再写。 -
审查前按
../../runtime/project-learning.md复盘并完成必要的 AGENTS.md 增量写回,纳入本次审查 diff;无新增记入缺陷档案。微缺陷通道也必须复盘,新增 AGENTS.md 改动导致不再满足单文件门槛时走完整流程。 -
失败测试转绿 + 存量基线不退化后,按
runtime/review.md审查本缺陷 diff(重点:根因是否真被修掉、有无只治症状、波及面有无遗漏) -
防护网测试本身是审查对象(实测最大问题类:测试是戏台):红的原因是否=该缺陷、断言测的是根因还是症状、有无安慰剂/前提共谋;核对第 3 步落档的红证据——没有红过的记录,测试可信度按不成立处理
-
所有缺陷零豁免;独立通道不可用则待审,
self-degraded仅作诊断,不得成功收口;通道故障不算代码 finding/实现审查轮次,有效 finding 不能靠换人消除;≤2 轮上限同样生效 -
{slug}先规范成跨平台安全的 ASCII kebab;令REVIEW_FEATURE=fix-{slug}、REVIEW_TASK=T-FIX-{slug}。主执行者按真实 diff 写{SPECS_DIR}/.reviews/fix-{slug}-T-FIX-{slug}-a{attempt}-handoff.json,格式与runtime/task-handoff.schema.json相同。先按 handoff 的完整changed_files运行cm-task-gate.py hash-implementation --project-root {CODE_PROJECT} --file ...,把返回的implementation_sha256写入 handoff,再真跑:
python3 {CM_WORKFLOW_ROOT}/scripts/cm-task-gate.py check-n4 \
--handoff {HANDOFF_PATH} --reviews-dir {SPECS_DIR}/.reviews \
--feature fix-{slug} --task T-FIX-{slug} --project-root {CODE_PROJECT}
- 独立审查凭证严格落
{SPECS_DIR}/.reviews/fix-{slug}-T-FIX-{slug}-r{attempt}.md,包含当前 handoff 文件名和 SHA。审查完成后必须真跑下列命令;只有当前 attempt 的independent: true且verdict: approved才能进入第 6 步:
python3 {CM_WORKFLOW_ROOT}/scripts/cm-task-gate.py check-n5 \
--handoff {HANDOFF_PATH} --reviews-dir {SPECS_DIR}/.reviews \
--feature fix-{slug} --task T-FIX-{slug} --project-root {CODE_PROJECT}
changes_requested后修改代码必须生成 attempt 2 handoff 并复审;第 2 轮仍有阻断项 写blocked并停止。文件存在、旧凭证或ls输出都不构成批准。- 后续回归、文档或经验整理如修改被审代码、测试或执行指令,原批准失效;重新形成证据并独立审查,不能重置轮次或在收口时顺手改实现
6. 回归(按波及面,不是只看 bug 消失)
- 跑第 3 步防护网测试(红→绿)+ 存量测试全量(对照基线)
- 按第 2 步波及面清单逐项走一遍关键流(同 B2 口径:波及面=回归范围)
- 回归失败的回路(显式分支,不许临场发挥):任何一项红 → 退回第 4 步重修,重修后必须复审且轮次并入第 5 步的 ≤2 轮总上限——上限耗尽仍打转 = 根因判断可疑,按升级出口处置,不许无限修-回归循环
7. 落盘(审计链闭合)
- 核验地图评估结果和已审文件版本,缺评估、待同步或审后变化不写成功
task_done;遵守回写合同的项目规则豁免,不把缺失地图静默跳过。 - 收口前核对复盘记录、AGENTS.md 的审查范围与磁盘摘要;有新增则回读确认,无新增如实记录。缺记录、无法写回或批准后变化时不写成功
task_done,按学习合同与第 5 步处理。 - 缺陷档案:
{SPECS_DIR}/fixes/{YYYYMMDD}-{简短slug}.md——现象 / 复现步骤 / 复现尝试(逐条「场景 → 改了哪个维度 → 结果(复现/未复现/环境不支持)」;按描述一次命中只写一行)/ 根因 / 修法(含放弃的方案)/ 波及面与回归结果 / 测试文件路径;命中跨边界证据条件时追加“证据链与假设”(调用链、边证据、最后正常边、首个失败边、反证结果)。这是缺陷知识库,同类 bug 再犯先查这里 - METRICS.md 追加一行:Feature 列写
fix,任务列写档案文件名,其余列同口径(轮次/拦截数/人工介入) - 根因具普遍性(如"平台 API 返回结构变了")→ 追记 LESSONS.md([已结构化]/[仅记忆] 分级同 N5)
- Git 按有效
policies.delivery:diff 不 stage/commit;branch/draft-mr 提交fix: {一句话} (档案: fixes/xxx.md),审查摘要进 commit message(同 N4) - 运行日志事件:
task_start/review/task_done/run_done照记,node 字段写FIX
微缺陷快速通道(四个硬门槛全中才准走)
门槛是客观项不是判断题——"感觉这个 bug 很小"不构成理由,四条全中才走,任一不中走完整七步:
- 只改文案/样式/配置常量——不新增、不修改任何条件分支与函数签名
- 单文件且 diff ≤ 10 行
- 波及面为零(改动处无被其他模块引用的行为;有业务地图查 08 映射表核实)
- 有截图/文案前后对照可作验收证据
快速通道可省:第 3 步防护网测试、第 6 步全量回归(用前后对照截图代替)。
不可省:独立审查(凭证照落)、地图评估(回写导致多文件则走完整流程)、缺陷档案(显式标注 快速通道)、METRICS 行(Feature 列写 fix-lite)。
快速通道的审查特化:独立审查是该通道的主要质量防线,第一职责是复核四个客观门槛;diff 任一项不符或波及面存疑即打回完整七步。
fix-lite 的占比进运行日志——快速通道被滥用(占比异常高/出现分支改动混入)时收紧门槛,数据说了算。
输出格式(每个缺陷收口时)
🔧 缺陷闭环: {slug}
根因: {一句话}
修法: {一句话} | 放弃方案: {有则一句话,无则省}
防护网: 新增 {测试文件}(红→绿) · 存量基线 {N} 项无退化
审查: 独立审查({channel}) {通过/N轮N条} | 回归: 波及面 {N} 项通过
档案: fixes/{文件名} METRICS 已记
学习: {AGENTS.md已写回并回读/已复盘,无新增}
业务地图: {已更新/已建局部地图/无需更新/项目规则豁免/待同步} {路径或原因}
边界
- 不承接:新功能(走 $cm-prd)、需求变更(走 $cm-prd --change)、架构级返工(升级出口交人立项)
- specs 目录没有 fixes/ 子目录时自动创建;没有 specs 目录的裸项目也可用:档案落代码项目
docs/fixes/,审查凭证落docs/fixes/.reviews/(第 5 步卡点同样生效),METRICS 跳过
Signals
- GitHub stars
- 23
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
cm-fix- Source
- github.com/kingxiaozhe/cm-workflow