I set out to do wiring. Four placeholders, one existing mechanism that already feeds 32 others into a prompt. The label on the task was “just wiring.” Small effort. What I found instead was that the answer I meant to wire up existed four times over, and that my tests had been proving something the running system never did.
One question — when is the next press release due? — was answered independently in four places inside a single project. Three of those were code; one was prose in a prompt that a language model works through. The threshold, 13 days, lived in three separately maintained spots. And the four copies had already drifted: only one of them knew the test switch that lets a test swap the real file for a throwaway copy. So every test that flipped that switch was checking something other than what ran in production — and every one of them was green.
I believed two things, both wrong. First, that a placeholder is a wire, not a part — I’d hang it on the existing answer and be done. That there was a single existing answer was an assumption I never checked; it sounded too obvious to check. Second, that a test which points the switch at a throwaway file tests the path production takes. An environment switch looked to me like a property of the system. It is only a property of the one constant that reads it.
The mechanism is unspectacular, which is exactly why it repeats: whoever passes a value along without checking whether someone already computes it turns n copies into n+1. Each of the four copies was reasonable the day it was born. There was a guard against unresolved placeholders, but none against duplication — so nothing was red. The test switch shows how a duplicate drifts quietly. It was retrofitted into one copy because a test otherwise clung to the real working tree. Nobody knew to carry it into the other three; they sat in other files, under other names, for other purposes. From then on the tests proved a path production did not walk. The bitter part: the prompt that had the model compute the deadline could not have fetched the finished answer anyway. That run has no shell access and may not start the status script that answers the question. It was asked to recompute a deadline whose result comes from a program forbidden to it. The same class hit a second time the same day — the tell that the first fix was cosmetic. The rules file loaded into context on every night run had grown to 160.002 characters, 83% of it permissions and logs as prose, a second copy of what code should ask at runtime. No program read the file at all. Moving it into data surfaced that of eleven findings kept there, one was long since done and one refuted — both still filed under “open,” paid for every night. It came down to 13.178 characters afterward.
Solved, deployed, measured against production. One derivation now answers the question — it leaves the date-reading where the test switch lives and only adds the due-date logic. The gate and the guard script ask it; the reason strings stayed word-for-word identical so nothing shifts silently in the logs. The prompt lost six of its seven reading jobs and kept exactly one: the journal file, which holds prose that needs a judgment, not a number you compare. Two guards make the regression hard: one asserts that exactly one module splits that file, with a mutation probe that catches a smuggled-in second parser; the other asserts the number in the gate equals the default in the module. Two finds made the work smaller than expected, and both were good news — a fourth module already read through the canonical function, so it was never a fifth copy, and the placeholder guard already ran generically across all prompts. What stays open is the effect. The baseline holds at 0,743 $ per run, and three more runs wait for the same shape.
The steps, in order
Jeder Loop nennt sein Modell — und wer einen Ausgang hat, faehrt auf opus
Every loop names its model — and whoever has an exit runs on opus
Der PR-Takt wurde viermal hergeleitet — jetzt einmal, und impuls rechnet nichts mehr nach
The PR cadence was derived four times — now once, and the impulse prompt computes nothing anymore
- 2026-09-08Made each loop state its own model instead of inheriting the account default, so a silent account-level change can’t swap the model on every run at once.
- 2026-09-08Moved the standing findings out of the always-loaded rules file into data, and cut two entries that were already done or refuted but still billed every night.
- 2026-09-08Collapsed the four derivations of the press-release deadline into one module, and stripped six of the prompt’s seven reading jobs down to the one that needs a human judgment.
- 2026-09-08Wrote up the pattern behind all of it: the right abstraction already exists every time — the readers use it and the writer routes around it.
None of that went first try. The first test for “the file is missing” was green-wrong and then red-wrong. I meant to test the branch by bending the path at a throwaway directory and reloading the module with a cache-buster. It failed. The cache-buster loads the module it sits in — the imported module with the cached path constant stays the old one. I had named that exact trap in a comment in the same file, and walked into it anyway. The fix was to leave the path alone and delete the file instead.
Then a character-set correction destroyed code. The house standard forbids ASCII stand-ins for German letters; a check flagged two such spots in my own comments. My replacement ran as a substring across the whole file and hit four occurrences — one of them an identifier, one an import path. What caught it was not the check but a dry run: a SyntaxError on load. I took back exactly the four wrong hits, cross-checked against the last commit. And the first commit attempt lost a race. While the pre-commit check ran, a parallel session in the same working tree landed its own commit; no data lost, but cannot lock ref ‘HEAD’, and my commit fell through. The index still held exactly my five files. The second run went through — no –force, no reset.
The finding itself was one search. Three copies of the same split, one grep:
$ grep -rn --include='*.mjs' "Versand-Log" . | grep -v node_modules | head -3
./growth/pr-reminder.mjs:110: const sec = md.split(/^## Versand-Log/m)[1] || '';
./loops/run-loop.mjs:628: const sec = readFileSync(runbook, 'utf8').split(/^## Versand-Log/m)[1] || '';
./loops/lib/signals.mjs:99: const sec = runbook.split(/^## Versand-Log/m)[1] || '';The tools here I’m inferring, not quoting — the record doesn’t name them. A test file was changed, so node –test ran; the record says nothing more than that.
Measured 2026-09-08. Three commits chosen by hand, each checked against the reading circle. The full thread ran 685312d8, 1dc38539, e421d27e.
685312d8 · 1dc38539 · e421d27e
