#!/bin/bash
#
# pre-commit (USER VERSION): block commits that would leave the ledger
# (specs/implement_issues.md) in a structurally invalid state.
#
# This is the USER-VERSION hook source, deployed to user projects at
# `.specpro/scripts/bash/pre-commit` and installed into `.git/hooks/` by
# `.specpro/scripts/bash/install-git-hooks.sh`. It carries ONLY the ledger
# structural check — the one check every specpro project needs.
#
# The bootstrap instance (the repository that develops specpro itself) uses a
# DIFFERENT hook with four additional development-gate checks (deployment
# mirror, tool-file language, shape register, cumulative records). That hook
# lives at `scripts/git-hooks/pre-commit` and is NOT deployed. Do not merge
# the two: the boundary between them is physical by design (plan.md →
# Commit-Gate Distribution), because instance-specific gates must be
# physically absent from user assets.
#
# Why this check exists: the ledger is position-structured and the failure
# mode is SILENT — a misfiled entry looks registered, the statistics table
# looks plausible, nothing errors. An instruction telling writers to
# self-check cannot reach a session that is already running, so the check has
# to be enforced at a point every writer must pass through. A commit is that
# point.
#
# Installed by: .specpro/scripts/bash/install-git-hooks.sh   (git hooks are
# not versioned — the hook SOURCE lives here so a fresh clone installs the
# same check; the specpro CLI installs it at init time as well)
# Bypass (deliberate, e.g. committing a known-broken WIP state): git commit --no-verify
#
# Scope: exits immediately unless the LEDGER itself is staged, so it costs
# nothing on unrelated commits.
#
# Layout note: a project may keep its spec artifacts in a nested repository
# mounted at the specs directory. The staged path is then `implement_issues.md`
# when this hook runs inside that repository and `specs/implement_issues.md`
# when it runs in a single-repository layout. Both are recognised, and the
# verifier is located relative to the repository root rather than assumed to
# be a sibling.

set -e

root=$(git rev-parse --show-toplevel 2>/dev/null) || exit 0
cd "$root" || exit 0

staged=$(git diff --cached --name-only)

ledger_rel=""
case "$staged" in
    *implement_issues.md*)
        for cand in specs/implement_issues.md implement_issues.md; do
            if echo "$staged" | grep -qx "$cand"; then ledger_rel="$cand"; break; fi
        done
        ;;
esac
[ -z "$ledger_rel" ] && exit 0

# Locate the verifier. It lives beside `.specpro/` — in a nested specs
# repository that is the PARENT directory, not a sibling.
verifier=""
for cand in .specpro/scripts/bash/verify-ledger.sh ../.specpro/scripts/bash/verify-ledger.sh; do
    if [ -x "$cand" ]; then verifier="$cand"; break; fi
done
if [ -z "$verifier" ]; then
    echo "pre-commit: verify-ledger.sh not found — skipping ledger check" >&2
    exit 0
fi

if ! LEDGER="$root/$ledger_rel" "$verifier"; then
    cat >&2 <<'EOF'

────────────────────────────────────────────────────────────────────────
✗ Commit blocked: the ledger (specs/implement_issues.md) failed its structural checks.

The violations are listed above. In short, the ledger's invariants are:
  · every issue entry sits INSIDE one of its '## [...] Phase Issues'
    sections — never appended to the end of the file
  · every entry's block carries exactly ONE `**Related**:` line, and every
    field line lies inside some entry's block
  · the statistics table at the top matches the actual per-section counts
  · the file ends with exactly one newline

The section entries are authoritative; the statistics table is derived.
Fix the file and re-stage it, or bypass deliberately with:
    git commit --no-verify
────────────────────────────────────────────────────────────────────────
EOF
    exit 1
fi

exit 0
