diff --git a/scripts/calib-push.py b/scripts/calib-push.py index 4c43e7b..6bd8ee1 100755 --- a/scripts/calib-push.py +++ b/scripts/calib-push.py @@ -22,9 +22,12 @@ Mechanics notes: prompts do not bias the Hessians (the corpus is drawn round-robin over source classes, so loss is class-neutral as long as failures are rare; a systematic 4xx is loud in the log and must be fixed, not ignored). -- a round that seals no tap bytes is a FAILURE, not a retry: the engine - answering 200 while the tap directory is wrong, full or read-only is - how a corpus gets pushed four times for nothing. +- a round that seals no tap bytes is NORMAL and continues: RADIANCE_CALIB_TOKENS + is a pooled floor and this campaign's corpus is 10.03M tokens against a 12M + floor, so round 1 seals nothing by construction. A tap that LOSES bytes fails + the run, and a run that never sees the engine's completion line exits non-zero. + The first version failed on a flat round, which aborted exactly one round too + early (2026-10-29). - before any prompt, the tap must carry the rig's own marker (`--tap-marker`, written by run-qwen38-bf16.sh calib) naming THIS container, and that container must be running. Measured 2026-10-29: @@ -112,6 +115,27 @@ def tap_bytes(path): return total +def round_verdict(before, after, done): + """What one round's tap bytes mean. + + 'done' the engine logged that it sealed the tap — the run is over + 'shrink' the tap LOST bytes: reset, pruned or replaced under us + 'grew' sealed bytes this round + 'flat' sealed nothing — which is legitimate: RADIANCE_CALIB_TOKENS is a + pooled floor, and a round that does not reach it has nothing to + write yet (the campaign's corpus is 10.03M tokens against a 12M + floor, so round 1 is always flat). Failing on it aborted the run + exactly one round too early. + """ + if done: + return "done" + if after < before: + return "shrink" + if after == before: + return "flat" + return "grew" + + def require_rig(a): """Refuse unless the rig that opened this tap is up and serving right now. @@ -198,11 +222,15 @@ def main(): if tap_done(a.container): break after = tap_bytes(a.tap_dir) - if after <= before: - print(f"FAIL: the tap at {a.tap_dir} sealed nothing this round " - f"({before} B before, {after} B after) — the engine is serving " - "without recording (wrong dir, full disk, read-only mount)", flush=True) + verdict = round_verdict(before, after, False) + if verdict == "shrink": + print(f"FAIL: the tap at {a.tap_dir} LOST bytes this round " + f"({before} B before, {after} B after) — it was reset or replaced " + "under us", flush=True) sys.exit(1) + if verdict == "flat": + print(f"round {rnd}: the tap sealed nothing yet (byte floor not reached; " + f"{before} B) — continuing", flush=True) else: print("max rounds exhausted, tap not done", flush=True) sys.exit(1) diff --git a/tests/qwen38_campaign.bats b/tests/qwen38_campaign.bats index afcdc12..f9ce0fe 100755 --- a/tests/qwen38_campaign.bats +++ b/tests/qwen38_campaign.bats @@ -699,3 +699,20 @@ window_fixture() { [[ "$output" == *"calib-push.py"* ]] [[ "$output" == *"AGENTTRASH"* ]] } + +@test "a flat calibration round is not a failure: the tap's floor is pooled" { + # round 1 of a 10.03M-token corpus against a 12M floor seals nothing, and the + # first version of this gate aborted the run there — one round too early. + run python3 - "$PUSHER" <<'PY' +import importlib.util, sys +spec = importlib.util.spec_from_file_location("cp", sys.argv[1]) +m = importlib.util.module_from_spec(spec) +spec.loader.exec_module(m) +print(m.round_verdict(8192, 8192, False), # flat: continue + m.round_verdict(8192, 4096, False), # shrink: fail + m.round_verdict(8192, 20000, False), # grew: continue + m.round_verdict(0, 0, True)) # done: stop +PY + [ "$status" -eq 0 ] + [ "$output" = "flat shrink grew done" ] +}