关于 melech-debug-mode
为编码 Agent 提供基于证据的本地 UI 调试流程,要求先在浏览器复现,再采集探针数据并据此排查。适合需要验证端到端行为且避免把测试脚本误当浏览器测试的工作。
主要功能
- 01优先通过本地 UI 复现问题
- 02用临时采集器收集探针事件
- 03验证运行时已加载探针
- 04按证据决定后续操作
- 05结束时移除探针并清理会话
适用场景
- 01排查本地网页中的交互故障
- 02验证代码修改后的浏览器行为
- 03区分端到端证据与补充诊断
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ adird/ agent-shell-hamelech --skill melech-debug-mode安装后在 Claude Code 中输入/melech-debug-mode确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdassets/collector.pyscripts/debug_session.pydm.shinstall-dm.shtests/test_debug_session.py详细介绍
调试模式
按照以下协议执行用户请求的工作流:
choose browser driver → attach if autopilot → define one complete attempt
→ start collector → add probes → prove probes loaded → run E2E → read evidence
→ act on evidence → rerun E2E if code changed → clean up
端到端(E2E)边界是浏览器中的本地 UI。单元、集成、AI 或测试框架运行都不算 E2E,即使运行中使用了真实模型、工具、沙箱、文件系统或后端也不例外。直接调用、脚本、合成请求或独立端点也不算 E2E。
在首次尝试浏览器操作之前,不要创建或运行测试框架。测试和直接调用仅可在浏览器复现之后作为补充诊断。如果无法通过本地 UI 执行所请求的行为,请说明此技能不提供相应的 E2E 流程;不要把测试框架重新标称为 E2E。
1. 选择驱动方式
- 默认对所有本地 UI 工作流使用 autopilot。
- 用户明确表示由自己操作、掌控操作权或使用
proceed→ manual。 - 用户拒绝浏览器控制、目标标签页不明确或不安全、目标似乎是生产环境,或重试后仍无法附加 → manual。
对于普通的本地 UI 操作,不要询问用户选择哪种方式。
使用 autopilot 时,先阅读已安装的 melech-live-browser/SKILL.md,显示其 Chrome 同意提示,并在进行任何诊断捷径之前开始附加流程。如果该文件缺失,请提供:
npx skills add https://github.com/AdirD/agent-shell-hamelech --skill melech-live-browser
询问用户是要安装该技能还是切换到手动模式。绝不要改用其他浏览器或配置文件。
autopilot 始终先要求用户在 chrome://inspect/#remote-debugging 中启用远程调试,并在 Chrome 提示时点击 Allow。如果附加失败,再次提出该请求并重试一次。只有该次重试失败后,才可回退到 manual。
manual 仍然使用正在运行的本地 UI 和相同的探查。向用户提供重置方式、操作步骤和用于判断结果的标准,要求他们完成一次复现后准确回复 proceed,然后停止并等待。只有收到该回复后才读取证据。
2. 定义一次尝试
说明:
- 重置方式和起始状态
- 确切的操作步骤
- 用于判断用户所请求结果的可观察现象
- 最多五项用于区分这些结果的探查
3. 启动采集器
定位已安装的技能目录,并确认 python3 和 portless 存在。如果缺少 Portless,请停止并请求:
npm install -g portless
首次使用需要进行设置时,运行 portless doctor,然后运行:
source <skill-dir>/scripts/dm.sh
dm start
dm 是为 python3 <skill-dir>/scripts/debug_session.py 加载的 shell 函数。如果后续步骤提示 dm 未定义,请重新加载 dm.sh,或直接调用该路径。
| 命令 | 用途 |
|---|---|
dm start | 启动一个临时采集器 |
dm status <session-dir> | 查看该会话的元数据和进程运行状态 |
dm logs <session-dir> [--run ID] [--after-seq N] [--tail N] | 读取精简 JSONL,每行一个完整事件 |
dm logs <session-dir> --pretty | 读取便于人类阅读的多行事件 |
dm stop <session-dir> | 拆除该会话 |
dm doctor --once | 获取所有活动会话的 JSON 快照 |
始终为 doctor 添加 --once:不带参数运行 dm doctor(或直接运行 dm)会在用户自己的终端中打开 curses TUI,并导致非交互式 shell 挂起或崩溃。
dm start 会输出后续所有步骤需要的信息:session_id、session_dir、log_endpoint、health_url、events_file 和 backend_host/backend_port。保存这些信息,然后在修改应用代码之前确认采集器能够响应:
curl -s "<health_url>" # {"ok":true,"entries":0}
health_url 和 log_endpoint 通过 Portless 路由。如果执行探查的运行环境无法访问该路由,同一采集器也会在 http://<backend_host>:<backend_port> 响应;仅替换源地址,并保留 log_endpoint 中的 /log/<token> 路径。
让采集器保持在本地;绝不要启用 LAN 模式、隧道、Tailscale、Funnel、ngrok 或其他远程暴露方式。
4. 添加探针
根据决定结果推导探针位置:应该或不应该运行的分支、转换前的值、边界输入和输出,以及错误路径。选择负责回答问题的那一层进行埋点——对于浏览器工作流,渲染和交互应检查页面或组件状态;持久化、验证和集成则应检查服务端处理程序。
对于每个已运行的目标,记录符合其生命周期的可用新鲜度基线:进程启动时间、构建标识或构建/重载日志游标。编辑后运行的一次性源码加载命令无需事先记录基线。
将每条观测作为一个小型 JSON 对象 POST 到 log_endpoint,并使用原样返回的地址(其中已嵌入会话令牌):
{
"run": "run-1",
"probe": "checkout-before-submit",
"hypothesis": "save commits exactly once",
"data": { "isDisabled": true, "itemCount": 2 }
}
采用即发即弃方式,确保采集器故障不会改变产品行为:
// DEBUG_MODE:<session-id>:checkout-before-submit
void fetch("<log-endpoint>", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
run: "run-1",
probe: "checkout-before-submit",
hypothesis: "save commits exactly once",
data: { isDisabled, itemCount: items.length },
}),
}).catch(() => {});
根据目标语言调整写法,同时保留载荷结构、标记注释、精简的字段选择和对失败的吞噬处理。发送布尔值、计数、枚举值、在开发环境中已安全处理的 ID,以及简短摘要;绝不要发送凭据、令牌、Cookie、授权标头、个人数据、完整请求体或无关状态。
即发即弃探针无法获知采集器是否拒收,因此在尝试前,先用真实的载荷结构验证一次事件是否送达:
curl -s -X POST "<log_endpoint>" -H 'content-type: application/json' \
-d '{"run":"run-0","probe":"delivery-check","data":{"ok":true}}'
# {"accepted":true,"seq":1}
任何其他响应都表示采集器拒收了事件,而不是代码路径未运行:缺少 content-type、请求体不是对象或格式错误、载荷超过 64 KB、URL 或令牌错误,或出现 sensitive_field_rejected。最后一种情况会丢弃键名(无论嵌套深度如何,忽略大小写和连字符)与凭据名称(如 token、secret、password、cookie、authorization、api_key 或 access_token)完全匹配的事件。请将字段改为描述性名称(例如 hasSessionToken),而不是删掉这条观测。
为每项临时编辑标记 DEBUG_MODE:<session-id>:<probe-id>,并跟踪所有改动过的文件。只运行证明埋点有效所需的最简编译、类型或语法检查;该检查产生的探针事件不属于 E2E 证据。不要创建测试文件或测试框架来加载探针。应在为浏览器工作流提供服务的同一组开发服务中加载探针。
在 E2E 测试前,证明每个长时间运行或预构建的目标都已加载探针。要求提供在探针编辑后产生且与相应源码或构建产物相关的证据:针对已编辑目标的新构建/HMR/重启标记、编辑后启动的源码加载进程,或特定于探针的加载事件。对于预构建运行时,需同时确认构建产物是在编辑后构建的,且进程已加载该产物。终端修改时间变化或旧的重启文本都不能证明新鲜度。Jest、Vitest、AI 测试框架或其他测试进程都不能证明为浏览器提供服务的运行时已加载探针。
如果运行时已过期,只有在现有跟踪记录、持久化输入、审计记录或其他权威边界记录能捕获相同的决定性事实时,才可用它替代探针。请指明确切记录;应用文案和推断出的 UI 行为均不符合要求。
否则,在安全的前提下,只重启目标服务。如果该进程由用户管理,或重启可能中断正在进行的工作,请暂停并询问:
<service>仍在运行探针编辑前的代码。请重新构建或重启,然后告诉我,我会继续。
Shell 送达检查成功只能证明采集器正常工作。
5. 运行浏览器尝试
初始使用 run-1,每次重试、补充诊断和变更后验证都递增运行 ID。每次完整尝试后,读取:
dm logs <session-dir> --run <run-id>
每一行都是一个信封:你的对象位于 payload 下,另有 seq 和 received_at。默认输出为 JSONL:每行都是一个完整的 JSON 对象,可独立解析。使用 --after-seq 只查看最新一次尝试新增的内容;运行产生大量输出时使用 --tail;仅在人工阅读时使用 --pretty。
自动驾驶
使用 melech-live-browser 选择现有应用标签页、获取快照并恰好驱动一次完整尝试,然后读取该次运行。只有在所述结果需要时,才通过实时浏览器关联控制台或网络证据,绝不能仅凭快照下结论。不要请求 proceed。如果附加或选择标签页失败,则切换到手动模式。
手动模式
告知用户当前处于手动模式,提供已定义的重置步骤、操作和判定结果,并让用户在尝试一次后准确回复 proceed。然后停止。只有收到 proceed 后才读取该次运行。
6. 根据证据采取行动
引用支持结果的事件顺序和值。不要根据相关性推断原因。
- 使用证据执行用户请求的下一步操作,不要扩大范围。
- 证据不完整 → 调整最少的探测项,并通过同一个 E2E 驱动器使用新的运行 ID 重复测试。
- 证据计划中仍有探测项,但意外没有任何事件 → 首先确认探测项编辑后,已重新构建或重启经过插桩的运行时。然后确认采集器正在提供服务:使用
health_urlcurl 或dm doctor --once(dm status仅报告进程是否存活),并重复传递检查。采集器已允许跨源 POST,因此对于页面侧探测,应怀疑应用的 CSPconnect-src或路由无法访问;修复后重复 E2E。 - 代码已更改 → 保留相关探测项,并在清理前重复相同的 E2E 工作流。
补充诊断
仅在首次浏览器 E2E 尝试后,才可使用聚焦测试、直接调用、临时诊断脚本、端点请求或合成请求来隔离更窄的问题。将这些标记为补充诊断,并使用单独的运行 ID;它们绝不能满足 E2E 门槛或变更后的验证要求。
7. 清理
在 E2E 结果明确且未更改代码、变更后的 E2E 验证成功,或中止后:
- 移除所有
DEBUG_MODE:<session-id>:探测项和仅用于调试的更改。 - 在已修改的文件中搜索
DEBUG_MODE:并检查差异。 - 停止浏览器操作,但不要关闭用户拥有的标签页。
- 运行
dm stop <session-dir>并确认removed: true。
如果拆除失败,报告会话目录和 PID;绝不要广泛终止进程或执行广泛的 Portless 清理。如果操作中断,使用 dm status、dm logs 或 dm doctor --once 找回保存的 session_dir,然后完成清理或中止清理流程。