The serve scripts and the deployer each hand-wrote the same missing/truncated
artifact gates; the 2026-10-01 crash-loop was those twins disagreeing
mid-cutover. scripts/lib/llm-gates.sh is the single place the refusal lives:
require_file / require_bytes / require_min_mib / require_dir_files /
require_image, each returning 1 and naming the endpoint, the artifact and the
remedy. New seam tests/llm_gates.bats pins the contract at the arguments-in /
status-and-stderr-out boundary.
New seams (written first, red against the pre-merge tree):
- llm_units.bats: every scripts/*.service unit points at files that
exist in this repo (the merged checkout path), env files included
- llm_secrets.bats: the live sudo password is never tracked (the
vllmScripts AGENTS.md once documented it)
- deployment_flow.bats: deploy.sh must restart the LLM services on
both targets and health-check both endpoints (7770, 52625)
- helpers.bash: has_no_leaked_sudo_pw (two-part assembly, same
pattern as the gitea check)