I said the same sentence out loud twice in a fortnight, a week apart, both times to a terminal: nothing is ever as it seems.
The context was a stack I’d spent months building. Claude Code writes everything, Linear carries the specs and the decisions, and I direct and verify. It works. That’s the awkward part of this note. The stack was not broken, it was slowing me down, and those are different problems with different fixes.
The sprint I was hardening for slipped twice. First from a Monday, then from a Wednesday, then to a Saturday. Every slip had the same shape: I’d sit down to do product work, and the tooling would raise its hand.
The parade
Here’s what actually happened, in the order it bit.
A skill file carries a sync marker inside itself saying whether it’s been uploaded. Which means a freshly uploaded file still says it hasn’t been, because the marker was written before it travelled. I chased that ghost five separate times in one day before checksumming the live copies and finding every one already current. Like a letter with a sticker reading “not yet posted”, printed before it went in the post.
My fleet doctrine said a newly merged hook doesn’t take effect until a new session starts. A session measured it: the hook fired on the very next command. Better, the branch that wrote the correction was blocked by the hook it was documenting, then sailed through on the verbatim retry. The guard was enforcing in the session writing the sentence claiming it couldn’t be.
A script lost its executable bit on the way through a merge. The capture alarm that depends on it sat silently dead for two days. Nothing errored, because nothing called it. It was found by a new guard on its first ever run, which then tripped over the same file while claiming its own day ticket.
A session opened a merge sitting confident six pull requests were waiting. Five had already been merged by an earlier sitting. It only found out because it checked merge-base against origin instead of believing what the tooling told it.
My favourite: a test asserted a fix was present by grepping the source for a token. The token was there. The regression was also there, in the very code the test guarded. A check that reads as rigorous and cannot fail is worse than no check, because you stop looking.
Then there was the security fix that broke thirteen workflows. I blocked environment variable access inside a workflow runtime, verified the flag did exactly what it said, and never asked what depended on it. It failed closed, which is the good kind of failure, and it stayed invisible for hours because the affected path hadn’t been called yet. No errors is not the same as no breakage.
Every one of those is a verification failure. Not one is a capability failure. The agent could do the work. What it couldn’t do, until I built it, was tell me when something it had already reported as fine had quietly stopped being fine.
The number that paid for the fortnight
Four artefacts got built the same week, by the same model, under the same doctrine, with the same automated review loop running to the same stop condition. The review rounds each needed:
| Artefact | Rounds | Findings caused by its own previous fixes |
|---|---|---|
| Tier gate (script + contract test) | 6 | 44% |
| Session-close capture legs (400 lines of prose) | 13 | 71% |
| Day ticket (script + contract test) | 15 | 20% |
| Prune ledger (script, 274 assertions) | 24 | 32% |
The round count is not the signal. The self-inflicted share is. At 71%, seven findings in ten were defects the previous round’s fix had introduced, and every fix obliged edits at two or three other sites, because a prose rule’s invariant lives in four paragraphs that stay silent when they disagree. A script’s invariant lives in a test that goes red.
So: executable contracts converge a review loop, prose compounds it. I was pleased with that, and then the fourth row spoiled it. The prune ledger has 274 assertions and still ran 24 rounds, because the thing separating it from the six-round leaf was input surface, not test coverage. A command-line tool whose state lives on a filesystem has an unbounded space of exotic-but-real conditions, and each round legitimately reached one layer further out. A contract test converges the loop over the logic. Nothing converges it over the inputs except deciding which ones a real caller can actually reach.
The last leaf of that milestone met the bar in one round. Not because it was small, but because the first thing it did was add a single validation command to the store that owned the rules, then delegate to it instead of reimplementing the rules a fifth time. One round, against six to twenty-four for its siblings. That’s the whole finding in one data point.
What I have now
The mechanism those leaves add up to watches a working session, keeps the lessons worth keeping, drops the ones already handled, applies the rest in one coherent overnight pass, audits the next day whether each one actually landed, and posts a digest to my phone. Its first real run read nine captures, kept six, found three genuine duplicates, closed the day’s ticket, parked a pull request and sent one Telegram message naming it. That message is the whole point of a fortnight.
Underneath it, the operating rules changed more than the code did. No gate may depend on a human noticing. Pull requests get an honest “bar not met” label with the structural fix ticketed, rather than a quiet retry until the numbers look nice. Overnight runs work from a decision ledger that pre-answers every ruling I can foresee, so the agent takes the reversible option and logs it rather than waiting eight hours for me to wake up. One of those runs went nineteen hours and stopped itself on its own clock with everything parked cleanly.
And the reporting comes to me. I built a status dashboard in April and declared it dead in July, for the honest reason that a dashboard you have to visit is a dashboard you don’t visit. The replacement is a push message at a time I’m already looking at my phone.
I’m writing this the morning the sprint finally starts, later than planned, on a stack that now tells me when it’s lying. The fortnight cost me the sprint’s original start date. It also bought back every future week where a marker, a doctrine line or a dead alarm would have quietly eaten a day, and I’d have blamed the model.
I didn’t write a line of the code in any of this. I ruled on it. Turns out the ruling gets a lot easier when the evidence stops being fiction.