ce-debug 流水线
独立的诊断-修复循环。五个阶段,不能跳过,测试先行的修复纪律,为调用方准备结构化返回。
ce-debug 是唯一拥有"诊断 → 修复"契约的技能。它可以独立运行(交互式),也可以作为叶子被 ce-babysit-pr(CI 失败)或 lfg(缺陷路由)调用。它在没有显式授权时绝不打开 PR 或推送,也绝不为了 CI 变绿而削弱一条断言。
五个阶段
| 阶段 | 发生什么 | 参考 |
|---|---|---|
| 0 | 分流:对输入分类——问题引用 / 堆栈跟踪 / 测试路径 / 描述 | references/investigate.md |
| 1 | 调查:拉取问题、复现、环境健全性检查、脏树暂存实验、回溯、跟踪器 / PR 历史搜索、假设锚定 | references/investigate.md + references/investigation-techniques.md(384 行) |
| 2 | 根因:完整的因果链 trigger→step→symptom;因果链门;发出 findings 段 + 修复方案选择问题 | references/investigate.md + references/anti-patterns.md |
| 3 | 修复:先开分支;记录修复前范围;编写回归测试;实施修复;pipeline 模式下仅限收敛修复 | references/fix.md |
| 4 | 交接:结构化返回 + 可选的 simplify / review / commit / PR 路由 | references/post-fix-handoff.md |
不存在跳级——一个硬 bug 在每个阶段都会花更长时间;它不会进入更少的阶段。
阶段 2 的因果链门
在能完整陈述整条链(从触发到每一步再到观察到的症状)且无缺口之前,不能进入阶段 3。"不知怎么 X 导致 Y" 就是缺口。findings 段必须先写到聊天里,再打开"修复方案选择"阻塞问题;仅在"根因已确认"上发出问题,会让用户在看不到因果链的情况下做选择。
修复方案选择门
用户在循环中时(交互模式)有三个选项:
- 现在修 → 阶段 3。
- 只要诊断——剩下的我来 → 跳到阶段 4 的总结,结束本技能。
- 重新思考设计(
ce-brainstorm)——仅当 bug 无法在当前设计内修复时。根因是责任/接口/需求的错误,而不只是大小问题。
收敛 vs 发散 修复
这是无人值守运行的承载边界:
| 类型 | 定义 | pipeline 模式下的动作 |
|---|---|---|
| 收敛 | 修复真实缺陷,使代码符合其既定/被测试过的意图(空解引用、差一、坏调用、对"编码了预期行为"的测试的回归) | 应用 + 提交 + 推送 |
| 发散 | 会改变既定契约、API 形态、默认值或产品/UX 决策,而非修复一个 bug。或者:一个"失败"是断言一个故意行为的测试,而修复将把它反转。或者:让 CI 变绿需要一次产品/设计决策 | 延后——以带类型化决策上下文的 needs-human 返回;绝不应用 |
当编排器传入 trajectory(复现的 check、heads_since_progress 等)时,先就它做推理再修:
- 渐进式失败迁移(A 已修、B 出现一次、B 已修、结束)→ 继续修。
- 震荡(同一项 check 在针对它的修复之后又出现;修复用一个失败换另一个)→ 延后。A 与 B 无法在不做出更大变更的前提下同时成立。更大的变更是一次产品/设计决策。以
needs-human返回,并指明两项失败的张力。 - 移动目标守护:若复现源自 base-branch 合并 / 依赖 bump / flaky infra,继续修;那不是震荡。
Pipeline 模式
当以 mode:pipeline 调用(由 ce-babysit-pr 或 lfg)时:
- 授权:
actions= fix / commit / push 在当前分支上;exclusions= merge、rebase、force-push、批准一个被门控的 CI 任务。你可以收窄,绝不扩宽。 - 若让 CI 变绿的唯一方法是某项被排除的动作,则以
needs-human延后。不要执行它。 - 仅限收敛修复。应用发散修复 = 延后。
- 在当前分支上操作;分支上下文由编排器决定。
- 提交
fix(ci): <summary>(或fix: <summary>)并推送。绝不削弱、跳过或 mock 断言。 - 跳过修复后润色与评审步骤(评审由编排器在其层级自行安排)。
- 把下面的结构化返回作为本技能最后写出的内容发出。
结构化返回(mode:pipeline)
{
"status": "fixed-and-pushed" | "fixed-not-pushed" | "diagnosed-no-fix" | "flaky-infra" | "needs-human",
"summary": "<one line: what happened>",
"root_cause": "<causal chain, brief>",
"changed_files": ["..."],
"head_sha": "<sha of the fix commit, when fixed-and-pushed or fixed-not-pushed>",
"residuals": [{
{
"type": "needs-human",
"sources": [
{ "id": "<failing-check-key>", "kind": "check" },
{ "id": "<owned-open-thread-id>", "kind": "thread" }
],
"decision_context": {
"quoted_feedback": "<the failure or constraint in in tension>",
"investigation": "<what was inspected and found>",
"decision_reason": "<why no bounded convergent fix is safe>",
"options": [ { "option": "<choice>", "tradeoff": "<gain and loss>" } ],
"recommendation": "<lean and why, or null>"
},
"thread_urls": ["<URL for every owned open thread, or empty when none>"]
}]
}
状态定义
| 状态 | 含义 |
|---|---|
| fixed-and-pushed | 已应用收敛修复,测试通过,已提交,推送成功。 |
| fixed-not-pushed | 同一修复已应用并在本地提交,但未发生推送。head_sha 是本地 commit。第一条残余说明原因。 |
| flaky-infra | 基础设施失败,非代码缺陷(调用方可重试)。 |
| diagnosed-no-fix | 已找到根因,但本次运行内没有可用的安全收敛修复。residuals[] 开放。 |
| needs-human | 需要发散 / 产品决策;未应用任何东西。residuals[]。 |
Return-to-caller 模式
当以 mode:return-to-caller 调用(由 lfg 在缺陷路由上)时:
- 同样的仅收敛修复纪律。
- 阶段 3:开分支 + 提交 fix-owned 文件,不推送。
- 跳过修复后润色与评审步骤。
- 发出带
status的结构化返回:"fixed" | "diagnosed-no-fix" | "needs-human" | "blocked"。
交互式交接(两个问题)
阶段 3 之后(或诊断模式下跳过),编排器在任何提交发生前问两个问题:
- 什么可以进这次提交?仅 fix-owned 文件。若 fix-owned 文件已带有用户的编辑,问三个选项:连同用户编辑一起提交 / 留 fix 不提交 / 停止。阶段 3 此前的确认只覆盖编辑,不覆盖把用户编辑与 fix 一起提交。
- 谁提交 + 是否发布?
- 发布 通过
ce-commit-push-pr——仅当三条全部成立:修复前的树干净;分支上没有任何用户尚未主动提供的工作;origin是能开 PR 的(gh真能开 PR 的地方)。先预览,再调用。 - 保持本地——其他情况下,调用
ce-commit,不推送任何东西。 - 非 git 仓库——不提交任何东西;总结后停止。
- 发布 通过
尊重上下文覆盖:如果用户说过"不要让技能开 PR"、"只提交"或"修完就停",照做。模糊的语气信号不算覆盖。
选择回归测试
对已确认缺陷的回归测试,落在已经存在覆盖该行为的归属处:从既有测试出发,不是新建文件。归属与命名规则在 references/fix.md——读它要在写阶段 2 的推荐之前,不是写到阶段 3 的编辑前才读。
一个测试因为变更故意反转了它所断言的行为而失败,它的预期没有错——那是发散情形,延后而非更新。
问题记录
若用户给了一个工单或问题,那里就是这个 bug 所在之处。把它的标识与 URL 一路带到阶段 4。若输入仅有堆栈跟踪、测试路径或描述,则本次运行没有问题记录。这是常态——无需 issue 记录就发版修复,永远不要为了凑记录而开一个工单。
升级而非蛮干
2–3 个假设已用尽而未确认,或3 次修复尝试失败:诊断为什么,而不是再试一次。这是 references/investigate.md 描述的明智升级。一个假设,一次变更;同时改几处看哪个管用,那是霰弹式调试。
参考
references/investigate.md— 阶段 0–2 细节references/investigation-techniques.md— 384 行深度调查(时序、并发、框架)references/anti-patterns.md— 调试反模式、预测质量references/fix.md— 阶段 3:测试先行、失败修复处理references/defense-in-depth.md— 防止复发的四层校验references/pipeline-mode.md— pipeline 模式按阶段覆盖references/return-to-caller.md.md— return-to-caller 模式references/post-fix-handoff.md— 质量步骤、跳过规则、路由