cm-fix
用户说“修复这个可复现 bug”或要求根据失败报告修代码时使用。执行红灯测试、根因定位、最小修复、独立审查和回归;尚未确认的问题先用 cm-test,新功能和架构重设计转交 cm-prd。
Install
npx skills add https://github.com/kingxiaozhe/cm-workflow/tree/main/skills/cm-fix
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install kingxiaozhe-cm-workflow@llmmart
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.
Reviews (0)
No reviews yet.
No comments yet.