ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Superpowers 的 systematic-debugging 技能:四阶段根因定位方法论与配套调试技术实战

Superpowers 的 systematic-debugging 技能:四阶段根因定位方法论与配套调试技术实战 Superpowers 的 systematic-debugging 技能四阶段根因定位方法论与配套调试技术实战【免费下载链接】superpowersAn agentic skills framework software development methodology that works.项目地址: https://gitcode.com/GitHub_Trending/su/superpowersSuperpowers 是一个面向编码 Agent 的技能框架与软件开发方法论其中systematic-debugging系统化调试技能定义了先找根因、后谈修复的强制流程四阶段根因调查 → 模式分析 → 假设与测试 → 实施逐级推进辅以根因回溯、纵深防御、条件等待三套配套技术。读完本文你既能把这套流程直接用于人工排障也能理解它如何被结构化地注入 AI 编码 Agent 的调试行为中。核心原则与铁律技能的开篇就给出了核心原则SKILL.mdCore principle:ALWAYS find root cause before attempting fixes. Symptom fixes are failure.永远先找到根因再尝试修复只修症状就是失败。由此衍生出调试铁律Iron LawNO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST 未完成根因调查之前禁止提出任何修复原文进一步明确如果你没有完成阶段 1你就没有资格提出修复方案而违反这个流程的字面要求就是违反调试的精神。这是整篇技能的灵魂——所有后续规则都在为这条铁律服务。何时使用该技能适用于任何技术问题SKILL.md测试失败test failures生产环境 bug行为不符合预期性能问题构建失败集成问题尤其必须使用的场景时间压力大紧急情况最诱使猜一把只要一个快速修复看起来很明显时你已经尝试过多个修复之后上一个修复没起作用你并没有完全理解问题以下情况也不允许跳过问题看起来很简单简单的 bug 也有根因你很赶时间仓促只会带来返工经理要求现在就修好系统化比反复试错更快四阶段流程四个阶段必须逐级完成每完成一个阶段才能进入下一个。阶段 1根因调查Root Cause Investigation在尝试任何修复之前必须完成以下五步。1. 仔细阅读错误信息。不要跳过错误或警告——它们经常直接包含答案。完整读完堆栈跟踪记下行号、文件路径和错误码。2. 稳定复现。能否可靠触发确切步骤是什么每次都发生吗如果不能稳定复现就去采集更多数据而不是靠猜。3. 检查最近的变更。什么改动可能导致了这个问题查看 Git diff、最近的提交、新增依赖、配置变更、环境差异。4. 在多组件系统中采集证据。当系统由多个组件串联如 CI → build → signing或 API → service → database时在提出任何修复之前先加入诊断埋点对每个组件边界 - 记录进入该组件的数据 - 记录离开该组件的数据 - 验证环境/配置是否正确传递 - 检查每一层的状态 只运行一次采集在哪里断掉的证据 然后分析证据定位出故障组件 然后才去深入调查那个特定组件技能文档给出了一个多层签名系统的完整示例SKILL.md# Layer 1: Workflow echo Secrets available in workflow: echo IDENTITY: ${IDENTITY:SET}${IDENTITY:-UNSET} # Layer 2: Build script echo Env vars in build script: env | grep IDENTITY || echo IDENTITY not in environment # Layer 3: Signing script echo Keychain state: security list-keychains security find-identity -v # Layer 4: Actual signing codesign --sign $IDENTITY --verbose4 $APP这套埋点运行一次后就能直接暴露出哪一层断掉——例如secrets → workflow ✓, workflow → build ✗把问题从全链路缩小到单个边界。5. 追踪数据流。当错误出现在调用栈深处时技能的完整方法是同目录下的 root-cause-tracing.md其快速版为坏值从哪里产生谁带着坏值调用了这里一直向上追到源头在源头修复而不是在症状处修复。阶段 2模式分析Pattern Analysis修复之前先找到模式SKILL.md找到能工作的例子——在同一代码库里定位相似的、正常运行的代码对照参考实现——如果你在实现某个模式就把参考实现完整读完每一行而不是略读识别差异——列出正常与故障之间的所有差异无论多小不要假设这个应该不影响理解依赖——这个功能还依赖哪些组件、配置、环境假设阶段 3假设与测试Hypothesis and Testing按科学方法推进SKILL.md形成单一假设——用我认为 X 是根因因为 Y的句式写下来必须具体做最小测试——做能验证该假设的最小改动一次只动一个变量不要同时修多处验证后再继续——生效则进入阶段 4没生效就形成新假设绝不在上面再叠一层修复不知道就说不知道——明说我不理解 X不要假装懂去求助、去研究。阶段 4实施Implementation修复根因而非症状SKILL.md先创建失败测试用例——最简单的复现能自动化就自动化没有框架就写一次性测试脚本修复之前必须先有这个测试。技能要求配合superpowers:test-driven-development技能skills/test-driven-development/SKILL.md来写合格的失败测试。实施单一修复——只针对已确认的根因一次一个改动不做顺手改进不捆绑重构。验证修复——测试通过了吗有没有弄坏其他测试问题真的解决了吗在宣称成功之前使用superpowers:verification-before-completion技能skills/verification-before-completion/SKILL.md。如果修复不生效——STOP。数一数已经试了几个修复少于 3 次回到阶段 1 用新信息重新分析达到 3 次则停止进入第 5 步质疑架构。3 次以上修复失败质疑架构本身。以下模式说明这是架构问题每次修复都在别处暴露新的共享状态/耦合修复需要大规模重构才能实现每次修复都在其他位置制造新症状。此时停下来问这个模式从根本上成立吗我们是不是靠惯性死守应该重构架构还是继续打症状补丁——在人类伙伴之前不得尝试第 4 次修复。文档特别强调这不是又一个失败的假设而是错误的架构。红旗信号出现即 STOP技能列出了必须立即停下、回到阶段 1 的思维模式SKILL.md先快速修一下回头再查试试改 X 看看行不行一次加多个改动跑一遍测试测试先跳过我手动验证应该是 X 的问题修一下我没完全搞懂但这招可能管用模式说的是 X但我改一改再用不追踪数据流就直接列出主要问题和修复方案已经试过 2 次以上还要再试一次每次修复都在不同的地方暴露新问题另外技能还教 Agent 识别人类协作者的纠正信号SKILL.md看到这些说法意味着做法错了应停下回到阶段 1协作者的话说明的问题Is that not happening?不是没发生吧你未经验证就做了假设Will it show us...?它会显示……吗你本该先加证据采集Stop guessing别再猜了你在不理解的情况下提修复Ultra-think this深度想一下该质疑基本假设而不是症状Were stuck?卡住了带烦躁语气你的方法已经失效常见借口与事实对照原文以一张完整的借口 → 现实对照表对抗合理化倾向SKILL.md完整继承如下借口现实问题很简单不需要流程简单问题也有根因。流程对简单 bug 一样快。紧急情况没时间走流程系统化调试比盲目试错更快。先试一下这个不行再查第一个修复会定下基调从一开始就把它做对。等确认修复有效后再补测试没测过的修复不会持久。先写测试才能证明它。一次修多个省时间无法隔离出哪个起作用还会引入新 bug。参考实现太长了我改改模式再用部分理解必然带来 bug完整读完它。我看到问题了修一下看到症状 ≠ 理解根因。再试一次修复2 次以上失败后3 次以上失败 架构问题。质疑模式别再修了。快速参考原文的四阶段速查表SKILL.md阶段关键活动成功标准1. 根因读错误、复现、查变更、采证据理解 WHAT 和 WHY2. 模式找可工作例子、对照比较识别出差异3. 假设形成理论、最小化测试确认根因或产生新假设4. 实施建测试、修复、验证Bug 解决、测试通过当流程揭示没有根因如果系统化调查表明问题确实是环境性、时序性或外部因素造成的技能给出的处理是SKILL.md确认你已经完整走完流程记录你调查过什么实施恰当的兜底处理重试、超时、明确的错误信息增加监控/日志便于将来排查。但原文同时提醒95% 的找不到根因其实是调查不完整。配套技术一根因回溯Root Cause Tracingroot-cause-tracing.md是阶段 1 第 5 步数据流追踪的完整展开root-cause-tracing.md。核心原则沿调用链向上回溯直到找到最初的触发者然后在源头修复。适用场景错误发生在执行深处而非入口点、堆栈跟踪显示很长的调用链、不清楚坏数据从何而来。五步回溯法以一个真实案例说明观察症状Error: git init failed in ~/project/packages/core——.git目录竟然被创建在了源码目录里找到直接原因是await execFileAsync(git, [init], { cwd: projectDir })这行直接导致的问谁调用了它WorktreeManager.createSessionWorktree()←Session.initializeWorkspace()←Session.create()← 测试里Project.create()调用继续向上追传参projectDir 空字符串空字符串作为cwd会解析为process.cwd()——也就是源码目录找到最初触发者测试在beforeEach之前就访问了context.tempDir而setupCoreTest()初始返回{ tempDir: }。根因顶层变量初始化时访问了尚为空的值。修复把tempDir改成在beforeEach之前访问就抛错的 getter。当无法手工追踪时加栈跟踪埋点。文档给出的做法是在危险操作之前打点// Before the problematic operation async function gitInit(directory: string) { const stack new Error().stack; console.error(DEBUG git init:, { directory, cwd: process.cwd(), nodeEnv: process.env.NODE_ENV, stack, }); await execFileAsync(git, [init], { cwd: directory }); }文档给出三条关键提示测试中要用console.error()而不是 loggerlogger 可能被抑制在操作失败之前记录而不是之后用npm test 21 | grep DEBUG git init捕获输出后从栈里找测试文件名、触发行号和模式同一测试同一参数。不知道是哪个测试造成的污染时二分脚本。仓库提供了可执行脚本 find-polluter.sh逐条运行测试文件并在第一次发现污染时停下./find-polluter.sh .git src/**/*.test.ts从脚本源码看find-polluter.sh它处理了三个实际工程细节接受带或不带./前缀的模式第 23 行因为find -path的**/无法匹配零层目录会同时尝试把**/折叠后的模式保证src/**/*.test.ts也能匹配到src/top.test.ts第 27 行每轮测试前若污染已存在则跳过该文件第 42-46 行。仓库还有一组对应的测试 test-find-polluter.sh它在一个玩具项目里用 stub 掉npm命令的方式任何测试一跑就创建pollution.marker验证了文档示例模式能同时命中顶层与嵌套测试文件、./前缀被接受、不匹配的模式如实报告Found 0 test files并走干净退出路径——这正是该脚本按可复现、可测试标准维护的证据。回溯文档还给出该案例的最终数据通过 5 层追踪找到根因在源头修复外加 4 层防御1847 个测试全部通过零污染。配套技术二纵深防御Defense-in-Depth找到根因并修复后defense-in-depth.md 要求在数据流经的每一层都加校验让 bug 在结构上不可能发生单一校验只能说明我们修了 bug多层校验才能说我们让 bug 不可能了。文档定义的四层结构defense-in-depth.md第 1 层入口校验——在 API 边界拒绝明显非法的输入function createProject(name: string, workingDirectory: string) { if (!workingDirectory || workingDirectory.trim() ) { throw new Error(workingDirectory cannot be empty); } if (!existsSync(workingDirectory)) { throw new Error(workingDirectory does not exist: ${workingDirectory}); } if (!statSync(workingDirectory).isDirectory()) { throw new Error(workingDirectory is not a directory: ${workingDirectory}); } // ... proceed }第 2 层业务逻辑校验——确保数据对当前操作有意义如initializeWorkspace中拒绝空projectDir。第 3 层环境护栏——在特定上下文中阻止危险操作例如测试环境下拒绝在临时目录之外执行git initasync function gitInit(directory: string) { // In tests, refuse git init outside temp directories if (process.env.NODE_ENV test) { const normalized normalize(resolve(directory)); const tmpDir normalize(resolve(tmpdir())); if (!normalized.startsWith(tmpDir)) { throw new Error( Refusing git init outside temp dir during tests: ${directory} ); } } // ... proceed }第 4 层调试埋点——记录上下文供事后取证目录、cwd、new Error().stack。应用该模式的四步追踪数据流坏值从哪来、在哪用→ 列出数据经过的所有检查点 → 在入口/业务/环境/调试各层加校验 → 逐层测试尝试绕过第 1 层验证第 2 层能接住。文档强调在那个 1847 个测试通过的真实案例中四层每一层都接住了别的层漏掉的 bug——不同代码路径绕过了入口校验、mock 绕过了业务校验、跨平台边界情况需要环境护栏、调试日志暴露了结构性误用。配套技术三基于条件的等待Condition-Based Waitingcondition-based-waiting.md 解决 flaky 测试中用任意延时猜时序的问题。核心原则等待你真正关心的那个条件成立而不是猜它需要多久。核心模式的对照condition-based-waiting.md// ❌ BEFORE: Guessing at timing await new Promise(r setTimeout(r, 50)); const result getResult(); expect(result).toBeDefined(); // ✅ AFTER: Waiting for condition await waitFor(() getResult() ! undefined); const result getResult(); expect(result).toBeDefined();常用场景速查表场景模式等待事件waitFor(() events.find(e e.type DONE))等待状态waitFor(() machine.state ready)等待数量waitFor(() items.length 5)等待文件waitFor(() fs.existsSync(path))复合条件waitFor(() obj.ready obj.value 10)通用轮询实现默认 10ms 一次轮询、5000ms 超时async function waitForT( condition: () T | undefined | null | false, description: string, timeoutMs 5000 ): PromiseT { const startTime Date.now(); while (true) { const result condition(); if (result) return result; if (Date.now() - startTime timeoutMs) { throw new Error(Timeout waiting for ${description} after ${timeoutMs}ms); } await new Promise(r setTimeout(r, 10)); // Poll every 10ms } }完整实现见同目录的 condition-based-waiting-example.ts其中包含来自真实调试会话的领域辅助函数waitForEvent、waitForEventCount、waitForEventMatch——例如 condition-based-waiting-example.ts 中waitForEvent每 10ms 轮询一次事件列表找到第一个匹配事件立即 resolve超时则 reject 并给出明确错误信息。文档同时列出三个常见错误轮询过快1ms 浪费 CPU应 10ms没有超时条件永不满足时死循环使用陈旧数据应在循环内部调用 getter 取新值。并且明确边界在测试真正的时序行为时防抖、节流间隔任意延时反而是正确的但前提是先等触发条件、基于已知时序而非猜测、并用注释解释为什么。文档记录的实际效果一次会话修复了 3 个文件里 15 个 flaky 测试通过率 60% → 100%执行时间快 40%。设计视角一个抗合理化的技能是如何被构建与验证的systematic-debugging不只是流程文档其 CREATION-LOG.md 公开了它的工程化构建过程对想让 Agent 稳定执行流程的读者很有参考价值语言选择用 ALWAYS / NEVER 而不是 should / try to用 STOP and re-analyze 制造显式停顿结构性防御阶段 1 强制无法跳到实施、单一假设规则防止霰弹枪式多点修复、显式失败模式如果第一个修复不生效配强制动作、反模式章节把借口原样列出来冗余设计根因要求出现在概述、使用时机、阶段 1、实施规则四处NEVER fix symptom 在四个不同语境下重复出现。构建日志记录的关键洞察是反模式章节是最重要的防弹手段——当执行者脑中浮现我就先加这个快速修复时看到该模式被原样列为错误行为会产生认知摩擦从而停下。这套抗压力设计通过了四类验证场景对应仓库中的测试文档学术场景无压力下的简单 bugtest-academic.md 以仅依据技能原文作答的方式考察规则内化以及三组高压场景——test-pressure-1.md 模拟生产事故每分钟 $15,000 损失下5 分钟加重试 vs 35 分钟调查的抉择test-pressure-2.md 模拟连续 4 小时加sleep超时失败后的沉没成本诱惑test-pressure-3.md 模拟资深工程师与 Tech Lead 在场时信任专家直接改的社会压力。构建日志给出的结果全部测试通过未发现合理化借口。小结与落地建议systematic-debugging技能的可复制性来自三件事强制的阶段门槛没有阶段 1 就没有修复资格、可执行的证据手段分层埋点、栈跟踪采集、find-polluter.sh二分定位、条件等待轮询、以及针对人性弱点的防御红旗清单、借口对照表、3 次失败即质疑架构。在实际使用中的建议人工排障时可把阶段 1 的五个检查点当作 checklist多组件链路问题优先跑一轮每层进/出数据埋点再定位组件修复完成后按 defense-in-depth 的四层清单自查入口校验、业务校验、环境护栏、调试埋点是否齐备若你的编码 Agent 加载了 Superpowers各 harness 的安装方式见 README.md该技能会在遇到 bug、测试失败或异常行为时自动触发——理解本文流程后你能更快判断 Agent 的调试行为是否合规例如它是否在未完成根因调查前就提出了修复或是否在第 3 次修复失败后停下来质疑架构。【免费下载链接】superpowersAn agentic skills framework software development methodology that works.项目地址: https://gitcode.com/GitHub_Trending/su/superpowers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表