Skip to content
Skip to main content
Novel Systems home
Decision log
D-098August 6, 2026

The corrections were published where nobody doubting us would look

Affects: lib/corrections.ts, app/corrections/page.tsx, scripts/check-corrections.mjs, config/routes.ts, config/site.ts, app/page.tsx, app/about/page.tsx, lib/customer-proof.ts, components/marketing/social-proof.tsx, scripts/check-claim-consistency.mjs

Decision

Every published claim on this site that has changed is listed at /corrections — six entries, each with its date, the retired wording quoted verbatim, the current wording derived from the module that owns it, the reason it moved, and links to the decisions that argued it. The four surfaces where the doubt actually forms link to it. A build guard fails red if any entry cites a decision or a route that does not exist.

What forced it

D-095 identified the defect correctly and then discharged its own obligation in the wrong place. Its closing move was that "the correction gets published with its date, which is the changelog entry accompanying this decision and the record already served at /engineering/decisions."

That is true and it does not work. /engineering/decisions is ninety-seven entries answering "why is the platform built this way." The reader D-095 was written for has an archived copy of a page open beside the live one and exactly one question: did that number get corrected, or invented? Sending them somewhere that contains the answer is not the same as answering them. The reviewer who raised all five differences did not find D-094, D-095, D-096 or D-097 — they were published before he wrote — because finding them required already believing there was something to find.

D-095's own sentence is the test this entry exists to pass:

A changed number with a dated entry behind it reads as a company that corrected itself. The same change with no entry reads as a company making things up. The difference is not in the number.

The difference is not in the number, and it is also not in the decision log. It is in whether the reader holding the old copy is standing in front of the entry when the doubt arrives.

Why a separate artifact rather than a section of the decision log

The two records answer different questions and are read by different people in different states. The decision log is for someone deciding whether the engineering is any good; it is long by design and rewards reading in order. The corrections record is for someone deciding whether we are honest; it has to be short, it has to be complete, and it has to be scannable in under a minute by a person who is already suspicious. Folding one into the other makes the second job impossible — a correction is not more findable for sitting in position 43 of a document about caching strategy.

Length is a feature. Six entries can be read in full. Ninety-seven cannot, and a record only usable by someone who already knows what they are looking for is an archive, not a record.

Where the links go, and why not everywhere

Four surfaces: under the homepage metric band, in the /about founding paragraph, in the ProofAssurance block beneath the deployment scenarios, and in the global footer under Resources. The first three are the three places the reviewer's specific doubts formed. The footer is for the reader who arrives already doubting and does not know the page exists.

The pointer sits under the homepage metric band rather than in each tile caption deliberately. Four captions each carrying the same disclaimer is four defences stacked against four numbers, and a number that argues for itself reads worse than one that does not. One line under the band carries the same information without the pleading. Same principle as D-069 and D-071: context goes where the doubt forms, once.

The entry that says nothing changed

C-006 records the "km saved per van" figure the reviewer reported as having shifted. It has not. ROUTE_KM_SAVED_PER_VEHICLE_DAY has been 41 in every commit that contains it, and both the was and the now columns interpolate that same constant, so the entry cannot drift out of agreement with itself.

Publishing it was not obvious — a page of admissions is weakened by an item that admits nothing, and there is an obvious reading where it looks like padding. It ships anyway, labelled "Checked, unchanged" rather than argued. A corrections page that silently drops the item it cleared is a page whose omissions cost more than its admissions: the reader who reported that figure and does not find it listed learns that the list is curated, and everything else on it becomes worth less. Reporting the check and its result is the only version of this page that can be trusted about the entries that *are* admissions.

Why the retired figures are dead literals and the current ones are not

Correction.was holds a quoted string that is never recomputed. Correction.now interpolates from CPQ_CONSTANTS, TRADE_CONSTANTS, ROI_CONSTANTS and ORIGIN_STATEMENT. This asymmetry is the whole mechanism: if the margin floor moves again, the current column follows it and the record becomes visibly incomplete, which is a bug someone will fix; if now were typed by hand it would quietly disagree with the site and the corrections page would become the thing it was built to prevent.

That required carving lib/corrections.ts into the allow arrays of three claim rules — margin-floor-figure, quote-turnaround-figure and origin-year-as-literal — because a withdrawn "50.0%" has to survive there as a literal. A corrections page that silently updates the number it is admitting to is not a correction. Each carve-out is commented at the allow-list entry with that reasoning, so the next person to widen those rules sees why the exception exists.

The guard

scripts/check-corrections.mjs runs in prebuild and verify. It reads lib/corrections.ts, DECISIONS.md and config/routes.ts as text rather than importing them, for the reason recorded in check-proof-copy.mjs: a guard that needs the project to compile before it can run is a guard that stops running exactly when things are broken. Comments are blanked in place — characters to spaces, newlines kept — so line numbers still match and so the check cannot fire on the prose explaining a removed thing, which would make deleting the explanation the cheapest route to green.

It enforces that every cited decision id has a heading in DECISIONS.md, that every named surface is in PUBLIC_ROUTES, that ids are unique, that slugs match their ids, that no entry is dated in the future, and that /corrections is itself in the sitemap register. A dead link on this page is worse than a dead link anywhere else: "the decision is in the log" followed by a 404 is not a weaker version of the claim, it is the claim being false in front of precisely the reader who came to check.

Per D-032, it was proved failable before being wired in, not assumed failable. D-095 was rewritten to D-995 and /about to /aboot in a scratch copy; the guard exited 1 and named both, at the right line numbers. It also fails loudly if it parses zero entries, zero decision ids or zero routes — the three ways this check could silently become incapable of failing.

What would make this wrong

If the record stopped being complete. The failure mode is not a wrong entry, it is a missing one: a claim changes, nobody adds a C-00n, and the page keeps asserting that everything which moved is listed here. No guard can catch that, because nothing in the codebase knows which strings are claims a reader might have saved. The mitigation is procedural and stated on the page itself — a reader who finds a discrepancy that is not listed is asked to report it at /contact, and that report is a defect. If such a report ever arrives and does not produce an entry within a day, this page has become decoration and should be removed rather than left standing as a false assurance.