ai-debug-harness
Self-driving Electron + Node debug harness with NDJSON logs, Playwright E2E, doctor preflight, and a YAML-frontmatter cookbook of known causes. Use when a voice-chat E2E flow misbehaves locally, audio publish silently fails, the agent worker emits warnings, or any LiveKit/Electron/Fastify error appe
Install
mkdir -p .claude/skills/ai-debug-harness && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15318" && unzip -o skill.zip -d .claude/skills/ai-debug-harness && rm skill.zipInstalls to .claude/skills/ai-debug-harness
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Self-driving Electron + Node debug harness with NDJSON logs, Playwright E2E, doctor preflight, and a YAML-frontmatter cookbook of known causes. Use when a voice-chat E2E flow misbehaves locally, audio publish silently fails, the agent worker emits warnings, or any LiveKit/Electron/Fastify error appears in the renderer console.About this skill
AI Debug Harness — Skill
This skill teaches an AI coding agent (or a human) how to drive the self-hosted debug harness for the VoiceAgent stack. The full design lives under blogs/ai-coding-agent-debug-system.
Trigger conditions
Load and follow this skill when ANY of these are true:
- The user reports the desktop app "doesn't connect" or "no audio."
- The renderer logs
BUNDLE PT=...collisions orNotAllowedError. - A test or run produces NDJSON under
.debug/logs/<runId>/and you need to reason about it. - The user asks to "reproduce", "bisect", or "diagnose" anything in the voice-chat path.
Loop invariant
You MUST follow this loop until the user task is fully resolved:
- Preflight — prefer recent successful doctor evidence when available.
Use
.debug/state/doctor-latest.jsonif it is fresh, successful, covers the requested mode, and its input hash still matches. Otherwise runpnpm debug:doctorfor full checks or letdebug:e2e/debug:reprorequest compact quick preflight. If any check hasok: false, fix the misconfiguration and re-run. Do NOT proceed until doctor passes. - Reproduce —
pnpm debug:e2e(orpnpm debug:repro -- <scenario>). This produces arunIdand a directory.debug/logs/<runId>/. - Read the run — open
.debug/runs/<runId>/report.json. Note thefailedAtstep and thematchedCookbookIds. - Match against the cookbook — for each id in
matchedCookbookIds, read the entry indocs/debug/cookbook.mdand apply itsfix_pattern. - If no match — read the FIRST line with
level: "error"in the per-source NDJSON files (preference: doctor → main → renderer → agent → api-gateway → livekit → whisper-api → fish-speech-api). Diagnose, fix, then append a new cookbook entry capturing the cause. UseappendNewEntry()fromscripts/debug/cookbook.tsor hand-author the frontmatter block. - Re-run the harness. If green, set the matching entry's
verified_in_runto the green run's id. - Stop when
harness.run.summaryshowsstatus: "passed"AND zero un-whitelisted error lines.
Reading NDJSON
Every line is { ts, level, source, runId, event, correlationId?, payload? }.
Use jq filters:
jq -c 'select(.level == "error")' .debug/logs/<runId>/*.ndjson
jq -c 'select(.event == "renderer.console.error")' .debug/logs/<runId>/renderer.ndjson
The schema reference lives at blogs/ai-coding-agent-debug-system/ndjson-schema.md.
Adding a cookbook entry
Format spec: blogs/ai-coding-agent-debug-system/cookbook-format.md.
Required frontmatter fields: id, symptom_jq, sources, likely_cause,
fix_pattern, verified_in_run (start as null, set to the run id once a
clean run reproduces+resolves the issue).
Commands
| Command | Purpose |
|---|---|
pnpm debug:doctor | Full synchronous preflight (Docker, LiveKit, GPU, ports, env) |
pnpm debug:e2e | Full Playwright Electron E2E with NDJSON capture |
pnpm debug:repro | Re-run a specific scenario by name and write report.json |
pnpm debug:bisect | git bisect run pnpm debug:e2e between two refs |
pnpm debug:clean | Prune .debug/ directories older than 7 days |
Hard rules
- NEVER edit a renderer file to call Node APIs directly. All disk I/O goes
through
window.electronAPI(contextBridge). - NEVER set
expected: trueon a cookbook entry to silence a real error. - NEVER commit anything under
.debug/(it is gitignored). - ALWAYS run
pnpm typecheck && pnpm testbefore declaring a fix done. - Keep user-facing debug summaries compact: report the run id, failed step, first failing source, unmatched error count, and cookbook ids instead of pasting full NDJSON logs unless the user asks.