Every comment that invoked a 'law' (50 word-boundary sites across 28 tracked files) now states what is going on and why, in terms that transfer to any project: gate twins drift until one side greenlights what the other refuses; a tag re-points while a digest pins; a restrictive engine behavior belongs to the runtime that imposed it and must be re-tested, not inherited; a speculative head is tensors in the file, not a flag; snapshot links dangle where the container resolves them; exit 0 is a clean stop to systemd, so a self-exiting daemon on on-failure goes dark reporting success. Event narratives and dates are gone from these comments; the mechanics carry the argument. Behavior-identical: bash -n, py_compile, yaml parse, full bats suite 408/408 green. One symbol rename rides along (stack script local scale_law -> scale_contract, with its log text).
173 lines
6.6 KiB
Bash
Executable File
173 lines
6.6 KiB
Bash
Executable File
#!/usr/bin/env bats
|
|
# Seam: the shared artifact gates every LLM endpoint runs before it starts.
|
|
#
|
|
# The rule these encode: a serve script and the deployer must refuse the
|
|
# SAME missing/truncated artifact, and they must refuse it the same way.
|
|
# Two hand-written copies of the same gates drift apart until a deploy
|
|
# passes what the unit would refuse; the library is the one place the
|
|
# refusal lives, and both callers source it.
|
|
#
|
|
# Everything here is observable: arguments in, exit status and stderr out.
|
|
# Nothing inspects the library's internals.
|
|
|
|
load helpers
|
|
|
|
LIB="$REPO_ROOT/scripts/lib/llm-gates.sh"
|
|
|
|
setup() {
|
|
TMP="$(mktemp -d)"
|
|
# A fixture with a known, independent size: 12 bytes.
|
|
printf '0123456789ab' > "$TMP/artifact.bin"
|
|
mkdir -p "$TMP/flat"
|
|
touch "$TMP/flat/tokenizer.json" "$TMP/flat/config.json"
|
|
}
|
|
|
|
teardown() {
|
|
rm -rf "$TMP"
|
|
}
|
|
|
|
# call <invocation> — run one gate in a fresh shell under `set -e`, exactly
|
|
# as a serve script sources the library, and capture status + both streams.
|
|
call() {
|
|
run env GATE_PREFIX="${GATE_PREFIX:-testgate}" PATH="$PATH" \
|
|
bash -c "set -euo pipefail; source '$LIB'; $1"
|
|
}
|
|
|
|
@test "a present artifact passes the file gate with no output" {
|
|
GATE_PREFIX=testgate call "require_file '$TMP/artifact.bin' checkpoint 'fetch it'"
|
|
[ "$status" -eq 0 ]
|
|
[ -z "$output" ]
|
|
}
|
|
|
|
@test "an absent artifact fails the file gate naming the path and the remedy" {
|
|
call "require_file '$TMP/absent.bin' checkpoint 'run scripts/download-frank-archon-swift15.sh'"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"checkpoint: missing"* ]]
|
|
[[ "$output" == *"$TMP/absent.bin"* ]]
|
|
[[ "$output" == *"run scripts/download-frank-archon-swift15.sh"* ]]
|
|
}
|
|
|
|
@test "the file gate refuses a directory where an artifact is required" {
|
|
# The serve gate is `-f`, not `-e`: a directory named like the payload
|
|
# (an unpacked staging dir) must not boot the engine.
|
|
call "require_file '$TMP/flat' checkpoint 'fetch it'"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"checkpoint"* ]]
|
|
}
|
|
|
|
@test "a symlinked artifact is refused: a HF snapshot link dangles in the container mount" {
|
|
ln -s "$TMP/artifact.bin" "$TMP/linked.bin"
|
|
call "require_file '$TMP/linked.bin' checkpoint 'fetch it'"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"checkpoint"*"missing"* ]]
|
|
}
|
|
|
|
@test "the byte gate accepts the exact contracted size" {
|
|
call "require_bytes '$TMP/artifact.bin' checkpoint 12 'fetch it'"
|
|
[ "$status" -eq 0 ]
|
|
[ -z "$output" ]
|
|
}
|
|
|
|
@test "the byte gate refuses a size mismatch quoting both the real and the expected size" {
|
|
# The Hub's declared byte count is the contract; curl writes the error
|
|
# body and exits 0, so a truncation is invisible without this gate.
|
|
call "require_bytes '$TMP/artifact.bin' checkpoint 42 'run the fetch script'"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"12 bytes"* ]]
|
|
[[ "$output" == *"expected 42"* ]]
|
|
[[ "$output" == *"run the fetch script"* ]]
|
|
}
|
|
|
|
@test "the byte gate is an equality contract, not a floor" {
|
|
# A LARGER file is not a better artifact: it is a different artifact
|
|
# (the compacted r2 of a checkpoint is byte-exact, not "at least").
|
|
call "require_bytes '$TMP/artifact.bin' checkpoint 6 'fetch it'"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"expected 6"* ]]
|
|
}
|
|
|
|
@test "the minimum-size gate accepts the threshold itself" {
|
|
dd if=/dev/zero of="$TMP/two-mib.rad" bs=1048576 count=2 status=none
|
|
call "require_min_mib '$TMP/two-mib.rad' container 2 'rebuild it'"
|
|
[ "$status" -eq 0 ]
|
|
[ -z "$output" ]
|
|
}
|
|
|
|
@test "the minimum-size gate refuses below the threshold naming both sizes" {
|
|
dd if=/dev/zero of="$TMP/one-mib.rad" bs=1048576 count=1 status=none
|
|
call "require_min_mib '$TMP/one-mib.rad' container 2 'rebuild it'"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"1 MiB"* ]]
|
|
[[ "$output" == *"2 MiB"* ]]
|
|
[[ "$output" == *"rebuild it"* ]]
|
|
}
|
|
|
|
@test "the flat-directory gate accepts a directory of regular files" {
|
|
call "require_dir_files '$TMP/flat' tokenizer 'fetch the tokenizer' tokenizer.json config.json"
|
|
[ "$status" -eq 0 ]
|
|
[ -z "$output" ]
|
|
}
|
|
|
|
@test "the flat-directory gate names the member that is absent" {
|
|
call "require_dir_files '$TMP/flat' tokenizer 'fetch the tokenizer' tokenizer.json vocab.json"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"tokenizer"*"missing"* ]]
|
|
[[ "$output" == *"vocab.json"* ]]
|
|
}
|
|
|
|
@test "the flat-directory gate refuses a symlinked member" {
|
|
# A HuggingFace cache snapshot's entries are symlinks into blobs/ and
|
|
# dangle inside the container mount even when the directory is real.
|
|
ln -s /nowhere/x "$TMP/flat/vocab.json"
|
|
call "require_dir_files '$TMP/flat' tokenizer 'fetch the tokenizer' tokenizer.json vocab.json"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"vocab.json"*"missing or a symlink"* ]]
|
|
}
|
|
|
|
@test "the flat-directory gate refuses a missing directory" {
|
|
call "require_dir_files '$TMP/nope' tokenizer 'fetch the tokenizer' tokenizer.json"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"tokenizer: missing"* ]]
|
|
}
|
|
|
|
@test "the flat-directory gate refuses a symlinked directory" {
|
|
# The snapshot directory itself can be the link (a HF cache blobs/
|
|
# sibling), and a link into the container mount dangles there too.
|
|
ln -s "$TMP/flat" "$TMP/linked-dir"
|
|
call "require_dir_files '$TMP/linked-dir' tokenizer 'fetch the tokenizer' tokenizer.json"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"tokenizer: missing"* ]]
|
|
}
|
|
|
|
@test "the image gate refuses a ref the storage does not hold" {
|
|
# A name@sha256 ref exists only if THAT manifest was pulled, so the
|
|
# gate is the ref itself — one command, no grep race.
|
|
skip_if_no_podman
|
|
call "require_image 'example.invalid/nothing@sha256:0000000000000000000000000000000000000000000000000000000000000000' 'podman pull it'"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == *"not in podman storage"* ]]
|
|
[[ "$output" == *"podman pull it"* ]]
|
|
}
|
|
|
|
@test "every failure names the endpoint the operator is standing in front of" {
|
|
GATE_PREFIX=frank-dragoon call "require_file '$TMP/absent.bin' checkpoint 'fetch it'"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" == frank-dragoon:* ]]
|
|
}
|
|
|
|
@test "a failing gate stops the caller from reaching the runtime" {
|
|
# The composition property that matters: the gate is not advisory. A
|
|
# serve script that calls it and then execs the engine must die first.
|
|
cat > "$TMP/serve-like.sh" <<EOF
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
source '$LIB'
|
|
require_file '$TMP/absent.bin' checkpoint 'fetch it'
|
|
echo RUNTIME-EXECUTED
|
|
EOF
|
|
run bash "$TMP/serve-like.sh"
|
|
[ "$status" -ne 0 ]
|
|
[[ "$output" != *"RUNTIME-EXECUTED"* ]]
|
|
[[ "$output" == *"checkpoint: missing"* ]]
|
|
}
|