The gemma-4-26b-a4b slugs were the last users of the purged `vllm-nightly-clean` engine. Migrate them to AWQ-4bit on stock `vllm-stable` v0.22.0, retiring the Ampere-dead AutoRound path. Why AutoRound is dead on Ampere: AutoRound int4-MIXED packs to `uint8b128`, which has no W4A16 kernel on sm_86 (Cutlass/Machete are Hopper-only; Triton W4A16 takes only uint4b8/uint4). The cyankiwi AWQ-4bit (pure uint4, compressed-tensors) resolves to Marlin WNA16 MoE on sm_86 and serves cleanly. Slug changes (registry 38 -> 36): - REMOVE vllm/gemma-a4b, vllm/gemma-a4b-awq (AutoRound/AWQ-bf16 duals) - RENAME vllm/gemma-a4b-single -> vllm/gemma-26ba4b-single (AWQ tp=1, :8040) - RENAME vllm/gemma-a4b-awq-mtp -> vllm/gemma-26ba4b-dual (AWQ tp=2 + ext MTP, :8041) Both on vllm-stable, kv bf16 (kv_cache_dtype=auto), kvcalc_key=SKIP (experimental; rebench-full/soak pending before Production). PR #40886 (AWQ compressed-tensors MoE key remap) is native in v0.22.0 — the vendored overlay + install entrypoint are dropped; patch marked deprecated_on 2026-06-06. vllm-nightly-clean deprecated (final purged-nightly engine, now zero registry users); gemma4-swa-moe added to vllm-stable supported_model_families; arch_patches engine_pin flipped to [email protected].0 loads:true. Boot-validated on 2x 3090 (2026-06-06): single tp=1 coherent + clean gemma4 tool-call; dual tp=2 + external MTP (num_spec_tokens=4) coherent + clean tool-call, draft layers wired. 3 AutoRound/AWQ-bf16 composes moved to _archive/ (kept for a future Hopper engine). Gate: 42/42 green. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
479 lines
22 KiB
Bash
Executable File
479 lines
22 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# test-submit-pull.sh — v0.8.2 STEP V2 (CONTRACT-1.2 / 1.3).
|
|
#
|
|
# Contract test for the user-invoked, consented failure on-ramp:
|
|
# scripts/pull.sh --submit-last / --submit <capture-dir>
|
|
# + the CONTRACT-1.2 surfacing pointer. The test IS the spec; the code is
|
|
# fixed to it. NO live Docker / GPU / HF-API and ZERO network / ZERO real
|
|
# `gh`: every `gh` invocation goes through an INJECTED mock `gh_runner`;
|
|
# consent is driven via an injected `_input`; capture bundles are built by
|
|
# the REAL `capture.emit_gate_capture` (genuine schema:2 artifacts) parsed
|
|
# via F1's read_gate_bundle and classified via the REAL F2 `classify`.
|
|
#
|
|
# Coverage (every CONTRACT-1.2 / 1.3 + RED-LINE assertion as a
|
|
# failing-then-passing check):
|
|
# * `--submit-last` resolves `.pull-captures/.last` (the V1 shared marker,
|
|
# read-only here); absent/stale -> the exact CONTRACT-1.3 error.
|
|
# * the `.last`-marker RACE: a SECOND terminal capture overwrites `.last`
|
|
# between capture and `--submit-last`; the verb RE-READS `.last` and
|
|
# re-shows the CURRENT bundle identity (no silent wrong-bundle submit).
|
|
# * consent: explicit `y` required; a decline performs ZERO network.
|
|
# * gh present (mock auth ok) -> reuses the SHIPPED F5 `dedup.submit`
|
|
# (effective_dedup_hash, bounded labels, +1-or-open) — NOT reimplemented.
|
|
# * gh-less + should_file=True (engine-support-unknown/no-arch-row ->
|
|
# kernel-unsupported): a prefilled PUBLIC issues/new URL carrying the
|
|
# loop:dedup-<hash> label.
|
|
# * gh-less + review-queued (`unknown` -> a correct-refusal abort_reason):
|
|
# the LOCAL _review-queue spool path + the no-public-issue line and
|
|
# ABSOLUTELY NO public issues/new URL (the §6.1 review-queue boundary).
|
|
# * CONTRACT-1.2: the surfacing pointer + `.last` fire whenever a gate
|
|
# bundle was EMITTED, regardless of exit code — proven on the
|
|
# bundle-emitted-but-exit-0 bypassable C0 path (NOT only exit-2).
|
|
# * leak-hygiene: nothing the on-ramp tells the user to share carries an
|
|
# unredacted absolute path.
|
|
# * gate path stays I/O-free: run_pull performs NO network / NO prompt /
|
|
# NO auto-send (the surfacing is a single stdout line, post-return).
|
|
# * import-time safety: importing submit_pull then kv-calc --calibration
|
|
# stays Overall: 7/7.
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
cd "$ROOT_DIR"
|
|
export PYTHONPATH="$ROOT_DIR${PYTHONPATH:+:$PYTHONPATH}"
|
|
|
|
python3 - "$ROOT_DIR" <<'PY'
|
|
from __future__ import annotations
|
|
|
|
import io
|
|
import json
|
|
import sys
|
|
import tempfile
|
|
from contextlib import redirect_stdout, redirect_stderr
|
|
from pathlib import Path
|
|
|
|
root = Path(sys.argv[1])
|
|
sys.path.insert(0, str(root))
|
|
|
|
from scripts.lib.profiles import capture as CAP # noqa: E402
|
|
from scripts.lib.profiles import dedup as D # noqa: E402
|
|
from scripts.lib.profiles import submit_pull as S # noqa: E402
|
|
from scripts.lib.profiles.classifier import ( # noqa: E402
|
|
FailureClass,
|
|
classify,
|
|
)
|
|
from scripts.lib.profiles.loop_input import read_gate_bundle # noqa: E402
|
|
|
|
failures: list[str] = []
|
|
|
|
|
|
def check(cond: bool, msg: str) -> None:
|
|
if cond:
|
|
print(f"PASS: {msg}")
|
|
else:
|
|
print(f"FAIL: {msg}", file=sys.stderr)
|
|
failures.append(msg)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Mock gh_runner — ZERO network / `gh`. Records argv; `auth status` ok/not.
|
|
# (Reuses the shipped D.GhResult seam so the type matches dedup.submit.)
|
|
# ---------------------------------------------------------------------------
|
|
class MockGh:
|
|
def __init__(self, *, authed=True):
|
|
self.calls: list[list[str]] = []
|
|
self.authed = authed
|
|
self.list_response = "[]"
|
|
|
|
def __call__(self, argv):
|
|
argv = list(argv)
|
|
self.calls.append(argv)
|
|
if argv[:2] == ["auth", "status"]:
|
|
return D.GhResult(self.authed, 0 if self.authed else 1, "",
|
|
"" if self.authed else "not logged in")
|
|
if not self.authed:
|
|
return D.GhResult(False, 127, "", "gh not found (mock)")
|
|
if argv[:2] == ["issue", "list"]:
|
|
return D.GhResult(True, 0, self.list_response, "")
|
|
if argv[:2] == ["issue", "create"]:
|
|
return D.GhResult(
|
|
True, 0,
|
|
"https://github.com/noonghunna/club-3090/issues/777", "")
|
|
if argv[:2] == ["issue", "comment"]:
|
|
return D.GhResult(True, 0, "", "")
|
|
if argv[:2] == ["label", "create"]:
|
|
return D.GhResult(True, 0, "", "")
|
|
return D.GhResult(True, 0, "", "")
|
|
|
|
|
|
def emit_gate(repo_root: Path, *, slug, abort_reason, ts) -> Path:
|
|
"""Build a REAL schema:2 gate bundle via the shipped emitter (also
|
|
writes the shared `.last` marker — V1 centralization)."""
|
|
out = CAP.emit_gate_capture(
|
|
slug=slug,
|
|
profile_like="vllm/minimal",
|
|
abort_reason=abort_reason,
|
|
confidence=None,
|
|
raw_verdict=None,
|
|
detail=f"gate hard-block: {abort_reason}",
|
|
der=None,
|
|
hardware_sm=8.6,
|
|
gpu_topology=(2, [24576, 24576], ["RTX 3090", "RTX 3090"]),
|
|
club3090_commit="cafef00d",
|
|
kv_calc_version="kvcalc-v0.8.0",
|
|
repo_root=repo_root,
|
|
ts=ts,
|
|
)
|
|
return Path(out["dir"])
|
|
|
|
|
|
def run_submit(repo_root, *, submit_last=True, capture_dir=None,
|
|
consent="y", gh):
|
|
"""Invoke the verb capturing stdout/stderr; ZERO network (mock gh)."""
|
|
out, err = io.StringIO(), io.StringIO()
|
|
answers = iter([consent])
|
|
|
|
def _inp(_prompt):
|
|
try:
|
|
return next(answers)
|
|
except StopIteration:
|
|
return ""
|
|
|
|
with redirect_stdout(out), redirect_stderr(err):
|
|
rc = S.submit_pull(
|
|
capture_dir=capture_dir,
|
|
submit_last=submit_last,
|
|
repo_root=Path(repo_root),
|
|
gh_runner=gh,
|
|
_input=_inp,
|
|
)
|
|
return rc, out.getvalue(), err.getvalue()
|
|
|
|
|
|
# ===========================================================================
|
|
# 1. --submit-last with NO marker -> the exact CONTRACT-1.3 error, rc=2.
|
|
# ===========================================================================
|
|
rr = Path(tempfile.mkdtemp())
|
|
gh = MockGh(authed=True)
|
|
rc, so, se = run_submit(rr, gh=gh)
|
|
check(rc == 2 and "no recent capture" in se
|
|
and "--submit <dir>" in se,
|
|
"no `.last` -> the CONTRACT-1.3 error 'no recent capture; use "
|
|
"`--submit <dir>`' (rc=2)")
|
|
check(gh.calls == [],
|
|
"unresolvable bundle -> ZERO gh calls (no network before resolve)")
|
|
|
|
# ===========================================================================
|
|
# 2. gh present + should_file=True (no-arch-row) -> reuses SHIPPED F5
|
|
# dedup.submit (NOT reimplemented). Consent `y` required first.
|
|
# ===========================================================================
|
|
rr = Path(tempfile.mkdtemp())
|
|
gd = emit_gate(rr, slug="Org/Exotic",
|
|
abort_reason="engine-support-unknown/no-arch-row",
|
|
ts="20260518T000001Z")
|
|
# Sanity: the real F1/F2 route this to kernel-unsupported / should_file.
|
|
_fi = read_gate_bundle(gd)
|
|
_cl = classify(_fi)
|
|
check(_cl.failure_class is FailureClass.KERNEL_UNSUPPORTED
|
|
and _cl.should_file is True,
|
|
"no-arch-row gate bundle classifies kernel-unsupported/should_file "
|
|
"(the §10-R9 solicited lever) via the REAL shipped F2")
|
|
|
|
gh = MockGh(authed=True)
|
|
rc, so, se = run_submit(rr, gh=gh, consent="y")
|
|
check(rc == 0 and "F5 action=" in so,
|
|
"gh present + consent y -> reuses the shipped F5 dedup.submit "
|
|
f"(rc={rc})")
|
|
check(any(c[:2] == ["issue", "list"] for c in gh.calls)
|
|
and any(c[:2] == ["issue", "create"] for c in gh.calls),
|
|
"F5 ran the shipped path (gh issue list then create) — NOT a "
|
|
"reimplemented submit")
|
|
|
|
# ===========================================================================
|
|
# 3. Consent gate: a decline performs ZERO network.
|
|
# ===========================================================================
|
|
gh = MockGh(authed=True)
|
|
rc, so, se = run_submit(rr, gh=gh, consent="n")
|
|
issue_calls = [c for c in gh.calls if c[:1] == ["issue"]]
|
|
check(rc == 0 and "declined" in so and not issue_calls,
|
|
"explicit decline -> nothing sent, ZERO `gh issue` network calls")
|
|
|
|
# ===========================================================================
|
|
# 4. The `.last`-marker RACE (RED-LINE): a SECOND capture overwrites
|
|
# `.last` between capture and --submit-last; the verb RE-READS `.last`
|
|
# and re-shows the CURRENT bundle identity (no silent wrong-bundle).
|
|
# ===========================================================================
|
|
rr = Path(tempfile.mkdtemp())
|
|
g_first = emit_gate(rr, slug="Org/First",
|
|
abort_reason="engine-support-unknown/no-arch-row",
|
|
ts="20260518T000010Z")
|
|
# A second terminal capture (a racing pull) overwrites `.last`.
|
|
g_second = emit_gate(rr, slug="Org/Second",
|
|
abort_reason="engine-support-unknown/no-arch-row",
|
|
ts="20260518T000011Z")
|
|
marker = (rr / ".pull-captures" / ".last").read_text().strip()
|
|
check(marker == str(g_second.relative_to(rr / ".pull-captures")),
|
|
"the shared `.last` marker is last-writer-wins (points at the SECOND "
|
|
"capture after the racing pull)")
|
|
gh = MockGh(authed=True)
|
|
rc, so, se = run_submit(rr, gh=gh, consent="n") # decline; only inspect.
|
|
check("Org/Second" in so and "Org/First" not in so,
|
|
"--submit-last RE-READS `.last` at submit + re-shows the CURRENT "
|
|
"(SECOND) bundle identity — NO silent wrong-bundle submit")
|
|
check(S.resolve_last(rr).resolve() == g_second.resolve(),
|
|
"resolve_last() resolves the marker's CURRENT target (the race "
|
|
"defense is keyed on a re-read, not a stale capture-time value)")
|
|
|
|
# ===========================================================================
|
|
# 5. gh-less + should_file=True -> a prefilled PUBLIC issues/new URL with
|
|
# the loop:dedup-<hash> label; NO `gh issue` calls.
|
|
# ===========================================================================
|
|
rr = Path(tempfile.mkdtemp())
|
|
gd = emit_gate(rr, slug="Org/Exotic",
|
|
abort_reason="engine-support-unknown/no-arch-row",
|
|
ts="20260518T000020Z")
|
|
gh = MockGh(authed=False) # gh unavailable / unauthed.
|
|
rc, so, se = run_submit(rr, gh=gh, consent="y")
|
|
fi = read_gate_bundle(gd)
|
|
cl = classify(fi)
|
|
h = D.effective_dedup_hash(fi, cl)
|
|
check(rc == 0
|
|
and "https://github.com/noonghunna/club-3090/issues/new?" in so
|
|
and f"loop%3Adedup-{h}" in so.replace("loop:dedup-", "loop%3Adedup-")
|
|
or f"loop:dedup-{h}" in so,
|
|
"gh-less + should_file=True -> a prefilled PUBLIC issues/new URL "
|
|
"(carries the loop:dedup-<hash> label)")
|
|
issue_calls = [c for c in gh.calls if c[:1] == ["issue"]]
|
|
check(not issue_calls,
|
|
"gh-less path makes ZERO `gh issue` network calls (paste-only)")
|
|
|
|
# Use the structured fallback API to assert the URL precisely.
|
|
fb = S.ghless_fallback(fi, cl, repo_root=rr, bundle_dir=gd)
|
|
check(fb["kind"] == "ghless-public-url" and fb["should_file"] is True
|
|
and fb["url"].startswith(
|
|
"https://github.com/noonghunna/club-3090/issues/new?")
|
|
and f"loop:dedup-{h}" in __import__("urllib.parse",
|
|
fromlist=["unquote"]).unquote(fb["url"]),
|
|
"ghless_fallback(should_file=True): public issues/new URL, "
|
|
"loop:dedup-<hash> label, deterministic")
|
|
# Title template: [<model>] <failure-class> on <topology> (dedup:<hash8>)
|
|
import urllib.parse as _up # noqa: E402
|
|
_q = _up.parse_qs(_up.urlparse(fb["url"]).query)
|
|
_title = _q["title"][0]
|
|
check(_title == f"[Org/Exotic] kernel-unsupported on 2x24576MiB "
|
|
f"(dedup:{h[:8]})",
|
|
f"gh-less deterministic title template (got {_title!r})")
|
|
|
|
# ===========================================================================
|
|
# 6. gh-less + review-queued (`unknown` correct-refusal) -> the LOCAL
|
|
# _review-queue spool path + the no-public-issue line; ABSOLUTELY NO
|
|
# public issues/new URL (the §6.1 review-queue boundary, RED-LINE).
|
|
# ===========================================================================
|
|
rr = Path(tempfile.mkdtemp())
|
|
gd = emit_gate(rr, slug="Org/DiskShort", abort_reason="disk-short",
|
|
ts="20260518T000030Z")
|
|
fi = read_gate_bundle(gd)
|
|
cl = classify(fi)
|
|
check(cl.failure_class is FailureClass.UNKNOWN
|
|
and cl.should_file is False,
|
|
"disk-short gate bundle classifies `unknown`/should_file=False "
|
|
"(a correct-refusal — review-queued, NOT public-filed)")
|
|
gh = MockGh(authed=False)
|
|
rc, so, se = run_submit(rr, gh=gh, consent="y")
|
|
check(rc == 0
|
|
and "not a public issue" in so
|
|
and "_review-queue" in so
|
|
and "issues/new" not in so
|
|
and "github.com" not in so,
|
|
"gh-less + review-queued -> local _review-queue spool path + the "
|
|
"no-public-issue line, ABSOLUTELY NO public issues/new URL")
|
|
fb = S.ghless_fallback(fi, cl, repo_root=rr, bundle_dir=gd)
|
|
check(fb["kind"] == "ghless-review-queued"
|
|
and fb["should_file"] is False
|
|
and "url" not in fb
|
|
and fb["spool_path"].endswith("_review-queue/"
|
|
f"{D.effective_dedup_hash(fi, cl)}.json"),
|
|
"ghless_fallback(review-queued): NO `url` key, points at the "
|
|
"_review-queue spool — the §6.1 boundary the suppression design "
|
|
"exists to keep clean")
|
|
|
|
# ===========================================================================
|
|
# 7. CONTRACT-1.2 RED-LINE — the surfacing pointer + `.last` fire whenever
|
|
# a gate bundle was EMITTED, regardless of exit code. Proven on the
|
|
# bundle-emitted-but-exit-0 bypassable C0 path (NOT only exit-2).
|
|
# ===========================================================================
|
|
from scripts.lib.profiles import pull as P # noqa: E402
|
|
|
|
|
|
class _Diag(dict):
|
|
pass
|
|
|
|
|
|
def _fake_res(*, ok, abort_reason, gate_dir):
|
|
"""A minimal PullResult-shaped object exercising main()'s surfacing
|
|
branch directly (the surfacing is keyed on
|
|
res.diagnostics['gate_capture']['dir'], NOT the exit code)."""
|
|
r = P.PullResult(
|
|
slug="Org/Phi", profile_like="vllm/minimal",
|
|
path="B", ok=ok, stratum=P.Stratum.C0,
|
|
)
|
|
r.abort_reason = abort_reason
|
|
r.diagnostics = {"gate_capture": {"dir": gate_dir}}
|
|
return r
|
|
|
|
|
|
# Exit-0 bypassable advisory path (ok-ish / non-abort-2) WITH an emitted
|
|
# bundle vs exit-2 hard-block WITH an emitted bundle: BOTH must surface.
|
|
buf0 = io.StringIO()
|
|
r0 = _fake_res(ok=True, abort_reason=None, gate_dir="/x/cap/exit0")
|
|
with redirect_stdout(buf0):
|
|
# Mirror main()'s post-return surfacing branch verbatim.
|
|
_gc = r0.diagnostics.get("gate_capture")
|
|
_gd0 = _gc.get("dir") if isinstance(_gc, dict) else None
|
|
if _gd0:
|
|
print(f"[pull] Diagnostics captured (redacted, no paths/tokens): "
|
|
f"{_gd0}")
|
|
print("[pull] Help improve the fit math — submit with: "
|
|
"scripts/pull.sh --submit-last")
|
|
out0 = buf0.getvalue()
|
|
check("Diagnostics captured" in out0 and "--submit-last" in out0,
|
|
"CONTRACT-1.2: an emitted gate bundle on the EXIT-0 bypassable path "
|
|
"still surfaces the submit pointer (NOT gated on exit==2 — the "
|
|
"no-arch-row §10-R9 lever is the exit-0 path)")
|
|
|
|
# Negative control: NO gate bundle emitted -> NO surfacing line.
|
|
buf_n = io.StringIO()
|
|
with redirect_stdout(buf_n):
|
|
_gc = ({}).get("gate_capture")
|
|
_gdn = _gc.get("dir") if isinstance(_gc, dict) else None
|
|
if _gdn:
|
|
print("[pull] Diagnostics captured ...")
|
|
check("Diagnostics captured" not in buf_n.getvalue(),
|
|
"CONTRACT-1.2: NO gate bundle emitted -> NO surfacing line "
|
|
"(trigger is bundle-emitted, precisely)")
|
|
|
|
# The real main() wiring: assert the surfacing branch reads
|
|
# diagnostics['gate_capture']['dir'] (source inspection — keyed on the
|
|
# bundle, not the exit code).
|
|
import inspect # noqa: E402
|
|
_msrc = inspect.getsource(P.main)
|
|
# The surfacing branch lives BEFORE `if res.ok:` and is keyed on the
|
|
# emitted gate-bundle dir; isolate that span and prove no exit-code gate.
|
|
_surf = _msrc.split('res.diagnostics.get("gate_capture")')[1].split(
|
|
"if res.ok:")[0]
|
|
check('res.diagnostics.get("gate_capture")' in _msrc
|
|
and '.get("dir")' in _surf
|
|
and "Diagnostics captured" in _surf
|
|
and "--submit-last" in _surf
|
|
and "_EXIT_ABORT" not in _surf
|
|
and "_EXIT_NEEDS_FLAG" not in _surf
|
|
and "res.ok" not in _surf,
|
|
"CONTRACT-1.2 wiring: main() surfacing is keyed on the emitted gate "
|
|
"bundle dir, with NO exit-code gate around it")
|
|
|
|
# ===========================================================================
|
|
# 8. Gate path is I/O-FREE (RED-LINE): submit_pull is the ONLY network
|
|
# site; run_pull has no submit/network/prompt. Source-level proof
|
|
# (run_pull never imports/calls submit_pull or gh).
|
|
# ===========================================================================
|
|
_rp_src = inspect.getsource(P.run_pull)
|
|
check("submit_pull" not in _rp_src and "gh_runner" not in _rp_src
|
|
and "_real_gh_runner" not in _rp_src and "input(" not in _rp_src,
|
|
"RED-LINE: run_pull (the gate path) has NO submit/gh/network/blocking-"
|
|
"prompt — submission is the separate, explicit, consented verb only")
|
|
# submit_pull REUSES dedup.submit + dedup.effective_dedup_hash (it never
|
|
# reimplements the F5 hash/serialization primitive — every dedup-hash use
|
|
# is qualified `_DEDUP.effective_dedup_hash`, never a local sha256 join).
|
|
_sp_src = inspect.getsource(S)
|
|
import re as _re # noqa: E402
|
|
_unqualified_eff = _re.findall(
|
|
r"(?<!_DEDUP\.)\beffective_dedup_hash\s*\(", _sp_src)
|
|
check("_DEDUP.submit(" in _sp_src
|
|
and "_DEDUP.effective_dedup_hash(" in _sp_src
|
|
and not _unqualified_eff
|
|
and "hashlib" not in _sp_src
|
|
and "sha256" not in _sp_src,
|
|
"RED-LINE: submit_pull REUSES the shipped dedup.submit / "
|
|
"dedup.effective_dedup_hash — it does NOT reimplement F5 dedup "
|
|
"(no local hashlib/sha256, no unqualified effective_dedup_hash)")
|
|
|
|
# ===========================================================================
|
|
# 9. Leak-hygiene (RED-LINE): nothing the on-ramp tells the user to share
|
|
# carries an unredacted absolute host path.
|
|
# ===========================================================================
|
|
rr = Path(tempfile.mkdtemp())
|
|
gd = emit_gate(rr, slug="Org/Exotic",
|
|
abort_reason="engine-support-unknown/no-arch-row",
|
|
ts="20260518T000040Z")
|
|
fi = read_gate_bundle(gd)
|
|
cl = classify(fi)
|
|
fb = S.ghless_fallback(fi, cl, repo_root=rr, bundle_dir=gd)
|
|
import urllib.parse as _up2 # noqa: E402
|
|
_decoded_body = _up2.unquote(
|
|
_up2.parse_qs(_up2.urlparse(fb["url"]).query)["body"][0])
|
|
_PCN = ".pull-captures"
|
|
check("/opt/ai" not in _decoded_body and "/home/" not in _decoded_body
|
|
and "/mnt/" not in _decoded_body,
|
|
"leak-hygiene: the gh-less URL body (built from the [E]-redacted "
|
|
"manifest) carries NO unredacted internal absolute path")
|
|
# RIG-INDEPENDENT (the real catch the /opt|/home check missed when gd was a
|
|
# tmp sandbox dir): the ABSOLUTE bundle dir must NEVER appear in the public-
|
|
# paste body; only the repo-relative `.pull-captures/...` pointer may.
|
|
check(str(gd) not in _decoded_body,
|
|
"leak-hygiene: the gh-less body MUST NOT contain the absolute capture "
|
|
f"dir ({gd}) — public-paste content is repo-relative only")
|
|
check(_PCN in _decoded_body and not any(
|
|
_seg.startswith("/") for _seg in _decoded_body.split("`")
|
|
if _PCN in _seg),
|
|
"leak-hygiene: the gh-less body's bundle pointer is repo-relative "
|
|
f"(`{_PCN}/<slug>/<ts>`), never an absolute path")
|
|
# The redacted-bundle pointer the message prints is the local capture dir
|
|
# (a tmp path here, by design the on-ramp's only emitted artifact) — assert
|
|
# the message NEVER instructs pasting terminal scrollback.
|
|
for ln in fb["lines"]:
|
|
check("paste your terminal" not in ln.lower()
|
|
and "terminal output" not in ln.lower(),
|
|
"leak-hygiene: the on-ramp never tells the user to paste their "
|
|
"terminal scrollback (console is not a safe submission source)")
|
|
|
|
# ===========================================================================
|
|
# 10. import-time safety: importing submit_pull then kv-calc --calibration
|
|
# stays Overall: 7/7 (no import side effects on the calibrator).
|
|
# ===========================================================================
|
|
import subprocess # noqa: E402
|
|
_cp = subprocess.run(
|
|
[sys.executable, str(root / "tools" / "kv-calc.py"), "--calibration"],
|
|
capture_output=True, text=True, cwd=str(root))
|
|
check("Overall: 7/7 (100%)" in _cp.stdout,
|
|
"import-time safety: submit_pull import does not perturb "
|
|
"kv-calc --calibration (still Overall: 7/7)")
|
|
|
|
# ===========================================================================
|
|
if failures:
|
|
print(f"\nSUMMARY: {len(failures)} assertion(s) FAILED.",
|
|
file=sys.stderr)
|
|
for f in failures:
|
|
print(f" - {f}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
print("\nSUMMARY: all v0.8.2 STEP V2 submit/on-ramp assertions passed "
|
|
"(CONTRACT-1.2 surfacing keyed on bundle-emitted-not-exit-code; "
|
|
"CONTRACT-1.3 --submit-last/--submit, consent, .last race re-read, "
|
|
"F5 reuse, gh-less should_file branch with NO public URL for "
|
|
"review-queued; gate path I/O-free; leak-clean).")
|
|
PY
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# CLI-contract: the submit verb is parsed BEFORE the slug/--profile-like
|
|
# requirement (a distinct top-level verb). NO network (no real `gh` resolves
|
|
# because no `.last` exists in a clean CI tree -> the rc=2 error path).
|
|
# ---------------------------------------------------------------------------
|
|
rm -rf "$ROOT_DIR/.pull-captures"
|
|
_sc(){ bash scripts/pull.sh "$@" >/dev/null 2>&1; echo $?; }
|
|
[ "$(_sc --submit-last)" = 2 ] || { echo "FAIL: --submit-last with no .last -> 2 (parsed w/o slug/--profile-like)" >&2; exit 1; }
|
|
[ "$(_sc --submit /nonexistent-xyz)" = 2 ] || { echo "FAIL: --submit <bad> -> 2 (parsed w/o slug/--profile-like)" >&2; exit 1; }
|
|
echo "PASS: --submit*/--submit-last is a distinct top-level verb (needs no slug/--profile-like; rc=2 on unresolvable, no network)"
|
|
rm -rf "$ROOT_DIR/.pull-captures"
|
|
|
|
echo "test-submit-pull.sh OK"
|