The audit record · counted, not remembered

What we found
when we counted.

The ledger below holds 7 audits and 62 cited figures — 41 counted out of the data, 21 quoted from the file that recorded the measurement. Every one of those figures carries the file it came out of, and a command re-derives or re-finds all of them on demand. Nothing on this page is a number somebody remembered.

This estate’s one recurring failure is a page asserting a figure its own data cannot support — a guide quoting a room count its register outgrew, a wire writing a headline number nobody checked, a crawl and an opening disagreeing about the same room on the same screen. Each of the entries below is a time somebody went and counted, and what the counting cost. One of them cost a fifth of a published collection; another halved a headline figure that had never been wrong row by row.

The ledger

What was checked, what turned up, what it cost.

In the order the estate did them. Each entry ends in its receipts: the figure, what it counts, and the path it came out of, relative to the site root. A figure carrying a hollow ring — — is quoted rather than counted; see Checking it for what that difference is worth.

  1. August 2026yum

    The fabricated-entry purge

    Checked: the whole restaurant record, entry by entry and field by field, after the guide was brought home from yum.llc and rebuilt.

    Found: 270 entries did not survive it. 103 were placeholders — rooms literally named “Munich Fine Dining 1”. 167 were invented variants of a real restaurant, thirteen different “Belcanto”s among them, each carrying its own made-up address, rating and review count. Worse than the invented rooms were the invented FIELDS on the real ones: the websites had been generated by truncating the name, and 55% of them did not resolve; the ratings, review counts, star quotes, phone numbers and opening hours had never been checked by anyone.

    Cost: a fifth of the collection, deleted rather than corrected, and every unsourceable field with it. What was rebuilt is what can be stood behind — the room, where it is, what it cooks, and its Michelin stars as last published. A surviving room carries ten fields and not one of them is a rating, a website, a phone number or an opening hour. Each card opens a Google Maps search instead, which finds a real restaurant and cannot be made to find one that does not exist. The kosher register was added afterwards under the same rule, carrying no field that would be wrong the first time anything changed.

    • August 2026the month the record was auditedyum/index.html
    • 270entries removedyum/index.html
    • 103of them placeholdersyum/index.html
    • 167of them invented variants of a real roomyum/index.html
    • 55per cent of the generated websites that did not resolveyum/index.html
    • 1,085rooms left in the collectionyum/restaurants.json
    • 218cities they stand inyum/restaurants.json
    • 51countriesyum/restaurants.json
    • 518rooms in the kosher register beside ityum/kosher.json
    • 10fields a surviving room carriesyum/restaurants.json
    • 0of the ten is a rating, website, phone or opening houryum/restaurants.json
    • 0rooms still named the way the 103 placeholders wereyum/restaurants.json
  2. 13 August 2026card

    What the wire may change by itself

    Checked: whether a rule that waits for two independent publishers to agree can be trusted to write a credit-card figure onto the page with nobody reading it first. The card desk claims every figure on it was checked against the real market on a stated date, and the watcher exists to keep that claim true without anyone remembering to go and look.

    Found: run against live Google News, that rule wrote a wrong sign-up bonus to 4 of the 7 cards that carry one. It read “Last chance to earn 100,000 miles” as a current offer. It took a headline marked “[Expired]”. It answered a question about the Sapphire Preferred with a Sapphire Reserve headline. And it read “earn up to 75K” — a ceiling — as the figure. Credit-card news is dominated by offers that have just ended, by records, by ceilings and by sibling cards quoted in the same sentence. The same rule, on the same day, made zero errors on annual fee and on the length of the 0% APR window.

    Cost: the split between what the watcher may change and what it may only propose stopped being a preference and became a measurement — and then stopped being a setting at all. It used to live entirely in a JSON file, which meant one edit to a data file could publish a wrong number and the page could do no better than ask nobody to make it. One constant in the code now proposes a bonus whatever the configuration says, and the desk’s own check fails on a configuration that claims otherwise. Fees and 0% windows still move on their own; a bonus waits for somebody to write the sentence.

    • 13 August 2026the day the rule was measured against a live wirecard/WATCHER.md
    • 4of 7 cards given a wrong bonus by the rulecard/card-watch.json
    • 0errors the same rule made on fee and 0% lengthcard/WATCHER.md
    • 13cards the watcher readscard/card-watch.json
    • 7of them carry a sign-up bonuscard/card-watch.json
    • 0of those bonuses may change without a personcard/card-watch.json
    • 13annual fees that maycard/card-watch.json
    • 40% APR windows that maycard/card-watch.json
    • 1constant, NEVER_AUTO, that makes the bonus rule unraisablecard/card-update.php
  3. Undatedthe front page

    The room that counted itself

    Checked: whether the words the front page uses for a room’s size still agree with the register the doors beneath them are built from.

    Found: they did not, and both numbers were on the same screen. The opening said “Games. Seven tables, one room.” while the crawl below it said “Games — Six tables, one room”, because one of the two was counted from the register and the other was a string somebody typed in 2026. EZ Score had arrived; only one of the two noticed. Four rooms were carrying a stale word when this was found.

    Cost: almost nothing to fix and the fix was still the wrong one twice over — retyping the four words would have been correct that afternoon and wrong again on the next property. So the figure is resolved at render time from the register, and the word in the register is only ever a default. That this was the right call is not an argument, it is observable: of the 13 rooms, 11 carry a line that opens with a number word, and none of the 11 is wrong today — because this audit found the one that was. Health’s line read “Six clinical desks” over a room the register gives eight, and the page printed eight anyway, which is the only reason the drift was visible at all. Build 464 corrected the default to match. The figure is checked on every run, so it is a tripwire rather than a boast: the resolver earns its place because the word is a default, and defaults drift.

    • 13rooms in the registerassets/js/portfolio-data.js
    • 143properties filed into one of themassets/js/portfolio-data.js
    • 11room lines that open with a number wordassets/js/portfolio-data.js
    • 0of those eleven that disagrees with its room todayassets/js/portfolio-data.js
    • 4rooms carrying a stale word when this was foundassets/js/site.js
    • 16chips a crawl row deals, off the whole shuffled registerassets/js/site.js
  4. 24 August 2026padel

    Eight thousand clubs, and the gaps in them

    Checked: whether the facility count meant what it said. OpenStreetMap contributors tag COURTS, not clubs, so a raw count of objects tagged sport=padel is roughly double the number of places a reader could go and play — and a directory that reports it as facilities is wrong by that factor while every individual row in it is correct.

    Found and done: the objects are clustered at 150 metres, so a club with eight courts is one facility with eight courts rather than eight facilities. That leaves 8,486 facilities carrying 16,252 courts: 8,210 of them clusters out of OpenStreetMap and 276 added by hand, because OpenStreetMap had one American facility and the United States is most of the sport’s growth. Every hand-added row was confirmed by fetching the club’s own website and reading a street address off the page, and the URL stays in the row as the evidence.

    Cost: the honest count is half the flattering one, and what the data does not know is now printed beside it. Only 2,263 of the 8,486 carry a name at all — contributors map the courts long before anyone fills in the club — 1,104 carry a website, and 32 rows name no country. Unnamed rows are labelled by where they are rather than given a name, and every row links to its own OSM object so a reader who knows better can fix the source rather than complain to the page.

    Still open: two files in this property disagree about the same pass. padel/facilities.json records 5,170 candidates rejected in the 24 August pass; the app’s own header says thirteen were rejected in the same pass. Both readings are cited below. Picking one here would be this page making a finding rather than recording one, and would bury a disagreement that somebody should settle in the property itself.

    • 24 August 2026the pass this record was last rebuilt inpadel/facilities.json
    • 8,486facilities in the databasepadel/facilities.json
    • 8,210of them clusters of OpenStreetMap objectspadel/facilities.json
    • 276added by hand against a club’s own websitepadel/facilities.json
    • 16,252courts across all of thempadel/facilities.json
    • 108countries named on a rowpadel/facilities.json
    • 32rows that name no country at allpadel/facilities.json
    • 2,263rows that carry a namepadel/facilities.json
    • 1,104rows that carry a websitepadel/facilities.json
    • 150metres, the radius the objects are clustered atpadel/assets/js/app.js
    • 5,170candidates the data file says were rejectedpadel/facilities.json
    • 13candidates the app header says were rejectedpadel/assets/js/app.js
  5. Undatedstocks

    The universe, cut to what it claims

    Checked: whether the roulette drew from the list its own label named. The control says it draws one random NYSE or Nasdaq listing.

    Found: the source is the SEC’s own company_tickers_exchange.json — the regulator’s file, which every company on the desk files with — and it holds 10,388 rows, which are not all NYSE or Nasdaq. The remainder are OTC, CBOE or untagged, and OTC is neither of the two exchanges the button names.

    Cost: a quarter of the source file, and a temptation refused. The shipped universe is those two exchanges and nothing else — 7,661 listings, 4,363 Nasdaq and 3,298 NYSE — and it was deliberately not curated any further. Trusts, preferred shares, small banks and companies nobody at the desk has heard of stay in, because that is what a random listing IS; a universe trimmed to names a reader recognises would be a curated tour wearing a wheel’s costume. A draw with too little tape to score is re-spun visibly and the passed-over symbol is named on the panel with its reason, and the floor is 200 sessions.

    • 10,388rows in the SEC’s own filestocks/tools/mkuniverse.py
    • 7,661kept: every NYSE and Nasdaq listing in itstocks/universe.js
    • 4,363of them Nasdaqstocks/universe.js
    • 3,298of them NYSEstocks/universe.js
    • 200sessions of tape a draw needs before it is readstocks/assets/js/rinse-roulette.js
  6. Undatedchangelog

    What a checksum cannot see

    Checked: the build record itself. Every row on it is a CRC diff of one shipped archive against the one before, so nothing on it was remembered — and the audit was of that claim, which is a stronger one than it sounds.

    Found: derivation makes the record honest about WHAT changed and silent about how much any of it mattered. A checksum knows a file changed, not whether the change was a rewrite or a comma. Three builds in the record touch one file each and are among the most consequential in it; one touches ninety and is a stylesheet being copied around. And HTML is not counted at all, because every build restamps a content hash into every page that references a changed asset, so one line changed in one script rewrites two hundred pages — counting those would make all 197 builds look identical and enormous.

    Cost: a page that has to argue against its own chart. The bars measure reach rather than effort and the Method band says so; the era notes exist precisely because the bars alone would mislead. The gaps are printed rather than smoothed: 12 build numbers between v252 and v460 have no archive on the shelf, so the diff either side of each spans two releases instead of one and their work is counted against the build that follows. The opening figures are counted from the record at load rather than typed into the markup — after the headline read “Eighty-four” for a long time past the point where the record had grown beyond a hundred and fifty, on the one page whose whole claim is that nothing on it was typed.

    • 197rows in the recordchangelog/assets/js/builds.js
    • 252the first build it describes, v252changelog/assets/js/builds.js
    • 460the last, v460changelog/assets/js/builds.js
    • 205archives opened, since a row is a diff of twochangelog/assets/js/builds.js
    • 12build numbers in that range with no archivechangelog/assets/js/builds.js
    • 2,238source files changed across the runchangelog/assets/js/builds.js
    • 1,061counted apart, as estate-wide sweepschangelog/assets/js/builds.js
    • 31rows that added a directory that had not existedchangelog/assets/js/builds.js
    • 191of the 197 changed at least one source filechangelog/assets/js/builds.js
  7. 6 September 2026the whole build

    The 461 review

    Checked: build 461, whole — every property, both editions, the generators, the relays and the headers. 127 agents, 10 of them auditors, against the shipped tree rather than against anyone’s account of it.

    Found: 18 high and 36 medium findings survived verification, 54 in all, alongside 36 low-severity items that were reported but not independently re-checked and are labelled that way. 18 ideas were filed beside them for work that did not exist yet. The build under review was itself a re-stamp: 252 files differed from build 460, none added and none removed, so most of what the review had to say was about what 461 had carried forward rather than what it had introduced.

    Cost: the findings run from data quality — a dark city guide still shipping cards that name their venues after a rating, long after the paper edition had been repaired — through edition continuity, where dark drawers routed readers back onto paper and flipped their edition estate-wide, down to plain arithmetic in drawer pages stating a room count one short of the register. One of the eighteen ideas is now a property: the delay board at /airports/ names this review in its own notes as where it came from.

    The report is not served. It ships in the tree, at audits/labs461-review.md, where the estate’s .htaccess denies every .md by basename — the same rule that holds back README.md and SECURITY-FIXES.md. A list of what is still wrong, with line numbers, is a working document and not a page; what belongs in public is the account above and the figures under it, which is what this entry is.

    • 6 September 2026the day the review was filedaudits/labs461-review.md
    • 127agents that ran itaudits/labs461-review.md
    • 10of them auditorsaudits/labs461-review.md
    • 18high findingsaudits/labs461-review.md
    • 36medium findingsaudits/labs461-review.md
    • 54verified findings in allaudits/labs461-review.md
    • 36low-severity items reported but not re-checkedaudits/labs461-review.md
    • 18ideas filed alongside themaudits/labs461-review.md
    • 252files that differed between build 460 and 461audits/labs461-review.md

