Files
boshu2__agentops/hooks/commit-review-gate.sh
T
Boden Fuller e8572ee8d9 feat(cli): backlog blitz wave 1 — bug fixes, test cleanup, skill templates (na-3re)
Wave 1 of na-3re (6 parallel issues, 0 file conflicts):

Issue 1 - Hook bugs:
- Merge double-jq in commit-review-gate.sh into single @tsv call
- Add session-aware dedup (PID-based) to intent-echo.sh

Issue 2 - Script bugs:
- Add pattern resolution logging to cherry-pick-wave.sh
- Improve coverage-ratchet.sh error handling for failed go test

Issue 3 - Run-ID classification:
- Fix rpiRunIDPattern: accept rpi-{8-12hex}, drop bare 8-hex false positives
- Update contract tests and serve tests for new pattern

Issue 4 - UTF-8 safety:
- Fix truncateGoal to use rune-safe slicing (was byte-slicing)
- Audit strings.Trim in goals/ — no misuse found

Issue 5 - Test cleanup:
- Strip 153 TestCov3_ prefixes across 15 files
- Merge fire_deep_test.go → fire_test.go
- Merge maturity_deep_test.go → maturity_test.go
- Fix malformed test names (lowercase after Test)

Issue 6 - Skill templates:
- Add test-fixture audit + go-build verification to /plan
- Add single-epic scope WARN to /crank
- Add footgun entries section to /post-mortem
2026-03-05 10:09:13 -05:00

68 lines
2.4 KiB
Bash
Executable File

#!/bin/bash
# commit-review-gate.sh - PreToolUse hook: inject staged diff before git commit
# Forces Claude to see its own changes before committing.
# Non-blocking (always exit 0). Injects diff as additionalContext.
# Kill switches
[ "${AGENTOPS_HOOKS_DISABLED:-}" = "1" ] && exit 0
[ "${AGENTOPS_COMMIT_REVIEW_DISABLED:-}" = "1" ] && exit 0
# Read stdin
INPUT=$(cat)
# Extract tool name and command
TOOL_NAME="${CLAUDE_TOOL_NAME:-}"
COMMAND="${CLAUDE_TOOL_INPUT_COMMAND:-}"
if [ -z "$TOOL_NAME" ] || [ -z "$COMMAND" ]; then
# Single jq call to extract both fields (avoids double-parse of stdin)
IFS=$'\t' read -r _jq_tool _jq_cmd < <(echo "$INPUT" | jq -r '[.tool_name // "", .tool_input.command // ""] | @tsv' 2>/dev/null) || exit 0
[ -z "$TOOL_NAME" ] && TOOL_NAME="$_jq_tool"
[ -z "$COMMAND" ] && COMMAND="$_jq_cmd"
fi
# Only fire on Bash + git commit
[ "$TOOL_NAME" = "Bash" ] || exit 0
echo "$COMMAND" | grep -q 'git commit' || exit 0
# Don't fire on --amend with no new changes (just message edit)
echo "$COMMAND" | grep -qE '\-\-amend.*\-\-no-edit' && exit 0
# Capture staged diff summary (separate call — different output format)
DIFF_STAT=$(git diff --cached --stat 2>/dev/null)
[ -z "$DIFF_STAT" ] && exit 0
# Capture full diff once and derive metrics (TOCTOU fix: index can change between calls)
FULL_DIFF=$(git diff --cached 2>/dev/null)
FILE_COUNT=$(printf '%s\n' "$FULL_DIFF" | grep -c '^diff --git' 2>/dev/null || echo 0)
[ "$FILE_COUNT" = "0" ] && exit 0
DIFF_LINES=$(printf '%s\n' "$FULL_DIFF" | wc -l | tr -d ' ')
DIFF_CONTENT=$(printf '%s\n' "$FULL_DIFF" | head -200)
TRUNCATED=""
if [ "$DIFF_LINES" -gt 200 ]; then
TRUNCATED=" (showing first 200 of $DIFF_LINES lines — run 'git diff --cached' for full diff)"
fi
# Build review context
REVIEW_MSG="SELF-REVIEW before committing ($FILE_COUNT files changed):
Check for: wrong variable references, changed defaults, removed error handling, silent data loss, YAML syntax errors.
Staged changes:
$DIFF_STAT
${TRUNCATED}
${DIFF_CONTENT}"
# Inject as additionalContext
if command -v jq >/dev/null 2>&1; then
jq -n --arg ctx "$REVIEW_MSG" '{"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":$ctx}}'
else
# Fallback: escape for JSON
safe_msg=${REVIEW_MSG//\\/\\\\}
safe_msg=${safe_msg//\"/\\\"}
safe_msg=$(echo "$safe_msg" | tr '\n' ' ')
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"additionalContext\":\"$safe_msg\"}}"
fi
exit 0