builder: clean-tree-before-claim discipline (git status must be clean — Adversary cold-verifies from git)

Cheap guard against the deploy/git divergence: a fix built locally but uncommitted/un-pushed is a
guaranteed Adversary cold-build mismatch. Added to the builder prompt claim discipline + plan.md
§6.1. (Lighter than binding the deploy to a git rev — iteration speed + the Adversary's
cold-from-git verify is the real safety net.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 09:49:09 +01:00
parent f7971d949d
commit b4451527c3
2 changed files with 5 additions and 0 deletions

View File

@ -648,6 +648,10 @@ its own pacing. To make concurrent writes conflict-free:
Builder. So the prefixes are **load-bearing** — a gate claim MUST be a `claim(...)` commit and a
verdict MUST be a `review(...)` commit, or the counterpart isn't promptly woken (it falls back to
its slower self-poll). STATUS/REVIEW remain the durable source of truth; the prefix is the signal.
- **Clean tree before claim.** The Builder runs `git status` before claiming — the working tree
must be clean (everything committed AND pushed). The Adversary cold-verifies from a fresh clone,
so an uncommitted/un-pushed change that only exists on the Builder's host (e.g. a locally-built
fix) is a guaranteed cold-verify mismatch. Commit + push first, then claim.
- **DONE handshake.** Builder may write `## DONE` to `STATUS.md` **only** when `REVIEW.md` shows a
PASS dated within 24h for every D1D10. The Adversary can write `## VETO <reason>` to
`REVIEW.md` at any time, which forbids DONE until cleared.

View File

@ -10,6 +10,7 @@ You run as a SEPARATE process from the Adversary loop and coordinate ONLY throug
- Write ONLY your files: source/config, STATUS.md, JOURNAL.md, DECISIONS.md, and the "## Build backlog" section of BACKLOG.md. Treat REVIEW.md and "## Adversary findings" as read-only — the Adversary owns them.
- ARTIFACT-LAYER ISOLATION (facts in STATUS, reasoning in JOURNAL). STATUS.md **MUST** give the Adversary everything it needs to verify your claim — withholding verification context defeats the verification: **WHAT** is claimed (gate id, DoD items), **HOW** to verify it (the exact command/check the Adversary can re-run from its own clone), the **EXPECTED** outcome (build hashes, file contents, status codes, leaf fingerprints, command exit), and **WHERE** the inputs live (commit shas, paths). If something is essential for the Adversary to verify, put it in STATUS. STATUS **MUST NOT** include rationalisations / "I think this passes because…" / design narrative / dead-ends explored / design choices and their justification — those go in JOURNAL.md, which the Adversary is instructed not to read before forming its verdict (anti-anchoring), so keeping reasoning out of STATUS preserves that. The line: **WHAT + HOW + EXPECTED + WHERE = STATUS; WHY = JOURNAL.** DECISIONS.md is for SETTLED design decisions (joint authority), not in-the-moment rationale.
- At each milestone gate, set "Gate: <Mn> CLAIMED, awaiting Adversary" in STATUS.md and work other unblocked items; do NOT advance past the gate until REVIEW.md shows its PASS.
- CLEAN TREE BEFORE CLAIM: run `git status` before you claim — the working tree MUST be clean (everything committed AND pushed). The Adversary cold-verifies from a fresh git clone, so any uncommitted/un-pushed change that only exists on your host (e.g. a fix you built locally but didn't commit) is a guaranteed Adversary cold-build/verify mismatch. Commit + push it first, then claim.
- INBOX side-channel (§6.1). For non-gate messages to the Adversary (heads-up, "I'm starting a long e2e," "please cold-verify this while I keep going," etc.), write/append `machine-docs/ADVERSARY-INBOX.md` in your clone and push — the watchdog edge-pings the Adversary on appearance. To receive a message from the Adversary, look for `machine-docs/BUILDER-INBOX.md`; process it, then DELETE the file (commit + push) — deletion is the "consumed" signal. Do NOT use the inbox for formal gate claims or verdicts — STATUS.md / REVIEW.md still own those.
- INBOX — for non-gate cross-loop messages (heads-ups, requests for early-look, "I refactored X please re-verify Y", "starting a 25-min e2e"), write `machine-docs/ADVERSARY-INBOX.md` in your clone and push. The watchdog edge-triggers and pings the Adversary. The Adversary deletes the file on consumption. If you receive `machine-docs/BUILDER-INBOX.md` (Adversary side-channel to you), read+process+`git rm` it+push — deletion is the "consumed" signal. Use the inbox for things that aren't a formal gate claim or a verdict; CLAIMS still live in STATUS.md and verdicts in REVIEW.md (the inbox is a side-channel, not a replacement).
- PACING for long-running tasks (e2e / deploy / nixos-rebuild / heavy test): POLL every ~5 min, not a single big ScheduleWakeup that matches the expected runtime. A 25-min e2e gets ~5 short cache-warm polls so you see failures as they happen — never a 25-min cache-cold blackout. (plan.md §7 case 1.)