A hollow ring marks a QUOTED figure: it records a measurement nothing in this tree can repeat, so the check confirms the file still says it rather than working it out again. Everything else is COUNTED — re-derived from the data on every run.

Checking it

Every figure here, re-derived on demand.

The command

python3 tools/mkaudits.py --check walks the table above, re-derives every counted figure from the file it came out of, finds every quoted one in the file that recorded it, and exits non-zero if a single one no longer holds. It also fails when a cited figure is missing from EITHER edition of this page: a figure that survives its source but has been edited out of the dark twin is still a broken citation, and the two editions of anything here are meant to differ by their colours and nothing else.

Counted, and quoted

A counted figure is worked out again from the data on every run. 1,085 rooms is the length of a file; 143 properties is a filter over the register; 16,252 courts is a sum down a column. If the collection grows tonight, the check fails tomorrow and this page is corrected rather than quietly wrong. A quoted figure records a measurement nothing here can repeat — nobody can re-run August’s news wire, so “4 of 7” can only be confirmed to still be written where this page says it is. That is a real difference in what a reader should take on trust, so it is a visible one.

Why this page is not generated

Nearly every page of this kind on the estate is written by a generator out of a register. This one is not, because no data file holds an account of what was found and why it mattered. So the arrangement is inverted: the sentences are written by hand and the figures inside them are checked against the tree, which is the half that rots. The only text on this page a program writes is the tally in the opening, and that is recounted from the citation table rather than read back off the page — a stamp that checked itself would agree with itself for ever.

