blob: 58668a5be05dc59be0a4d0d234b8f96ba05b4fe5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
#!/usr/bin/env bats
# hooks/inbox-boundary-check.sh — Stop hook that soft-nudges the agent to
# process pending inbox/ handoffs before yielding. Blocks the stop ONCE (emits
# a block decision + reason) when inbox-status reports pending items; on the
# harness re-entry (stop_hook_active: true) it steps aside so an unprocessable
# item or a mid-task pause never wedges. Self-skips where there's no inbox/ or
# no inbox-status. The real inbox-status is copied into the test project so the
# hook runs against real code, not a stub.
setup() {
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../.." && pwd)"
SCRIPT="$REPO_ROOT/hooks/inbox-boundary-check.sh"
INBOX_STATUS="$REPO_ROOT/claude-templates/.ai/scripts/inbox-status"
TMPDIR_T="$(mktemp -d)"
CWD="$TMPDIR_T/proj"
mkdir -p "$CWD/.ai/scripts"
cp "$INBOX_STATUS" "$CWD/.ai/scripts/inbox-status"
chmod +x "$CWD/.ai/scripts/inbox-status"
}
teardown() {
rm -rf "$TMPDIR_T"
}
# Feed Stop-hook JSON on stdin. $1 = stop_hook_active (default false).
run_hook() {
local active="${1:-false}"
printf '{"cwd":"%s","hook_event_name":"Stop","stop_hook_active":%s}' \
"$CWD" "$active" | bash "$SCRIPT"
}
@test "pending handoffs block the stop with a count in the reason" {
mkdir -p "$CWD/inbox"
printf 'x\n' >"$CWD/inbox/2026-07-19-from-home-thing.org"
printf 'y\n' >"$CWD/inbox/2026-07-19-from-work-other.org"
run run_hook
[ "$status" -eq 0 ]
# Valid JSON with a block decision.
echo "$output" | jq -e '.decision == "block"'
echo "$output" | jq -e '.reason | test("2 pending")'
echo "$output" | jq -e '.reason | test("inbox.org")'
}
@test "a clean inbox (only artifacts) emits nothing" {
mkdir -p "$CWD/inbox"
touch "$CWD/inbox/.gitkeep"
printf 'done\n' >"$CWD/inbox/PROCESSED-2026-07-19-old.org"
run run_hook
[ "$status" -eq 0 ]
[ -z "$output" ]
}
@test "soft-nudge: stop_hook_active=true steps aside even with pending items" {
mkdir -p "$CWD/inbox"
printf 'x\n' >"$CWD/inbox/2026-07-19-from-home-thing.org"
run run_hook true
[ "$status" -eq 0 ]
[ -z "$output" ]
}
@test "no inbox/ directory is a silent no-op" {
run run_hook
[ "$status" -eq 0 ]
[ -z "$output" ]
}
@test "inbox-status absent degrades to a silent no-op" {
mkdir -p "$CWD/inbox"
printf 'x\n' >"$CWD/inbox/2026-07-19-from-home-thing.org"
rm -f "$CWD/.ai/scripts/inbox-status"
# Also ensure nothing named inbox-status is on PATH for this run.
run env PATH="/usr/bin:/bin" bash -c '
printf "{\"cwd\":\"'"$CWD"'\",\"hook_event_name\":\"Stop\"}" | bash "'"$SCRIPT"'"'
[ "$status" -eq 0 ]
[ -z "$output" ]
}
@test "the emitted reason names the project for context" {
mkdir -p "$CWD/inbox"
printf 'x\n' >"$CWD/inbox/2026-07-19-from-home-thing.org"
run run_hook
echo "$output" | jq -e '.reason | test("proj")'
}
|