#!/usr/bin/env bash
# planu-spec-sanctity.sh — SPEC-587: PostToolUse spec-folder sanctity guard
#
# Blocks writes to planu/specs/SPEC-*/ for any file that is NOT in the
# approved whitelist. Installed by init_project when Claude Code is detected.
#
# Exit codes:
#   0  — write is allowed (or this hook does not apply to the event)
#   2  — write is BLOCKED; message goes to stderr for Claude Code to surface
#
# Hook type: PostToolUse
# Environment variables provided by Claude Code:
#   CLAUDE_TOOL_NAME        — name of the tool that was called (e.g. "Write", "Edit")
#   CLAUDE_TOOL_INPUT_JSON  — JSON-encoded tool input

set -euo pipefail

# ---------------------------------------------------------------------------
# Whitelist: files allowed inside planu/specs/SPEC-*/
# ---------------------------------------------------------------------------
ALLOWED_FILES=(
  "spec.md"
  "progress.json"
)

# ---------------------------------------------------------------------------
# Only intercept file-write tools
# ---------------------------------------------------------------------------
TOOL_NAME="${CLAUDE_TOOL_NAME:-}"
case "$TOOL_NAME" in
  Write|Edit|MultiEdit|NotebookEdit) ;;
  *) exit 0 ;;
esac

# ---------------------------------------------------------------------------
# Extract file_path from tool input JSON
# ---------------------------------------------------------------------------
INPUT_JSON="${CLAUDE_TOOL_INPUT_JSON:-}"
if [[ -z "$INPUT_JSON" ]]; then
  exit 0
fi

# Use python3 if available, else fall back to node, else try jq
FILE_PATH=""
if command -v python3 &>/dev/null; then
  FILE_PATH=$(python3 -c "
import json, sys
try:
    d = json.loads(sys.stdin.read())
    print(d.get('file_path', d.get('path', '')))
except Exception:
    print('')
" <<< "$INPUT_JSON")
elif command -v node &>/dev/null; then
  FILE_PATH=$(node -e "
try {
  const d = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));
  process.stdout.write(d.file_path || d.path || '');
} catch { process.stdout.write(''); }
" <<< "$INPUT_JSON")
elif command -v jq &>/dev/null; then
  FILE_PATH=$(jq -r '.file_path // .path // ""' <<< "$INPUT_JSON")
fi

if [[ -z "$FILE_PATH" ]]; then
  exit 0
fi

# ---------------------------------------------------------------------------
# Check whether the path is inside a planu/specs/SPEC-*/ directory
# ---------------------------------------------------------------------------
# Normalise to remove leading ./ or absolute prefix
NORMALISED="${FILE_PATH#./}"
NORMALISED="${NORMALISED#/*/}"   # strip any leading absolute segment

# Match pattern: planu/specs/SPEC-<anything>/<filename>
if [[ "$NORMALISED" =~ ^(.*/)?planu/specs/SPEC-[^/]+/([^/]+)$ ]]; then
  BASENAME="${BASH_REMATCH[2]}"

  case "$BASENAME" in
    technical.md|progress.md|HU.md|FICHA-TECNICA.md|PROGRESS.md)
      cat >&2 <<EOF
[planu-spec-sanctity] BLOCKED: "$FILE_PATH" is a legacy spec artifact.

Planu specs are unified in spec.md. Put technical planning, file ownership,
and progress into inline sections: ## Technical, ## Files, and ## Progress.
EOF
      exit 2
      ;;
  esac

  # Check against whitelist
  for allowed in "${ALLOWED_FILES[@]}"; do
    if [[ "$BASENAME" == "$allowed" ]]; then
      exit 0
    fi
  done

  # Not in whitelist — block the write
  cat >&2 <<EOF
[planu-spec-sanctity] BLOCKED: "$FILE_PATH" is not in the spec folder whitelist.

Allowed files inside planu/specs/SPEC-*/ are:
  - spec.md
  - progress.json

Do NOT create technical.md, progress.md, implementation-brief.md, prompt.md,
risk-register.md, PLAN.md, NOTES.md, ADRs, or other files here.
Keep implementation notes in conversation context or in src/.
EOF
  exit 2
fi

# Path does not match — allow unconditionally
exit 0
