This repo had no .pql/hooks/ at all — the four replication hooks were never installed, because pql's installer used to ignore a redirected core.hooksPath. It works with .config/hooks now, so init prepends a two-line shim to each hook that sources the pql half. Existing hook bodies are untouched; the shim goes above them. What this buys: post-merge now runs `pql plan upgrade`, so a pull that brings in a newer changelog format migrates it forward automatically instead of replaying under superseded rules. .gitattributes gains a rule for changelog files at the root of .pql/changelog/. The existing `**/*.sql` pattern requires a directory component and so did not match the new 0000-format.sql marker, which would have made it a merge conflict rather than a union merge. Note for a follow-up: the hand-folded pql block in .config/hooks/post-merge (lines ~10-12) is now redundant with the shim, so plan import and decisions sync each run twice per pull. Both are idempotent, so this is waste rather than breakage — but that block and its stale "installer is dead" comment can be dropped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
63 lines
2.5 KiB
Bash
Executable File
63 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# pql: source .pql/hooks/pre-commit
|
|
_pql_hook="$(git rev-parse --show-toplevel)/.pql/hooks/pre-commit"; [ -f "$_pql_hook" ] && . "$_pql_hook"
|
|
# Pre-commit hook dispatcher. Runs modular checks from tooling/.
|
|
# Installed via: git config core.hooksPath .config/hooks
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
|
ERRORS=0
|
|
|
|
run_check() {
|
|
local script="$1"
|
|
local label="$2"
|
|
if [ -x "$REPO_ROOT/$script" ]; then
|
|
if ! "$REPO_ROOT/$script"; then
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
else
|
|
echo "pre-commit: WARNING — $label skipped ($script not found or not executable)"
|
|
echo " Run 'make setup' or check that $script exists and is executable."
|
|
fi
|
|
}
|
|
|
|
# --- Checks ---
|
|
run_check "tooling/check-fact-ids" "fact_id validation"
|
|
|
|
# --- pql: decision integrity + durable planning changelog ---
|
|
# Replaces the old SQLite decisions-sync hook. Decisions are markdown-sourced (D-8):
|
|
# `decisions validate` is the decision-ID/format gate (supersedes the never-built
|
|
# check-decision-ids), and `plan export --stage` flushes any ticket mutations to the
|
|
# git-tracked .pql/changelog/ and stages them so planning state lands in this commit.
|
|
# pql installs its own hooks into .pql/hooks, which git ignores under
|
|
# core.hooksPath=.config/hooks — so the logic is folded in here by hand instead.
|
|
if command -v pql >/dev/null 2>&1; then
|
|
if ! pql decisions validate >/dev/null; then
|
|
echo "pre-commit: pql decisions validate failed — malformed decision record(s)."
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
pql plan export --stage >/dev/null 2>&1 || \
|
|
echo "pre-commit: WARNING — pql plan export failed; changelog not refreshed."
|
|
else
|
|
echo "pre-commit: WARNING — pql not on PATH; decision validate + changelog export skipped."
|
|
fi
|
|
|
|
# Run cargo audit only when Cargo.toml or Cargo.lock changed
|
|
if git diff --cached --name-only | grep -qE '(Cargo\.toml|Cargo\.lock)$'; then
|
|
echo "pre-commit: Cargo dependency change detected — running cargo audit..."
|
|
if command -v cargo-audit >/dev/null 2>&1 || cargo audit --version >/dev/null 2>&1; then
|
|
if ! (cd "$REPO_ROOT/server" && cargo audit); then
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
else
|
|
echo "pre-commit: WARNING — cargo-audit not installed, skipping advisory check"
|
|
echo " Install with: cargo install cargo-audit"
|
|
fi
|
|
fi
|
|
|
|
if [ "$ERRORS" -gt 0 ]; then
|
|
echo ""
|
|
echo "pre-commit: $ERRORS check(s) failed. Commit aborted."
|
|
exit 1
|
|
fi
|