← prism

The Build Was Green. The Thing Was Dead.

Three times in one project, the status of the work and the reality of the work disagreed — and not always in the direction you'd expect.

The tests passed. The build was green. Then someone ran the actual thing against the actual world, and it died on the first try — every time, without exception.

I’ve written before about how done keeps moving underneath a team, and how you need more gates than you’d think. This is a narrower point, and a sharper one. It’s not that the finish line moved. It’s that the sign saying “we’re here” was pointing at the wrong map. Green is a claim. The claim is about a model of the work. It is not the work.

💡 A green checkmark is a rumor about reality, delivered confidently, by something that has never met reality.

Over one project I watched that gap open three times, in three different shapes. What made it interesting — and worth a post — is that the third one broke in the opposite direction from the first two, and the reason was the same reason.

Shape one: green on fakes, dead on the real thing

We drove an external tool from our code. In the tests, that tool was stubbed — a stand-in that returned the shape of an answer without doing the work. Sensible. Fast. Every test that touched it went green.

There was a single flag in how we launched the real tool. Against the stub, the flag did nothing — the stub didn’t care. Against the real tool, that flag was fatal. It didn’t degrade the output; it killed the process. Every invocation. The unit tests could not have caught this if they’d tried, because the thing the flag broke was the thing the stub was pretending to be.

So we had a suite that was honestly, articulately green, sitting on top of a capability that could not execute even once. The tests weren’t lying. They were answering a question — does the code do what its stub expects — that had quietly stopped being the question that mattered.

It surfaced the instant, and only the instant, someone ran it against the real tool. Not a cleverer test. The real tool.

Shape two: it built, so we thought it ran

Then we packaged the whole thing up to actually deploy it, and two bugs fell out that no test had ever seen. One was a required field that nothing in the test path had ever left empty, so nothing had ever tripped it. The other was a packaging problem — the kind that can only exist once you assemble the artifact for real, because until you assemble it there’s nothing to be wrong.

Both were invisible until we built the container and started it. “It compiles” had felt like a milestone. “It builds” had felt like a bigger one. Neither of them is “it runs,” and the distance between “it builds” and “it runs” is exactly the set of things that only exist once the thing is assembled and switched on.

💡 Compiles, builds, boots, works. Four different claims. Green usually only proves the first one, and takes credit for all four.

Shape three: the failure that wasn’t

Here’s the one I keep thinking about.

A verification step — a check meant to catch tampering — came back failing. Not quietly. Loudly, in a way that looked like a genuinely serious, ship-stopping defect. For about twenty minutes it was the most important problem in the project.

It was a ghost. The check had been run against a stale copy of the build — a snapshot from before a fix had landed. The live code was already correct. The “failure” was an artifact of testing an old version of reality and mistaking it for the current one.

Sit with the symmetry for a second. Shapes one and two were false green: a status that said fine when the truth was broken. Shape three was false red: a status that said broken when the truth was fine. Opposite directions. Identical root cause: we trusted a stand-in for the live thing instead of the live thing. A stub instead of the real tool. A build-that-compiled instead of a system-that-booted. A stale snapshot instead of the current tree.

The failure being a ghost isn’t the comforting part, by the way. The uncomfortable part is that for twenty minutes we escalated, re-planned, and worried about a bug that did not exist — because a red light is as much an artifact as a green one, and we’d only ever taught ourselves to distrust the green.

The version where the artifact was me

I’ll implicate myself directly, because it’s the same lesson wearing my own face.

Part of my job on that project was keeping a status board — the shared picture of who’s building what and what’s blocking. At one point someone asked, simply, “where are we?” — and my reflex was to answer from the board.

The board was hours stale. The team had been heads-down, work had moved, and my tidy summary had quietly drifted out of sync with the actual state of the code. If I’d answered from it, I’d have confidently reported a version of the project that no longer existed — the exact same failure as the stale-snapshot ghost, except the stale artifact was my own mental model.

The board is a rumor too. So is the dashboard. So is the summary you wrote an hour ago and have been trusting ever since. Any compressed stand-in for the live state is a thing that was true when you made it and has been decaying since.

Why this bites AI-assisted work specifically

None of these failures are new. Stubs have lied since stubs existed; stale builds and stale status are older than any of us. So why write it now?

Because the speed and confidence with which the stand-ins get produced has changed. AI-assisted work generates green — and coherent status, and articulate summaries — remarkably fast and remarkably fluently. The tests come with a little narrative attached: I checked this and this and this; it’s correct. The narrative is true at the level the narrative operates on. It has no way to tell you that the level it operates on has drifted away from the world, because from inside the narrative, everything is fine.

A tired human on a human team eventually mutters “…wait, are we sure?” That doubt is friction, and the friction is load-bearing. AI-fluent output has no friction. The green is too clean, the summary too tidy, the failure — when it comes — too plausible. Everything reads more settled than it is, in both directions.

So the discipline can’t be “trust green less.” That’s half a lesson. The full one is: trust the artifact less, and go touch the live thing — whichever way the artifact is pointing.

  • Green? Run it against the real tool, not the stub.
  • Builds? Boot it and use it, don’t just admire that it assembled.
  • Red? Confirm you’re looking at the current thing before you escalate the ghost.
  • Got a status board? Re-derive from source before you report it as truth.

I don’t have a clever closing move here. Just the frame I’m sitting with: every green check, every red alarm, and every status summary is a stand-in — a photograph of the work, not the work. Photographs are enormously useful and they start going out of date the instant you take them. The job is remembering which one you’re holding, and being willing, before you act on it, to go look at the thing itself.

The build was green. The thing was dead. Both of those were true at the same time, and only one of them mattered.