The post had to name a tool it never saw

8–12 minutes
measured on my own machine
The post had to name a tool it never saw

Three nights in a row, my critic failed the same kind of X post for the same reason. On September 12 it gave a 6 and wrote that no tool was named. The next night it said it again. Since September 7, the outbound queue had sent 0 posts without my click. The two that went out on September 13, I approved by hand. In the same window the screenshot under each post had stopped. Up to September 7, 26 screenshots were made, each in the night run between 01:19 and 01:36. After that, none, and nothing complained.

What I wanted was simple. Each X post retells a post from the blog. I wanted it to name a tool by its real name and to show the piece it retells. A post about a broken check should say which check. The screenshot under it should prove the thing exists. The critic was there to hold that line. The writer was there to meet it.

I believed the writer would pull the names out of the work itself. The work had names everywhere: files, commands, test suites. So when the critic complained, I read it as a writing problem. The writer was being vague, and the fix was a sharper prompt. So I sharpened the prompt first, before I knew that the names never arrived. It could not have worked. A sharper prompt had nothing to point at. I had skipped the earlier question: what did the writer actually have in front of it?

Where the names got lost

The cause sat in neither the critic nor the writer. It sat in the material. The blog prose paraphrases on purpose. In the core sentences the brief saw for one post, the names had turned into “a configuration file”, “the cockpit”, “the test file that now enforces the coupling”. Plenty of numbers, not one proper name. The brief filled its mandatory field with a paraphrase. The writer obediently wrote what the brief said. Then the critic ran a probe that no paraphrase can pass. Two guards asked the same question, and the lenient one went first. It let through what the strict one then killed, after the paid step. The names were never lost. Every post has a fact sheet that lists them one by one: proper names, tools, the core file, and for each number what it counts. They just never travelled into the brief.

79e1c81d · 2026-09-14

Der X-Post bekam nie einen Namen zu sehen — jetzt bekommt er sie aus dem Faktenblatt

The X post never got to see a name — now it gets them from the fact sheet

The three commit subjects, in the original German.
The three commit subjects, in the original German.

The new module, xblatt.mjs, fetches exactly that material and comes with 12 tests. The repository name stays behind on purpose. The confidentiality check at the X outbound flags it as an unknown proper noun. That is how card #510 got stuck on September 12. The file name goes instead, since nobody on X can visit a directory anyway. The sheet also carries the parts of its own measurement date, because the number checker needs them as permission. Those are now recognised by their data, not by a list of banned phrases.

The directory that holds the fact sheets is now searched for, not assumed, with 3 more tests. When the code started from the app directory, the derived path pointed at a folder that does exist but holds only topic files. The sheet reader would have returned null. No error, no message, just an X post without names. I now recognise a location by what is in it, not by where a formula says it should be.

f76d4e99 · 2026-09-15

BlogFactory: der X-Screenshot fiel seit dem 07.09. still aus — die Kopplung war ein Kommentar

The X screenshot had been failing silently since September 7 — the coupling was a comment

The screenshot broke because two parts read one word differently. The screenshot module, new on September 7 and fail-closed, photographs only what the post names. A comment in it said the writer prompt guaranteed that name. The prompt did ask for a tool name, but it meant libraries. The writer met the rule with getElementById and ps and never named a product. Eight of eight drafts. I measured that on the post text, not on the payload. The payload carried the site name in loop prose and faked a mention.

I fixed the cause, not the place where it showed up. Loosening the list of allowed surfaces would have undone the reason that list exists. The writer prompt got a rule zero: product and purpose in the first block, exactly one. The final check now counts product names. Zero means no image. Two means ambiguous, and also no image. And the coupling became a test. Every surface must appear in the prompt, and the prompt may not invent one. A mutation probe turned the new test red.

0d78398b · 2026-09-15

BlogFactory: die X-Posts waren ein Tagebuch — das Genre wird umgestellt

The X posts were a diary — the genre gets switched

Then I read the drafts that passed every rule, and they were boring. The five house examples all had the same shape: something of mine broke, here is the cause. Clean, with a number and a cause, and the reader takes nothing away. People read a diary, but they do not share it. Posts may now take three forms: a technique to copy, a trap with what it cost, or a tool held against its own claim. The hardest rule is one question: what can the reader do differently tomorrow?

What happened, in order

  1. 2026-09-14Built a small module that pulls the proper names, tools and core file from each post’s fact sheet and hands them to the X brief. The repository name is left out, because the outbound confidentiality check would block the post.
  2. 2026-09-14The queued task said to push a new X branch out of the publish step. I measured first and found that branch already existed, built the other way round: it pulls published posts instead of being pushed. The planned work was the wrong work. What was missing was the names.
  3. 2026-09-15Traced the dead screenshots to one word that two parts read differently. Gave the writer prompt a rule zero, made the final check count product names, and turned the coupling comment into a test.
  4. 2026-09-15Moved the posts from diary to something a reader can use: three allowed forms, a yield question as the hardest rule, and a critic that rejects instead of only noting.
All 8 steps in the record. I left out the journals that belong to other projects.
All 8 steps in the record. I left out the journals that belong to other projects.

The record quotes one tool in my own words: `curl …:8790/api/pacing`. It belongs to a different thread from the same days, a usage dashboard, not this work. For this work I can only infer. Test files changed, so node –test was part of the loop. The record does not say that I ran it, or what it printed.

The new module went out to the always-on machine and ran live. The first X post scored 8, above the release threshold, and both outbound gates were green. The card proof is still open. Each loop makes exactly one card per day, and the 01:30 run had already made it: card #531 hangs on artifact 425, built from the old material. My forced run wrote artifact 431, scored 8, with no card. That is correct behaviour, not a defect. The record does not say what the next night brought. One thing is ruled out: if the score drops again, a missing name is no longer the cause. The screenshot fix is proven by tests and a mutation probe. The record shows no new screenshot in production.

What the record supports, and what it leaves open.
What the record supports, and what it leaves open.

Three commits from 2026-09-14 and 2026-09-15, plus the handover journal from 2026-09-14. Every figure is taken from the commit bodies and the journal as written.

79e1c81d · f76d4e99 · 0d78398b

Georg Singer

Georg Singer

I automate my own projects in public and write down what each one cost. Physics degree, doctorate in computer science, nine systems in production on hardware I own, all of it built in my own time.

More from the log