#!/usr/bin/env bash
# foxhunt-audit-router.sh
#
# PostToolUse hook router. Reads Claude Code tool-input JSON from stdin,
# inspects the file path being edited, and emits at most one one-line hint
# to stdout suggesting which foxhunt-* auditor agents to dispatch.
#
# Contract:
#  - Completes in <200 ms.
#  - Never spawns agents itself.
#  - Always exits 0 (never blocks).
#  - One suggestion per (path, agent) per session, tracked in
#    .claude/.foxhunt-audit-state (gitignored, cleared at SessionStart).

set -u  # not -e; we want to exit 0 even on errors

REPO_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
STATE_FILE="$REPO_ROOT/.claude/.foxhunt-audit-state"
mkdir -p "$(dirname "$STATE_FILE")" 2>/dev/null || exit 0
touch "$STATE_FILE" 2>/dev/null || exit 0

# Read tool input from stdin; bail if not JSON or no file_path
INPUT="$(cat 2>/dev/null || true)"
[ -z "$INPUT" ] && exit 0

# Extract file path. Claude Code sends keys like "tool_input": {"file_path": "..."}
# Be lenient: try multiple JSON shapes via grep/sed (avoid jq dep).
PATH_FOUND="$(printf '%s' "$INPUT" | grep -oE '"file_path"[[:space:]]*:[[:space:]]*"[^"]+"' | head -1 | sed -E 's/.*"file_path"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/')"
[ -z "$PATH_FOUND" ] && exit 0

# Make path repo-relative if absolute
case "$PATH_FOUND" in
  "$REPO_ROOT"/*) REL="${PATH_FOUND#$REPO_ROOT/}" ;;
  /*)             REL="$PATH_FOUND" ;;
  *)              REL="$PATH_FOUND" ;;
esac

# Routing table: build SUGGEST list of agent names
SUGGEST=()
case "$REL" in
  *.cu)                                  SUGGEST+=("gpu-contract-auditor") ;;
  *cuda/*.rs|*/cuda/*)                   SUGGEST+=("gpu-contract-auditor") ;;
  crates/*/build.rs)                     SUGGEST+=("gpu-contract-auditor") ;;
esac
case "$REL" in
  */experience_kernels.cu|*reward*.rs|*reward*.cu|*controller*.rs|*trader_*.rs)
    SUGGEST+=("reward-controller-auditor") ;;
esac
case "$REL" in
  *sp*_isv_slots.rs)                     SUGGEST+=("isv-discipline-auditor") ;;
  crates/ml-*/*.rs|crates/ml-*/**/*.rs)  SUGGEST+=("isv-discipline-auditor") ;;
esac
case "$REL" in
  docs/superpowers/specs/*.md|docs/superpowers/plans/*.md|docs/plans/*.md)
    SUGGEST+=("sp-critical-reviewer") ;;
esac
case "$REL" in
  MEMORY.md|*memory/pearl_*.md|*memory/feedback_*.md)
    SUGGEST+=("memory-curator") ;;
esac
# Default for any rust file in crates/ services/ bin/ that didn't match above
case "$REL" in
  crates/*.rs|crates/**/*.rs|services/*.rs|services/**/*.rs|bin/*.rs|bin/**/*.rs)
    # Add code-hygiene unconditionally for Rust source
    SUGGEST+=("code-hygiene-auditor") ;;
esac

[ "${#SUGGEST[@]}" -eq 0 ] && exit 0

# Dedupe SUGGEST and filter against state file (one suggestion per (path, agent) per session)
EMIT=()
for AGENT in "${SUGGEST[@]}"; do
  KEY="$REL|$AGENT"
  if ! grep -Fxq "$KEY" "$STATE_FILE" 2>/dev/null; then
    echo "$KEY" >> "$STATE_FILE"
    # Dedupe within this invocation too
    case " ${EMIT[*]:-} " in *" $AGENT "*) ;; *) EMIT+=("$AGENT") ;; esac
  fi
done

[ "${#EMIT[@]}" -eq 0 ] && exit 0

# Emit single-line hint, prefixed for grep
JOINED="$(printf '%s, ' "${EMIT[@]}")"; JOINED="${JOINED%, }"
echo "[foxhunt-audit] $REL — suggest: $JOINED"
exit 0
