关于 ce-debug
ce-debug 是用于定位故障根因的调试技能,并可在获准后以测试优先的方式修复。它强调证据、一次验证一个假设,并在多次尝试失败后升级处理。
主要功能
- 01提供文件与行号证据的因果追踪
- 02交互式与非交互式模式
- 03经用户授权后进行测试优先修复
- 04谨慎处理调试输出中的机密
- 05假设或修复多次失败后升级
适用场景
- 01根据日志或问题引用调查故障
- 02选择修复或仅提交诊断结果
- 03向编排技能返回结构化结果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ everyinc/ compound-engineering-plugin --skill ce-debug安装后在 Claude Code 中输入/ce-debug确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/anti-patterns.mddefense-in-depth.mdfix.mdinvestigate.mdinvestigation-techniques.mdpipeline-mode.mdpost-fix-handoff.mdreturn-to-caller.md详细介绍
调试与修复
找出故障的根本原因,然后——在用户选择的情况下——遵循测试优先原则进行修复。
完成标准: 清晰说明从触发因素到症状的因果链,不留空白,并提供文件:行号证据;同时,要么已交付经过验证的修复(PR、提交,或按用户选择停止),要么已提供仅包含诊断结果的摘要。适时升级,不要一味尝试: 如果 2–3 个假设都未获证实,或 3 次修复尝试均失败,就应诊断原因,而不是继续重试——这就是 references/investigate.md 中所述的明智升级。每次只验证一个假设、只做一项更改;同时改动多处以观察效果属于无差别调试。
<bug_description> 是调用此技能时传入的内容——故障描述、mode: 标记或问题引用(#123、org/repo#123、问题 URL)——来源可以是用户,也可以是调用此技能的技能(ce-babysit-pr / lfg 在 mode:pipeline 下会传入失败的作业和日志尾部;lfg 的缺陷流程会传入 mode:return-to-caller 和用户自己的引用)。如果未提供,则为空。
模式
默认模式为交互模式:进行调查,执行第 2 阶段的修复选择关卡,然后完成第 4 阶段的交接。
mode:pipeline(由 ce-babysit-pr 或 lfg 等编排器设置):全程以非交互方式运行,绝不调用阻塞式提问工具。从 <bug_description> 中移除此标记,然后阅读 references/pipeline-mode.md 并遵循其中的说明——它会覆盖所有“询问用户”的步骤,采用保守的默认选项;将第 2 阶段的修复关卡替换为“修复结论一致的 Bug,将结论不一致的 Bug 延后”;并将第 4 阶段的交接替换为结构化返回,其 status 必须严格为以下之一:fixed-and-pushed | fixed-not-pushed | diagnosed-no-fix | flaky-infra | needs-human。调用方会根据这些精确拼写进行分支判断,因此不得重命名、缩写或添加其他状态。
mode:return-to-caller(由 lfg 在其缺陷流程中设置):以非交互方式运行,但修复后的所有工作均由调用方负责。从输入中移除此标记,然后阅读 references/return-to-caller.md 并遵循其中的说明——它保留第 0–3 阶段和“结论一致则修复,否则延后”的修复边界;应用第 3 阶段的分支规则,使修复提交到功能分支;提交由修复涉及的文件,但不推送;跳过修复后的润色和审查步骤;并返回结构化结果,其 status 必须严格为以下之一:fixed | diagnosed-no-fix | needs-human | blocked。同样必须保持状态拼写完全一致。
阻塞式提问
每当此技能要求询问用户时,都要使用当前工具列表中已有的宿主阻塞式提问工具(根据能力匹配,而非宿主特定名称)。当前工具列表中存在该工具,即证明它可用;绝不要通过调用面向用户的提问工具来确认它是否存在。如果列表中列出了匹配的工具但尚未加载,则使用宿主的工具发现机制加载该能力——不要搜索其他宿主的工具名称。只有当列表中没有此类工具,或实际提问调用出错时,才可退回到宿主聊天界面的编号选项。绝不能悄悄跳过提问,也不能在没有收到答复的情况下结束某个阶段。
证据中的机密信息
调试过程会不断显示原始输出——命令结果、捕获的负载、日志摘录——而执行框架可能会在命令运行时立即呈现其输出,因此构造命令时就要检查机密信息,而不是事后再处理。凭据应放在环境变量中,而不是命令行参数中;如果命令输出可能包含机密信息(详细 HTTP 跟踪、转储的标头、配置或环境变量输出),就将输出捕获到文件,并且只展示经过脱敏的摘录,在每个机密值的位置写入 <REDACTED>。任何展示、写入或提交的内容中都不得出现机密信息(凭据、令牌、身份验证标头、连接字符串)。如果脱敏后缺少诊断所需的信息,应告知用户并征求意见,而不是取消脱敏。
产物根目录
仅在首次拼接 <root>/ 路径时解析 <root>——如果某次运行没有拼接任何路径,则完全跳过此步骤。
拼接任何产物路径之前,先解析 CE 产物根目录 <root>。
- 读取
<repo-root>/.compound-engineering/config.yaml中的docs_root(<repo-root>=git rev-parse --show-toplevel)。不要从config.local.yaml读取。若未设置,则<root>仍为docs,与之前完全一致。 - 验证已设置的值:它必须是仓库内的相对目录,解析符号链接后的实际路径必须仍在仓库内,且不能是仓库根目录或位于
.git/下。否则停止并报错,指出docs_root及其值——绝不回退到docs。 - 使用
<root>作为唯一产物位置:若其不存在则创建;将每个路径拼接为<root>/<subdir>,其中使用本技能自己的子目录;绝不同时读取docs。
执行流程
按顺序执行五个阶段:0 分诊 -> 1 调查 -> 2 根因 -> 3 修复 -> 4 交接。 除阶段 0 的简单错误快速路径外,不得跳过任何阶段,也不划分复杂度等级。复杂错误只会让每个阶段耗时更长,不会减少阶段数量。
现在阅读 references/investigate.md,并按其中要求执行阶段 0-2——包括获取问题、复现、环境检查和脏工作树暂存实验、向后追踪、搜索跟踪器和 PR 历史、以证据支撑假设,以及升级表。此处只列出以下关卡。
已记录的问题。 如果用户提供了工单或问题报告,无论它属于哪个系统,那个就是此错误已有的记录;Sentry 问题与 Linear 工单同样有效。将其标识符和 URL 带到阶段 4。如果输入只有堆栈跟踪、测试路径或描述,则本次运行没有已记录的问题。这是正常情况,不是需要填补的空缺:直接交付修复,不必先创建记录;绝不为了制造记录而新建工单,也绝不询问用户是否要创建。阶段 1 的跟踪器搜索用于查找以往工作,绝不为该错误建立新的归属记录。若已有与此错误相关的工单,应在阶段 4 中关联,而不是创建。
简单错误快速路径(从输入即可看出原因、一行修复、不需要深入追踪)在编辑前仍须通过阶段 2 的修复选择关卡:它可以省去调查流程,但不能替用户决定是否应用修复。
选择回归测试。 对于已确认的缺陷,回归测试应放在现有测试已覆盖该行为的位置:从已有测试入手,而不是新建文件。编写阶段 2 的建议之前就阅读 references/fix.md,了解测试位置和命名规则,不要等到阶段 3 编辑前才读。如果某项更改有意反转测试所断言的行为,导致测试失败,那么预期结果并没有错——这种情况属于下文的分歧情形,应暂缓处理,而不是更新测试。
阶段 2 门槛:先说明,再提问
因果链门槛: 在能够解释完整链条——从触发因素到每个步骤,再到观察到的症状——且没有任何断点之前,不要进入阶段 3。“不知怎么,X 导致了 Y”就是一个断点。只有调查陷入僵局时,用户才能授权基于当前最佳假设继续。
确认根本原因后,将调查结果写成用户可见的内容:附带 file:line 引用的因果链;拟议的修复方案及其会更改的文件;应使用、添加、修改或加强哪些测试,以及现有测试本应能否发现此问题;任何相关工单或 PR,以及它们如何影响建议——如果已有未关闭的 PR 修复了此问题,应先提供该链接,而不是提出新的修复方案。
同一轮中先说明,再过门槛: 在完整写出调查结果之前,不要提出修复方案选择问题——可以在当前轮,也可以在紧接着的上一条助手消息中写出。在模态测试框架中,阻塞式提问工具只会呈现问题本身,因此如果仅在“根本原因已确认”后就发问,用户做选择时就看不到因果链。列出选项不等于说明调查结果,承诺选择后再解释也为时已晚。
如果请求尚未授权下一步操作,请根据 阻塞式提问 询问用户要采用哪种路径,并提供以下三个选项。明确要求修复即进入阶段 3。明确要求仅诊断则跳至阶段 4。mode:pipeline 和 mode:return-to-caller 均不提问。无论选择哪条路径,测试建议都属于诊断内容。
- 立即修复 — 进入阶段 3
- 仅诊断——我来继续处理 — 跳过修复,撰写阶段 4 的总结,然后结束此技能
- 重新审视设计(
ce-brainstorm)— 仅当无法在当前设计内修复此 Bug 时使用:根本原因是职责或接口不当,而非逻辑错误;需求本身有误;或所有候选修复方案都是基于已不再成立的假设进行变通。问题规模本身不构成设计问题。
mode:pipeline 和 mode:return-to-caller: 不要提问。进入阶段 3 并实施收敛式修复;如果修复会推翻有意确立的契约、行为或产品决策(包括用于断言预期行为的“失败”测试),则属于发散式修复,应按 references/pipeline-mode.md 或 references/return-to-caller.md 的规定暂缓,而不应实施。此处绝不转交给 ce-brainstorm;设计问题应作为 needs-human 残留项处理。
阶段 3:修复
如果用户选择了“仅诊断”,则跳至阶段 4 的总结。如果用户选择了“重新审视设计”,则控制权已移交给 ce-brainstorm,此技能随即结束。
编辑任何文件前,先阅读 references/fix.md——了解测试优先顺序、修复失败规则,以及纵深防御和事后复盘的触发条件。是否可以开始修复由两条规则决定,因此在此列出:
- 分支。 检查
git status;如果用户在需要修改的文件中有尚未暂存的工作,编辑前请先确认。如果当前分支是默认分支,则无需询问,创建一个功能分支——根据 Bug 派生分支名,执行git checkout -b <name>,并说明你切换到了哪个分支。通过与main、master或去掉origin/前缀后的git rev-parse --abbrev-ref origin/HEAD进行比较,判断是否为默认分支——原始输出为origin/<name>,不去掉前缀就无法匹配。 - 记录修复前的范围: 当前
HEAD、git status --short是否干净,以及任何已存在的更改文件。之后在工作过程中维护一份修复涉及文件清单(为此 Bug 修改的测试和实现文件)。阶段 4 的两个问题都依据此记录作答,事后无法还原。
阶段 4:交接
mode:pipeline — 跳过整个交互式交接流程。 不进行润色或审查,不提出遗留问题,不预览,也不提供记录经验的选项。按照 references/pipeline-mode.md 提交并推送收敛后的修复,然后输出该参考文档定义的结构化返回。有分歧或需要人工处理的事项应在此处延后(在开放的讨论串或调用方的运行报告评论中提出——绝不可放在 PR 正文中)。mode:return-to-caller — 同样跳过: 在功能分支上提交由修复负责的文件,不推送任何内容,并输出 references/return-to-caller.md 定义的结构化返回。在这两种模式下,返回内容都是此技能最后写入的内容。它会结束此技能,但不会结束本轮对话。调用方在同一会话中运行,其下一步操作遵循该返回;不要向调用方宣布交接。此部分其余内容仅适用于交互式流程。
结构化摘要 — 始终先写入:
## Debug Summary
**Problem**: [What was broken]
**Root Cause**: [Full causal chain, with file:line references]
**Recommended Tests**: [Tests to add/modify to prevent recurrence, with specific file and assertion guidance]
**Fix**: [What was changed — or "diagnosis only" if Phase 3 was skipped]
**Prevention**: [Test coverage added; structural fix or defense-in-depth if applicable, or the structural fix left as follow-up]
**Confidence**: [High/Medium/Low]
如果跳过了阶段 3,写完摘要后即停止——用户已表示接下来由自己处理。不要提示。
如果执行了阶段 3,请立即阅读 references/post-fix-handoff.md,并在下面进行分流之前遵循其中的说明。 该文档定义了修复后的质量步骤:上下文覆盖检查、机械式修复的跳过规则、避免 ce-simplify-code 和 ce-code-review 涉及分支上无关工作的范围限定、遗留发现的处理方式、## Post-Fix Quality 块,以及提供记录经验选项的标准。正文中不包含这些内容。下面的分流只指出要执行哪项操作,不会说明确保其安全的范围规则,因此不能凭空决定。跳过阅读会导致未经审查的修复被交付,让审查涉及分支上无关的工作,并使已接受的发现遗留在会话中。
路由
提交修复时,不要夹带用户未提供的任何内容——无论是提交、推送还是 PR。不要询问是否要创建 PR;是否获得许可不是决定因素。交接由两个问题决定。根据第 3 阶段记录的修复前范围作答,而不是根据分支是如何创建的。通过平台的技能调用原语直接执行操作——绝不能只是告诉用户输入命令。
1. 哪些内容可以进入提交——仅限修复涉及的文件。 这是对问题 2 中负责提交的技能的约束,本身不是一项操作。无论走哪条路径,无论是否涉及远程仓库,都必须遵守。不要在此处提交。
- 如果修复涉及的文件没有任何预先存在的编辑,这些文件就是提交范围。将它们传给负责提交的技能。
- 如果修复涉及的文件已经包含用户的编辑,就无法单独提交修复:
ce-commit按文件分组,绝不会拆分文件。请在任何提交发生之前(遵循阻塞性问题中的要求)询问:是否要连同用户的编辑一起提交该文件、让修复保持未提交,还是停止。只有选择第一项才继续。选择其他两项都会终止交接,因此不会执行问题 2,也不会有任何提交;说明留下了什么以及原因。每个选项都会舍弃一些内容,Agent 无权替用户决定,因此必须提出这个问题。第 3 阶段的确认涵盖的是编辑该文件,从未涵盖将用户的编辑与修复一起提交。
2. 由谁提交,以及是否发布。 以下情况中恰好执行一种。
-
发布:以下三个条件必须全部满足:修复前的工作树干净;分支上没有用户尚未提供的工作;
origin具备创建 PR 的能力:gh在某处确实能够创建 PR。根据当前仓库的情况判断这些条件。两个事实让这件事没有表面上看起来那么简单。ce-commit-push-pr会推送整个分支,其 PR 会包含分支上的每个提交,而不仅是你的修复。因此要考察的是分支,而不是你的差异。它还会先推送再创建 PR,所以如果远程端的gh无法创建 PR,就会导致分支已发布却没有 PR。- 已经推送不等于已经提供。开放 PR 中的提交正在接受审查,因此视为已提供;此流程会更新该 PR,而不是另开一个。为备份或触发 CI 而推送的提交不算已提供,创建首个 PR 会将它们发布出去。请与远程端比较,而不是与本地引用比较:本地分支(包括第 3 阶段可能从中分出的默认分支)本身可能领先于已推送的内容。
如果无法确认这三个条件全部满足,就走本地路径;这是安全的选择,预览不能替代它。否则,预览将要提交的内容、目标分支,以及 PR 是新建还是更新,然后调用
ce-commit-push-pr技能,并设置branding:on。 它会按问题 1 规定的范围提交,因此不要提前提交。预览是说明,不是提问。展示最终生成的 PR URL。 -
保留在本地:以上任一条件不满足时。按问题 1 规定的范围调用
ce-commit技能,不要推送。用一行说明哪些内容保留在本地以及原因,并说明用户提出要求后你会推送并创建 PR。不要事先询问;本地提交可以撤销。 -
不是 Git 仓库:不提交任何内容。完成总结和质量区块后停止。
上下文覆盖(“不要用技能创建 PR”“只提交”“修复后停止”)——遵循用户的要求;如果用户要求如此,到此为止,不要提交。含糊的语气暗示不构成覆盖。
PR 创建后——应用参考资料中的学习记录标准。仅当修复符合该标准时才提出记录;如果用户接受,则调用 ce-compound 技能,然后只提交并推送它实际写入或更新的产物,使开放的 PR 纳入这些更改。如果没有写入任何内容,则结束,不要为了文档而提交。