# BEGIN: AI GUARDRAILS 

# Detect package manager (check if tool is available before using it)
# Priority: bun > yarn > npm (bun first since package.json engines prefer it)
if ([ -f "bun.lockb" ] || [ -f "bun.lock" ]) && command -v bun >/dev/null 2>&1; then
  PACKAGE_MANAGER="bun"
  EXECUTOR="bunx"
elif [ -f "yarn.lock" ] && command -v yarn >/dev/null 2>&1; then
  PACKAGE_MANAGER="yarn"
  EXECUTOR="yarn"
elif [ -f "package-lock.json" ]; then
  PACKAGE_MANAGER="npm"
  EXECUTOR="npx"
else
  # Default to npm if no lock file is found or tool is not available
  PACKAGE_MANAGER="npm"
  EXECUTOR="npx"
fi

# Get the commit message file path
COMMIT_MSG_FILE=$1

WORK_ITEM_SCRIPT="node_modules/@codyswann/lisa/all/copy-overwrite/scripts/lisa-work-item.mjs"
if [ ! -f "$WORK_ITEM_SCRIPT" ]; then
  WORK_ITEM_SCRIPT="scripts/lisa-work-item.mjs"
fi
if [ ! -f "$WORK_ITEM_SCRIPT" ]; then
  WORK_ITEM_SCRIPT="all/copy-overwrite/scripts/lisa-work-item.mjs"
fi

# Several INDEPENDENT gate families bite at this one moment, and each of the
# checks below knows only its own. Whichever refuses first, the operator is told
# about ALL of them here — otherwise satisfying every requirement the refusal
# names still says nothing about whether the commit will be accepted, which is
# exactly the property those checklists exist to provide. Owned by neither
# check, because neither can know what the other installs.
GATE_FAMILIES_SCRIPT="node_modules/@codyswann/lisa/all/copy-overwrite/scripts/lisa-commit-msg-gates.mjs"
if [ ! -f "$GATE_FAMILIES_SCRIPT" ]; then
  GATE_FAMILIES_SCRIPT="scripts/lisa-commit-msg-gates.mjs"
fi
if [ ! -f "$GATE_FAMILIES_SCRIPT" ]; then
  GATE_FAMILIES_SCRIPT="all/copy-overwrite/scripts/lisa-commit-msg-gates.mjs"
fi

# Never the reason a commit fails: the caller has already decided to refuse.
lisa_commit_gate_families() {
  [ -f "$GATE_FAMILIES_SCRIPT" ] || return 0
  command -v node >/dev/null 2>&1 || return 0
  node "$GATE_FAMILIES_SCRIPT" list --hook "$0" --refused "$1" 2>/dev/null || true
}

if ! command -v node >/dev/null 2>&1; then
  echo "❌ Commit blocked: Node.js is required to validate tracker work items."
  exit 1
fi
if ! node "$WORK_ITEM_SCRIPT" validate-commit "$COMMIT_MSG_FILE"; then
  lisa_commit_gate_families traceability
  exit 1
fi

echo "📝 Validating commit message with commitlint..."
$EXECUTOR commitlint --edit $1

if [ $? -ne 0 ]; then
  echo ""
  echo "❌ Commit message does not follow conventional commits format!"
  echo ""
  echo "📖 Examples of valid commit messages:"
  echo "  - feat: add new feature"
  echo "  - fix: resolve bug in login"
  echo "  - docs: update README"
  echo "  - style: format code"
  echo "  - refactor: restructure auth module"
  echo "  - test: add unit tests for utils"
  echo "  - chore: update dependencies"
  echo ""
  echo "Format: <type>(<optional scope>): <subject>"
  echo ""
  echo "For more info, see: https://www.conventionalcommits.org/"
  lisa_commit_gate_families commit-conformance
  exit 1
fi

# Check for Co-Authored-By line (skip for merge commits)
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
# `printf '%s\n'`, never `echo "$COMMIT_MSG"`. Under a POSIX/XSI `echo` the
# backslash escapes are interpreted, and `\c` means "stop output here" — so a
# message containing `\copy`, `\cite`, or a Windows path like `C:\config` is
# silently truncated at that point before grep ever sees it. The
# `Co-Authored-By:` trailer is always the last line, so it is always the part
# lost, and the hook then rejects a commit whose trailer is present and
# correctly formatted while pointing the author at the trailer.

# Skip AI co-authorship check for merge commits (e.g., from git pull)
if printf '%s\n' "$COMMIT_MSG" | grep -qE "^Merge (branch|pull request|remote-tracking)"; then
  echo "🔀 Merge commit detected, skipping AI co-authorship check"
  exit 0
fi

# Skip AI co-authorship check for automated release commits (e.g., from standard-version in CI)
if printf '%s\n' "$COMMIT_MSG" | grep -qE "^chore\(release\):"; then
  echo "🚀 Release commit detected, skipping AI co-authorship check"
  exit 0
fi

echo "🤖 Checking for AI co-authorship..."

# Accept attribution from any supported coding agent (Claude or Codex),
# case-insensitively. Claude Code emits "Co-Authored-By: Claude"; the Codex CLI
# emits "Co-authored-by: Codex <noreply@openai.com>".
if ! printf '%s\n' "$COMMIT_MSG" | grep -Eiq "Co-authored-by:.*(Claude|Codex)"; then
  echo ""
  echo "❌ Commit message must include AI co-authorship!"
  echo ""
  echo "All commits must include a Co-authored-by line for a coding agent (Claude or Codex)."
  echo ""
  echo "If you're using Claude Code, use the /git:commit command"
  echo "If you're using Codex, enable commit_attribution in .codex/config.toml"
  echo ""
  lisa_commit_gate_families ai-coauthorship
  exit 1
fi

# END: AI GUARDRAILS
