- T1-T7 全部勾选,spec_verify --all 七项 exit=0 入 runs.jsonl - check 门禁收敛;交付:备份三件套/gitea 28.2.0/Artalk 2.10.0/ git.wait4x.online + /artalk 公网接入/发布链地基与回滚预案 - 生产 Halo 全程未动(healthy + 200 复查通过) - 含 spec pre-commit/pre-push 门禁钩子入库 Spec: 2026-10-24_add-blog-infra Co-authored-by: GLM-5.3
80 lines
3.0 KiB
Bash
Executable File
80 lines
3.0 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
# The source hook fails closed unless rendered; install_git_hooks.py
|
|
# replaces these placeholders with absolute paths in installed copies.
|
|
repo=$(git rev-parse --show-toplevel)
|
|
checker="/home/wait4x/.pi/agent/skills/spec/scripts/check_all_spec_packages.py"
|
|
# Checker resolution:
|
|
# 1. SPEC_CHECK_ALL_SCRIPT environment override — the explicit operator
|
|
# escape hatch; the path in effect is echoed to stderr so a swap is
|
|
# never silent.
|
|
# 2. The absolute path rendered by install_git_hooks.py, already held in
|
|
# $checker when the placeholder above was replaced. Repository content
|
|
# can never replace the gate checker; an unrendered template fails
|
|
# closed below.
|
|
if [ -n "${SPEC_CHECK_ALL_SCRIPT:-}" ]; then
|
|
checker="$SPEC_CHECK_ALL_SCRIPT"
|
|
printf '%s\n' "spec gate: using SPEC_CHECK_ALL_SCRIPT override: $checker" >&2
|
|
fi
|
|
|
|
if [ ! -f "$checker" ]; then
|
|
printf '%s\n' \
|
|
"error: Spec gate checker not found at: $checker" \
|
|
" The checker script is expected at the path above." \
|
|
" Fix:" \
|
|
" 1. Re-run: python3 scripts/install_git_hooks.py --root \"$repo\"" \
|
|
" 2. The checker lives in the spec skill package under scripts/" >&2
|
|
exit 1
|
|
fi
|
|
|
|
python="/home/wait4x/miniconda3/bin/python3.13"
|
|
python_placeholder_prefix=__SPEC_PYTHON_
|
|
python_placeholder="${python_placeholder_prefix}PLACEHOLDER__"
|
|
if [ "$python" = "$python_placeholder" ]; then
|
|
python=${SPEC_PYTHON:-$(command -v python3 || true)}
|
|
fi
|
|
if [ -z "$python" ]; then
|
|
printf '%s\n' "error: Spec gate requires a trusted Python interpreter" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$python" != "${python##*/}" ] && [ ! -x "$python" ]; then
|
|
printf '%s\n' "error: Spec gate requires a trusted Python interpreter" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Branch-aware gate routing (AUD-07): the full gate guards the irreversible
|
|
# paths — commits on the main branch (the merge destination) and commits
|
|
# carrying archive paths on any branch. In-flight WIP commits on spec/*
|
|
# integration branches get the structural lint only; the full gate
|
|
# re-engages at the main-branch merge (pre-push + push_spec_package).
|
|
# The channel is decided by objective Git facts (branch name, staged
|
|
# paths), never by a committer-declared footer.
|
|
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)
|
|
case "$branch" in
|
|
spec/*)
|
|
if git diff --cached --name-only --diff-filter=ACMRT 2>/dev/null | grep -q "specs/archive/"; then
|
|
: # Archive-carrying commits keep the full gate on every branch.
|
|
else
|
|
printf '%s\n' \
|
|
"spec gate: WIP commit on integration branch $branch — structural lint only;" \
|
|
"the full gate runs for main-branch and archive-carrying commits" >&2
|
|
exec "$python" "$checker" --root "$repo" --lint-only
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
baseline=""
|
|
for ref in refs/heads/main refs/heads/master; do
|
|
if baseline=$(git rev-parse --verify "$ref" 2>/dev/null); then
|
|
break
|
|
fi
|
|
baseline=""
|
|
done
|
|
set --
|
|
if [ -n "$baseline" ]; then
|
|
set -- --legacy-baseline "$baseline"
|
|
fi
|
|
"$python" "$checker" --root "$repo" "$@"
|
|
"$python" "$checker" --root "$repo" --index "$@"
|