fix(audit): repair kiro-cli audit integration#1215
Conversation
Three independent bugs prevented `swamp init --tool kiro` from recording
any kiro-cli shell commands to the audit log:
1. Normalizer only accepted `tool_name: "execute_bash"`, but kiro-cli
emits `"shell"` at runtime. Every real event was dropped. Accept
`execute_bash`, `shell`, and `execute_cmd` — the aliases the
kiro-cli agent schema recognizes.
2. `.kiro/agents/swamp.json` shipped with `"tools": ["*"]`, which fails
kiro-cli schema parsing and causes silent fallback to the default
agent — so the swamp postToolUse hook never ran. Replace with an
explicit list: read, write, shell, grep, glob, thinking, todo.
3. `swamp init --tool kiro` did not write the workspace-scoped
`.kiro/settings/cli.json`. Without it, plain `kiro-cli chat` (no
--agent flag) loads the built-in agent instead of swamp. Now
created with `{ "chat.defaultAgent": "swamp" }`, merging into any
existing file and leaving a user's non-swamp preference untouched
(with a warning).
There was a problem hiding this comment.
Code Review
Clean, well-scoped fix for three independent bugs preventing swamp init --tool kiro from recording shell commands to the audit log. All three bugs are real, the root causes are well-understood, and the fixes are minimal and correct.
Blocking Issues
None.
Suggestions
-
Malformed
cli.jsonhandling (repo_service.ts:1499):ensureKiroCliDefaultAgentcatchesDeno.errors.NotFoundbut will throw a rawSyntaxErrorif the file exists with invalid JSON. A graceful fallback (log a warning, overwrite) might be friendlier, though this is a narrow edge case. -
Kiro IDE camelCase test for
"shell"alias (hook_input_test.ts): The new snake_case tests cover"shell"and"execute_cmd", but the Kiro IDE camelCase tests only exercise"execute_bash"as thetoolName. Adding one camelCase test withtoolName: "shell"would confirm the alias works through the IDE path too. The code handles it correctly — this is just test completeness.
Both are minor — neither blocks merge. The PR has good test coverage for all three bugs, correct error handling for the non-swamp-defaultAgent case, proper use of atomicWriteTextFile, and appropriate comments explaining why (the silent "*" failure, the runtime alias mismatch). DDD-wise, ensureKiroCliDefaultAgent fits naturally as a private method on RepoService alongside the existing kiro methods, and KIRO_SHELL_TOOL_NAMES is a clean domain constant.
There was a problem hiding this comment.
Adversarial Review
Critical / High
None.
Medium
-
src/domain/repo/repo_service.ts:1498-1499— malformedcli.jsonproduces an unhelpful error.
If.kiro/settings/cli.jsonexists but contains empty or invalid JSON (e.g. a 0-byte file left by an interrupted write, or a hand-edited file with a trailing comma),JSON.parse(content)throwsSyntaxError. The catch block only handlesDeno.errors.NotFoundand re-throws everything else, so the user gets an opaque parse error from the guts ofinit/upgradeinstead of a message like "cli.json is corrupt, overwriting." This is a realistic scenario for files users might hand-edit.Breaking example:
echo "" > .kiro/settings/cli.json && swamp init --tool kiro .
Suggested fix: CatchSyntaxErroralongsideNotFound, log a warning that the existing file is malformed, and fall through to re-create it (treating it the same as not-found).
Low
-
src/domain/audit/hook_input.ts:143-144— comment mentionsexecuteBash(camelCase) as an alias but it's absent fromKIRO_SHELL_TOOL_NAMES.
The docstring says configs accept"executeBash" / "execute_bash" / "execute_cmd", but the Set only contains the latter two plus"shell". This is correct —executeBashis a config-level alias that doesn't appear in hook payloads — but a future contributor reading the comment might add it to the Set unnecessarily, or worse, might removeshellthinking the comment is authoritative. Consider rephrasing the comment to make the distinction between config aliases and runtime names explicit. -
src/domain/repo/repo_service.ts:1497-1502— non-object JSON incli.jsonsilently corrupts settings.
Ifcli.jsoncontains valid JSON that isn't an object (e.g."hello",42,[1,2]), the spread...existingSettingsproduces numeric keys from array indices or string characters. The write succeeds but the result is garbage. Extremely unlikely in practice. -
src/domain/repo/repo_service.ts:1497-1531— TOCTOU between read and atomic write.
The read-modify-write cycle oncli.jsonis not itself atomic. A concurrentswamp init(or user edit) between thereadTextFileandatomicWriteTextFilecould lose one writer's changes. Theoretical for a local dev config file that's written once during init.
Verdict
PASS — The three bug fixes are correct, well-tested, and well-scoped. The normalizer fix properly expands the tool name set, the agent config fix avoids kiro-cli's silent fallback, and the cli.json creation addresses a genuine missing integration step. The medium finding (malformed JSON) is worth hardening but doesn't block merge.
Summary
Three independent bugs prevented
swamp init --tool kirofrom ever recording a kiro-cli shell command to the audit log. End-to-end verified against a throwaway repo withkiro-cli chat→swamp audit.Bug 1 — normalizer dropped every real event
src/domain/audit/hook_input.tshard-codedtool_name !== "execute_bash", but kiro-cli emitstool_name: "shell"at runtime (it's Amazon Q Developer CLI under the hood;execute_bash/execute_cmd/shellare all aliases its agent schema accepts, andshellis the canonical runtime name). Accept all three.Bug 2 — agent config used invalid
tools: ["*"]The
.kiro/agents/swamp.jsontemplate used"tools": ["*"], which fails kiro-cli schema parsing and causes silent fallback to the built-inkiro_defaultagent — so the swamp postToolUse audit hook never fires. Replaced with an explicit list:["read", "write", "shell", "grep", "glob", "thinking", "todo"].Bug 3 — no workspace default agent
swamp init --tool kirocreated the hook + agent but never wrote.kiro/settings/cli.json. Without it, plainkiro-cli chat(no--agentflag) loads the default agent and skips swamp entirely. Now created with{ "chat.defaultAgent": "swamp" }. If the file already exists, merge the key while preserving unrelated settings; if a non-swampchat.defaultAgentis already set, leave it alone and log a warning.Test Plan
shellandexecute_cmdcases tohook_input_test.ts; existingexecute_bash/ Kiro-IDE camelCase cases still passrepo_service_test.tscases covering all-three-files output, cli.json merge with unrelated keys preserved, and non-swamp defaultAgent preserveddeno check/deno lint/deno fmt --checkcleandeno run test: 4709 pass (one unrelated parallel-env-var flake insrc/libswamp/auth/logout_test.tsthat passes in isolation; not touched here)deno run compile+ manualswamp init --tool kiro ./tmp— confirmed.kiro/settings/cli.jsoncontains{"chat.defaultAgent":"swamp"}and.kiro/agents/swamp.jsonhas the explicit tools list