The nightly system had 122 passing tests. It had cleared an adversary review. Every unit was green. It also could not launch, and no test had caught it.
i.What the tests saw
The automation wrapper was built to be careful. Before any unattended run, it checks the working tree for foreign writes. If something outside the system’s own scope has touched a tracked file, the run halts. The guard exists for a simple reason: an AI system running unattended on a dirty tree is a liability.
The test suite for this guard was thorough. It injected foreign-write signals. It confirmed the halt. It confirmed clean-tree pass-through. 122 tests, zero failures.
What the tests did not inject: the guard’s own output.
ii.The self-blocking structure
The launch sequence worked like this. The wrapper claims a work unit, writing a record to a state file that lives in the tracked tree. Then it invokes the driver. The driver’s first precondition is a clean tree.
The wrapper’s own claim dirtied the tree before the driver ever ran.
The adversary review had confirmed each component behaved correctly in isolation. The quiet path, where the system runs without contention, had been validated against an isolated store. What had never run was the actual launch path, in the actual repo, with the wrapper writing before the driver checked.
The result was a deadlock by design. Every successful run would have dirtied the state file. Every subsequent scheduled invocation would have found a dirty tree and halted. The scheduler would have retried, found the same dirt, and halted again. The system would have never cleared its own backlog.

On automation metabolism When you wrap automation in a cleanliness gate, decide what counts as the system's own breathing before the first unattended fire.
iii.The fix was classification, not code
The resolution required no new logic. It required a decision about what the cleanliness guard was actually for.
The guard exists to catch foreign writes, writes from outside the system’s intended scope. A run-claim record is not a foreign write. It is the system’s own metabolism: runtime state the system produces as a normal byproduct of doing its job. That state is meaningless to a new session reading the repo. It is noise to a git history. It should not be tracked at all.
The fix: move the runtime state file to gitignore. The guard stays strict for real foreign writers. It becomes blind to the machine’s own breathing. The structure that was a deadlock becomes a clean separation between persistent state, which the guard watches, and runtime state, which it correctly ignores.
iv.The reusable call
This failure class is distinct from “tests green, broken in production.” That failure happens when a test covers the logic but not the environment. This failure happened because the test covered the environment correctly, but the environment the tests used was not the real launch environment. The adversary validated the isolated path. The real path had never fired.
Two principles travel from this incident.
First: the quiet path and the launch path are different tests. Validating a system against an isolated store tells you the logic is correct. It does not tell you the system can start. The launch path needs its own test, in the real repo, under real preconditions.
Second: before any cleanliness gate goes unattended, name what counts as the system’s own output and exclude it explicitly. A guard that cannot distinguish the system’s metabolism from a foreign write will block itself on the first real run. The distinction is not obvious. It requires a deliberate call before the system runs, not after it fails to.
The 122-test suite was not wrong. It was testing the right things about the wrong starting state.
Drafted with Bishop, my AI partner.
Words picked, edited, and approved by me.
Model provenance: Claude Code (Claude Opus and Sonnet)