mcpField
D
debug-agent

debug-agent

github.com/millionco开发3.6k122 次安装29 周前更新
代码仓库

关于 debug-agent

debug-agent 是一套要求依据运行时证据排查软件问题的指令技能,面向编码 Agent,涵盖假设、日志、复现、分析和验证。

主要功能

  1. 01基于运行时证据的调试流程
  2. 02按假设布置日志
  3. 03NDJSON 日志服务配置
  4. 04基于日志验证修复
  5. 05保留调试日志的规则

适用场景

  1. 01排查仅凭代码难以诊断的问题
  2. 02复现时并行验证多个原因
  3. 03通过修复前后的运行日志确认结果

安装

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

$npx skills add https://github.com/millionco/expect --skill debug-agent

安装后在 Claude Code 中输入/debug-agent确认已加载。

详细介绍

调试模式

你现在处于调试模式。必须使用运行时证据进行调试。

采用这种方法的原因:传统 AI Agent 会贸然修复问题,并声称有 100% 的把握,但由于缺少运行时信息,最终往往会失败。 它们只根据代码进行猜测。你不能也绝不能这样修复 Bug——你需要实际的运行时数据。

系统化工作流程:

  1. 提出 3-5 个关于 Bug 发生原因的准确假设(详细说明,宁多勿少)
  2. 在代码中添加日志(参见“日志记录”部分),并行验证所有假设
  3. 请用户重现 Bug。提供清晰、带编号的重现步骤。提醒用户:如果添加日志的文件已缓存或打包,请重启相关应用/服务。请用户完成后予以确认。
  4. 分析日志:根据日志行证据,对每个假设作出评估(已确认/已排除/无法确定)
  5. 仅在有 100% 把握且有日志证据时修复;此时不要移除日志记录
  6. 通过日志验证:请用户再次运行,并对比修复前后的日志,引用相应日志条目
  7. **如果日志证明问题已解决,且用户确认:**移除日志记录并进行说明。**如果修复失败:**先移除基于已排除假设所做的任何代码更改(保留日志记录和已证实的修复),然后根据不同子系统提出新假设,并添加更多日志记录
  8. **确认成功后:**说明问题所在,并简要总结修复内容(1-2 行)

重要约束:

  • 在获得运行时证据之前,绝不要修复
  • 始终结合运行时信息和代码进行判断(绝不能只看代码)
  • 在修复后的验证日志证明成功,且用户确认没有其他问题之前,不要移除日志记录
  • 修复往往会失败;预期会反复迭代,并优先选择迭代。花更多时间收集更多数据,才能得到更好、更准确的修复结果

日志记录

STEP 0:启动日志服务器(必须在添加任何日志记录之前完成)

重要:服务器是一个长时间运行的进程。必须在后台运行。

在添加任何日志记录之前,先将调试服务器作为后台进程运行。整个调试会话期间服务器都必须保持运行——这不是一次性命令。

npx debug-agent 2>&1 &

**必须在后台运行此命令。**不要在前台运行,也不要等待命令完成——它永远不会完成,因为它是一个持久运行的服务器。请使用 &(Shell 后台运行)、nohup,或 Agent 的后台/异步命令执行功能。如果 Agent 平台支持 block_until_ms: 0 或等效功能,请使用该功能。如果支持在单独的终端中运行命令,请这样做。此命令绝不能阻塞工作流程。

服务器启动时会向标准输出打印一行 JSON:

{
  "sessionId": "a1b2c3",
  "port": 54321,
  "endpoint": "http://127.0.0.1:54321/ingest/a1b2c3",
  "logPath": "/tmp/debug-agent/debug-a1b2c3.log"
}

捕获并记住以下值:

  • 服务器端点:endpoint 的值(通过 POST 请求发送日志的 HTTP 端点 URL)
  • 日志路径:logPath 的值(NDJSON 日志写入此路径)
  • 会话 ID:sessionId 的值(此调试会话的唯一标识符)

如果服务器启动失败,请立即停止并告知用户。

  • 未获得有效的日志配置时,不要继续添加日志记录。
  • 服务器具有幂等性——如果已有服务器在运行,它会返回现有服务器的信息,而不会启动重复实例。
  • 无需预先创建日志文件;首次写入日志时会自动创建。
STEP 1:了解日志格式
  • 日志以 NDJSON 格式(每行一个 JSON 对象)写入日志路径指定的文件。
  • 对于 JavaScript/TypeScript,运行时会通过 POST 请求将日志发送到服务器端点,日志服务器会将其作为 NDJSON 行写入日志路径指定的文件。
  • 对于其他语言(Python、Go、Rust、Java、C/C++、Ruby 等),建议使用该语言的标准库文件 I/O,直接将 NDJSON 行追加到日志路径指定的文件中。

日志条目示例:

{
  "sessionId": "a1b2c3",
  "id": "log_1733456789_abc",
  "timestamp": 1733456789000,
  "location": "test.js:42",
  "message": "User score",
  "data": { "userId": 5, "score": 85 },
  "runId": "run1",
  "hypothesisId": "A"
}
步骤 2:插入埋点日志
  • 在 JavaScript/TypeScript 文件中,使用此单行 fetch 模板(将 ENDPOINT 和 SESSION_ID 替换为步骤 0 中的值),即使可以访问文件系统也不例外:
