The MultiEdit deny rule was already dropped in the hotfix; this is task 10's follow-up half — the guard that catches the next fossil. The claude adapter's review branch spells "cannot edit files" in the vendor's own tool names, and that roster moves: a rule naming a tool the installed CLI does not have is refused at startup, so the launch dies before the agent speaks. Membership assertions could not see that happening, so the stub-binary test now asserts each mode's flag list literally (settings payload elided) — a deny name added or renamed shows up as a diff a reviewer must re-verify against the installed CLI. The run script carries the same warning where the list actually lives. The helper drops a leaked AGENT_MODEL, since --model would otherwise appear in an argv now compared whole; test_agent_model.py owns that flag. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
56 lines
2.6 KiB
Bash
Executable File
56 lines
2.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Claude adapter: run one headless job to completion.
|
|
#
|
|
# Contract (same for every adapter):
|
|
# env in: AGENT_PROMPT the full prompt
|
|
# AGENT_MODE work | act-pr | review — the launch intent
|
|
# (see core/adapters/README.md)
|
|
# AGENT_COMMANDS comma-separated neutral command prefixes the
|
|
# project lets agents run (tests/checks)
|
|
# AGENT_MODEL optional; a claude model name/alias passed
|
|
# through as --model. Absent = the CLI's own
|
|
# resolution (user settings), untouched.
|
|
# AGENT_CWD working directory (already set as cwd by the board)
|
|
# BOARD_* passthrough for the event bridge
|
|
# stdout: captured by the board as the job log; the closing report's
|
|
# marker lines (NOT READY:, PR REVIEW:, ...) are parsed from it
|
|
# exit: 0 = completed; anything else = failed
|
|
#
|
|
# Headless runs have no human to answer permission prompts: whatever the
|
|
# generated settings do not allow is denied. hook_settings.py grants each
|
|
# intent exactly what its own prompt demands (commit and test for work,
|
|
# push for act-pr, gh pr review for review) — never bypassPermissions.
|
|
#
|
|
# BOARD_CLAUDE_BIN overrides the binary (used by the test stubs).
|
|
set -euo pipefail
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
BIN="${BOARD_CLAUDE_BIN:-claude}"
|
|
MODE="${AGENT_MODE:-work}"
|
|
SETTINGS="$(python3 "$HERE/hook_settings.py" "$MODE")"
|
|
|
|
# The ${arr[@]+...} expansion keeps set -u happy on bash 3.2 when unset.
|
|
MODEL_ARGS=()
|
|
if [ -n "${AGENT_MODEL:-}" ]; then
|
|
MODEL_ARGS=(--model "$AGENT_MODEL")
|
|
fi
|
|
|
|
if [ "$MODE" = "review" ]; then
|
|
# "Cannot edit files" has to be spelled in the vendor's own tool names,
|
|
# and that roster moves under us: a deny rule naming a tool the
|
|
# installed CLI does not have is refused outright ("matches no known
|
|
# tool"), so the launch dies before the agent speaks — which is how the
|
|
# retired MultiEdit killed every review and relevance launch (task 10).
|
|
# Re-check these names against the installed CLI rather than memory
|
|
# whenever the list is touched; tests/test_adapter_permissions.py
|
|
# asserts the flag list whole so any edit surfaces in review.
|
|
exec "$BIN" -p "$AGENT_PROMPT" --settings "$SETTINGS" \
|
|
${MODEL_ARGS[@]+"${MODEL_ARGS[@]}"} \
|
|
--permission-mode default \
|
|
--disallowedTools Edit Write NotebookEdit
|
|
else
|
|
# work and act-pr both mutate the worktree; the allowlist differs.
|
|
exec "$BIN" -p "$AGENT_PROMPT" --settings "$SETTINGS" \
|
|
${MODEL_ARGS[@]+"${MODEL_ARGS[@]}"} \
|
|
--permission-mode acceptEdits
|
|
fi
|