What's Changed
- feat(doctor): add swamp doctor audit preflight diagnostic (swamp-club#156) (#1227)
Summary
Adds swamp doctor audit [--tool <name>] — a new preflight diagnostic that verifies the AI-tool audit integration configured in the repo is healthy end-to-end. Non-zero exit on any fail, safe to gate in CI.
doctor is registered as a parent namespace so future diagnostics (doctor datastore, doctor vault, ...) plug in as siblings. Implements swamp-club#156.
Five checks
| Check | Scope | What it catches |
|---|---|---|
binary-on-path |
all 4 tools | AI tool binary missing from PATH |
swamp-binary-on-path |
all 4 tools (+ Kiro baked-path) | swamp missing from PATH, or kiro hook's baked absolute path orphaned by brew upgrade |
agent-config-loadable |
per-tool parser | config missing, malformed, or broken (e.g. Kiro tools: ["*"]) |
default-agent-set |
Kiro only | .kiro/settings/cli.json not pointing chat.defaultAgent at swamp |
recording-smoke-test |
all 4 tools | upstream normalizer drift — synthetic postToolUse payload piped through swamp audit record --from-hook must land as a row in today's audit JSONL |
The headline verification
Temporarily removing "shell" from KIRO_SHELL_TOOL_NAMES in hook_input.ts, recompiling, and running doctor against a freshly-init'd kiro repo produces:
✗ recording-smoke-test synthetic kiro payload did NOT land in today's audit JSONL
hint: The hook normalizer in src/domain/audit/hook_input.ts may have drifted from the upstream contract...
4 passed, 1 failed, 0 skipped — OVERALL: FAIL
Reverted before this commit. This is the load-bearing proof that the feature protects against future upstream drift instead of being theatre.
Name override
The issue body says "please NOT doctor". The team picked doctor anyway — the command is a namespace and will grow; the name fits that shape. Acknowledging here for reviewer context.
Scope note on the three cited Kiro bugs
Issue 156 cites three concrete bugs as motivation. Their status in this PR:
tools: ["*"]in kiro agent config →agent-config-loadableflags it with a hint; NOT fixed here.- Missing
chat.defaultAgent: "swamp"→default-agent-setflags it; NOT fixed here. - Hard-coded
tool_name === "execute_bash"in Kiro normalizer → already fixed upstream of this PR.src/domain/audit/hook_input.ts:146-150hasKIRO_SHELL_TOOL_NAMES = new Set(["execute_bash", "shell", "execute_cmd"]). This PR's diagnostic catches the class of bug, it does not fix that specific one.
Ancillary changes
- Extract
todaysAuditFilePathhelper.src/infrastructure/persistence/jsonl_audit_repository.tshad two duplicate copies of thecommands-YYYY-MM-DD.jsonlformat string; moved tosrc/domain/audit/audit_path.tsand consumed by both the writer and the doctor smoke-test reader. Single source of truth for the filename format. - Reserve
echo swamp-doctor-smoke-testas a sentinel command prefix. The smoke-test writes a real audit row with this prefix; the audit timeline filters it out of the default view. Opt in withswamp audit --include-diagnostic. - Add
parseAiToolOrThrowinsrc/cli/ai_tool_parser.ts— central validator for--toolflags, so bogus values fail with a usage error listing valid names. - Docs:
design/audit.md,design/audit-doctor.md, and a short "verify the audit integration" block in theswamp-reposkill.
Follow-ups
- UAT coverage tracked in systeminit/swamp-uat#160 (CLI) and systeminit/swamp-uat#161 (adversarial).
- swamp-club has GitHub issues disabled —
content/manual/reference/doctor.mdand a "verify the integration" section for eachcontent/manual/how-to/use-swamp-with-*.mdneed to be routed through the team's docs process. - POSIX-only PATH resolution — documented; Windows support deferred.
Test Plan
-
deno check— clean -
deno lint— clean -
deno fmt --check— clean -
deno run test— 4922 passed, 0 failed, 1 ignored -
deno run compile— produces working binary - Manual smoke-run on freshly-init'd kiro / claude / cursor / opencode repos — all pass
- Regression injection (remove
"shell"fromKIRO_SHELL_TOOL_NAMES, recompile, rerun) — smoke-test correctly FAILS on kiro - Real-repo test against
~/code/kiro-audit(existing audit history) — passes; sentinel filter confirmed withswamp audit --include-diagnostic - CWD-independence adversarial test — ran from CWD=
/with--repo-dir /tmp/..., synthetic row landed in the target repo, not the CWD
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260424.234336.0-sha.0022d1ca/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/macOS (Intel):
curl -L https://github.com/systeminit/swamp/releases/download/v20260424.234336.0-sha.0022d1ca/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/Linux (x86_64):
curl -L https://github.com/systeminit/swamp/releases/download/v20260424.234336.0-sha.0022d1ca/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/Linux (aarch64):
curl -L https://github.com/systeminit/swamp/releases/download/v20260424.234336.0-sha.0022d1ca/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/