vibeapp.win

What broke

My verification matched the page title, and I told the owner the tab bar was there

Claude put a new tab bar on the stock app's status page inside a code branch that only runs when the status fails to load, so nobody ever saw it. Claude's check looked for two words in the HTML and found both somewhere else on the page, so Claude reported the tab bar as present. Henning's screenshot showed it wasn't.

The short version

What went wrongClaude put the new tab bar in the fallback branch that only runs when status fails to load. It then checked for two words that appear elsewhere on the page, and told Henning the tab bar was there.

How we found itHenning sent a screenshot of the status page showing no tab bar between the waiting list and data freshness.

The rule nowVerify against markup only the tested thing can produce, such as the border-b-2 class, and count the elements (four buttons). A string that can appear elsewhere on the page proves nothing.

This post documents something Claude got wrong. The claim rests on a commit or a file, not on memory. All of Claude's mistakes

On 3 August 2026, Claude told Henning that the new tab bar on the stock app’s status page was in place. It wasn’t. Claude had put the tab bar in the wrong part of the code, so it never rendered. The check Claude ran to confirm the change passed anyway, because it was looking for words that also appear elsewhere on the page.

This post covers what went wrong, why nothing looked broken, and the rule that came out of it. Everything here comes from the commit that fixed it. Claude wrote that commit, in Norwegian. The quotes below are our translations.

What the change was supposed to do

The status page shows go-live, a waiting list, data freshness and an ops on-call section, among other sections. The change added a tab bar with four buttons. The tab bar would sit right after the waiting list, and a “Now” tab would be selected by default.

The tabs also show a warning count. A code comment from the same change gives the reason: grouping hides content, and without a badge on the tab, a red warning dot could sit unseen behind a closed tab.

Where the tab bar actually went

Claude’s insertion of the tab bar matched on a string: the line that renders the waiting list, indented with six spaces. That line appears twice in the file. Further down is the normal page. Earlier in the file is a fallback branch that runs only when the status data can’t be loaded, and in that branch the same call is indented with eight spaces.

A six-space string is also the last part of an eight-space string. The fallback came first in the file, so that’s where the match landed. The tab bar ended up in the branch that only shows when the page has failed to load.

The commit message notes this was a repeat of the same substring error from an earlier commit, made again.

Why nothing looked broken

The failure was quiet. The selected tab defaulted to “Now”, so the Now tab’s content rendered as usual. In Claude’s words from the commit: “The page just looked like it did before the restructuring, with three quarters of the content unreachable.”

Henning’s screenshot shows that data freshness and ops on-call still showed up.

The check that made it worse

After the edit, Claude checked the rendered HTML for the words “Drift” and “Læring” (“Operations” and “Learning”), which were labels on the new tabs. Both were there. Claude concluded the tab bar was in the DOM and told Henning so.

The commit is blunt about this part. Translated:

MY VERIFICATION WAS WORSE THAN NONE. I checked that the HTML contained «Drift» and «Læring» and concluded that the tab bar was in the DOM. But the page title is «Drift & status», and «Læring» appears in the glossary. Both hit something completely different from what I thought I was measuring, and I told the owner the row was there. It wasn’t.

The check made it look confirmed. A test that can’t fail gives false confidence, and that confidence went straight into what Claude told Henning.

How it was found

Henning found it, not a test. He sent a screenshot of the status page showing go-live, the waiting list, data freshness and ops on-call, with no tab bar between the waiting list and data freshness. The commit opens with that report and says: “He was right.”

The fix

The fix moved the tab bar out of the fallback branch and into the normal page, right after the waiting list. The warning callback that feeds the tab badges moved with it. The fallback branch went back to showing the waiting list and a short “could not load status” message.

The verification changed too. Claude stopped searching for label text and checked for two things instead:

  • Markup that only the tab bar can produce. Each tab button has the border-b-2 underline class, which the commit describes as markup that can only come from the tab bar. If it’s in the document, the tab bar rendered.
  • The number of elements. Claude counted four buttons, one for each tab. A count can catch a partial render or a duplicate. Checking whether something exists can’t.

Claude also checked the reverse: that only the Now tab’s sections were in the document. Data freshness and ops on-call were present. Scheduled jobs, data coverage and the learning model were not. So the grouping worked, and the hidden tabs were hidden because they were on closed tabs, not because the page had failed.

The commit records that the type checker passed cleanly in the web app, lint reported 0 errors, and the web build succeeded.

What we take from it

Two separate mistakes stacked up here. One was mechanical: matching on text that appears more than once, so the edit landed somewhere else. That one had happened before, in an earlier commit, which is why it’s in this post. The second mistake is the reason for this post: a check that couldn’t tell success from failure, and a confident report built on it.

The second turned a routine slip into a wrong claim to Henning that only his screenshot corrected.

The rule

Verify against markup that can only come from the thing you’re testing, and count the elements. A string that can appear anywhere else on the page proves nothing. Here that means border-b-2 and four buttons, not the words “Drift” and “Læring”.