|
14 | 14 | # hook_commit_failure_tracker — warn at commit time about untracked failures |
15 | 15 | # hook_worktree_bash_guard — block cd into main repo from worktree |
16 | 16 | # hook_worktree_edit_guard — block mkdir targeting main repo from worktree |
17 | | -# hook_bug_close_guard — require --reason flag on bug ticket closes |
18 | 17 | # hook_review_integrity_guard — block direct writes to review-status files |
19 | 18 | # hook_blocked_test_command — block broad test commands, redirect to validate.sh |
20 | 19 | # hook_tickets_tracker_bash_guard — block Bash commands referencing .tickets-tracker/ |
@@ -495,79 +494,6 @@ hook_worktree_edit_guard() { |
495 | 494 | return 0 |
496 | 495 | } |
497 | 496 |
|
498 | | -# --------------------------------------------------------------------------- |
499 | | -# hook_bug_close_guard |
500 | | -# --------------------------------------------------------------------------- |
501 | | -# PreToolUse hook: enforce --reason flag on bug ticket closes. |
502 | | -hook_bug_close_guard() { |
503 | | - local INPUT="$1" |
504 | | - local HOOK_ERROR_LOG="$HOME/.claude/hook-error-log.jsonl" |
505 | | - trap 'printf "{\"ts\":\"%s\",\"hook\":\"bug-close-guard\",\"line\":%s}\n" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$LINENO" >> "$HOOK_ERROR_LOG" 2>/dev/null; return 0' ERR |
506 | | - |
507 | | - # Early-exit: skip unless command contains 'tk' (substring match) |
508 | | - if [[ "$INPUT" != *"tk"* ]]; then |
509 | | - return 0 |
510 | | - fi |
511 | | - |
512 | | - local COMMAND |
513 | | - COMMAND=$(parse_json_field "$INPUT" '.tool_input.command') |
514 | | - if [[ -z "$COMMAND" ]]; then |
515 | | - return 0 |
516 | | - fi |
517 | | - |
518 | | - # Only act on `tk close` commands |
519 | | - if ! [[ "$COMMAND" =~ tk[[:space:]]+close[[:space:]]+([^[:space:]]+) ]]; then |
520 | | - return 0 |
521 | | - fi |
522 | | - local TICKET_ID="${BASH_REMATCH[1]}" |
523 | | - |
524 | | - # Find ticket file |
525 | | - local REPO_ROOT |
526 | | - REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "") |
527 | | - if [[ -z "$REPO_ROOT" ]]; then |
528 | | - return 0 |
529 | | - fi |
530 | | - |
531 | | - local TICKET_FILE="" |
532 | | - if [[ -f "$REPO_ROOT/.tickets/${TICKET_ID}.md" ]]; then |
533 | | - TICKET_FILE="$REPO_ROOT/.tickets/${TICKET_ID}.md" |
534 | | - else |
535 | | - TICKET_FILE=$(find "$REPO_ROOT/.tickets" -maxdepth 1 -name "*${TICKET_ID}.md" ! -name "*${TICKET_ID}.*.*" 2>/dev/null | head -1) |
536 | | - fi |
537 | | - |
538 | | - if [[ -z "$TICKET_FILE" ]] || [[ ! -f "$TICKET_FILE" ]]; then |
539 | | - return 0 |
540 | | - fi |
541 | | - |
542 | | - # Read type from frontmatter |
543 | | - local TICKET_TYPE |
544 | | - TICKET_TYPE=$(head -10 "$TICKET_FILE" | grep -m1 '^type:' | sed 's/^type:[[:space:]]*//' | tr -d '[:space:]') |
545 | | - |
546 | | - # Non-bug tickets are always allowed |
547 | | - if [[ "$TICKET_TYPE" != "bug" ]]; then |
548 | | - return 0 |
549 | | - fi |
550 | | - |
551 | | - # Bug ticket — require --reason flag |
552 | | - if [[ "$COMMAND" != *"--reason"* ]]; then |
553 | | - echo "BLOCKED [bug-close-guard]: Bug tickets require --reason flag." >&2 |
554 | | - echo "Add --reason=\"Fixed: <description>\" or --reason=\"Escalated to user: <findings>\"" >&2 |
555 | | - trap - ERR; return 2 |
556 | | - fi |
557 | | - |
558 | | - # Check for investigation-only language without escalation |
559 | | - local INVESTIGATION_PATTERN='(Investigated|investigated|code path|works correctly|no fix needed|correct behavior|feature works correctly|no code change)' |
560 | | - local ESCALATION_PATTERN='([Ee]scalat|[Uu]ser confirmed|[Uu]ser decision|[Uu]ser approved|[Bb]y design|[Ww]orks as designed)' |
561 | | - |
562 | | - if [[ "$COMMAND" =~ $INVESTIGATION_PATTERN ]] && ! [[ "$COMMAND" =~ $ESCALATION_PATTERN ]]; then |
563 | | - echo "WARNING [bug-close-guard]: Reason looks like investigation findings, not a fix." >&2 |
564 | | - echo "Consider using --reason=\"Escalated to user: <findings>\" instead." >&2 |
565 | | - return 0 |
566 | | - fi |
567 | | - |
568 | | - return 0 |
569 | | -} |
570 | | - |
571 | 497 | # --------------------------------------------------------------------------- |
572 | 498 | # hook_tool_use_guard |
573 | 499 | # --------------------------------------------------------------------------- |
|
0 commit comments