#!/usr/bin/env bash # tests/witness-gate.sh — ADR 0012 boot-order witness gate. # # Compares the package/intern-table dumps from the elisp host and the # self-compiled funcl. A non-empty diff means host and self-host see # the registration table in different orders, which means literal- # pool offsets will diverge once Phase 2.1 flips the symbol # representation — and stage2 != stage3 the moment that happens. # # Run this before merging anything that touches ag-bootstrap-standard- # packages, the reader's intern sites, or the macro-eval gensym path. # # Exit codes: # 0 outputs match — gate green # 1 outputs differ — gate hard fail # 2 build broken or missing artifacts set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$ROOT" if [ ! -x build/funcl-stage2 ]; then echo "witness-gate: build/funcl-stage2 missing — run 'make build' first" >&2 exit 2 fi if [ ! -x build/funcl-stage1 ]; then echo "witness-gate: build/funcl-stage1 missing — run 'make build' first" >&2 exit 2 fi HOST_OUT="$(mktemp -p /tmp witness-host.XXXXXX)" SELF_OUT="$(mktemp -p /tmp witness-self.XXXXXX)" STAGE1_OUT="$(mktemp -p /tmp witness-stage1.XXXXXX)" trap 'rm -f "$HOST_OUT" "$SELF_OUT" "$STAGE1_OUT"' EXIT emacs --batch -l elisp/funcl-host.el -f funcl-host-main dump-symbols \ 2>/dev/null > "$HOST_OUT" build/funcl-stage2 --dump-symbols > "$SELF_OUT" build/funcl-stage1 --dump-symbols > "$STAGE1_OUT" ok=0 if ! diff -q "$HOST_OUT" "$SELF_OUT" > /dev/null; then echo "witness-gate: host vs funcl DIVERGE" >&2 echo "--- host ---" >&2 cat "$HOST_OUT" >&2 echo "--- funcl ---" >&2 cat "$SELF_OUT" >&2 echo "--- diff ---" >&2 diff "$HOST_OUT" "$SELF_OUT" >&2 || true ok=1 fi if ! diff -q "$STAGE1_OUT" "$SELF_OUT" > /dev/null; then echo "witness-gate: stage1 vs funcl DIVERGE" >&2 diff "$STAGE1_OUT" "$SELF_OUT" >&2 || true ok=1 fi if [ $ok -eq 0 ]; then printf "witness-gate: %d packages, host == stage1 == funcl\n" \ "$(wc -l < "$SELF_OUT")" fi exit $ok