#!/usr/bin/env sh
# Pre-commit: scoped + fast. NEVER bypass with --no-verify — a failure here is a
# real problem in something you staged. What each step proves, and what CI adds
# on top, is the gate matrix in rules/23-git-commits-hooks-and-release-gates.md.

echo "pre-commit 1/4: lint-staged (eslint --fix --max-warnings 0 + prettier on staged files)"
npx lint-staged || exit 1

# gitleaks over the staged diff with the committed .gitleaks.toml. Without the
# binary installed it warns loudly and continues; CI scans every PR commit.
echo "pre-commit 2/4: secret scan of the staged changes"
node tools/gates/secret-scan.mjs || exit 1

# The committed .ai knowledge layer and the inventory snapshot are GENERATED
# from the tree, so they are regenerated and staged here — after lint-staged has
# settled the bytes they hash — then verified in the same pass.
#
# The generators read the WORKING TREE, but CI regenerates from what was
# committed. So everything not being committed is parked first, and restored by
# the trap even if a generator fails or the shell is interrupted: losing a
# developer's uncommitted work to a hook would be far worse than a failed check.
echo "pre-commit 3/4: knowledge layer + inventory snapshot (regenerate, stage, verify)"
STASH_MSG="pre-commit-knowledge-$$"
STASHED=0
STASH_REF=""
if ! git diff --quiet || [ -n "$(git ls-files --others --exclude-standard)" ]; then
  STASH_BEFORE=$(git rev-parse -q --verify refs/stash 2>/dev/null || true)
  if git stash push --quiet --keep-index --include-untracked --message "$STASH_MSG"; then
    STASH_AFTER=$(git rev-parse -q --verify refs/stash 2>/dev/null || true)
    if [ -n "$STASH_AFTER" ] && [ "$STASH_AFTER" != "$STASH_BEFORE" ]; then
      STASHED=1
      STASH_REF=$STASH_AFTER
    fi
  fi
fi
restore_stash() {
  if [ "$STASHED" = "1" ]; then
    STASHED=0
    sh scripts/hooks/restore-stash.sh "$STASH_REF" "$STASH_MSG"
  fi
}
trap 'restore_stash' EXIT INT TERM

# Records a `knowledge` receipt for the staged tree, so pre-push does not verify
# the same tree again (rules/34).
node tools/affected/index.mjs knowledge --record || { echo "→ knowledge layer check failed"; exit 1; }

restore_stash
trap - EXIT INT TERM

# Root-invariant checks (lockfile, ESLint config, tsconfig) and typecheck of the
# workspaces the STAGED change affects, after rebuilding any stale shared
# package. Skipped only where a receipt for this exact staged tree proves it.
echo "pre-commit 4/4: root checks + typecheck of affected (staged) workspaces"
node tools/gates/pre-commit.mjs || exit 1

echo "pre-commit OK"
