Claude Skill

cm-fix

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

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download kingxiaozhe-cm-workflow-skills_cm-fix-3f79f65.zip · 24 KB
Part of kingxiaozhe/cm-workflow — 24 skills

Install

skills CLI npx skills add https://github.com/kingxiaozhe/cm-workflow/tree/main/skills/cm-fix
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install kingxiaozhe-cm-workflow@llmmart
Git git clone https://github.com/kingxiaozhe/cm-workflow.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole kingxiaozhe/cm-workflow collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

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;随后执行:

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 不是执行、外发或完成许可。

JS 步骤留在 unknown 时先检查原调用和磁盘现场。只有本地复现、诊断、测试、修复、回归、 复盘及走查等列在 JS 宿主手册 的步骤, 才可在确认后用 abandon_step 说明原因并重做;普通 advance/run 不会自行放弃。 独立审查、Learning 写回及交接文件仍按各自恢复或人工检查路径处理,不走此出口。

裸项目、无自动测试/纯视觉替代、父 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 跳过
Files (cm-workflow)
  • references
    • cross-boundary-debugging.md 2.7 KB
      # 跨边界排障参考
      
      仅在缺陷涉及**跨进程/跨服务、异步队列或流、路由目标错误、缓存/状态不一致、时序偶现**时读取。普通可复现缺陷继续按 `cm-fix` 七步闭环,不补这份表。
      
      ## 边界
      
      - 这是定位与观测方法,不是新的修复入口、状态文件或完成标准。
      - 只使用本地、最小且已脱敏的日志、断言、指标或测试夹具;不自动联网、不外发日志、不安装依赖、不重启服务、不清理缓存。
      - 不记录 token、Cookie、密码、个人数据、完整请求体、生产数据库记录或内部端点;需要关联时只保留安全的请求/关联 ID 和必要字段摘要。
      - 观测证据只用于定位;仍须遵守 `cm-fix` 的失败证据、红灯测试、独立审查、回归和档案要求。
      
      ## 1. 画出调用链并定义证据
      
      先用一行描述从触发到结果的路径:
      
      ```text
      触发 → 生产者 → 传输/状态 → 消费者 → 结果
      ```
      
      再在修改行为前定义每条边的最小证据:
      
      | 边 | 预期证据 | 实际证据 | 结论 |
      | --- | --- | --- | --- |
      | E1:触发 → 生产者 | 安全关联 ID 与关键状态一致 | {待观测} | {待判断} |
      | E2:生产者 → 传输/状态 | 事件/状态写入成功 | {待观测} | {待判断} |
      | E3:传输/状态 → 消费者 | 消费到同一关联 ID 与版本 | {待观测} | {待判断} |
      | E4:消费者 → 结果 | 用户可观察结果符合契约 | {待观测} | {待判断} |
      
      复现后标明:**最后一个正常边**、**第一个失败边**,以及根因所在的最小区间。没有实际证据不得填写“已确认”。
      
      ## 2. 逐个检验可证伪假设
      
      | 假设 | 支持证据 | 反证试验 | 结果 |
      | --- | --- | --- | --- |
      | {具体且可证伪的根因} | {来自哪条边的最小证据} | {一次只改变一个变量的本地试验} | 支持 / 排除 / 待证据 |
      
      - 一次只检验一个假设;失败时回到链路和证据,不叠加猜测式补丁。
      - 确认的根因必须能解释首个失败边;开始修复前仍按 `cm-fix` 第 3 步建立红灯测试。仅 `cm-fix` 已明确的纯视觉形态可用修前截图/录屏作为该步骤的证据。
      - 多轮修复/回归仍无法解释证据时,按 `$cm-fix` 升级出口交 `$cm-prd --change`,不继续扩大补丁。
      
      ## 3. 落档
      
      触发本参考时,把调用链、边证据、最后正常边、首个失败边与假设表写入既有
      `{SPECS_DIR}/fixes/{YYYYMMDD}-{slug}.md` 的“证据链与假设”小节;没有 specs 目录的裸项目使用 `docs/fixes/{YYYYMMDD}-{slug}.md`。观测中档案只记录已观察到的事实和等待条件;证据到手后按原 slug 续跑既有闭环。
      
    • js-host.md 20.3 KB
      # cm-fix 当前会话 JS 入口
      
      这是现有七步流程的执行接线,不是另一套修复或完成规则。路径从本参考解析,
      插件根为 `../../..`;不使用固定缓存路径、不安装或更新用户级 Skill。
      
      ## 启动与权限
      
      1. 完成 Skill 的只读准入,重读目标根及适用 AGENTS;核对真实缺陷、代码根、specs 根、
         命令式失败签名与测试范围。同仓specs使用下文protectSpecs模式。先确认当前环境支持原命令执行器;Windows
         进程树暂不支持。没有旧测试但能写新回归测试时,按下文显式声明无存量测试;
         纯视觉替代、裸项目走下文原owner分支,不能伪造命令或specs跨过。
      2. 从当前真实宿主确定 `--runtime codex|claude`,不能让模型选择另一端规避失败。
         用真实会话身份作为 `--host-context`;恢复必须保留原身份、配置与 runtime,不冒用旧会话。
         换会话恢复时,`--host-context` 填当前真实会话,另加 `--original-host-context` 填创建这次运行的旧会话 ID
         (取自 `specs/.reviews/.execution/<runId>/state.json` 首条 `fix-configuration` 记录的
         `configuration.hostContextId`)。durable 配置与指纹保持原样、旧记录一字不改;填错只会 `fingerprint_mismatch`
         失败退出。同会话重开不带此参数。换过几次会话都只填最初那个:新会话第一次签审查授权前,会先在存档里追加一条
         `fix-host-joined-N` 记下自己,所以之后任何会话都认得它签过的授权。只打开看状态不会写这一条。
         创建会话、记下的接手会话、当前会话都算宿主,reviewer 必须独立于其中每一个;接手会话最多记 16 个。
         0.16.1、0.16.2 期间换会话签过授权的旧运行没有这条记录,只能由当时签授权的那个会话继续。
      3. 配置是数据文件,不是脚本模块。读取 `../../../scripts/cm-fix-host.mjs` 的配置解析与
         `--help`,按已批准范围填写 `specsRoot`、`identity`、`defect`、`reproduction`;后者为
         `{cwd, command, expectedFailure:{exitCode,outputIncludes}, timeoutMs}`,命令使用 argv 数组。
         可选 `redTest`、`baseline`、`testAuthor`、`repair`、`walkthrough`、`applicableAgentFiles`
         必须先按 `../../../runtime/js/cm-fix/` 中对应模块的实际合同配置,不能临场发明字段。
         首次启动前固定所需配置;持久运行不支持通过改配置文件解除阻断。
         地图同步按 `../../codebase-context/references/writeback.md` 在启动前确定文档路径并纳入
         已批准的 `repair.scope`;`fix_repair` 内完成回写,缺范围不在宿主外补写。
         本次参考且保留路径的现有地图加入 `repair.requirements` 作为只读审核材料;新建或已批准删除/改名
         的地图只进写 scope,由真实 diff 的 after/before 携带;不能为审核把只读材料变成写权限。
      4. 根因/最终 reviewer 配置及诊断沿用 `../../../scripts/cm-ai-host.mjs` 的
         `readConversationReviewConfiguration` 和对应 runtime preflight 合同;诊断输入是该脚本
         所要求的 cm-ai 配置,不把 fix 配置直接当作诊断配置。诊断不等于真实模型可用或外发批准。
         Claude 不能复用 Codex receipt 或非空 disabledSkills;不手造诊断、grant 或 Review 结果。
      5. 启动参数只包含当前已获授权的操作。`--allow-reproduction` 授权实际复现,不是只读开关。
         根因/最终 Review 的真实调用须另有本轮包与模型授权,分别使用 `--allow-cause-review`、
         `--allow-final-review`;测试编写/修复也要求原 reviewer 诊断与各自权限,不能以诊断代授权。
      
      ```bash
      node "{CM_WORKFLOW_ROOT}/scripts/cm-fix-host.mjs" serve \
        --config "{FIX_CONFIG}" --mode create --host-context "{真实当前会话ID}" \
        --allow-reproduction --runtime codex
      ```
      
      这是已授权复现的最小启动示意,不是完整修复配置。Claude 改为 `--runtime claude`;
      重开使用 `--mode resume`,它与下文观测恢复消息 `resume` 不是同一操作。
      
      ### 用驾驭员,不要手搓中间人
      
      宿主靠标准输入一行一行喂 JSON,而当前会话每次只能执行一条命令、抱不住长活进程。**不要临场
      写一个中间人脚本**——一次真实实跑里两次配错(走查模块对不上、任务编号重名)根源都在这儿。
      仓库自带 `scripts/cm-fix-drive.mjs`,一次只做一步:
      
      ```bash
      node "{CM_WORKFLOW_ROOT}/scripts/cm-fix-drive.mjs" --plan "{PLAN}" advance
      ```
      
      `PLAN` 是一份小 JSON:宿主配置路径、代码根、`create|resume`、当前真实会话 ID、换会话时的
      原会话 ID、`--allow-*` 开关数组(原样传给宿主,不另造一套词)、答案目录。宿主中途的反问
      (学习记录、诊断、测试内容、修复内容、复盘)从答案目录里按种类读文件——**你的工作是把内容
      写进文件,再调一次驾驭员**;它绝不替你编任何一份。恢复时学习记录自动复用存档里已记的那份。
      
      它最要紧的一条护栏:按「这一步会反问什么」**先查齐答案文件,再发指令**。宿主默认不重派
      结果不明的步骤;只有下文列出的本地步骤可经显式授权、说明原因后放弃并重做。缺答案硬发仍会让
      整轮停在 `unknown`,不能靠普通 `advance` 解除。建运行前它还会预告:任务编号是否已被
      审查结论占住、配置引用的文件是否存在、受保护模式下有没有沙箱跑不了的 tsx/vitest 类命令。
      
      它只是方便,不是放权:能做什么仍由宿主的开关说了算。
      按当前授权选择 `--review-config` 及 CLI 列明的 `--allow-*`,不要一次性全开。
      
      ### 同仓 specs 的受保护修复
      
      在原fix启动配置显式设置`"protectSpecs":true`,QA子运行则设在原owner/template的configuration内。
      这不增加权限:原复现、编写测试、修复、回归、Review、Learning写回和finish仍分别授权。
      复现/红测/存量基线/修后及审后回归/命令走查使用同一原生specs只读沙箱;日志、证据和Learning仍由原owner负责。
      固定命令执行器使用本机Codex sandbox,不调用模型;Claude宿主的推理和Review仍属Claude,不借用Codex身份或诊断。
      
      沙箱里 `network={enabled=false}`,而这个开关同时管着 unix domain socket 的 listen。于是**凡是要开本地
      IPC socket 的命令都会失败**,典型的是 `tsx` CLI(启动时在 TMPDIR 建 `<pid>.pipe`,报
      `Error: listen EPERM`),`vitest` 等同理;写 TMPDIR 文件本身不受影响。这不是配置能绕开的:放开它就等于
      给测试命令放开整个外网。配 `baseline.commands` / `redTest` / `walkthrough` 时请避开这类命令,例如把
      `npm test`(内部串联 12 个 `tsx xxx.test.ts`)换成逐文件的
      `node --import ./node_modules/tsx/dist/loader.mjs <file>`,覆盖面不变而沙箱能跑。
      
      沙箱内失败只会留下 `outcome:"failed"` 和 `host check exited N`——原始输出**有意**不进证据(可能含密钥、
      且不稳定)。要看真实原因,手工重放 `specsPermissionArgs` 拼出的那条 `codex sandbox ... -- <命令>`。
      配置里留了跑不了的命令,代价是修复前后都失败、回归判 `unresolved_failure`,整轮卡在 `regression_blocked`。
      
      `fix_test_author`/`fix_repair`请求若有`editMode:"protected-text-v1"`,当前会话只读取和生成提案,**不直接修改文件**。
      按请求scope和expected返回`{outcome,edits:[{path,beforeSha256,content}]}`,content为完整UTF-8正文,null删除已有文件,
      beforeSha256严格复制expected中该路径的摘要(原不存在则null);不能改路径范围或先自行落盘。blocked须edits为空数组。
      原64KiB通道上限不变,不能用外部脚本/命令/binary替代超限正文;无法表达则如实阻断,不切回无保护写入。
      固定子进程校验整组路径/原摘要后在沙箱内写入;符号链接、硬链接或漂移拒绝。保留原diff检查、Review和门禁。
      这是同一次原已登记操作,不新增provider调用或作者身份;中途失败可能留下部分改动,原owner保留unknown,不能自动重试或回滚。
      恢复必须保持原配置,旧运行不能临时开启/关闭保护。宿主本身仍是受信执行者,语义/浏览器请求不授权修改项目文件。
      
      ### 本地 unknown 步骤的显式放弃与重做
      
      先核对旧进程已停止、检查可能留下的本地改动和测试输出。仅在原运行 `stage=unknown` 且决定重做该本地步骤时,
      以 `--allow-abandon` 启动 cm-fix 宿主,再发送 `{"requestId":"abandon-1","operation":"abandon_step","reason":"本次放弃的具体原因"}`。
      原因须为非空单行、至多 1000 UTF-8 字节;每个运行最多 8 次。QA-fix 子宿主使用 `--allow-qa-fix-abandon`,
      其 `fix_action` 请求带 `fixOperation:"abandon_step"` 和 `reason`。驾驶员从 PLAN 的 `reason` 读取原因,
      `permissions` 须含 `--allow-abandon`,此操作不需要答案文件。
      
      允许的 `pending`:`reproduce`、`diagnose`、`observation_reproduce`、`observation_diagnose`、
      `test_author`、`red_test`、`baseline`、`repair`、`regression`、`retrospective`、`walkthrough`、
      `post_review_regression`,以及 `revision_test_author`、`revision_test_check`、`revision_repair`、
      `revision_regression`、`revision_retrospective`、`revision_walkthrough`、`revision_post_review_regression`。
      拒绝 `cause_review`、`final_review`、`revision_final_review`、`learning_writeback`、
      `revision_learning_writeback`、`handoff`、`revision_handoff`;最终审查仍只走既有人工续审。
      
      成功放弃只追加 `fix-abandoned-N` 和 `abandon` 日志,`status.abandoned` 列出步骤、原因、时间;
      旧 intent 和部分结果保留。下一次单独执行原步骤,新 intent/result 使用 `-retry-N-` ID,
      红灯原始输出另存 `-retry-N.md`,不覆盖旧输出。`advance`/`run` 遇到 `unknown` 仍停下,
      且放弃本身不证明旧操作没有产生部分本地改动。未经显式授权或不在上表的步骤返回 `fix_abandon_unavailable`。
      
      ### 无specs普通项目
      
      无specs普通项目可省略specsRoot或传null;代码根仍来自reproduction.cwd。原owner将档案存于docs/fixes,
      审查/控制证据存于docs/fixes/.reviews,使用原无specs日志模式并跳过METRICS。不创建规格或假任务,原Review/Learning/finish不变。
      
      ### 无法写自动红测的纯视觉缺陷
      
      先用获准内置浏览器取得真实修前截图/录屏,并固定本地路径及SHA256。reproduction配置为
      `{kind:"visual",cwd,timeoutMs,before:{path,sha256,kind:"screenshot"或"video",description},reason,environment,steps,expected}`;
      reason说明无法写自动红测的原因;environment沿原local/test载体映射:web/browser,app/模拟器或设备,小程序/开发者工具或设备;步骤与预期必须明确。
      redTest使用相同视觉配置并加testFiles:[],不配testAuthor或假命令;baseline仍保留实际存量测试,确无存量才用下节显式声明。
      修复/回归等原权限不变。视觉回归qa_browser带before/evidenceRoot,实际比较并将新的修后载体保存到该证据目录,
      返回`{verdict:"PASS"或"FAIL"或"BLOCKED",after:{path,sha256,kind,description}或null,environment,cleanup,explanation}`。
      cleanup为completed/not_needed/failed,缺载体或清理失败必须BLOCKED且after:null;不要用静态推断、旧图或合成图作为真实PASS。
      JS核对路径/媒体签名/摘要与独立修前修后载体,视觉判断仍由当前工具宿主负责,不声称像素自动断言。
      修前/修后证据以visual检查进入同一原handoff/独立Review/finish,不伪造shell command或exitCode。
      原最终walkthrough仍按其已有qa_browser合同返回;两种请求看具体payload,不混用结果格式。
      
      ### 无存量测试声明格式
      
      先检查项目测试文件和声明的测试命令;确实没有旧测试时,启动配置的 `baseline` 可用:
      
      ```json
      {"cwd":"{CODE_PROJECT}","testFiles":[],"commands":[],"timeoutMs":60000,
       "noExistingTests":"已检查哪些目录和命令;为什么没有存量测试(不超过1000 UTF-8字节)"}
      ```
      
      这只是当前宿主的明确声明,JS 不从空数组证明项目没有测试。它进入原配置指纹、基线记录、
      缺陷交接和最终独立 Review;缺失声明或同时列出旧测试/命令均拒绝,不自动跳过失败旧测试。
      仍配置真实 `redTest`(需要编写时使用原 `testAuthor`),取得原始失败输出后才能 `baseline`;
      该操作仍需 `--allow-baseline`,只记录声明,不执行假命令、不生成测试通过证据。
      修复后的原红灯测试必须变绿,审后回归、走查、Learning 与唯一完成门禁照常执行。
      恢复保持原声明;不能更改配置把已有失败基线变成“无存量测试”。纯视觉/无法自动化不是此分支。
      
      ## 当前会话处理请求
      
      保留可交互进程句柄,收到 `host_ready` 后发送一行 JSON
      `{"requestId":"step-1","operation":"advance"}`。控制消息不带额外 identity。
      持续读取输出,不能等控制请求结束才回应中途的 `host_request`。
      
      | host_request kind | 当前会话职责 |
      | --- | --- |
      | fix_learning | 读取请求中的项目规则,返回真实应用记录及原 contextDigest。 |
      | fix_diagnose | 按 Skill 第2步定位,返回实际根因、影响与方案;证据不足如实返回。 |
      | fix_test_author / fix_repair | 读取匹配工程 Skill,仅执行请求的固定业务 scope;不写规格、审查凭证或保护指令。 |
      | fix_retrospective | 如实复盘,返回候选教训或无新增;AGENTS 写回由 owner 处理。 |
      | qa_logic / qa_browser | 按原走查合同处理;浏览器仅用已授权内置浏览器,不用静态推断冒充实跑。 |
      
      结果严格使用对应模块合同,沿原 `sessionId/callId/requestDigest` 发送 `host_result`;
      不从项目文件自动接受伪造结果。读取角色 Skill 不证明已调用配置声明的模型。
      
      ## 推进与收口
      
      按每次返回 stage 选择 CLI 已有 operation,不发送虚构的 `complete`:
      复现/定位 → 条件根因审查 → 测试编写/红灯/基线 → 修复/回归 → 复盘/Learning →
      handoff → 最终独立 Review/发布 → 原 N5 → 审后回归/走查 → 档案/finish。
      各执行操作仍要求其独立 `--allow-*`。不要在 JS 外手写日志、handoff、Review、任务完成或指标。
      
      设计升级使用现有操作,不新增执行权限:诊断 `design_change` 先走 `cause_review`。
      批准后,有 `redTest` 返回 `design_change_required`;若还需 `testAuthor`,先返回
      `test_author_required` 并执行 `author_tests`,再执行 `red_test`。红测必须按原规则匹配失败退出码和签名;
      意外绿灯、无关失败或证据漂移都不能升级归档。红测成功只到 `escalation_required`,不进入基线、修复或回归。
      非视觉运行没有 `redTest` 配置时,批准后直接到 `escalation_required`,档案明确写出没有失败测试及配置缺失原因。
      视觉运行必须配置匹配的视觉 `redTest`(`testFiles:[]`),先执行 `red_test` 核验修前载体,再进入升级归档;
      档案记录无法自动化的声明和真实视觉证据。缺少视觉 `redTest` 时,打开运行即报 `fix_visual_configuration_required`。
      
      在 `escalation_required` 可用 `publish_dossier` 单独保存“升级立项”档案;`finish` 仍需
      `--allow-finish`,它保存同一档案、写 `run_done`(phase 为 `escalation`、result 为 `escalated`),
      然后返回 `escalationRunEnded:true` 并关闭 owner。档案含缺陷、根因、影响范围、诊断方案、根因审查凭证、
      失败测试与红证据路径,建议 `$cm-prd --change` 接手并把测试转绿作为验收;所有内容按数据处理。
      原测试留在代码目录,不删除或回滚。重开原运行可收完中断的归档/日志,重复 finish 不重复写退出事件;
      冲突日志报 `fix_escalation_exit_conflict`。退出后 stage 为 `escalated`,始终不具备修复完成资格,
      不能继续修复,也不写 task_done/METRICS。QA-fix 父宿主返回 `qa_fix_incomplete` 和该终态,不恢复父 QA 或自动立项。
      驾驭员仍使用 `author_tests`、`red_test`、`publish_dossier`、`finish`;后两项不会反问学习或诊断答案。
      
      观测中可 `publish_dossier` 后授权 `finish` 正常退出,但不是缺陷修复成功;新证据由
      `resume` 消息携带 `evidenceFiles`(1–3 个明确 specs 内文件)绑定最新档案,再授权推进。
      观测恢复定位成功后必须先通过原根因审查,即使只有单层、少于三个模块也不例外。
      旧版本已经绕过该审查并执行测试/修复的记录仍可读取,但会返回
      `observation_cause_review_correction_required`;保留历史并暂停,不在 JS 外补凭证或重置身份。
      若结果包含 `causeReviewCorrection`,可先取 `cause_review_package`,
      在明确授权该后补包后通过原 `cause_review` 补审;批准才回到保留的测试/基线/修复待办阶段。
      审查包与凭证标注后补,历史不改写。已修复、尚在等待回归或复盘的旧记录也可补审;
      包必须携带原修复范围内的修前/修后完整内容与原复现失败证据,不声称已做审后回归。批准后仍继续原待办。
      已完成复盘、正在等待 Learning 写回或交接的旧记录,补审复用原复盘/写回审查包,
      保留真实回归结果及 AGENTS.md 的原审查范围;批准后继续原待办,不重做或省略写回。
      交接已生成但最终审查尚未登记时,也可补审;补审绑定原 handoff SHA,交接文件不得改写,
      批准后仍须发起原最终独立审查。原最终审查已完成且 approved、任务尚无完成记录时,
      等待 N5、审后回归或收口的旧记录也可补审:绑定原最终登记/观察摘要,排除原最终审查线程,
      保留原批准与交接字节,补审批准后继续原门禁。进行中、unknown、未批准或已开始完成写入的
      旧记录不在此恢复范围,不自动重试或重开。
      第一轮最终审查要求增加或完善测试时,先读 [第二轮补测接续](test-extension.md):`prepare_revision` 可附 `tests`,
      再走 `author_tests` → `revision_test_check` → 原修复和审查链;已准备但未修复的旧第二轮也能追加计划。
      
      首轮 changes_requested 或已批准后的明确回归/走查失败走 `prepare_revision`,保留历史,
      第二次修复仍需 fresh 独立 Review;不得重置 ≤2 轮上限。unknown 不自动重派;上表中的本地步骤只在显式放弃后重做。
      
      修复完成仅认原 `finish` 的当前结果与证据;待授权、失败、漂移、缺证据如实报告,
      不手工补成功。finish 接受 `policies.delivery` 的任一取值,只要求它在收尾写记录期间不变;
      它写档案/METRICS/task_done,**不执行 Git**——branch/draft-mr 的提交、推送、开 MR 仍由执行者按
      SKILL 第 7 步单独完成并记 `delivery` 事件。Git/发布/安装都不在这些开关的权限内。
      退出通道用 `host_close` 或 EOF;只有用户明确取消才发 `cancel`。
      
      本接线是源 Skill 指令,不证明安装副本已加载或真实双宿主验收。保持原输出格式,
      同时报告已做、剩余、阻断和下一步;完整 JS workflow 的其余缺口不降为可选项。
      
      ### 复现尝试记录
      
      复现结果可带 `attempts: [{scenario, dimension, outcome}]`,`outcome` 仅为
      `reproduced|not_reproduced|unsupported`;非空时末条必须分别与总体
      `reproduced|not_reproduced|blocked` 一致,不能代替命令退出码与失败签名证据。
      旧结果缺省此字段仍可读取并沿原流程恢复,旧档案保持原字节,不伪造补齐历史。
      新结果由原 producer 记录至少一条;观测档案发布(含恢复后继续观测)对显式空数组
      报 `fix_reproduction_attempts_required`,缺省仅保留旧记录兼容。
      当前 JS owner 仍只执行配置中已授权的固定复现命令,并据真实结果记录一次尝试;
      本次未新增多场景调度、配置入口或执行权限,不把这一条记录当作已完成探索的证据。
      Skill 第 1 步的单维度探索与 3 个场景/15 分钟上限仍适用;需要改变命令/环境而当前
      owner 配置不能表达时,报告接线缺口,保持原运行身份与权限边界,不在 owner 外补跑或改 journal。
      
    • test-extension.md 3.8 KB
      # 审查要求补测试时的第二轮接续
      
      原始红灯输出、测试摘要、存量基线和第一轮审查保持原样。当前测试集可以通过已登记的第二轮
      测试编写扩充;修复回调仍只能改原业务范围,不得修改测试。
      
      ## 适用范围与证据规则
      
      - 仅第一轮最终审查 `changes_requested` 可登记补测计划,必须引用其中真实的 finding ID,并说明遗漏场景及覆盖补充理由。
      - 计划可选原 `redTest.testFiles`、`baseline.testFiles`,或原快照中不存在的新文件;不得把已有业务文件重新声明成测试,不得与 `repair.scope` 重叠。
      - 此路径统一记录为**覆盖补充**,不声称新增测试在原修复前代码上变红。原始红灯仍是缺陷复现证据;计划和实跑结果交第二轮独立审查核对。
      - 编写后、第二轮修复前,执行计划命令并持久记录真实结果。成功或失败都如实保留;命令不可用、超时或结果未知不能继续。
      - 第二轮修后回归和审后回归都执行原命令及补测命令,全部通过才可继续。只需补测试时,修复可记录业务代码无新增变化,不要求制造无意义改动。
      
      命令须实际覆盖所列新增或扩展的测试;声明不能代替执行。补测理由、选定发现、编写摘要、修订前结果、
      修后结果都进入第二轮交接、审查和收尾档案。审查者核对断言是否补足发现,不能把无关命令成功当覆盖证明。
      
      ## 调用顺序
      
      在原运行发送 `prepare_revision`,附以下 `tests`;需要原 `--allow-repair`。已到 `revision_prepared`
      且尚未修复的旧运行也可追加这份计划,原准备记录不改写。计划一旦登记,不能换计划或重置轮次。
      
      ```json
      {
        "requestId": "prepare-tests",
        "operation": "prepare_revision",
        "tests": {
          "testFiles": ["tests/boundary.test.mjs"],
          "command": ["node", "--test", "tests/boundary.test.mjs"],
          "reason": "覆盖补充:第一轮遗漏空输入,新增断言核对该边界;不把此次运行声明为原始红灯。",
          "findingIds": ["F1"]
        }
      }
      ```
      
      使用 `cm-fix-drive.mjs` 时,将同一对象放在驾驭员计划的 `revisionTests` 字段;它只在
      `prepare_revision` 时转交 `tests`,不会修改已绑定的运行配置。
      
      | 返回阶段 | 下一操作 | 所需原启动权限 |
      | --- | --- | --- |
      | `revision_test_author_required` | `author_tests` | `--allow-test-author` |
      | `revision_test_check_required` | `revision_test_check` | `--allow-regression` |
      | `revision_prepared` | `repair` | `--allow-repair` |
      | `revision_regression_required` | `regression`,之后沿原复盘、交接、第二轮审查、审后回归和收尾 | 各操作原权限 |
      
      同仓保护模式继续使用 `protected-text-v1`:测试编写只返回限定路径的编辑提案;宿主按原摘要写入。
      只有已登记补测的第二轮 `fix_repair` 请求含 `allowUnchanged:true` 时,才允许 `repaired` 搭配空 `edits`。
      补测本身仍须产生实际测试变化,不能用空提案冒充补测完成。
      
      ## 根因审查与恢复边界
      
      根因审查仍绑定全部 `affectedPaths` 的原始文件字节,包括参与诊断的测试。若后续 test-author
      合法修改其中的测试,宿主核对“受审原字节 → 编写前快照 → 已登记编写结果 → 当前文件”的关系;
      仅认可该次编写的精确变化。业务源码变化、未登记修改或原审查凭证变化仍阻断,不把测试整体排除出根因包。
      
      测试编写、执行或修复登记后丢失结果,保持 `unknown`,不自动重派、回滚、换 taskId 或重置审查轮次。
      未登记的手改保持漂移阻断;同 taskId 的已审证据仍受 `fix_evidence_name_taken` 保护。此路径不支持
      纯视觉测试、不增加第三轮、不解除已有命令失败或证据损坏,也不允许修改运行配置来绕过检查。
      
  • SKILL.md 19.8 KB
    ---
    name: cm-fix
    description: 用户说“修复这个可复现 bug”或要求根据失败报告修代码时使用。执行红灯测试、根因定位、最小修复、独立审查和回归;尚未确认的问题先用 cm-test,新功能和架构重设计转交 cm-prd。
    ---
    
    # 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` 不是执行、外发或完成许可。
    
    JS 步骤留在 `unknown` 时先检查原调用和磁盘现场。只有本地复现、诊断、测试、修复、回归、
    复盘及走查等列在 [JS 宿主手册](references/js-host.md#本地-unknown-步骤的显式放弃与重做) 的步骤,
    才可在确认后用 `abandon_step` 说明原因并重做;普通 `advance`/`run` 不会自行放弃。
    独立审查、Learning 写回及交接文件仍按各自恢复或人工检查路径处理,不走此出口。
    
    裸项目、无自动测试/纯视觉替代、父 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,再真跑:
    
    ```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. 落盘(审计链闭合)
    
    - 核验地图评估结果和已审文件版本,缺评估、待同步或审后变化不写成功 `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 的占比进运行日志——快速通道被滥用(占比异常高/出现分支改动混入)时收紧门槛,数据说了算。
    
    ## 输出格式(每个缺陷收口时)
    
    ```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 跳过
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related