fetch('ENDPOINT',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({sessionId:'SESSION_ID',location:'file.js:LINE',message:'desc',data:{k:v},timestamp:Date.now()})}).catch(()=>{});
  • 在 非 JavaScript 语言(Python、Go、Rust、Java、C、C++、Ruby)中,通过标准库文件 I/O 以追加模式打开日志路径,写入一行包含有效负载的 NDJSON,然后关闭文件。尽可能让这些代码片段保持精简简短(最好一行,或仅几行)。

  • 根据正在调查的代码复杂度和待验证的假设,决定插入多少条埋点日志。如果问题高度集中,放置一条合适的日志可能就足够;复杂的多步流程可能需要更多。目标是用最少的日志确认或排除所有假设。指南:

    • 至少需要 1 条日志;绝不可完全跳过埋点
    • 不超过 10 条日志——如果你认为需要更多,先缩小假设范围
    • 通常为 2-6 条,但请自行判断
  • 根据假设,从以下类别中选择相关的日志位置:

    • 函数入口处的参数
    • 函数出口处的返回值
    • 关键操作之前的值
    • 关键操作之后的值
    • 分支执行路径(执行了哪个 if/else 分支)
    • 疑似错误或边缘情况的值
    • 状态变更和中间值
  • 每条日志必须至少对应一个假设(在有效负载中包含 hypothesisId)。

  • 使用此有效负载结构:{sessionId, runId, hypothesisId, location, message, data, timestamp}

  • **必须:**将每条调试日志都包裹在可折叠的代码区域中:

    • 使用适合语言的区域语法(例如,JS/TS 中的 // #region debug log、// #endregion)
    • 这样编辑器会自动折叠调试埋点,保持代码整洁
  • **禁止:**记录机密信息(令牌、密码、API 密钥、个人身份信息)

步骤 3:每次运行前清除之前的日志文件(强制)
  • 在让用户运行之前,删除日志路径中的文件。
  • 如果无法删除或删除失败:告知用户手动删除日志文件。
  • 这样可确保新运行的日志干净,不会与旧数据混杂。
  • 不要使用 Shell 命令(rm、touch 等);只能使用 delete_file 工具。
  • 清除日志文件不等于移除埋点;此处不要从代码中移除任何调试日志。
  • **重要:**只能删除你自己的日志文件(步骤 0 中的日志路径)。绝不可删除、修改或覆盖属于其他调试会话的日志文件。其他会话可能在同一目录中使用不同的会话 ID 文件名保存日志——请勿触碰。
步骤 4:用户运行程序后读取日志
  • 用户运行程序并在其界面中确认完成后,不要让他们输入“完成”;然后读取日志路径中的文件。
  • 日志文件将包含埋点生成的 NDJSON 条目(每行一个 JSON 对象)。
  • 分析这些日志以评估假设并找出根本原因。
  • 如果日志文件为空或缺失:告知用户复现可能未成功,并请他们重试。
步骤 5:修复期间保留日志
  • 实施修复时,暂时不要移除调试日志。
  • 验证运行期间必须保留日志。
  • 你可以将日志标记为 runId="post-fix",以区分验证运行与初始调试运行。
  • 禁止:在分析修复后的验证日志之前,或用户明确确认成功之前,移除或修改任何文件中先前添加的日志。
  • 只有在修复后的验证运行成功(有基于日志的证据)或用户明确要求移除时,才移除日志。

关键提醒(必须遵守)

  • 修复期间保持埋点处于启用状态;直到验证成功或用户明确确认前,不要移除或修改日志。
  • 禁止:使用 setTimeout、sleep 或人为延迟作为“修复”;应使用适当的响应性机制、事件或生命周期。
  • 禁止:在分析修复后的验证日志或收到用户明确确认之前移除埋点。
  • 验证必须对比修复前后的日志,并引用日志行;没有日志证据时不得声称修复成功。
  • 不要手动创建日志文件;它会自动创建。
  • 清空日志文件不等于移除埋点。
  • 绝不要删除或修改不属于本次会话的日志文件。只能操作步骤 0 中的确切路径所指向的日志文件。
  • 始终优先通过提出新假设,并利用日志证据来提供修复方案。
  • 如果所有假设都被否定,必须提出更多假设,并据此添加更多埋点。
  • **移除被否定假设对应的代码更改:**当日志证明某个假设有误时,撤销为该假设所做的代码更改。不要累积防御性保护、推测性修复或未经证实的更改。只保留有运行时证据支持的修改。
  • 优先复用现有架构、模式和实用工具;避免过度设计。修复应精准、针对性强,并尽可能精简,同时最大化效果。

服务端 API 参考

方法效果
POST /ingest/:sessionId将 JSON 请求体作为 NDJSON 行追加到日志文件
GET /ingest/:sessionId读取完整的日志文件内容
DELETE /ingest/:sessionId清空日志文件

评论

支持 Markdown