Harden the cross-checkout gate so a do-nothing binary cannot pass it
This gate reported green from 2026-07-25 to 2026-07-30 while testing nothing. It was not badly written: set -eu, no pipelines, and a success marker printed only after the command are exactly the right shape, and the failure did propagate once there was a failure to propagate. It was hollowed out from outside. The released sigil of that period had no env subcommand and exits 0 for unknown subcommands, so the one command that mattered never ran and never complained.
Correct authorship was not enough, so the gate no longer trusts exit status alone. It now requires evidence the built program actually ran -- its own stdout -- and checks the lock step produced a non-empty lock. Either condition alone can lie: a non-zero status with no output, or a zero status from a binary that never ran anything.
Also asserts git and minisign are present as a separate loud step. A missing minisign is the sharp case: it surfaces through sigil as "root signature ... failed", accusing the trust chain rather than the environment.
The regression test for the gate itself is stated in its header: run it against a sigil older than 0.18.0 and it must FAIL. Before this commit it passed.
scripts/gate-crosscheckout.sh | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 55 insertions(+), 2 deletions(-)scripts/gate-crosscheckout.shmodified
#!/bin/shset -eu# PROPERTY UNDER TEST: everything needed to get from a BARE GIT CLONE to a# running program is either committed, or hash-pinned and fetchable. Nothing# may depend on the checkout it was authored in -- not an untracked file, not a# forgotten `git add`, not a warm store, not an absolute path. Hence: fresh# clone at a new path, fresh HOME, fresh store.## WHY THE ASSERTIONS BELOW ARE ON OBSERVED OUTPUT, NOT EXIT STATUS.# This gate reported green from 2026-07-25 to 2026-07-30 while testing nothing.# It was not badly written: `set -eu`, no pipelines, and a success marker# printed only after the command are exactly the right shape, and the failure# did propagate. It was hollowed out from OUTSIDE -- the released sigil of the# day had no `env` subcommand and exited 0 for unknown subcommands, so the one# command that mattered never ran and never complained. Correct authorship was# not enough. A binary that does nothing successfully must not be able to pass# this gate, so the check below requires evidence the built program actually# ran: its own stdout.## To confirm this gate still works, run it against a sigil older than 0.18.0.# It must FAIL. Before the hardening it passed.repo=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)sigil_bin=${SIGIL_BIN:?set SIGIL_BIN to a sigil binary with env support (0.18.0+)}registry=${SIGIL_REGISTRY_METADATA:?set SIGIL_REGISTRY_METADATA to root-signed registry metadata this binary accepts}# Assert each external dependency separately and loudly. Folded into an `&&`# chain, an absent tool short-circuits to a non-zero status indistinguishable# from the failure this gate exists to report. A missing `minisign` is the# sharp case: it surfaces as "root signature ... failed", which accuses the# trust chain rather than the environment.for tool in git minisign; do command -v "$tool" >/dev/null 2>&1 || { echo "cross-checkout gate: FATAL: $tool is not on PATH; the gate did not run" >&2 exit 1 }donescratch=$(mktemp -d /tmp/sigil-channel-clone.XXXXXX)trap 'rm -rf "$scratch"' EXIT HUP INT TERMgit clone --quiet --no-hardlinks "$repo" "$scratch/core-channel"# Authoring: resolve demo/env.sgl against the clone's signed catalogue and# realize it. `env shell` consumes an env.lock, never environment source, so# the lock step is separate and comes first.lock_status=0SIGIL_REGISTRY_METADATA="$registry" \HOME="$scratch/home" SIGIL_CHANNEL="$scratch/core-channel" \ "$sigil_bin" env --store "$scratch/store" lock \ -f "$scratch/core-channel/demo/env.sgl" --lock-file "$scratch/env.lock" -f "$scratch/core-channel/demo/env.sgl" --lock-file "$scratch/env.lock" \ >"$scratch/lock.out" 2>&1 || lock_status=$?if [ "$lock_status" -ne 0 ] || [ ! -s "$scratch/env.lock" ]; then echo "cross-checkout gate: FAILED at lock" >&2 echo " exit status: $lock_status; env.lock present and non-empty: no" >&2 sed 's/^/ | /' "$scratch/lock.out" >&2 exit 1fi# Consumption: deliberately WITHOUT SIGIL_REGISTRY_METADATA and without# SIGIL_CHANNEL, which also holds the lock-only consumption boundary honest.run_status=0HOME="$scratch/home" \ "$sigil_bin" env --store "$scratch/store" shell \ -f "$scratch/env.lock" -- hello -f "$scratch/env.lock" -- hello >"$scratch/hello.out" 2>&1 || run_status=$?# Both conditions, because either alone can lie: a non-zero status with no# output, or a zero status from a binary that never ran the program at all.if [ "$run_status" -ne 0 ] || ! grep -q '^Hello, world!$' "$scratch/hello.out"; then echo "cross-checkout gate: FAILED at run" >&2 echo " exit status: $run_status" >&2 echo " expected 'Hello, world!' on stdout; captured output follows" >&2 sed 's/^/ | /' "$scratch/hello.out" >&2 exit 1fiecho "cross-checkout gate: fresh clone bootstrapped, locked, and ran hello from the lock"