# Cm Fix

> 用户说“修复这个可复现 bug”或要求根据失败报告修代码时使用。执行红灯测试、根因定位、最小修复、独立审查和回归；尚未确认的问题先用 cm-test，新功能和架构重设计转交 cm-prd。

- Skill: `kingxiaozhe/cm-fix` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add kingxiaozhe/cm-fix`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kingxiaozhe/cm-fix/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: kingxiaozhe (https://skillmd.com/u/kingxiaozhe)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kingxiaozhe/cm-fix

---


# cm-fix — 缺陷修复小闭环

执行前读取 `../../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；随后执行：

```bash
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 才拿到硬证据）
- 复现不了 → 不猜着修，走**观测闭环**（偶现 bug 专用，两段式）：
  ① 先判断是否命中跨边界证据条件；命中时按参考先列“边 → 预期证据 → 实际证据”，再在可疑路径加最小观测点（日志/埋点——观测点本身按最小改动+审查纪律入库，**观测点不是修复尝试**）
  ② 缺陷档案先落半份，状态记 `观测中`，写清"等什么证据（哪个日志出现什么内容）"
  ③ 本次命令正常收口退出，不挂着等——运行日志记 `run_done`,detail 写「观测中:等{什么证据}」;状态文件 state 复位,不留悬挂的 running
  ④ 证据到手后再次运行 `$cm-fix` 附上证据，**按 slug 定位 `fixes/` 下的半份档案**,从第 2 步定位续跑,档案续写、状态改 `修复中`,运行日志记 `resume`(detail 注证据摘要)
  ——**"我改了点东西你再试试"依然被禁止**

### 2. 定位（先找根因，不是找改哪行能让现象消失）

- 有业务地图（`docs/codebase-context/`）→ 先查 07 业务线路定位所在链路，08 修改影响映射表查波及面
- 无地图 → 从失败点向上追调用链，找到**根因层**（现象在 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）
- 写不了自动化测试的形态（如纯视觉）→ 截图/录屏留"修前"证据

### 4. 修复（最小改动）

- 只改根因层，**禁止顺手重构**（N3 同款纪律：看不惯的代码记 LESSONS 待触发备忘，事后走 `$cm-refactor`，不在修 bug 时动）
- 修法有多个方案 → 自主决策选最优，`decision` 事件留痕
- **升级出口**：定位发现是设计缺陷/需要跨模块大改 → **停止硬修**，报告根因并建议走 `$cm-prd --change` 变更模式立项——bug 命令不承接架构手术。**已建资产不弃**:第 3 步的失败测试保留入库（它是缺陷的客观复现,新方案转绿即验收）,档案状态记 `升级立项`,注明测试路径供立项后的流程直接接手

### 5. 审查（独立审查同 N4）

- 审查前按 `../../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，再真跑：

```bash
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 步：

```bash
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. 落盘（审计链闭合）

- 收口前核对复盘记录、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 的占比进运行日志——快速通道被滥用（占比异常高/出现分支改动混入）时收紧门槛，数据说了算。

## 输出格式（每个缺陷收口时）

```text
🔧 缺陷闭环: {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 跳过

