用途
Debug 技能用于排查需要运行时证据的前端/UI 缺陷,核心理念是“不要猜,而是假设 → 埋点 → 复现 → 分析 → 修复 → 验证”。它适用于以下触发信号:即将让用户“打开 DevTools 控制台查看…”“复现 bug 并告诉我你看到了什么”“加个 console.log 然后告诉我输出”“点击 X、打开 Y、检查控制台是否出现 Z”。典型场景是:与其让用户手动打开浏览器、打开控制台、执行操作、复制日志,不如让日志在服务端被捕获,由你直接读取,省去用户复制粘贴。
主要能力
- 启动日志服务器并创建调试会话,服务器会依据描述生成唯一 session_id 和日志文件路径。
- 在 JavaScript/TypeScript 或 Python 代码中插入埋点日志,日志以 NDJSON 形式写入 .debug 目录。
- 覆盖状态/取值问题(null、undefined、类型错误)、条件逻辑(走了哪个分支)、异步时序(竞态、加载顺序)和用户交互流程(弹窗、表单、点击)。
- 提供日志端点:POST /session 创建会话并返回 {session_id, log_file};POST /log 写入日志;GET / 返回状态和日志目录。
- 针对 CORS、混合内容与 CSP 提供绕过方案,如 sendBeacon、Vite 开发服务器代理、最后手段的本地放行。
- 针对 Chrome 扩展:内容脚本受隔离世界与严格 CSP 限制,无法直接访问 localhost:8787,需经后台脚本(service worker)中转,注入脚本(MAIN world)可通过 window.postMessage 转给内容脚本再转后台。
使用方式
参数为项目路径:/debug /path/to/project,若未提供则使用当前工作目录。
启动服务器:
node skills/debug/scripts/debug_server.js /path/to/project &
创建会话:
curl -s -X POST http://localhost:8787/session -d '{"name":"fix-null-userid"}'
若 8787 端口被占用:lsof -ti :8787 | xargs kill -9 后重启。
随后按九个阶段推进:启动日志服务器、生成 3-5 条具体可测试且覆盖不同子系统的假设、在代码中添加 3-8 处埋点(包裹在 // #region debug … // #endregion 中,覆盖入口/出口、关键操作前后、分支路径,并用 hypothesisId 标注)、清空日志并提供复现步骤、读取日志逐条判定假设(CONFIRMED / REJECTED / INCONCLUSIVE)、仅在证据确认根因后修复、清空日志让用户复现并对比修复前后日志验证、可选地做“五个为什么”根因分析、最后在确认解决后移除所有埋点。
JavaScript/TypeScript 埋点示例:
// #region debug
const SESSION_ID = 'REPLACE_WITH_SESSION_ID';
const DEBUG_LOG_URL = 'http://localhost:8787/log';
const debugLog = (msg, data = {}, hypothesisId = null) => {
const payload = JSON.stringify({
sessionId: SESSION_ID, msg, data, hypothesisId,
loc: new Error().stack?.split('\n')[2],
});
if (navigator.sendBeacon?.(DEBUG_LOG_URL, payload)) return;
fetch(DEBUG_LOG_URL, { method: 'POST', body: payload }).catch(() => {});
};
// #endregion
Python 埋点示例:
# #region debug
import requests, traceback
SESSION_ID = 'REPLACE_WITH_SESSION_ID'
def debug_log(msg, data=None, hypothesis_id=None):
try:
requests.post('http://localhost:8787/log', json={
'sessionId': SESSION_ID, 'msg': msg, 'data': data,
'hypothesisId': hypothesis_id, 'loc': traceback.format_stack()[-2].strip()
}, timeout=0.5)
except: pass
# #endregion
清空日志:: > /path/to/project/.debug/debug-$SESSION_ID.log
读取日志:cat /path/to/project/.debug/debug-$SESSION_ID.log
适用场景
- 状态/取值问题(null、undefined、类型错误)。
- 条件逻辑判断(走了哪个分支)。
- 异步时序问题(竞态、加载顺序)。
- 用户交互流程(弹窗、表单、点击)。
- Chrome 扩展中的内容脚本与注入脚本调试。
限制与规则
- 没有运行时证据绝不动手修复;必须始终先收集日志。
- 验证通过前绝不移除埋点;确认修复后再移除。
- 不确定就继续加日志,不要猜测。
- 若所有假设都被拒绝,应换不同子系统重新生成假设并继续迭代。
- 高频事件(mousemove、scroll)只在状态变化时记录,避免日志过多;可按 hypothesisId 过滤。
- 无法复现时需向用户询问确切步骤并检查环境。
- 日志不达通常是混合内容(HTTPS 应用访问 http://localhost:8787)、CSP connect-src 限制或 CORS 预检导致;可用开发服务器代理(Vite 示例的 /__log 同源转发)、sendBeacon 或本地放行来处理。
- 修复内容是否对外发布、支持的平台范围、收费与价格等信息暂未提供。
日志格式
每行为 NDJSON,例如:
{"ts":"2024-01-03T12:00:00.000Z","msg":"Button clicked","data":{"id":5},"hypothesisId":"H1","loc":"app.js:42"}