Refresh the remaining test fixtures after archiving Genesis and purged-nightly vLLM composes. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
297 lines
12 KiB
Bash
Executable File
297 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# test-generate-compose.sh — v0.8.0 STEP 4 (club-3090 #141 / PR #147).
|
|
#
|
|
# Golden-parity + refusal/degraded contract for scripts/generate-compose.sh.
|
|
# This test is the contract; the generator is fixed to it (never the
|
|
# reverse). It imports the STEP-2 patch_attribution.reaches() — it does NOT
|
|
# reimplement compose parsing or reachability (RED-LINE).
|
|
#
|
|
# 5 golden triples, all verified genesis_equipped:false in
|
|
# profile_runtime.yml, spanning every in-scope engine class:
|
|
# vllm/minimal vllm-stable, tp1, fp8, drafter=None
|
|
# vllm/dual vllm-stable, tp2, fp8, mtp
|
|
# vllm/gemma-bf16-mtp vllm-gemma-stable, gemma, bf16
|
|
# vllm/gemma-int8-mtp vllm-gemma-stable, int8-PTH, multi-file overlay
|
|
# vllm/gemma-mtp-tp1 vllm-gemma-stable, single-card fp8 risk path
|
|
#
|
|
# Per triple: generate -> semantic diff vs the shipped compose differs ONLY
|
|
# at the two patch insertion points (image expression + every constant
|
|
# reproduce verbatim) -> selected+wired subset-of shipped -> wired patches
|
|
# pass reaches() on the GENERATED compose (actual wiring, not header text)
|
|
# -> selected-but-undelivered NOT reachable -> 3-category header present ->
|
|
# NO --trust-remote-code emitted. Plus the refusal/degraded matrix.
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
|
|
python3 - "$ROOT_DIR" <<'PY'
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
root = Path(sys.argv[1])
|
|
sys.path.insert(0, str(root))
|
|
|
|
from scripts.lib import generate_compose as gc # noqa: E402
|
|
from scripts.lib.profiles import patch_attribution as pa # noqa: E402
|
|
from scripts.lib.profiles.compose_registry import COMPOSE_REGISTRY # noqa: E402
|
|
|
|
errors: list[str] = []
|
|
|
|
|
|
def check(cond: bool, msg: str) -> None:
|
|
if not cond:
|
|
errors.append(msg)
|
|
|
|
|
|
patches = gc.load_patches(root)
|
|
pmap = {p["id"]: p for p in patches}
|
|
runtime = gc.load_runtime(root)
|
|
|
|
GOLDEN = [
|
|
"vllm/minimal",
|
|
"vllm/dual",
|
|
"vllm/gemma-bf16-mtp",
|
|
"vllm/gemma-int8-mtp",
|
|
"vllm/gemma-mtp-tp1",
|
|
]
|
|
|
|
# --------------------------------------------------------------------------
|
|
# 0. kv_arg map is unit-tested (brief §STEP 3 step 9 — documented + tested).
|
|
# --------------------------------------------------------------------------
|
|
KV_EXPECT = {
|
|
"bf16": None,
|
|
"fp16": None,
|
|
"fp8_e5m2": "fp8_e5m2",
|
|
"fp8_e4m3": "fp8",
|
|
"int8_per_token_head": "auto+PTH",
|
|
"q4_0": "q4_0",
|
|
"k8v4": "k8v4",
|
|
}
|
|
for fmt, want in KV_EXPECT.items():
|
|
got = gc.kv_arg(fmt)
|
|
check(got == want, f"kv_arg({fmt!r})={got!r}, expected {want!r}")
|
|
|
|
|
|
def normalize(body: str, markers: list[str]) -> list[str]:
|
|
"""Comment-free service body minus (a) the governed --trust-remote-code
|
|
token and (b) every patch-wiring insertion-point line for the profile's
|
|
selected patches. What remains is the constant/param substrate that must
|
|
reproduce verbatim between shipped and generated."""
|
|
out = []
|
|
for ln in body.splitlines():
|
|
s = ln.strip()
|
|
if s in ("- --trust-remote-code", "--trust-remote-code"):
|
|
continue
|
|
if any(m in ln for m in markers):
|
|
continue
|
|
if s == "":
|
|
continue
|
|
out.append(ln.rstrip())
|
|
return out
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# 1. Golden-parity per triple.
|
|
# --------------------------------------------------------------------------
|
|
for prof in GOLDEN:
|
|
prt = (runtime.get("profiles") or {}).get(prof) or {}
|
|
check(prt.get("genesis_equipped") is False,
|
|
f"{prof}: golden triple must be genesis_equipped:false")
|
|
|
|
out_text, meta = gc.generate(root, prof)
|
|
|
|
# 3-category header present, above `services:` (so service_body drops it).
|
|
check("[1] selected + WIRED" in out_text, f"{prof}: header missing category [1]")
|
|
check("[2] selected + UNDELIVERED" in out_text, f"{prof}: header missing category [2]")
|
|
check("[3] EXCLUDED" in out_text, f"{prof}: header missing category [3]")
|
|
check("GENERATED by scripts/generate-compose.sh" in out_text,
|
|
f"{prof}: header missing provenance line")
|
|
|
|
gen_body = pa.service_body(out_text)
|
|
shipped_path = root / meta["source"]
|
|
ship_body = pa.service_body(shipped_path.read_text(encoding="utf-8"))
|
|
|
|
# Header lives above services: -> service_body() must have removed it.
|
|
check("GENERATED by scripts/generate-compose.sh" not in gen_body,
|
|
f"{prof}: generator header leaked into the service body")
|
|
|
|
# Image expression reproduces verbatim (correction #2 — never rewritten).
|
|
shipped_image = next((ln.strip() for ln in ship_body.splitlines() if ln.strip().startswith("image: ")), None)
|
|
check(shipped_image is not None and shipped_image in gen_body,
|
|
f"{prof}: image expression not reproduced verbatim")
|
|
|
|
# NO --trust-remote-code emitted for an in-scope profile (correction #1).
|
|
check("--trust-remote-code" not in gen_body,
|
|
f"{prof}: --trust-remote-code emitted for in-scope profile")
|
|
check(meta["trc_emitted"] is False, f"{prof}: meta.trc_emitted must be False")
|
|
|
|
# Semantic diff differs ONLY at the two patch insertion points: with the
|
|
# governed trc token and the selected patches' wiring lines normalized
|
|
# away, the remaining body is byte-identical (constants verbatim).
|
|
selected = gc.select_patches(patches, prof)
|
|
markers: list[str] = []
|
|
for p in selected:
|
|
markers.extend(gc._patch_wiring_markers(p))
|
|
a = normalize(ship_body, markers)
|
|
b = normalize(gen_body, markers)
|
|
check(a == b,
|
|
f"{prof}: semantic diff is NOT confined to the two insertion points "
|
|
f"(+{len(set(b)-set(a))} / -{len(set(a)-set(b))} non-wiring lines)")
|
|
|
|
# selected+wired subset-of shipped patch set.
|
|
shipped_reaches = {
|
|
pid for pid in (meta["wired"] + meta["undelivered"] + meta["degraded_omitted"])
|
|
if pa.reaches(root, pmap[pid], meta["source"])
|
|
}
|
|
for pid in meta["wired"]:
|
|
check(pa.reaches(root, pmap[pid], meta["source"]),
|
|
f"{prof}: wired patch {pid} is not in the shipped compose "
|
|
f"(selected+wired must be a subset of shipped)")
|
|
|
|
# wired patches pass reaches() on the GENERATED compose (actual wiring,
|
|
# not header text — correction #4: the header WARNING block is above
|
|
# services: and is comment-stripped, so it cannot create a hit).
|
|
with tempfile.NamedTemporaryFile("w", suffix=".yml", delete=False) as fh:
|
|
fh.write(out_text)
|
|
gen_file = fh.name
|
|
try:
|
|
for pid in meta["wired"]:
|
|
check(pa.reaches(root, pmap[pid], gen_file),
|
|
f"{prof}: wired patch {pid} does not reach the GENERATED compose")
|
|
|
|
# selected-but-undelivered (delivery-gap) patches are NOT reachable
|
|
# in the generated compose (correction #4). The golden delivery-gap
|
|
# case is the python_sidecar qwen3coder patch — sound spec markers.
|
|
for pid in meta["undelivered"]:
|
|
check(not pa.reaches(root, pmap[pid], gen_file),
|
|
f"{prof}: undelivered patch {pid} is reachable in the "
|
|
f"generated compose (must be omitted)")
|
|
finally:
|
|
os.unlink(gen_file)
|
|
|
|
# At least one golden carries a real delivery-gap (the correction-#4 case).
|
|
_, m_min = gc.generate(root, "vllm/minimal")
|
|
check("qwen-qwen3coder-tool-parser-deferred-commit" in m_min["undelivered"],
|
|
"vllm/minimal must surface the qwen3coder delivery-gap as undelivered")
|
|
check("qwen-vllm-pr35936-required-fallback" in m_min["wired"],
|
|
"vllm/minimal must wire the pr35936 fallback")
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# 2. Refusals — scope gates + validation + foundational.
|
|
# --------------------------------------------------------------------------
|
|
def expect_refuse(profile: str, code: int, needle: str, accept_degraded=False,
|
|
env: dict | None = None) -> None:
|
|
saved = {}
|
|
if env:
|
|
for k, v in env.items():
|
|
saved[k] = os.environ.get(k)
|
|
os.environ[k] = v
|
|
try:
|
|
try:
|
|
gc.generate(root, profile, accept_degraded=accept_degraded)
|
|
errors.append(f"{profile}: expected Refuse({code}) [{needle}], generated OK")
|
|
except gc.Refuse as r:
|
|
check(r.code == code,
|
|
f"{profile}: refuse code {r.code}, expected {code}")
|
|
check(needle in str(r),
|
|
f"{profile}: refuse message {str(r)!r} missing {needle!r}")
|
|
finally:
|
|
if env:
|
|
for k, v in saved.items():
|
|
if v is None:
|
|
os.environ.pop(k, None)
|
|
else:
|
|
os.environ[k] = v
|
|
|
|
|
|
# genesis_equipped:true -> clean scope-gate refuse. No Genesis-equipped
|
|
# compose remains in the registry post-#254, so synthesize the profile_runtime
|
|
# bit that scope_gate consumes.
|
|
genesis_runtime = {
|
|
"profiles": {
|
|
"synthetic/genesis": {
|
|
"genesis_equipped": True,
|
|
"genesis_equipped_evidence": "synthetic test fixture",
|
|
}
|
|
}
|
|
}
|
|
try:
|
|
gc.scope_gate(
|
|
"vllm-nightly-mtp",
|
|
gc.load_engine(root, "vllm-nightly-mtp"),
|
|
genesis_runtime,
|
|
"synthetic/genesis",
|
|
)
|
|
errors.append("synthetic/genesis: expected genesis_equipped:true refuse")
|
|
except gc.Refuse as r:
|
|
check("genesis_equipped:true" in str(r),
|
|
f"synthetic/genesis: refuse message {str(r)!r} missing genesis_equipped:true")
|
|
|
|
# llama.cpp profile is outside the generator scope; current fixture lacks its engine profile.
|
|
expect_refuse("llamacpp/default", gc.EXIT_REFUSE, "engine profile not found")
|
|
|
|
# foundational failed-guard -> hard-refuse even with --accept-degraded.
|
|
expect_refuse("vllm/gemma-int8-mtp", gc.EXIT_REFUSE,
|
|
"foundational drift-guard failed", accept_degraded=True,
|
|
env={"CLUB3090_FORCE_GUARD_FAIL": "gemma-vllm-pr40391-rebased"})
|
|
|
|
# capability-scoped failed-guard -> DEGRADED, needs --accept-degraded.
|
|
expect_refuse("vllm/gemma-int8-mtp", gc.EXIT_DEGRADED_NOACK, "DEGRADED",
|
|
accept_degraded=False,
|
|
env={"CLUB3090_FORCE_GUARD_FAIL": "gemma-vllm-gemma4-tool-parser-fixes"})
|
|
|
|
# capability-scoped failed-guard WITH --accept-degraded -> proceeds, the
|
|
# patch is OMITTED (never wired) and the compose is flagged DEGRADED.
|
|
os.environ["CLUB3090_FORCE_GUARD_FAIL"] = "gemma-vllm-gemma4-tool-parser-fixes"
|
|
try:
|
|
dtext, dmeta = gc.generate(root, "vllm/gemma-int8-mtp", accept_degraded=True)
|
|
check(dmeta["degraded"] is True,
|
|
"gemma-int8 forced-fail: meta.degraded must be True")
|
|
check("gemma-vllm-gemma4-tool-parser-fixes" in dmeta["degraded_omitted"],
|
|
"gemma-int8 forced-fail: tool-parser patch must be in degraded_omitted")
|
|
check("gemma-vllm-gemma4-tool-parser-fixes" not in dmeta["wired"],
|
|
"gemma-int8 forced-fail: a failed-guard patch must NEVER be wired")
|
|
check("WARNING: DEGRADED" in dtext,
|
|
"gemma-int8 forced-fail: header must carry the DEGRADED warning")
|
|
dbody = pa.service_body(dtext)
|
|
leaked = [l for l in dbody.splitlines()
|
|
if "patches/vllm-gemma4-tool-parser-fixes/" in l and l.strip().startswith("-")]
|
|
check(not leaked,
|
|
f"gemma-int8 forced-fail: {len(leaked)} tool-parser overlay mount "
|
|
f"line(s) leaked into a DEGRADED-omitted compose")
|
|
finally:
|
|
os.environ.pop("CLUB3090_FORCE_GUARD_FAIL", None)
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# 3. Convenience tuple is NOT authoritative — prints matches, non-zero.
|
|
# --------------------------------------------------------------------------
|
|
rc = gc.main(["--model", "gemma-4-31b", "--engine", "vllm-gemma-stable"])
|
|
check(rc == gc.EXIT_AMBIGUOUS,
|
|
f"convenience tuple should exit EXIT_AMBIGUOUS, got {rc}")
|
|
rc = gc.main([])
|
|
check(rc == gc.EXIT_USAGE, f"no args should exit EXIT_USAGE, got {rc}")
|
|
rc = gc.main(["--profile", "vllm/does-not-exist"])
|
|
check(rc == gc.EXIT_USAGE, f"unknown profile should exit EXIT_USAGE, got {rc}")
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Verdict.
|
|
# --------------------------------------------------------------------------
|
|
if errors:
|
|
print("[generate-compose] FAIL")
|
|
for e in errors:
|
|
print(f" - {e}")
|
|
sys.exit(1)
|
|
|
|
print(f"[generate-compose] PASS: {len(GOLDEN)} golden triples, "
|
|
f"semantic-diff confined to insertion points, reaches() wired/undelivered "
|
|
f"verified, no --trust-remote-code emitted, refusal+degraded matrix green")
|
|
PY
|