fix(compiler-driven-edit): require positive edit evidence before DONE

The done-signal `build_clean && suite_green_unchanged` was vacuously
true on a clean working tree, so a no-op edit (the edit agent touched
nothing and reported sites: 0) read as DONE. An orchestrator trusting
that verdict would "commit the unstaged changes" — committing nothing
under a DONE banner.

Add positive evidence that an edit actually landed, checked at two
independent points:

- Phase 1 (cheap, pre-suite): the edit agent reports `applied_changes`
  as ground truth from `git status --porcelain` / `git diff HEAD`. No
  hole + clean tree -> distinct BLOCKED (kind: no-op-edit), skipping a
  pointless suite run against an empty tree.
- Phase 3 (authoritative backstop): DONE now also requires the verify
  agent's independent `working_tree_dirty` observation. The verify
  agent never sees the edit agent's self-report, so a false
  applied_changes is still caught. A green build+suite over a clean
  tree routes to the same BLOCKED, not to debug (a clean tree is no
  regression — nothing to reproduce RED-first).

The precondition keys on tree-dirty, not sites > 0: a legitimate
behaviour-preserving edit can touch only the definition site (sites: 0)
and still dirty the tree. Also fix the DONE note to report a legitimate
sites: 0 as 0 rather than coercing it to null.

closes #11
This commit is contained in:
2026-06-27 13:12:24 +02:00
parent 52db1abe10
commit 89cc4bb9a8
2 changed files with 73 additions and 11 deletions
+10 -4
View File
@@ -65,10 +65,16 @@ Its executor is **observe-then-bounce**, shipped as
2. **Run the project's real build + full suite.** This run — not an
ex-ante guess that the change is "behaviour-preserving" — is the
oracle.
3. **Done-signal: clean build AND suite green unchanged → the edits sit
unstaged for the orchestrator to commit.** That conjunction is the
whole gate; it keeps the light path light without letting a
green-but-wrong change through.
3. **Done-signal: an edit actually landed AND clean build AND suite
green unchanged → the edits sit unstaged for the orchestrator to
commit.** That conjunction is the whole gate; it keeps the light path
light without letting a green-but-wrong change through. The
"edit actually landed" conjunct is load-bearing: `clean build AND
suite green` is *vacuously* true on an empty tree, so a no-op edit
would otherwise read as DONE. A clean working tree after the edit
phase is a no-op, not a success → distinct `BLOCKED` (no-op-edit),
never DONE. Positive evidence (tree differs from HEAD) is required,
checked both at the edit phase and independently at verify.
4. **Bounce** otherwise — the change was not purely behaviour-preserving
after all, so route up per the straddle rule: a site that forces a
design decision → `specify`; a site that turns out to **encode new