Communitygithub.com

调试模式技能

与代理无关的调试模式技能,支持本地 NDJSON 日志收集。

调试模式技能 是什么?

该技能提供了一个与具体 AI 代理无关的调试模式,核心功能是本地 NDJSON 日志的收集与分析。它适用于 Claude Code、Cursor、Codex 等任何基于终端的 AI 代理开发环境。技能的工作流程是一个假设驱动的调试循环:用户显式激活调试模式后,代理会生成多个假设,并在代码中插入临时探针来收集结构化事件日志。这些日志通过一个小型本地回环 HTTP 收集器接收,并写入操作系统临时目录下的 NDJSON 文件。调试循环包含严格的检查点机制,确保代理在有足够证据前不会进行猜测性修复。该技能强调安全性,禁止记录任何敏感信息。它内置了多种编程语言(如 JavaScript、Node.js、Python)的帮助器模板,使得在不同项目中快速插入调试探针变得非常容易。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add wangnan0916/debug-mode-skill

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

调试模式

仅当用户显式调用 debug-mode、$debug-mode、debug mode 或 instrumented debugging 后使用此技能。

如果用户未明确选择加入,则正常调试。仅在临时运行时插桩能实质性帮助时提及此技能。

核心循环

运行假设驱动的调试循环:

  1. 阅读相关代码、复现细节和现有日志。
  2. 列出 2-5 个排序的假设,使用例如 H1、H2、H3 的 ID。 每个假设必须预测运行时探针将显示的内容。
  3. 启动或复用回环收集器(收集器约定)。
  4. 添加 3-8 个有针对性的探针以区分假设。使用发送到 DEBUG_URL + "/log" 的结构化事件,切勿使用 stdout/stderr。遵循下文的事件结构、区域标记和帮助器。
  5. 在手动检查点停止。发送检查点模板。在用户回复 A、B 或 C 之前,不要分析、修复或移除探针。
  6. 收到 A 后,检查打印的 LOG_FILE,将每个假设分类为 CONFIRMED(已确认)、REJECTED(已拒绝)或 INCONCLUSIVE(尚无结论),并且仅当日志能解释根本原因时进行最小的修复。遵循下文的证据摘要。
  7. 在一次带有 runId: "post-fix" 标签的修复后运行中保持探针活跃。
  8. 用户对修复后检查点回复 B 后,移除所有插桩并运行相关检查。遵循下文的清理清单。

硬性规则

  • 绝不在添加探针后跳过手动复现检查点。
  • 在此技能激活时,绝不要靠猜测进行修复。
  • 在用户确认修复后检查之前,绝不要移除探针。
  • 绝不要提交调试日志或临时插桩代码。
  • 绝不要记录秘密、令牌、cookies、授权头、API 密钥、原始请求体、可能包含私有数据的原始响应,或非必要的个人数据。

收集器约定

打包的收集器特意保持小巧:

  • GET /health 检查现有收集器是否可复用。
  • POST /log 接受一个 JSON 对象并异步追加一行 NDJSON。 它在验证后返回 200;该行在后台写入。
  • 不同的会话写入独立的文件并拥有独立的队列,因此写入可以跨会话并行进行。
  • 日志默认保存在操作系统临时目录下,位于工作区之外。
  • --ensure 打印 DEBUG_URL、SESSION_ID、LOG_DIR、LOG_FILE 和 HEALTH_URL。
  • 收集器在第一个事件时创建 LOG_FILE。不要在复现后执行 touch、预创建、截断或清除它。
  • 收集器仅限回环。不要将其绑定到 0.0.0.0 或任何公共接口。

使用以下命令启动或复用:

node <skill-dir>/scripts/log-server.mjs --ensure --session <session_id> --host 127.0.0.1 --port 0

在阻止本地端口监听器的托管沙箱中,在首次尝试时请求代理的正常批准。将原因限定为启动或复用这个仅限回环的调试收集器。

检查点模板

添加探针后,停止并发送此形状,填充真实的会话详情:

我已添加调试模式探针,收集器正在写入:

- 会话:<session_id>
- 日志文件:<LOG_FILE>
- 调试端点:<DEBUG_URL>/log

请手动复现该 bug,然后回复:

A - 已复现
B - 已修复
C - 其他;描述发生的情况

对于修复后验证,仅更改开场句:

我已保持调试模式探针活跃以进行修复后验证,收集器正在写入:

- 会话:<session_id>
- 日志文件:<LOG_FILE>
- 调试端点:<DEBUG_URL>/log

请手动验证原始 bug,然后回复:

A - 已复现
B - 已修复
C - 其他;描述发生的情况

将检查点回复解释为一个小的状态机:

  • 修复前的 A:读取 NDJSON 日志,分类假设证据,然后仅修复已确认的原因或添加更窄的探针。
  • 修复后的 A:bug 仍然复现。读取修复后日志,继续使用更窄的假设或探针。
  • 修复前的 B:不是终止状态。将其视为 bug 在插桩条件下未复现的证据,并请求澄清或更窄的复现步骤。
  • 修复后的 B:移除探针并运行最终检查。
  • 任何时间的 C:将用户的文本视为证据。调整复现步骤、假设或探针。

