Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions hooks/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" session-start",
"command": "AUTODEV_HOOK=session-start; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"async": false
}
]
Expand All @@ -18,7 +18,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" pre-tool-scope-guard",
"command": "AUTODEV_HOOK=pre-tool-scope-guard; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"timeout": 15
}
]
Expand All @@ -28,7 +28,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" pretool-pr-review-reminder",
"command": "AUTODEV_HOOK=pretool-pr-review-reminder; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"timeout": 10
}
]
Expand All @@ -38,7 +38,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" pretool-demo-fidelity-guard",
"command": "AUTODEV_HOOK=pretool-demo-fidelity-guard; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"timeout": 10
}
]
Expand All @@ -50,7 +50,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" record-activity",
"command": "AUTODEV_HOOK=record-activity; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"timeout": 10
}
]
Expand All @@ -60,7 +60,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" posttool-pr-created",
"command": "AUTODEV_HOOK=posttool-pr-created; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"timeout": 10
}
]
Expand All @@ -72,7 +72,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" prompt-strict-interpretation",
"command": "AUTODEV_HOOK=prompt-strict-interpretation; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"timeout": 10
}
]
Expand All @@ -82,7 +82,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" portfolio-inventory-reminder",
"command": "AUTODEV_HOOK=portfolio-inventory-reminder; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"timeout": 10
}
]
Expand All @@ -94,7 +94,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" completion-claim-guard",
"command": "AUTODEV_HOOK=completion-claim-guard; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"timeout": 30
}
]
Expand All @@ -106,7 +106,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" subagent-scope-guard",
"command": "AUTODEV_HOOK=subagent-scope-guard; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"timeout": 15
}
]
Expand All @@ -118,7 +118,7 @@
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" pre-compact-snapshot",
"command": "AUTODEV_HOOK=pre-compact-snapshot; AUTODEV_ROOT=\"${AUTODEV_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-}}}}\"; for AUTODEV_ROOT_CAND in \"$AUTODEV_ROOT\" . \"$HOME/.codex/plugins/cache/autodev-marketplace/autodev\"/* \"$HOME/.claude/plugins/marketplace/autodev\"/*; do [ -n \"$AUTODEV_ROOT_CAND\" ] || continue; if [ -x \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" ]; then exec \"$AUTODEV_ROOT_CAND/hooks/run-hook.cmd\" \"$AUTODEV_HOOK\"; fi; done; printf '{}\\n'",
"timeout": 10
}
]
Expand Down
43 changes: 43 additions & 0 deletions tests/hook-contracts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,48 @@ run_hook_wrapper() {
hooks/run-hook.cmd "$hook" >"$stdout_file" 2>"$stderr_file" <<<"$payload"
}

test_hooks_manifest_commands_do_not_require_claude_plugin_root() {
local tmp payload cmd count stdout_file stderr_file stdout_text status
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' RETURN
payload='{"source":"startup","tool_name":"Bash","tool_input":{"command":"echo hi"},"prompt":"continue","cwd":"'"$tmp"'","transcript_path":"'"$tmp"'/session.jsonl"}'
touch "$tmp/session.jsonl"

count=0
while IFS= read -r cmd; do
count=$((count + 1))
stdout_file="$tmp/stdout-${count}.json"
stderr_file="$tmp/stderr-${count}.txt"
set +e
(
cd "$tmp"
printf '%s' "$payload" | env -u AUTODEV_PLUGIN_ROOT -u CLAUDE_PLUGIN_ROOT -u CODEX_PLUGIN_ROOT -u CURSOR_PLUGIN_ROOT \
LC_ALL=C LANG=C LC_CTYPE=C sh -c "$cmd"
Comment on lines +60 to +61
) >"$stdout_file" 2>"$stderr_file"
status=$?
set -e

if [ "$status" = "127" ]; then
fail "hooks.json command ${count}: must not require CLAUDE_PLUGIN_ROOT; stderr: $(cat "$stderr_file")"
continue
fi
if [ "$status" != "0" ]; then
fail "hooks.json command ${count}: expected exit 0, got ${status}; stderr: $(cat "$stderr_file")"
continue
fi
stdout_text="$(cat "$stdout_file")"
if ! printf '%s' "$stdout_text" | jq -e . >/dev/null 2>&1; then
fail "hooks.json command ${count}: expected JSON stdout, got: ${stdout_text}; stderr: $(cat "$stderr_file")"
fi
done < <(jq -r '.. | objects | select(.type? == "command") | .command' hooks/hooks.json)

if [ "$count" = "0" ]; then
fail "hooks.json command discovery: expected at least one command hook"
return
fi
pass "hooks.json commands: run without CLAUDE_PLUGIN_ROOT and emit JSON"
}

# emit_locked_fixture <plan-abs-path> <name>
# Writes a minimal-but-valid locked plan to <plan-abs-path>, then runs
# hooks/scope-lock-apply against it from the repo root. The plan body is
Expand Down Expand Up @@ -1817,6 +1859,7 @@ test_demo_fidelity_fail_open_when_state_unwritable() {
}

require_jq
test_hooks_manifest_commands_do_not_require_claude_plugin_root
test_session_start_json
test_session_start_time_dedup_suppresses_rapid_refires
test_session_start_resume_target_checkpoint
Expand Down
Loading