Three failures in one morning, and the same rule every time

Published on September 8, 2026 · Seven of them went green on the first run: the page answers, the button is there, the page's own code is valid, saving works.

Le cockpit, apres reparation

This morning, three things broke. Not one of them was repaired where it showed.

It is a rule we have coded, not merely written down: fix the cause, then the consequence. Never the other way round, never one without the other. Here are the three cases, in the order they happened.

First case: the button that could not be clicked

Patrick opens a page where ten articles are waiting for his approval. He clicks. Nothing.

The symptom says: "the button is broken". The temptation is to rebuild the button.

We started by writing the checks. Seven of them went green on the first run: the page answers, the button is there, the page's own code is valid, saving works. Everything worked.

The file that stores the choices, however, contained a single line — the one written by our own test. No trace of Patrick. His click had never arrived.

The cause was not the button. The page was running as a program launched by hand, attached to a working session. Every time we restarted it, it died for a few seconds. We measured those gaps ourselves: the page answered "code 0", meaning nobody on the line. Patrick arrived during one of them.

There was a second, quieter defect: even when it worked, the page said nothing after a click. There was no way to know whether it had registered.

Two repairs, then. The page became a service that gets back up on its own — we killed it brutally, and it answered five seconds later. And it now displays, next to the button, "twelve approved — saved" in green, or "not saved" in red.

Second case: the button that claimed to have worked

Later, three buttons show up as "already run". Patrick clicked nothing. And the articles are not online: the site answers "this page does not exist".

Here again, the symptom misleads. One could wipe the state and move on.

Reading the program, the cause jumps out. The dashboard wrote "done" at start-up of the script, never at its success. It launched the program and recorded "done" within the second, without ever looking at the result. A script could fail immediately: the button stayed green.

Worse: "already run" replaced the button. You could not even try again.

That is exactly the blind check we denounce elsewhere: it never breaks down, it reassures.

The dashboard now waits for the result. Four states instead of two — to run, running, succeeded, failed — and the button always stays clickable.

Third case: the word written twice

Ten articles finally go out. All ten are refused. The message is identical on every line:

REFUSED (article-metatron): article-article-metatron.html missing from staging

The word "article-" appears twice. One could rename the files so it passes. That would be repairing the consequence.

We went and read the publishing gate. Line 94:

FILES="article-$SLUG.html"

The gate adds "article-" itself. So it had to be given the bare name — "metatron" — and certainly not "article-metatron". The file is indeed called article-metatron.html. The two are not the same thing, and that is the whole trap.

Renaming the files would have worked once. Then broken on the next article.

What the three cases have in common

In all three, the place where it shows is not the place where it is broken.

A button that does not respond is not a broken button: it is a dead server. A state that lies is not a state to wipe: it is a program that never looks at its own results. A missing file is not a file to rename: it is a name given twice.

Repairing the symptom is mopping the floor without closing the tap. It comes back. Later, further away, more expensive.

The test that said no first

One question remains: how do you know you touched the real cause?

A test written after the repair goes green even if you repaired the wrong place. It proves nothing. Only a test that failed on the cause first proves anything.

We did it every time. The check "the page says nothing after a click" was red. The check "the dashboard says done at start-up" was red. The check "the script passes a name with article-" was red. Then green, afterwards.

And for the dashboard we went further: we built a button that fails on purpose. The dashboard answered:

"failed": true, "code": 3, "why": "I am going to fail on purpose"

Red, with the reason, and a "Try again" button. Only then did we remove that test.

A guard that has never said no is a promise, not a guard.

The rule became a guardrail

A written rule is not followed; a coded rule is.

So we placed a guard that refuses any answer announcing a repair without two things in the same message: the cause, named in plain words, and a test seen red beforehand. It runs for both our assistants. Its own test bench returns sixteen green checks out of sixteen, including five refusals actually observed.

Two exits remain always allowed, because they are honest: "I don't know why yet, here is what would settle it", and "this action belongs to a human". What is forbidden is announcing a repair with no cause, or with a test that never had the chance to say no.

And the consequence, then?

We repair that too. Always after, never instead.

The lying state was wiped. The files kept their names. The page got its buttons back. But each of those repairs came after the cause was closed — otherwise we would simply have reset a counter that was going to lie again within the hour.

Three failures, one morning, one rule. This is not rigour for its own sake: it is the difference between a day of work and the same day done over tomorrow.

🔭