#!/usr/bin/env bash
# The whole gate, once: typecheck, lint, every package's tests. A green run
# on a clean tree is remembered by that tree's hash, so the pre-push hook can
# skip a suite that already passed on exactly what is being pushed.
#
#   pnpm verify        run the gate (what CI runs), remember a green clean tree
#   .githooks/verify --check   exit 0 only if HEAD's tree is remembered green
set -euo pipefail
cd -- "$(git rev-parse --show-toplevel)"

gitdir="$(git rev-parse --git-dir)"
marker="$gitdir/ghost-verified-tree"
tree="$(git rev-parse 'HEAD^{tree}')"

if [[ "${1:-}" == --check ]]; then
  [[ -f "$marker" && "$(cat "$marker")" == "$tree" ]]
  exit
fi

# Save this run's output for the next failure diagnosis. `--check` stays
# above this line so a probe never truncates the log.
exec > >(tee "$gitdir/ghost-verify-last.log") 2>&1

# @ghost/daemon typechecks against @ghost/extensions' built declarations, so a
# tree that has never been built (every fresh worktree, and the scratch worktree
# a master push comes from) fails typecheck for a missing module rather than for
# anything wrong with it.
pnpm build
pnpm typecheck
pnpm lint
pnpm test
# Owner scripts outside the workspace packages.
bun test scripts
# What the gate checks beyond the workspace: the packaging scripts
# (they diff packaging/arch/.SRCINFO against a fresh makepkg render and chain
# the other packaging suites, including the installer this repository
# publishes).
bash packaging/arch/test-check-dependencies.sh

# A dirty tree was not what the suite proved; only a clean HEAD earns the marker.
if [[ -z "$(git status --porcelain)" ]]; then
  printf '%s\n' "$tree" > "$marker"
else
  rm -f "$marker"
  printf 'verify: green, but the working tree is dirty, so HEAD is not marked verified\n' >&2
fi
