假设驱动调试与文件记录Skill debug-with-file

这个技能用于通过假设驱动的调试方法,结合文档记录、理解演进和分析辅助纠正,高效定位和修复软件bug。关键词包括调试、假设驱动、文档记录、分析验证、bug定位、软件维护。

测试 0 次安装 0 次浏览 更新于 3/16/2026

name: debug-with-file description: 通过文档记录探索、理解演进和分析辅助纠正的交互式假设驱动调试。 argument-hint: “BUG="<bug描述或错误信息>"”

Codex Debug-With-File 提示

概述

增强的证据驱动调试,带文档记录探索过程。记录理解演进,整合洞察,并使用分析来纠正误解。

核心工作流:探索 → 记录 → 日志 → 分析 → 纠正理解 → 修复 → 验证

相对于 /prompts:debug 的关键增强

  • understanding.md:探索和学习的时间线
  • 分析辅助纠正:验证和纠正假设
  • 整合:简化被证明错误的理解以避免杂乱
  • 学习保留:保留学到的内容,即使是失败的尝试

目标 Bug

$BUG

执行过程

会话检测:
   ├─ 检查是否存在此bug的调试会话
   ├─ 存在 + understanding.md 存在 → 继续模式
   └─ 未找到 → 探索模式

探索模式:
   ├─ 在代码库中定位错误源
   ├─ 在 understanding.md 中记录初始理解
   ├─ 生成可测试假设并进行分析验证
   ├─ 添加 NDJSON 日志插桩
   └─ 输出:假设列表 + 等待用户复现

分析模式:
   ├─ 解析 debug.log,验证每个假设
   ├─ 使用分析评估假设并纠正理解
   ├─ 更新 understanding.md:
   │   ├─ 新证据
   │   ├─ 纠正的误解(删除线 + 更正)
   │   └─ 整合当前理解
   └─ 决策:
       ├─ 确认 → 修复根因
       ├─ 不明确 → 添加更多日志,迭代
       └─ 全部拒绝 → 辅助新假设

修复与清理:
   ├─ 基于确认的假设应用修复
   ├─ 用户验证
   ├─ 记录最终理解和经验教训
   ├─ 移除调试插桩
   └─ 如果未修复 → 返回分析模式

实现细节

会话设置与模式检测

步骤 0:确定项目根目录

检测项目根目录,确保 .workflow/ 产物位置正确:

PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)

优先通过 git 获取仓库根目录;非 git 项目回退到 pwd 取当前绝对路径。 存储为 {projectRoot},后续所有 .workflow/ 路径必须以此为前缀。

const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
const projectRoot = bash('git rev-parse --show-toplevel 2>/dev/null || pwd').trim()

const bugSlug = "$BUG".toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 30)
const dateStr = getUtc8ISOString().substring(0, 10)

const sessionId = `DBG-${bugSlug}-${dateStr}`
const sessionFolder = `${projectRoot}/.workflow/.debug/${sessionId}`
const debugLogPath = `${sessionFolder}/debug.log`
const understandingPath = `${sessionFolder}/understanding.md`
const hypothesesPath = `${sessionFolder}/hypotheses.json`

// 自动检测模式
const sessionExists = fs.existsSync(sessionFolder)
const hasUnderstanding = sessionExists && fs.existsSync(understandingPath)
const logHasContent = sessionExists && fs.existsSync(debugLogPath) && fs.statSync(debugLogPath).size > 0

const mode = logHasContent ? 'analyze' : (hasUnderstanding ? 'continue' : 'explore')

if (!sessionExists) {
  bash(`mkdir -p ${sessionFolder}`)
}

探索模式

步骤 1.1:定位错误源

// 从bug描述中提取关键词
const keywords = extractErrorKeywords("$BUG")

// 搜索代码库以找到错误位置
const searchResults = []
for (const keyword of keywords) {
  const results = Grep({ pattern: keyword, path: ".", output_mode: "content", "-C": 3 })
  searchResults.push({ keyword, results })
}

