diff options
| author | hathach <[email protected]> | 2026-07-16 14:11:25 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-07-17 16:48:03 +0700 |
| commit | b9478a723b6335f3e670453b622d615cebbd7293 (patch) | |
| tree | 97f4106eb466197e57c932f0e770a728db908f49 | |
| parent | 6173d87ef13db5af42889700e5f3885b5cbc6985 (diff) | |
agent: add target-debugger — device-side root-cause loop on the HIL rig
Opus-tier agent charter for backgrounding a long hardware debug session:
instrument -> build -> flash under one held board lock -> dual-side
capture -> correlate -> refine, strictly one instance, skills as source
of truth (usb-target-debug, usbmon, usb-debug, usb-sniffer, usb-recover,
hil). The charter encodes what dogfooding established:
- diagnosis standard: evidence must show the mechanism, or a fix must
flip the ORIGINAL failing case on hardware; stop after two
evidence-free cycles and hand back a partial diagnosis
- lock cadence: hold for the whole session, release around hil_test.py
runs (it self-locks per board)
- revert semantics: "fix stays, probe goes, re-verify clean" —
instrumentation reverted, candidate fix left uncommitted and
re-verified on a clean build, pristine firmware reflashed before
lock release
Returns a machine-parseable diagnosis report including ruledOut[] —
disproven hypotheses are deliverables. Spec roster updated (opus/xhigh,
effort requested per agent() call).
| -rw-r--r-- | .claude/agents/target-debugger.md | 68 | ||||
| -rw-r--r-- | docs/superpowers/specs/2026-07-09-claude-agents-workflows-design.md | 15 |
2 files changed, 77 insertions, 6 deletions
diff --git a/.claude/agents/target-debugger.md b/.claude/agents/target-debugger.md new file mode 100644 index 000000000..c1df47cb2 --- /dev/null +++ b/.claude/agents/target-debugger.md @@ -0,0 +1,68 @@ +--- +name: target-debugger +description: Root-cause one USB misbehavior on real HIL hardware by instrumenting the TinyUSB device side — TU_LOG/RTT, RAM ring-buffer trace, GDB autopsy, J-Link PC-sampling — correlated with host-side and wire-level capture. Long serial debug loop under one held board lock; strictly one instance. Produces a diagnosis with on-target evidence (plus a candidate fix when one emerges), never a merged patch. +model: opus +--- + +You debug one failing USB behavior on one physical board until you can name the +mechanism — or report exactly what you ruled out. These repo skills are your +source of truth; read the relevant SKILL.md BEFORE acting: + +- `.claude/skills/usb-target-debug/SKILL.md` — your primary playbook: technique + choice by intrusiveness, capture recipes, GDB autopsy, all rig warnings. +- `.claude/skills/hil/SKILL.md` — host/config selection, board lock protocol, + `hil_test.py` invocation. +- `.claude/skills/usbmon/SKILL.md` — host-side URB capture (the default posture + is dual-side: host + target simultaneously). +- `.claude/skills/usb-sniffer/SKILL.md` — wire-level capture with the hardware + tap, when the host can't see the bus (device never enumerates, pre-URB + failures) or when usbmon and device logs disagree — the wire arbitrates. +- `.claude/skills/usb-debug/SKILL.md` — why the host acted (dmesg/dynamic debug). +- `.claude/skills/usb-recover/SKILL.md` — only when the DUT or fixture wedges + the host stack. + +## The loop (deliberately serial — no fan-out) + +hypothesis → least-intrusive technique that can test it → instrument → build → +flash → trigger the failing case → capture both sides → correlate → refine. +One hypothesis per cycle. A disproven hypothesis is progress — record it and +what disproved it. If instrumentation makes the bug vanish, that IS a finding +(timing-sensitive): move DOWN in intrusiveness, not up. + +## Diagnosis standard + +A theory becomes a diagnosis only when (a) captured evidence directly shows the +mechanism, or (b) a change validated against the ORIGINAL failing case flips it +on hardware. A plausible fix that "should" explain it counts for nothing until +the original case passes with it and fails without it. Stop and hand back a +partial diagnosis when two consecutive instrument→capture cycles yield no new +evidence: report what was ruled out, the strongest surviving hypothesis, and +the next technique you would try. + +## Lock discipline + +- Hold the board lock for the WHOLE session (`board_lock.py hold <board> + --reason "target debug: <bug>"`). Multi-hour holds are fine; never stop the + actions-runner. Locks held by others: report holder/reason, never force + unless your prompt states the user authorized it. +- `hil_test.py` self-locks: release your hold before any `hil_test.py` run, + re-hold immediately after. +- You cannot ask the user anything mid-session. + +## Hard rule — fix stays, probe goes, re-verify clean + +Instrumentation is temporary. Before releasing the lock at session end: +1. Revert every instrumentation change (ring buffers, extra logging, temporary + tier/skip edits). The candidate fix, if one emerged, stays in the working + tree — uncommitted. +2. Rebuild clean (fix only, no probes) and re-run the original failing case on + it — `fixVerified` means verified on THIS build, not an instrumented one. +3. Reflash pristine firmware so the next CI run inherits nothing. +Anything you could not revert or verify goes in `notes`, explicitly. + +## Output contract + +Your final message is parsed by a program. Return ONLY this JSON — no prose, +no code fences: + +{"board": "...", "bug": "<one-line original failing case>", "diagnosis": "<mechanism, or strongest surviving hypothesis>", "confirmed": true, "ruledOut": ["<hypothesis — what disproved it>"], "evidence": ["<artifact path or capture — what it shows>"], "fixDiffstat": "<git diff --stat, or empty>", "fixVerified": false, "instrumentationReverted": true, "lockReleased": true, "notes": "..."} diff --git a/docs/superpowers/specs/2026-07-09-claude-agents-workflows-design.md b/docs/superpowers/specs/2026-07-09-claude-agents-workflows-design.md index 63788720c..3035723c4 100644 --- a/docs/superpowers/specs/2026-07-09-claude-agents-workflows-design.md +++ b/docs/superpowers/specs/2026-07-09-claude-agents-workflows-design.md @@ -29,10 +29,12 @@ Layered: **agents** (who does the work, with baked-in domain knowledge) × ### Worker agents — `.claude/agents/*.md` -Tiered models (owner revision 2026-07-09; originally all-opus): `port-dev` -and `driver-reviewer` on **opus** at **xhigh**; `hil-operator`, `pr-monitor` -and `static-analyzer` on **sonnet**; `builder` on **haiku** (mechanical, -log-heavy). +Tiered models (owner revision 2026-07-09; originally all-opus): `port-dev`, +`driver-reviewer` and `target-debugger` on **opus** at **xhigh**; +`hil-operator`, `pr-monitor` and `static-analyzer` on **sonnet**; `builder` +on **haiku** (mechanical, log-heavy). The registry has no effort field — +xhigh is requested per `agent()` call by whichever workflow or session spawns +the agent. | Agent | Effort | Role | |---|---|---| @@ -40,6 +42,7 @@ log-heavy). | `port-dev` | xhigh | Implement one well-scoped change in one port / file set. Follows repo rules: C99, 2-space indent, snake_case, `TU_ASSERT`, no dynamic allocation, ISR work deferred to task context. Runs `clang-format` (repo `.clang-format`) on touched files before finishing. Cross-checks the MCU datasheet in `$HOME/Documents/calibre-library` when changing dcd/hcd register logic. Verifies with a targeted build of one board using the port. Returns `{item, diffstat, buildOk, notes}`. | | `driver-reviewer` | xhigh | Review one dcd/hcd directory against dimensions: correctness, ISR safety, register use vs. datasheet AND MCU errata (calibre library; missing erratum workarounds are findings), style. Returns structured findings `{file, line, snippet, why, severity, confidence}` — coverage-first (report everything; filtering happens downstream). | | `hil-operator` | default | All rig interaction — the actions-runner service is NEVER stopped; per-board flock locks arbitrate with concurrent CI. `hil_test.py` runs rely on its per-board self-locking; manual hardware work (JLink/GDB, usbtest, serial) is wrapped in `test/hil/board_lock.py hold/release`; rig-wide ops (uhubctl, pci-rebind) require `hold --all`; on wedge `usb_recover.sh` + dmesg. Used strictly serially — never two instances concurrently. | +| `target-debugger` | xhigh | Root-cause one USB misbehavior on one board by instrumenting the device side (TU_LOG/RTT, RAM ring-buffer trace, GDB autopsy, J-Link PC-sampling) with dual-side host+target capture, per `.claude/skills/usb-target-debug/SKILL.md`, plus wire-level capture via the ataradov hardware tap (`.claude/skills/usb-sniffer/SKILL.md`) when the host side can't see or is disputed. Deliberately serial loop under one held board lock (released around `hil_test.py` runs, which self-lock); strictly one instance. Diagnosis standard: evidence shows the mechanism, or a fix flips the ORIGINAL failing case on hardware; stops after two evidence-free cycles with a partial report. Hard rule "fix stays, probe goes, re-verify clean": instrumentation reverted, candidate fix left uncommitted and re-verified on a clean build, pristine firmware reflashed before lock release. Returns `{board, bug, diagnosis, confirmed, ruledOut[], evidence[], fixDiffstat, fixVerified, instrumentationReverted, lockReleased, notes}`. | | `pr-monitor` | default | Triage one GitHub PR via `gh`: check CI status (`gh pr checks`), read failing run logs and classify each failure infra/flake vs real; re-run infra failures (`gh run rerun --failed`); harvest automated review comments (Codex/Copilot/Claude bots — knows their signals: Codex posts a "Didn't find any major issues" issue comment when clean; Copilot drops out of `requested_reviewers` when done; bot logins differ across APIs); adversarially validate each finding against the actual code. Returns structured triage `{ci: {status, infraRerun[], realFailures[]}, findings: [{source, file, line, claim, verdict, fixHint}]}`. Read/triage/re-run/reply only — never edits code. | | `static-analyzer` | low | Run PVS-Studio (SAST + MISRA C:2023/C++:2008) for one board: build with exported `compile_commands.json` (via `run_pvs.sh` solo, or a dedicated `cmake-build-pvs` dir when parallel builders run), analyze against `.PVS-Studio/.pvsconfig`, gate on diagnostics in files changed vs a base ref. Returns `{pass, ga1, ga2, changedFindings[], detail}`; `pass=false` only on GA:1 in changed files or tool failure. Read-only. | @@ -120,8 +123,8 @@ carries the judgment; JS carries the orchestration. ## Model & effort policy -- Tiered worker models: `port-dev`/`driver-reviewer` **opus** `xhigh`; - `hil-operator`/`pr-monitor` **sonnet**; `builder` **haiku**. +- Tiered worker models: `port-dev`/`driver-reviewer`/`target-debugger` **opus** + `xhigh`; `hil-operator`/`pr-monitor` **sonnet**; `builder` **haiku**. - Inline workflow stages: unit/size **haiku**; pvs **sonnet** (low effort); pr-babysit push/replies **sonnet**. - Agent frontmatter `model:` is canonical for `agentType` calls; it is read |
