diff --git a/skills/software-development/debugging/SKILL.md b/skills/software-development/debugging/SKILL.md new file mode 100644 index 0000000..9728fdc --- /dev/null +++ b/skills/software-development/debugging/SKILL.md @@ -0,0 +1,182 @@ +--- +name: debugging +description: "Debugging methodology and tools: systematic root-cause analysis, Python pdb/debugpy, Node.js inspect/CDP, Hermes TUI slash commands." +version: 2.0.0 +author: Hermes Agent +license: MIT +platforms: [linux, macos, windows] +metadata: + hermes: + tags: [debugging, troubleshooting, root-cause, pdb, debugpy, node-inspect, cdp, hermes-tui] + related_skills: [test-driven-development, writing-plans] +--- + +# Debugging — Methodology & Tools + +Four-layer debugging: systematic root-cause methodology first, then language-specific tooling for Python (pdb/debugpy), Node.js (inspect/CDP), and Hermes TUI slash commands. + +## Section 1: Systematic Debugging (Methodology) + +**Core principle:** ALWAYS find root cause before attempting fixes. Symptom fixes are failure. + +### The Four Phases + +**Phase 1: Root Cause Investigation** +1. Read error messages carefully — they often contain the exact solution +2. Reproduce consistently — can you trigger it reliably? +3. Check recent changes — `git log --oneline -10`, `git diff` +4. Gather evidence in multi-component systems — log at each boundary +5. Trace data flow — where does the bad value originate? + +**Phase 2: Pattern Analysis** +1. Find working examples in the same codebase +2. Compare against reference implementations +3. Identify every difference between working and broken +4. Map dependencies and assumptions + +**Phase 3: Hypothesis and Testing** +1. Form a SINGLE hypothesis: "I think X is the root cause because Y" +2. Make the SMALLEST possible change to test it +3. Verify BEFORE continuing — did it work? + +**Phase 4: Implementation** +1. Create failing test case first (RED) +2. Implement single fix addressing root cause (GREEN) +3. Verify fix with full test suite +4. If fix doesn't work: Rule of Three — after 3 failed fixes, question the architecture + +### Iron Law +``` +NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST +``` + +### Red Flags — Stop and Follow Process +- "Quick fix for now, investigate later" +- "Just try changing X and see if it works" +- "One more fix attempt" (after 2+ failures) +- Each fix reveals a new problem in a different place + +See `references/systematic-debugging.md` for the full methodology with rationalizations table and Hermes tool integration patterns. + +--- + +## Section 2: Python Debugging (pdb + debugpy) + +### Quick Reference: When to Use What + +| Tool | When | +|---|---| +| `breakpoint()` + pdb | Local, interactive, simplest | +| `python -m pdb` | Launch existing script under pdb, no source edits | +| `debugpy` | Remote/headless/attach to running process (DAP protocol) | +| `remote-pdb` | Cleanest agent-friendly remote pdb over TCP | + +### pdb Inside the REPL + +| Command | Action | +|---|---| +| `n` | next line (step over) | +| `s` | step into | +| `c` | continue | +| `b file:line` | set breakpoint | +| `p expr` / `pp expr` | print / pretty-print | +| `w` | where (stack trace) | +| `!stmt` | execute arbitrary Python | +| `interact` | full Python REPL in current scope | + +### Debugging pytest +```bash +pytest tests/test_foo.py::test_bar --pdb -p no:xdist # xdist breaks pdb +``` + +### Remote Debug with debugpy +```python +import debugpy +debugpy.listen(("127.0.0.1", 5678)) +debugpy.wait_for_client() # blocks until IDE attaches +``` + +### Remote Debug with remote-pdb (simpler) +```python +from remote_pdb import set_trace +set_trace(host="127.0.0.1", port=4444) # then: nc 127.0.0.1 4444 +``` + +### Key Pitfalls +- pdb under pytest-xdist silently hangs — always use `-p no:xdist` +- `breakpoint()` in CI/non-TTY hangs — never commit it +- `PYTHONBREAKPOINT=0` disables all breakpoint() calls +- debugpy.listen only blocks if wait_for_client() is also called +- ptrace_scope=1 (Ubuntu default) may block attach-to-PID + +See `references/python-debugpy.md` for full recipes (post-mortem, Hermes subprocess debugging, one-shot patterns). + +--- + +## Section 3: Node.js Debugging (inspect + CDP) + +### Quick Reference + +| Tool | When | +|---|---| +| `node inspect` | Built-in CLI REPL, quick poking | +| `ndb` / CDP via `chrome-remote-interface` | Scriptable automation, many breakpoints | + +### Launch and Attach +```bash +node --inspect-brk script.js # pause on first line +node inspect -p # attach to running process +kill -SIGUSR1 # enable inspector on existing process +``` + +### The `debug>` REPL +- `sb('file.js', 42)` — set breakpoint +- `cont` / `next` / `step` / `out` — navigate +- `repl` — drop into JS REPL in paused scope +- `bt` — backtrace +- `exec expr` — evaluate once + +### Debugging Hermes ui-tui +```bash +# Build first, then debug the built output +cd ui-tui && npm run build +node --inspect-brk dist/entry.js +# In another terminal: node inspect -p +``` + +### Key Pitfalls +- `node inspect` CLI does NOT follow TypeScript sourcemaps — break in built `dist/*.js` +- `--inspect` vs `--inspect-brk`: former doesn't pause, your breakpoints may race +- Port 9229 is default; use `--inspect=0` for random port when multiple processes +- `--inspect` on parent does NOT inspect children — use `NODE_OPTIONS='--inspect-brk'` + +See `references/node-inspect-debugger.md` for CDP scripting, heap snapshots, CPU profiles, and Vitest debugging. + +--- + +## Section 4: Debugging Hermes TUI Slash Commands + +Hermes slash commands span three layers: +``` +Python backend (hermes_cli/commands.py) ← COMMAND_REGISTRY + │ +TUI gateway (tui_gateway/server.py) ← slash.exec / command.dispatch + │ +TUI frontend (ui-tui/src/app/slash/) ← local handlers + fallthrough +``` + +### Common Issues +1. **Command in TUI but not autocomplete** → missing from `COMMAND_REGISTRY` in `commands.py` +2. **Command in autocomplete but doesn't work** → check both gateway handler and TUI local handler +3. **Behavior differs CLI vs TUI** → different implementations exist; check both +4. **Config persists but UI doesn't update** → need `patchUiState(...)` alongside `config.set` +5. **Gateway silently ignores** → command not in `GATEWAY_KNOWN_COMMANDS` or is `cli_only` + +### Investigation Steps +```bash +search_files --pattern "/commandname" --file_glob "*.ts" --path ui-tui/ +search_files --pattern "commandname" --path hermes_cli/commands.py +search_files --pattern "complete.slash|slash.exec" --path tui_gateway/ +``` + +See `references/debugging-hermes-tui-commands.md` for the full investigation guide, fix patterns, and verification checklist.