事件结构

使用结构化的、低容量的事件。一个典型的事件如下所示:

{
  "session": "<session_id>",
  "runId": "pre-fix",
  "probe": "settings.beforePersist",
  "hypothesis": "H1",
  "file": "src/settings/save.ts",
  "fn": "saveSettings",
  "vars": {
    "enabled": true,
    "userId": "redacted"
  }
}

修复前使用 runId: "pre-fix",修复后验证使用 runId: "post-fix"。对于高频路径,仅记录状态变化或积极采样。

区域标记

包裹所有临时插桩代码,以便清理可以是机械性的:

// #region DEBUG_MODE_PROBE <session_id> settings-before-persist
debugModeLog({
  probe: "settings.beforePersist",
  hypothesis: "H1",
  file: "src/settings/save.ts",
  fn: "saveSettings",
  vars: { enabled, userId: "redacted" },
});
// #endregion DEBUG_MODE_PROBE <session_id>

常见的注释形式:

// #region DEBUG_MODE_PROBE <session_id> ...    JavaScript, TypeScript, Java, C#, Go, Rust, C, C++
# #region DEBUG_MODE_PROBE <session_id> ...     Python, Ruby, Shell, YAML
<!-- #region DEBUG_MODE_PROBE <session_id> -->  HTML, Vue, Svelte
/* #region DEBUG_MODE_PROBE <session_id> */     CSS 和 C 风格的块上下文
-- #region DEBUG_MODE_PROBE <session_id> ...    SQL, Lua

帮助器

对于浏览器或前端 JavaScript,使用 assets/browser-log-helper.js 作为规范的帮助器模板。将其复制到被插桩的模块或脚本中,替换 <session_id> 和 <DEBUG_URL>,并保持函数名 debugModeLog。

对于 Node.js 或服务器端 JavaScript,使用 assets/node-log-helper.js 作为规范的帮助器模板。将其复制到被插桩的模块或脚本中,替换 <session_id> 和 <DEBUG_URL>,并保持函数名 debugModeLog。

对于不依赖第三方库的 Python:

# #region DEBUG_MODE_PROBE <session_id> debug-log-helper
import json
import urllib.request

DEBUG_MODE_URL = "<DEBUG_URL>/log"

def debug_mode_log(event):
    try:
        payload = {"session": "<session_id>", **event}
        data = json.dumps(payload).encode("utf-8")
        req = urllib.request.Request(
            DEBUG_MODE_URL,
            data=data,
            headers={"content-type": "application/json"},
            method="POST",
        )
        urllib.request.urlopen(req, timeout=0.5).close()
    except Exception:
        pass
# #endregion DEBUG_MODE_PROBE <session_id>

证据摘要

在收到 A 回复后,在编辑代码之前总结证据:

H1 设置状态在 API 调用前丢失
状态:已确认
证据:settings.beforePersist 记录了 enabled=false,而 UI 事件记录了 enabled=true。

H2 API 拒绝该值
状态:已拒绝
证据:本次复现中没有发生 API 调用。

下一步:修复 onToggle 和 saveSettings 之间的本地状态交接。

如果每个假设都是 REJECTED(已拒绝)或 INCONCLUSIVE(尚无结论),则从不同的子系统生成新假设并添加更窄的探针。不要凭感觉打补丁。

故障排除

  • 日志为空:确认应用执行了插桩路径,会话 ID 匹配,并且端点包含 /log。
  • 浏览器请求被阻止:检查混合内容、CSP 的 connect-src、扩展隔离或 content-script 上下文。
  • CORS/预检问题:收集器处理 OPTIONS;如果仍然失败,尝试 navigator.sendBeacon、同源开发服务器代理或服务器端插桩。
  • 主机被拒绝:使用 127.0.0.1、localhost 或 ::1;切勿绑定到局域网或公共接口。
  • 沙箱阻止监听器:使用所需的批准重试一次此回环收集器。如果批准被拒绝,说明本地收集被阻止,并且仅当存在安全的基于文件的探针路径时才回退。
  • 日志过多:用更窄的状态变化探针替换嘈杂的探针。
  • 无法复现:询问确切的步骤、环境、输入数据或屏幕录制;不要凭空编造修复。

清理清单

在声明任务完成之前:

  • 重新运行原始复现步骤,或最接近的可用自动化检查。
  • 移除每对标记为 DEBUG_MODE_PROBE <session_id> 的区域。
  • 搜索会话 ID、DEBUG_MODE_PROBE、#region DEBUG_MODE_PROBE 和 #endregion DEBUG_MODE_PROBE。
  • 移除打印的 LOG_FILE 处的会话 NDJSON 日志,或确认应将其保留为本地证据。
  • 仅保留产品修复和任何有用的回归测试。

相关技能