Skip to content

feat: the daemon builds the review agent's command — no MCP unless allowlisted, the skill shipped in the prompt, JSON output - #96

Merged
fiddur merged 2 commits into
developfrom
feat/93-agent-command
Sep 7, 2026
Merged

feat: the daemon builds the review agent's command — no MCP unless allowlisted, the skill shipped in the prompt, JSON output#96
fiddur merged 2 commits into
developfrom
feat/93-agent-command

Conversation

@fiddur

@fiddur fiddur commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

prepare was the raw argv, so it could not carry the flags the review's safety rests on: the agent ran with the reviewer's MCP servers (in #14188 it called gcloud with the reviewer's credentials inside a checkout the author controls), their memory, their CLAUDE.md and their skills, and it re-ran pnpm typecheck/pnpm test in nearly every prepare although CI had already done it.

The agent block replaces it — model, effort, mcpAllow, extraArgs, maxBudgetUsd — and the daemon builds the rest in buildAgentArgv:

  • --setting-sources "", so no user settings load at all: no MCP servers, no memory, no CLAUDE.md, no installed skills.
  • mcpAllow (exact tool names) switches to --setting-sources user plus a PreToolUse hook on mcp__.* running the new hidden diffity inbox mcp-gate, which exits 2 for anything not on the list. The prompt then says which tools it may read the ticket or document with.
  • A deny list for gh pr review|comment|merge, gh api, and pnpm|npm|npx|yarn|bun|make.
  • The shipped diffity-review skill body in --append-system-prompt, so the review no longer depends on the reviewer's installed skills; the prompt points at the system prompt instead of the skill.
  • --output-format json, parsed by parseAgentOutput into the text verdictOf reads plus the run's cost, duration, turns, tokens and models. Stats ride on every PrepareResult but are not persisted — that is (2). subtype: error_max_budget_usd fails the attempt with the budget as the reason.

A loaded config that still has prepare is refused by name, with the migration in the message. The page's Settings panel gains model, effort, MCP allowlist and budget; the README's inbox section covers the block, what the built command closes off, and the migration.

Verified: npm test at the root is green (1069 tests, 135 files); inbox mcp-gate exercised end to end against the built dist (allowed tool 0, denied tool 2 with the message, built-in tool 0, garbage stdin 2); every flag the builder emits is present in the installed claude --help.

One thing to call out: the live-answer pass now also runs with --setting-sources "" and no system prompt, so the answering agent can no longer load the diffity-live skill the live prompt still names. The prompt spells out the reply command, so answers should still land, but if that skill is doing real work there we should ship its body too.

Part of #93

🤖 Generated with Claude Code

https://claude.ai/code/session_01Bwp5QefjsjMFeq6CK6cT6w

fiddur and others added 2 commits September 7, 2026 15:31
`prepare` was raw argv, so it could not carry the flags the review's safety
rests on, and the agent ran with the reviewer's MCP servers, memory and
skills. The `agent` block replaces it — model, effort, mcpAllow, extraArgs,
maxBudgetUsd — and `buildAgentArgv` builds the rest: `--setting-sources ""`
so no user settings load at all, a PreToolUse gate (`inbox mcp-gate`) when
MCP tools are allowlisted, a deny list for the gh writes and the package
managers CI has already run, `--output-format json` for the run's cost, and
the shipped diffity-review skill in the system prompt.

A loaded config that still has `prepare` is refused by name.

Part of #93

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bwp5QefjsjMFeq6CK6cT6w
… out of the deny list

Review findings on #96:

- The answer pass ran with no skills installed and nothing in their place,
  while the live prompt still told it to follow diffity-live. `skillBody`
  now takes the skill name, and the answer argv ships the live body.
- `extraArgs` sat after the variadic `--disallowedTools`, so a non-flag
  extra arg was read as another denied tool; the deny list goes last.
- A budget hit with no `agent.maxBudgetUsd` read "$null".
- The page let the browser submit a budget of 0, which the daemon refuses.
- The README claimed no Claude settings load even with `mcpAllow` set.
- `inbox mcp-gate` had no test of the command itself.

Also, from the new tests: the log's write stream had no error handler, so a
log that could not be opened would end the daemon on an unhandled event, and
`runAgent` resolved before the log had flushed.

Part of #93

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bwp5QefjsjMFeq6CK6cT6w
@fiddur
fiddur marked this pull request as ready for review September 7, 2026 13:48
@fiddur
fiddur merged commit 70f95c4 into develop Sep 7, 2026
2 checks passed
@fiddur
fiddur deleted the feat/93-agent-command branch September 7, 2026 13:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant