Add run --baseline: execute every check against the unmodified tree#38
Conversation
Two of twelve lanes in a real fix swarm failed on verify assertions that were wrong about the PRE-change tree — one demanded a status its own lane spec forbade, one was unsatisfiable on a pristine repo. An honest worker burned ~100k tokens against the latter before anyone knew the check was the bug. run --baseline makes that question answerable in one command, before any worker spawns: every task's check runs against a fresh scratch taskdir (a detached worktree of the repo when the manifest uses worktrees), and the report shows pass/FAIL with the check's own output excerpt. Reading it is the orchestrator's judgment call, which the report spells out: a FAIL is expected for assertions that demand the new behavior workers will build; a FAIL on an assertion about unchanged behavior means the check itself is broken and will burn worker attempts against something no model can satisfy. Design notes: - spawns nothing: runs before preflight_engine_bins on purpose, so a missing engine binary cannot block baseline - writes no model-log rows and touches neither the manifest workdir nor the repo (scratch worktrees are removed; the scratch root is deleted) - checks run for real, including any exports they perform — same semantics as at run time - exits 0 regardless of failures: baseline reports, the orchestrator judges Test: end-to-end manifest with a deliberately nonexistent engine binary and two checks — one asserting current tree state (must pass baseline), one demanding a worker-built file (expected FAIL) — asserting the report lines, the excerpt, the guidance, exit 0, an absent model log, and zero leaked taskdirs or worktrees. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # ringer.py
Resolve each baseline taskdir and refuse keys that escape the scratch root (same rule as the real run path), and surface failed worktree removals per task and in the summary instead of letting a clean report hide leaked state. Merge with current main keeps --baseline alongside --allow-noncanonical-route. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Merging — thank you. This is the most doctrine-aligned PR in the queue: "a check that cannot fail is trusting the worker with extra steps" has been in the README for weeks, and Maintainer-side before merge (authorship stays yours): resolved the parser conflict with current main ( Also queued on our side, sparked partly by this: a structured failure-class field on eval rows so "the check was broken" vs "the model failed" vs "the engine was down" becomes sliceable scoreboard signal. Your #35/#36 verdicts feed the same taxonomy — the joint-design thread on #33/#36 is the place if you want in on that. Thanks again for the consistently excellent work. |
Every merged community contributor must appear in README Contributors — tests/test_contributors.py audits git history (squash authors + merged-PR handles) against the section and fails on any omission; CI checks out full history for it. README refresh: all four merged contributors credited (#24 #30 #4 #37 #38), --baseline documented, canonical-route enforcement mentioned in the taxonomy section, CI badge added. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ateBJones-Projects#38) * Add run --baseline: execute every check against the unmodified tree Two of twelve lanes in a real fix swarm failed on verify assertions that were wrong about the PRE-change tree — one demanded a status its own lane spec forbade, one was unsatisfiable on a pristine repo. An honest worker burned ~100k tokens against the latter before anyone knew the check was the bug. run --baseline makes that question answerable in one command, before any worker spawns: every task's check runs against a fresh scratch taskdir (a detached worktree of the repo when the manifest uses worktrees), and the report shows pass/FAIL with the check's own output excerpt. Reading it is the orchestrator's judgment call, which the report spells out: a FAIL is expected for assertions that demand the new behavior workers will build; a FAIL on an assertion about unchanged behavior means the check itself is broken and will burn worker attempts against something no model can satisfy. Design notes: - spawns nothing: runs before preflight_engine_bins on purpose, so a missing engine binary cannot block baseline - writes no model-log rows and touches neither the manifest workdir nor the repo (scratch worktrees are removed; the scratch root is deleted) - checks run for real, including any exports they perform — same semantics as at run time - exits 0 regardless of failures: baseline reports, the orchestrator judges Test: end-to-end manifest with a deliberately nonexistent engine binary and two checks — one asserting current tree state (must pass baseline), one demanding a worker-built file (expected FAIL) — asserting the report lines, the excerpt, the guidance, exit 0, an absent model log, and zero leaked taskdirs or worktrees. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Baseline hardening: key containment + leaked-worktree reporting Resolve each baseline taskdir and refuse keys that escape the scratch root (same rule as the real run path), and surface failed worktree removals per task and in the summary instead of letting a clean report hide leaked state. Merge with current main keeps --baseline alongside --allow-noncanonical-route. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Jonathan Edwards <justfinethanku@gmail.com> (cherry picked from commit 3de9b28)
Independent of #35/#36/#37 — new function + one flag + one dispatch branch; no overlap with those diffs.
Problem
The check is the product — but nothing exercises the checks themselves before workers spawn. In a real 12-lane fix swarm (2026-07-14), two lanes failed on verify assertions that were wrong about the pre-change tree: one demanded a status its own lane spec forbade, and one was unsatisfiable on a pristine repo (a
tsx -eCJS/ESM quirk). An honest worker burned ~100k tokens against the unsatisfiable one before anyone knew the check was the bug.Feature
ringer.py run manifest.json --baselineexecutes every task's check against the unmodified tree and reports — spawning no workers:Design notes:
preflight_engine_binson purpose, so a missing engine binary can't block baselineVerifier, includingexpect_filesandCHECK_TIMEOUT_S)Test
End-to-end (
tests/test_baseline_mode.py): worktrees manifest on a temp git repo, a deliberately nonexistent engine binary, and two checks — one asserting current tree state (must pass), one demanding a worker-built file (expected FAIL). Asserts the report lines and excerpt, the guidance text, exit 0, an absent model log, and zero leaked taskdirs or worktrees. Full suite: no new failures (the pre-existingtest_design_reference/test_scoreboard_pagefailures reproduce on clean main).🤖 Generated with Claude Code