A journal path stood where the hash belonged

8–11 minutes
measured on my own machine
A journal path stood where the hash belonged

One of my finished images has a step strip. In one row, a 78-character journal path stood where a commit hash should have been. That row’s text column got squeezed into three narrow lines, and every other row stayed on one line. The suite was green. The only way to find it was to open the image and look at it, and that is how I found it.

The goal was easy to say. A chain of agents builds each post on this blog from a fact sheet, and the same chain makes the images. For every step a post tells, the image prints the evidence next to it: the commit, or the journal entry. I wanted evidence that points at the record it claims. No more than that, and no less.

I believed that a reference that looks like a reference is one. If a short hex string sat next to a sentence, I read it as proof. If a slot was labelled commit, I assumed a commit was in it. I checked whether the value had the right shape. I never asked where it came from. Everything else in this story rests on that belief.

The reference came from a list position, not from the evidence. The fact sheet holds every recorded step, and the article tells some of them. The image code joined the two lists by index: sentence three of the article got the hash of step three on the sheet. That only works when both lists have the same length and the same order. The first time, the sheet had 7 steps and the article told 4. It came out right by accident, because the first four sheet steps happened to be the four commits, in order. The second time, the sheet had 10 steps and the article told 6. The kind of each step, commit or journal, was also looked up by index. When the lookup found nothing, it fell back to a default of commit. So a journal entry was treated as a commit, and the render printed its raw path.

Two passes over one belief

1672349f · 2026-09-11

Die SHA neben dem Satz kam aus der Listenposition — vier Fehler, die nur das Bild zeigte

The hash next to the sentence came from the list position — four errors that only the image showed

The first pass came from the first live run of the image chain against a real draft. It turned up four defects, and I found every one by looking. Besides the guessed hash, the cover said 1 dead ends: when text is computed, the plural has to be computed too. A footer reported 0 journal entries next to a panel that read 3 from the same sheet. The footer was counting the article’s steps, and the article only told commits. A zero that looks like a finding is really a question nobody asked.

The fourth defect taught me the most. Every row ended mid-word, cut at 88 characters with no ellipsis. My first repair raised the limit to 118. That pushed the hash out of the 1400px frame, so it disappeared completely. It was a worse trade, and again only the image showed it. Each row is now three flexible columns, so nothing can push the reference out.

5386e86d · 2026-09-12

Ein Journalpfad stand als SHA in der Schrittleiste — gefunden, indem ich das Bild angesehen habe

A journal path stood as a hash in the step strip — found by looking at the image

The first pass made the writer name each reference itself, and a gate checks it against the sheet. If a reference is missing, the strip prints no evidence rather than invented evidence. But one field stayed on the old path: the kind of step. The writer did not name it, so the index guessed, and the guess was commit. A default that guesses is worse than no default. Now the kind is read from the reference itself. A hash is 7 to 40 hex characters and nothing else.

The commit subjects in their original wording, the evidence each step points back to.
The commit subjects in their original wording, the evidence each step points back to.
  1. 2026-09-11Ran the image chain against a real draft for the first time. I checked the text but did not look at the images. When I finally did, four defects were there, starting with a hash attached to each sentence by its position in a list.
  2. 2026-09-12Opened a finished image and saw a long file path where a hash belonged. The step kind had fallen back to a default of commit. I made the kind come from the shape of the reference itself.
  3. 2026-09-12Wrote up the session: nine defects across the image chain, and a test found none of them. Every one came from a run on real data, an image someone looked at, or a measurement on production.
  4. 2026-09-15Found a related case one step over. The image generator wrote the cover file, but it recorded the file on the blog record instead of the social-post record with the same slug.
All recorded steps in the order they happened. This post tells four of them.
All recorded steps in the order they happened. This post tells four of them.

The related case came three days later and had the same shape. A script that generates missing images filtered its selection correctly by format. Then it called the image function with the format fixed to blog. The image got made and the file got written, but it was recorded on the wrong record. That meant two runs, two images, paid for twice, and the social post still had no image, so the outbound check blocked it. Both times the script reported zero errors. I only saw the problem by querying the record instead of trusting the message.

88db7ee1 · 2026-09-15

BlogFactory: der Bildgenerator buchte das Titelbild beim falschen Datensatz

The image generator booked the cover image on the wrong record

The record names one command I used: `git status –porcelain — loops/ growth/`. I was waiting for it to come back clean before a deploy in a neighbouring project. The second fix changed a test file, so a test runner such as `node –test` was probably involved. The record does not say I ran it, so I will not claim I did. It also does not say how long any of this took.

It is partly solved. The reference now comes from the evidence, not from a position. Its kind comes from its own shape, and no default is left to guess. The cover image is now recorded on the record whose format was requested. What remains is the shared file path. Both formats of one slug still write to the same image file, with no format in the name, so they still overwrite each other. Separating them means changing the path, and 386 existing images depend on it. I have not done that yet. Nobody has seen the image checker pass either. The journal says that path stays unproven until the first post built by the chain is live.

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

Commits 1672349f (2026-09-11), 5386e86d (2026-09-12) and 88db7ee1 (2026-09-15), plus the journal entry of 2026-09-12 on the image chain. The span covers 4 days.

1672349f · 5386e86d · 88db7ee1

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