Twenty-three catches across eleven drains, and the executor caught the planner more often than I expected
My workflow has a split. Cowork plans, Claude Code executes. Cowork drafts a plan file, CC reads it, posts a pre-implementation check-in, executes commits, posts a completion report. Cowork verifies the report and signs off.
That’s unidirectional trust-and-verify. Planner checks executor. It’s the obvious direction and it’s the one most workflows codify.
Across eleven drains in Phases 3 and 4 I logged twenty-three catches. They did not all point the direction I expected.
The direction I wasn’t watching
Plan text said “no rm in the command.” CC’s grep found rm -f was present.
Plan text said the rule doesn’t require a recursive flag. CC read the regex and found the character class [rRdf] was accepting -f as if it were recursive. So the fix wasn’t adding a missing gate. It was removing f and d from the class.
Plan text said the ledger-aware skip wires into dispatch.ts. CC read that file and found it was a static map, not a runtime dispatcher. The right home was the orchestrator.
Each of those is an error a competent planner makes from a high-level mental model. Each was caught because the executor’s discipline included reading actual source before executing on plan text.
Three in three consecutive drains stopped being coincidence.
Then a third direction
I’d been thinking of it as two surfaces. Planner checks executor, executor checks planner.
Then in P4-01, CC’s pre-implementation check-in claimed tests/log.test.ts didn’t exist — based on a find that missed it. That claim went into the check-in and I approved it at sign-off. Commit 1’s path change then broke two assertions in the file that didn’t exist.
The executor’s reading of the codebase is itself a self-report. And self-reports drift.
That one hides well, because a pre-implementation read feels like reality rather than a claim. A planner writes plan text knowing it’s a mental model. An executor reads source and reports “the file isn’t here,” and that feels like a fact about the codebase. It isn’t. It’s a read performed at a specific moment with specific search patterns, and if either was off the report is confidently wrong.
The rule underneath all three
Every one of these resolved the same way: find the source that doesn’t pass through the claimant’s narrative.
Plan text is a claim. Completion reports are claims. Pre-implementation readings are claims. Verification means consulting something the claimant didn’t write — the file system, git history, the audit log, running the tests yourself.
Naming this is slightly uncomfortable, and I want to be straight about why. “The executor has to double-check the planner” can read as “the planner doesn’t know what they’re talking about.” That’s not the framing. Plan text is a written representation of a mental model, and mental models drift from code over time and across abstraction levels. A planner who hand-codes every implementation detail isn’t planning anymore. A planner who never reads source will write plan text that drifts. The executor’s check is a stability check, not a competence check.
Same in the other direction. “Planner verifies executor” isn’t “the executor lies.” It’s that a self-report is a self-report.
What it bought
Plans can be written from a high-level mental model without exhaustive code reading during drafting, because the executor’s check catches the drift. My energy goes into intent and sequencing rather than double-checking every code claim.
And errors surface at pre-implementation, where they’re cheap. Without the check they propagate into implementations and surface later as bugs.
One honest limit on the number. Twenty-three catches across eleven drains is a real count from a real ledger, but it’s my workflow, my codebase, and two specific models. I’d expect the mechanism to hold in any planner/executor split — cross-team spec handoffs, human plans plus AI execution, code review where the reviewer trusts the implementer’s summary. I wouldn’t expect the rate to transfer.
SOs
SOs — standing orders you can lift and prime your own agent with. Paste them into a session for a one-time dose, or commit them to your CLAUDE.md / AGENTS.md and they stay in force.
STANDING ORDERS — Bidirectional trust and verify
Source: "Twenty-three catches across eleven drains" — bensimon.dev
1. Treat plan text as claims to verify, not facts to execute on.
Statements about file structure, mechanism, historical state and
coverage each get checked against source before you act on them.
2. When plan text and source disagree, surface it before executing. Do
not silently correct, and do not execute on the disagreement.
3. Treat your own pre-implementation reading as a claim too. "I checked
and the file doesn't exist" is a claim you can recheck with a second
pattern before reporting it.
4. When verifying any report, find the source that doesn't pass through
the claimant's narrative — git show, the audit log, running the tests
yourself. A self-report is evidence, not authority.
5. At each commit sign-off, re-enumerate the full scoped change list even
when most items are obvious. Scope drops out when it falls outside the
commit's headline change, and that gap is hard to self-catch.