mcpField
R
root-cause-tracing

root-cause-tracing

github.com/secondsky开发240431 次安装5 周前更新
代码仓库

关于 root-cause-tracing

面向开发者的调试技能,指导沿调用链逆向追踪错误,定位最初触发原因,而非只处理表面症状。包含测试污染排查和堆栈记录方法。

主要功能

  1. 01沿调用链追溯错误来源
  2. 02用堆栈记录定位触发点
  3. 03逐个运行测试查找污染源
  4. 04在源头修复并增加防护

适用场景

  1. 01排查深层调用中的错误
  2. 02定位无效数据的来源
  3. 03找出导致测试污染的用例

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/secondsky/claude-skills --skill root-cause-tracing

安装后在 Claude Code 中输入/root-cause-tracing确认已加载。

详细介绍

根因追踪

概述

Bug 往往会在调用栈深处显现(在错误的目录中运行 git init、在错误的位置创建文件、使用错误的路径打开数据库)。你的直觉可能是修复错误出现的位置,但这只是在处理症状。

**核心原则:**沿调用链向上追踪,直到找到最初的触发点,然后从源头修复。

适用场景

适用于:

  • 错误发生在执行流程深处(而非入口点)
  • 堆栈跟踪显示调用链很长
  • 不清楚无效数据来自哪里
  • 需要找出是哪个测试或代码触发了问题

追踪流程

1. 观察症状
Error: git init failed in ~/project/packages/core
2. 找到直接原因

是什么代码直接导致了这个问题?

await execFileAsync('git', ['init'], { cwd: projectDir });
3. 追问:是谁调用了它?
WorktreeManager.createSessionWorktree(projectDir, sessionId)
  → called by Session.initializeWorkspace()
  → called by Session.create()
  → called by test at Project.create()
4. 继续向上追踪

传入的值是什么?

  • projectDir = ''(空字符串!)
  • 空字符串作为 cwd 时,会解析为 process.cwd()
  • 那就是源代码目录!
5. 找到最初的触发点

空字符串是从哪里来的?

const context = setupCoreTest(); // Returns { tempDir: '' }
Project.create('name', context.tempDir); // Accessed before beforeEach!

添加堆栈跟踪

无法手动追踪时,可以添加检测代码:

// 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()(不要使用 logger——它可能不会显示)

运行并捕获:

bun test 2>&1 | grep 'DEBUG git init'

分析堆栈跟踪:

  • 查找测试文件名
  • 找出触发调用的行号
  • 识别模式(同一个测试?同一个参数?)

找出导致污染的测试

如果某个问题在测试期间出现,但你不知道是哪个测试导致的:

使用二分脚本逐个运行测试:

# Example: find which test creates .git in wrong place
bun test --run --bail 2>&1 | tee test-output.log

脚本会逐个运行测试,并在发现第一个造成污染的测试时停止。

实例:空的 projectDir

**症状:**在 packages/core/(源代码目录)中创建了 .git

追踪链:

  1. git init 在 process.cwd() 中运行 ← cwd 参数为空
  2. WorktreeManager 接收到空的 projectDir
  3. Session.create() 接收到空字符串
  4. 测试在 beforeEach 之前访问了 context.tempDir
  5. setupCoreTest() 最初返回 { tempDir: '' }

**根因:**顶层变量初始化时访问了空值

**修复:**将 tempDir 改为 getter,在 beforeEach 执行前访问时抛出错误

还添加了纵深防御:

  • 第 1 层:Project.create() 验证目录
  • 第 2 层:WorkspaceManager 验证目录不为空
  • 第 3 层:NODE_ENV 守卫拒绝在 tmpdir 之外运行 git init
  • 第 4 层:在运行 git init 前记录堆栈跟踪

核心原则

**绝不要只修复错误出现的位置。**追溯问题,找出最初的触发点。

堆栈跟踪提示

**在测试中:**使用 console.error(),不要使用 logger——logger 可能被抑制
**操作之前:**在执行危险操作之前记录日志,不要等操作失败后再记录
**包含上下文:**目录、cwd、环境变量、时间戳
捕获堆栈:new Error().stack 会显示完整调用链

实际效果

来自一次调试会话:

  • 通过 5 层追踪找到了根因
  • 从源头修复(getter 验证)
  • 增加了 4 层防御
  • 1847 项测试通过,没有造成任何污染

评论

支持 Markdown