// 识别受影响文件和函数
const affectedLocations = analyzeSearchResults(searchResults)

步骤 1.2:记录初始理解

创建 understanding.md

# 理解文档

**会话 ID**:${sessionId}
**Bug 描述**:$BUG
**开始时间**:${getUtc8ISOString()}

---

## 探索时间线

### 迭代 1 - 初始探索(${timestamp})

#### 当前理解

基于bug描述和初始代码搜索:

- 错误模式:${errorPattern}
- 影响区域:${affectedLocations.map(l => l.file).join(', ')}
- 初始假设:${initialThoughts}

#### 代码搜索证据

${searchResults.map(r => `
**关键词:"${r.keyword}"**
- 找到位置:${r.results.files.join(', ')}
- 关键发现:${r.insights}
`).join('
')}

#### 下一步

- 生成可测试假设
- 添加插桩
- 等待复现

---

## 当前整合理解

${initialConsolidatedUnderstanding}

步骤 1.3:生成假设

分析bug并生成3-5个可测试假设:

// 基于错误模式生成假设
const HYPOTHESIS_PATTERNS = {
  "not found|missing|undefined|未找到": "data_mismatch",
  "0|empty|zero|registered": "logic_error",
  "timeout|connection|sync": "integration_issue",
  "type|format|parse": "type_mismatch"
}

function generateHypotheses(bugDescription, affectedLocations) {
  // 基于错误分析生成针对性假设
  // 每个假设包括:
  // - id: H1, H2, ...
  // - description: 可能出错的地方
  // - testable_condition: 要记录的内容
  // - logging_point: 添加插桩的位置
  // - evidence_criteria: 确认/拒绝的条件
  return hypotheses
}

保存到 hypotheses.json

{
  "iteration": 1,
  "timestamp": "2025-01-21T10:00:00+08:00",
  "hypotheses": [
    {
      "id": "H1",
      "description": "数据结构不匹配 - 预期键不存在",
      "testable_condition": "检查字典中目标键是否存在",
      "logging_point": "file.py:func:42",
      "evidence_criteria": {
        "confirm": "数据显示缺失键",
        "reject": "键存在且值有效"
      },
      "likelihood": 1,
      "status": "pending"
    }
  ]
}

步骤 1.4:添加 NDJSON 插桩

对于每个假设,在指定位置添加日志:

Python 模板

# region debug [H{n}]
try:
    import json, time
    _dbg = {
        "sid": "{sessionId}",
        "hid": "H{n}",
        "loc": "{file}:{line}",
        "msg": "{testable_condition}",
        "data": {
            # 在此处捕获相关值
        },
        "ts": int(time.time() * 1000)
    }
    with open(r"{debugLogPath}", "a", encoding="utf-8") as _f:
        _f.write(json.dumps(_dbg, ensure_ascii=False) + "
")
except: pass
# endregion

JavaScript/TypeScript 模板

// region debug [H{n}]
try {
  require('fs').appendFileSync("{debugLogPath}", JSON.stringify({
    sid: "{sessionId}",
    hid: "H{n}",
    loc: "{file}:{line}",
    msg: "{testable_condition}",
    data: { /* 捕获相关值 */ },
    ts: Date.now()
  }) + "
");
} catch(_) {}
// endregion

步骤 1.5:输出给用户

## 生成的假设

基于错误 "$BUG",生成 {n} 个假设:

{hypotheses.map(h => `
### ${h.id}: ${h.description}
- 日志位置:${h.logging_point}
- 测试内容:${h.testable_condition}
- 确认证据:${h.evidence_criteria.confirm}
- 拒绝证据:${h.evidence_criteria.reject}
`).join('')}

**调试日志**:${debugLogPath}

**下一步**:运行复现步骤,然后返回进行分析。

分析模式

步骤 2.1:解析调试日志

// 解析 NDJSON 日志
const entries = Read(debugLogPath).split('
')
  .filter(l => l.trim())
  .map(l => JSON.parse(l))

// 按假设分组
const byHypothesis = groupBy(entries, 'hid')

// 验证每个假设
for (const [hid, logs] of Object.entries(byHypothesis)) {
  const hypothesis = hypotheses.find(h => h.id === hid)
  const latestLog = logs[logs.length - 1]

  // 检查证据是否确认或拒绝假设
  const verdict = evaluateEvidence(hypothesis, latestLog.data)
  // 返回:'confirmed' | 'rejected' | 'inconclusive'
}

步骤 2.2:分析证据并纠正理解

审查调试日志并评估每个假设:

  1. 解析所有日志条目
  2. 按假设 ID 分组
  3. 比较证据与预期条件
  4. 确定裁决:确认 | 拒绝 | 不明确
  5. 识别先前理解中的错误假设
  6. 生成更正

步骤 2.3:更新理解与更正

understanding.md 中追加新迭代:

### 迭代 ${n} - 证据分析(${timestamp})

#### 日志分析结果

${results.map(r => `
**${r.id}**:${r.verdict.toUpperCase()}
- 证据:${JSON.stringify(r.evidence)}
- 推理:${r.reason}
`).join('
')}

#### 纠正的理解

先前识别和纠正的误解:

${corrections.map(c => `
- ~~${c.wrong}~~ → ${c.corrected}
  - 错误原因:${c.reason}
  - 证据:${c.evidence}
`).join('
')}

#### 新洞察

${newInsights.join('
- ')}

${confirmedHypothesis ? `
#### 识别根因

**${confirmedHypothesis.id}**:${confirmedHypothesis.description}

支持此结论的证据:
${confirmedHypothesis.supportingEvidence}
` : `
#### 下一步

${nextSteps}
`}

---

## 当前整合理解(已更新)

${consolidatedUnderstanding}

步骤 2.4:更新 hypotheses.json

{
  "iteration": 2,
  "timestamp": "2025-01-21T10:15:00+08:00",
  "hypotheses": [
    {
      "id": "H1",
      "status": "rejected",
      "verdict_reason": "证据显示键存在且值有效",
      "evidence": {...}
    },
    {
      "id": "H2",
      "status": "confirmed",
      "verdict_reason": "日志数据确认时序问题",
      "evidence": {...}
    }
  ],
  "corrections": [
    {
      "wrong_assumption": "...",
      "corrected_to": "...",
      "reason": "..."
    }
  ]
}

修复与验证

步骤 3.1:应用修复

基于确认的假设,在受影响文件中实施修复。

步骤 3.2:记录解决方案

understanding.md 中追加:

### 迭代 ${n} - 解决方案(${timestamp})

#### 应用的修复

- 修改的文件:${modifiedFiles.join(', ')}
- 修复描述:${fixDescription}
- 解决的根因:${rootCause}

#### 验证结果

${verificationResults}

#### 经验教训

从此调试会话中学到的:

1. ${lesson1}
2. ${lesson2}
3. ${lesson3}

#### 未来关键洞察

- ${insight1}
- ${insight2}

步骤 3.3:清理

通过搜索区域标记移除调试插桩:

const instrumentedFiles = Grep({
  pattern: "# region debug|// region debug",
  output_mode: "files_with_matches"
})

for (const file of instrumentedFiles) {
  // 移除区域标记之间的内容
  removeDebugRegions(file)
}

会话文件夹结构

{projectRoot}/.workflow/.debug/DBG-{slug}-{date}/
├── debug.log           # NDJSON 日志(执行证据)
├── understanding.md    # 探索时间线 + 整合理解
└── hypotheses.json    # 假设历史与裁决

理解文档模板

# 理解文档

**会话 ID**:DBG-xxx-2025-01-21
**Bug 描述**:[原始描述]
**开始时间**:2025-01-21T10:00:00+08:00

---

## 探索时间线

### 迭代 1 - 初始探索(2025-01-21 10:00)

#### 当前理解
...

#### 代码搜索证据
...

#### 生成的假设
...

### 迭代 2 - 证据分析(2025-01-21 10:15)

#### 日志分析结果
...

#### 纠正的理解
- ~~[错误]~~ → [更正]

#### 分析结果
...

---

## 当前整合理解

### 已知信息
- [有效理解点]

### 被证伪的
- ~~[证伪的假设]~~

### 当前调查重点
[当前焦点]

### 剩余问题
- [未解问题]

调试日志格式(NDJSON)

每行是一个 JSON 对象:

{"sid":"DBG-xxx-2025-01-21","hid":"H1","loc":"file.py:func:42","msg":"检查字典键","data":{"keys":["a","b"],"target":"c","found":false},"ts":1734567890123}
字段 描述
sid 会话 ID
hid 假设 ID(H1, H2, …)
loc 代码位置
msg 测试内容
data 捕获的值
ts 时间戳(毫秒)

迭代流程

首次调用(BUG="error"):
   ├─ 会话不存在 → 探索模式
   ├─ 提取错误关键词,搜索代码库
   ├─ 在 understanding.md 中记录初始理解
   ├─ 生成假设
   ├─ 添加日志插桩
   └─ 等待用户复现

复现后(BUG="error"):
   ├─ 会话存在 + debug.log 有内容 → 分析模式
   ├─ 解析日志,评估假设
   ├─ 更新 understanding.md:
   │   ├─ 证据分析结果
   │   ├─ 纠正的误解(删除线)
   │   ├─ 新洞察
   │   └─ 更新的整合理解
   ├─ 更新 hypotheses.json 与裁决
   └─ 决策:
       ├─ 确认 → 修复 → 记录解决方案
       ├─ 不明确 → 添加日志,记录下一步
       └─ 全部拒绝 → 辅助新假设

输出:
   ├─ {projectRoot}/.workflow/.debug/DBG-{slug}-{date}/debug.log
   ├─ {projectRoot}/.workflow/.debug/DBG-{slug}-{date}/understanding.md(演进文档)
   └─ {projectRoot}/.workflow/.debug/DBG-{slug}-{date}/hypotheses.json(历史)

错误处理

情况 行动
空的 debug.log 验证复现是否触发了代码路径
所有假设被拒绝 基于证伪的假设生成新假设
修复无效 记录失败修复尝试,基于精炼理解迭代
>5 次迭代 审查整合理解,以完整上下文升级
理解过长 积极整合,将旧迭代归档到单独文件

整合规则

更新“当前整合理解”时:

  1. 简化证伪项:移至“被证伪的”并单行摘要
  2. 保留有效洞察:将确认发现提升至“已知信息”
  3. 避免重复:不在整合部分重复时间线细节
  4. 关注当前状态:当前所知,而非过程
  5. 保留关键更正:保留重要错误→正确转换以用于学习

差(杂乱)

## 当前整合理解

在迭代1我们以为X,但在迭代2我们发现Y,然后在迭代3...
还有我们检查A找到B,然后检查C...

好(整合)

## 当前整合理解

### 已知信息
- 错误在运行时更新时发生,而非初始化
- 配置值为None(非缺失键)

### 被证伪的
- ~~初始化错误~~(时序证据)
- ~~缺失键假设~~(键存在)

### 当前调查重点
为什么配置值在更新时为None?

关键特性

特性 描述
NDJSON 日志 结构化调试日志与假设跟踪
假设生成 分析辅助的假设创建
探索文档记录 understanding.md 带时间线
理解演进 时间线 + 更正跟踪
错误纠正 删除线 + 错误假设推理
整合学习 当前理解部分
假设历史 hypotheses.json 带裁决
分析验证 在关键决策点

适用场景

最适合:

  • 需要多轮调查的复杂bug
  • 调试过程学习有价值
  • 团队需要理解调试原理
  • bug可能复发,文档有助于预防

现在为bug执行 debug-with-file 工作流:$BUG