#!/usr/bin/env bash
# PreToolUse hook: refuse to write a SQL file that uses SELECT *.
#
# WHY THIS EXISTS
# A skill can say "never SELECT *" and the model still slips. A skill is a
# request. This hook is enforcement: it reads what is about to be written and
# says no if the query uses SELECT *, so the rule holds whether or not the model
# remembered it.
#
# INSTALL
#   1. Save as .claude/hooks/no-select-star.sh, then: chmod +x .claude/hooks/no-select-star.sh
#   2. Add it to .claude/settings.json under hooks.PreToolUse with matcher "Write|Edit".
#
# TEST WITHOUT CLAUDE
#   echo '{"tool_input":{"file_path":"qry_signups.sql","content":"select * from t"}}' | .claude/hooks/no-select-star.sh
#   -> a JSON line with "permissionDecision":"deny"

set -uo pipefail

if ! command -v python3 >/dev/null 2>&1; then
  printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"no-select-star: python3 not found, so the check could not run. Failing closed on purpose."}}\n'
  exit 0
fi

cat | python3 -c '
import json, re, sys

try:
    event = json.load(sys.stdin)
except Exception:
    print(json.dumps({"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "allow"}}))
    sys.exit(0)

ti = event.get("tool_input", {}) or {}
path = ti.get("file_path", "") or ""

# Only inspect SQL files. Everything else passes.
if not path.endswith(".sql"):
    print(json.dumps({"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "allow"}}))
    sys.exit(0)

# Gather the text this write would put on disk, across Write, Edit, and MultiEdit.
chunks = [ti.get("content", ""), ti.get("new_string", "")]
for e in ti.get("edits", []) or []:
    chunks.append(e.get("new_string", ""))
text = "\n".join(c for c in chunks if c)

# SELECT * (optionally SELECT DISTINCT * or SELECT table.*), case-insensitive,
# any whitespace. count(*) does not match: the * must follow SELECT directly.
if re.search(r"select\s+(distinct\s+)?(\w+\s*\.\s*)?\*", text, re.IGNORECASE):
    reason = ("no-select-star: this query uses SELECT *, which our conventions forbid. "
              "List the columns explicitly, then write it again.")
    print(json.dumps({"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": reason}}))
else:
    print(json.dumps({"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "allow"}}))
'