Where the figures come from

Every one carries its path, relative to the site root, and they are the properties’ own working files rather than anything written for this page: yum/restaurants.json, card/card-watch.json, assets/js/portfolio-data.js, padel/facilities.json, stocks/universe.js, changelog/assets/js/builds.js and the rest. Read one and you can disagree with this page on the evidence.

What this is not

The four things this record refuses to be.

It is not a list of what is wrong

These are audits that were run and finished. Findings still open are not here — they live in the build record’s era notes and in the review documents that travel with the tree. A page that mixed the two would let a closed audit stand in for an open problem, which is a comfortable way to be dishonest and the exact failure the ledger above is about.

It cannot audit itself

The check confirms that every figure still holds. It says nothing about whether the sentences around them are fair, whether an audit that found little was looking in the right place, or whether an audit that is not here should have been. That is not a judgement a checksum can make — the same limit the build record states about its own bars, one entry up.

Three of these are undated

An audit is dated here out of its own files and nowhere else. The room-strip fix, the stocks universe cut and the build record’s method note carry no date in the code that records them; the build record’s prose places them, but prose is a recollection of when rather than a record of it. Rather than print a date no file supports, those three say nothing, which is the whole habit this property is here to keep.

Where two files disagree, both are printed

The padel entry carries two different counts of the same rejected-candidate pass, taken from two files in the same property. Choosing between them here would be this page making a finding rather than recording one — and would hide the disagreement instead of leaving it where somebody can settle it at the source.