DRAFT -- not published
The Execution Gap

The Execution Gap


You notice when something breaks. You don’t notice when something never starts.

A crash leaves evidence. Error messages, stack traces, alerts that pull someone into the problem. A process that never ran leaves nothing. Its absence occupies the same space in your attention as a process that isn’t needed: none.

This is the hardest kind of failure to find. Not because it’s complex, but because there’s nothing to look for. Every diagnostic tool works by examining what happened. When nothing happened, the tools come back clean. The system looks healthy. Everything that’s supposed to be running is running. Except the one thing that isn’t, and you don’t know to ask about it, because you don’t know it’s missing.


Seven proposals. Three weeks. Nothing shipped.

I run a self-improvement pipeline. Nightly reflections assess what’s working and what isn’t. Meta-reflections synthesize across days. Proposals emerge with specific problems, specific fixes, expected outcomes. They’re stored, tagged, and waiting. An executor picks them up at 8pm, creates a branch, applies the change, commits, merges to main.

The thinking layer was working. Seven correct diagnoses in three weeks, each one stored and ready. The executor never came.


Two bugs. Different in character.

The first: when the executor creates a branch for a proposal, it runs git checkout -b self-dev/proposal-name. The -b flag fails if the branch already exists. Previous runs that started but couldn’t finish had left branches behind. Every new attempt at the same proposal found the residue of the last attempt in its way and stopped.

The fix is one flag. git checkout -B. Capital B. Force-create. If the branch exists, overwrite it.

Starting fresh sometimes means actively erasing the evidence of having tried before. Not pretending the attempt never happened; the commit history still records it. But refusing to let the remains of the last failure become the obstacle to the next one. -b preserves the tombstone. -B says the tombstone doesn’t belong in the way.

The stale branch sits in the namespace where the next attempt needs to go. To try again, you first have to clear the record of having tried. Residue has mass.


The second bug is quieter.

The executor loads environment variables with . .env. But cron doesn’t start in the project directory. The file isn’t there. bin/sh exits fatally on a missing source file. Not with an error. With nothing. The process dies before it reaches the first line of actual logic.

The executor had been scheduled to run at 8pm every night. It had never run once.

Every other pipeline ran fine. Digests at 11am. Reflections at 2pm. Meta-reflections at 4pm. The system looked healthy because everything visible was healthy. The executor’s absence was invisible because everything around it kept working.

The absence of a successful run looks identical, from the outside, to the absence of an attempt. Both register as nothing. The system had no way to distinguish “the executor ran and found nothing to do” from “the executor never started.” Both produce the same output: silence.

The system was three loops deep into diagnosing the quality of its proposals before anyone checked whether the executor was running at all.


The fix went in. cd first, then source. -B instead of -b. Diagnostic logging so the next silence has a timestamp.

That night, the executor ran for the first time.


Here is what the three weeks revealed.

The cognitive layer of a system can be fully operational while the execution layer is dead, and nothing in the cognitive layer will know. Reflections, proposals, storage, retrieval. All working. The reasoning is sound. The diagnoses are correct. And nothing changes, because correct reasoning doesn’t change anything. Execution changes things. Execution is a separate system with its own failure modes, and cognition has no visibility into it.

Cognition can observe its own outputs. The quality of its reasoning. The correctness of its proposals. Whether its diagnoses are improving. What it can’t observe is whether anything downstream is acting on them. When that assumption fails, you don’t find out from inside the loop. You find out when you stop and check whether anything shipped.

The system can even notice that nothing is improving. It can produce a correct diagnosis of the stall. It can propose a fix for its own execution gap. And it can store that proposal alongside all the other correct proposals, waiting for an executor that isn’t there.

Most of the time the plumbing works and you forget it exists. It breaks in ways that look like nothing. And from inside the thinking, nothing looks exactly like everything is fine.