STANDING
audits/museum/2026-07-21_independent-audit.md
sha256 e45855d2d06b59bd · 13115 bytes ·
original held in the private archive
---
Filed: 2026-07-21, by a separate session recovering it from an orphaned scratchpad the same day. The
audit itself was produced 2026-07-21, before this filing.
Target: the archive museum (`museum/site`) as it stood at commit `3ae00e3` ("Sync archive to public
repo b89b099 (2026-07-21)"), with the museum pinned to app release v2.8.0 (commit
`80bf9bb8b148efa4acf9b23e3c529514f937e941`) — i.e. the museum immediately BEFORE commit `e1fa0ab`
("museum: fix 5 self-audit defects") landed. Findings 1, 2, 3, 5, and 7 below are exactly the five
defects that commit fixed (confirmed by diffing the commit message against this report). Findings 4
and 6 were left open at that commit and, per this session's own check, remain open as of the filing
date.
Auditor: an independent Claude session, instructed to audit the museum from artifacts alone (the
generator, the generated site, the archive's records, and git) rather than from any prior session's
account of its own work.
Standing caveat: this was a Claude session auditing work built by Claude sessions, so it shares their
blind spots. A clean result from it is weak evidence, not clearance — see its own "Known limitation"
section immediately below, which makes the same point about itself. An external human reviewer is
still warranted, particularly for anything this report verified only via computed styles rather than
actual rendered pixels (screenshots timed out in its environment).
Everything below this line is the auditor's original report, unedited.
---
# Independent audit — RobCo Archive Museum (2026-07-21)
Derived from artifacts (generator, generated site, records, git), not from prior sessions' accounts.
Fixed nothing. Committed nothing. Working tree left clean.
## Known limitation (part of the deliverable)
I am a Claude session auditing work done by Claude sessions; I share their blind spots. A clean
result from me is WEAK evidence. Where I found nothing I say what I ran that could have found it.
Screenshots timed out repeatedly in this environment, so the visual checks are computed-style /
canvas measurements, not eyeballed pixels — a real gap for a phone-first owner. An external human
reviewer is still warranted.
## Nothing catastrophic. Generator runs, exits 0, output reproduces. Two HIGH user-visible defects,
both of the "museum is wrong about itself" class the owner keeps catching.
---
## Findings, ranked by consequence
### 1. HIGH — Lobby stat "Operators 3" is wrong AND contradicts the lede on the same screen
- generate.mjs:3290 counts distinct author **emails** (`%ae`). The app repo has 3 distinct author
emails: `dependabot[bot]`, and TWO GitHub noreply emails that are both the owner
(`63738028+zerckzzyHD@…` and `zerckzzyHD@…`).
- Distinct author **names** (`%an`) = 2 (zerckzzyHD, dependabot[bot]). Real humans = 1.
- So the card (a) splits the single owner into two via email variants, (b) counts a **bot** as an
"Operator", and (c) directly contradicts the masthead lede on the same page (generate.mjs:3456:
"how **one operator** built an operating system").
- Evidence: `git -C !RobCo-UOS log --all --format=%ae | sort -u` → 3; `--format=%an` → 2. Present in
both the committed lobby and a fresh regen.
- Proven wrong if: the owner considers his two noreply emails as two operators and wants the bot
counted — but the "one operator" lede says otherwise.
### 2. HIGH — Lobby condition report flags "UNCLASSIFIED 3" (amber) about the museum's own repo
- The lobby's condition report shows **UNCLASSIFIED 3** as a WARN. The three:
`.claude/launch.json`, `memory-audit/AUDIT.md`, `memory-audit/REPAIR_LOG.md`. All tracked (appear
in a fresh clone); the committed museum shows the same, so it is **live today**.
- This is the exact class the brief cited (bugs/ previously tripped it). Two causes:
- `.claude/launch.json` is build/preview tooling. The manifest walk (generate.mjs `walk()`)
excludes only `museum/`, not `.claude/`, so tracked tooling leaks into the manifest — the same
leak class as the README.txt bug, except this file is *tracked*, so the git-ls-files fix never
caught it. By the museum's own exclusion rationale ("the museum is not itself an archive
artifact") this file should not be an exhibit at all.
- `memory-audit/` is a real archive folder the classifier (generate.mjs `classify()`) doesn't
recognize — it knows `memory/` but not `memory-audit/`, so both files hit the catch-all.
- By the generator's own standard (the bugs/ fix comment calls sitting in UNCLASSIFIED "an
integrity-report false alarm"), this is a defect to fix by excluding tooling or classifying content.
- Proven wrong if: the owner wants those three genuinely surfaced as unfiled — but a bot config file
as an "unclassified archive document" is hard to defend.
### 3. MODERATE — A malformed redirect-ledger.json silently drops all 363 redirects, build says "done"
- `readRedirectLedger()` (generate.mjs:355) catches *every* error and returns `{}`. Injected a broken
ledger: stub output went **363 → 0**, logged only as "0 old hash address(es) redirected" —
indistinguishable from a legitimately empty ledger. No warning; build reports "done — museum".
Validation (generate.mjs:3520) checks index/css/placeholders/shards/min-pages but NOT redirect count.
- Consequence if it ever triggers (bad merge, truncated write): every one of the 363 old hash
addresses 404s, with no signal. Contrast: the release-pin path ABORTS loudly on bad input; the
ledger/measurements/intent-pairs paths degrade silently. "Ritual not gate" (don't block the release)
is right; *silent* is the issue — it should warn "ledger present but unparseable".
- Realistic trigger probability is low (the ledger is a committed 31 KB JSON), so MODERATE not HIGH.
### 4. MODERATE — Gallery captures are the one exhibit surface that lost the lamplit adjacency
- The approved identity ("Records Office Dark") rule: "Every dark instrument window gets a cream
slide-mount keyline; the capture plates keep lamplit buff mats (#d9d0b6)" — the adjacency effect,
8.6:1 vs 1.4:1, "must not be simplified away."
- Verified present on: growth chart (cream `--tape #ddd4ba`, 9.68–10.07:1 vs room), room thumbnails
(`.mz-thumb`, 1px cream `#d9d0b6` keyline), intent-vs-reality (padded cream `.mat #d9d0b6`).
- Missing on **galleries**: `.mz-galcell` = dark card `#2f312a` + dark `#565849` rule border, image
border 0 — no cream keyline. Galleries are the most capture-dense pages (~22 dark app screenshots
each); dark screenshots on dark cards separate from the room by ~1.05:1 — the exact "invisible as a
shape, 1.4:1" failure the identity was written to prevent. Matches the brief's warning that
galleries "inherited the new stylesheet through shared class names."
- Judgment call (a dense grid *might* have been meant to be simpler), but the plain reading of the
spec is that captures stay lit. VERIFIED via computed styles at 360/412px.
### 5. MODERATE-LOW — Growth page contradicts itself about where the check counts come from
- One caption: the check count is "measured … how many checks executed when each tag's own declared
runner was run." Another line on the same page: "dates and **recorded check counts from the
changelog's own release markers**." The chart plots the **measured** value (v2.7.0 = 1,543), not the
changelog value (1,557). The data layer carries both (`cm`=measured, `cr`=recorded) but only plots
`cm`. So the "from the changelog" phrase misattributes the provenance of the numbers on the very
exhibit built to distinguish measured-vs-copied. The plotted NUMBERS are correct; the WORD about
them is not. VERIFIED in growth.html.
### 6. LOW — v2.8.0 shows two ship dates
- Lobby badge "SHIPPED 2026-07-10" (from the changelog `Date:` marker) vs growth-currency
"2026-07-11" (the tag's commit date). A midnight/timezone artifact (tag committed 00:32 -0400).
Harmless, but it is two dates for one release.
### 7. LOW (comment only) — Stale justification comment
- generate.mjs:1347 cites "v2.8.0 (2938 vs 2951)" as evidence measurement catches changelog drift.
But 2951 is the *HEAD* changelog figure; the generator reads the changelog at the *pinned tag*,
where the recorded count is 2938 = the measured count (no divergence at v2.8.0). The v2.7.0 example
in the same comment (1543 vs 1557) *is* a genuine divergence at the pinned ref, so the design
justification stands on its own; only the v2.8.0 number is misleading. Not rendered anywhere.
---
## Verified clean (with the check that could have caught a problem)
- **Reproducibility (executed):** two in-place regens + two independent clones (a bare-clone-derived
clone AND a direct clone) all produced **byte-identical** `museum/site`, same stamp
`80bf9bb · b90ea7ac10b687f7`, 0 broken links (5,914 checked). `diff -rq` across all four = identical.
- **CRLF invariant (executed):** the system gitconfig sets `core.autocrlf=true` (the documented
hazard); a fresh checkout of `generate.mjs` is still 0 CRLF / 3556 LF — `.gitattributes eol=lf`
wins. This is the bug that content-hash addressing would rename every page over; it holds.
- **Growth line counts (independently reproduced):** 8,975 / 36,879 / 94,435 for v1.6.8 / v2.7.0 /
v2.8.0 match exactly by re-running the ls-tree + cat-file newline count. The 2.5× v2.7→v2.8 jump is
real (non-test code alone grew 21,193 → 51,567, 2.4×); ~45% of the count is test files, and the axis
label is explicit that it counts all `.js/.mjs/.css/.html`.
- **Release rooms shipped/in-flight:** 2.8.5 correctly renders IN FLIGHT (dashed) via
`releaseTags.has('v'+room)` — a real tag check, not folder presence; 2.8.0/2.6.0/2.5.0 SHIPPED with
dates. Commits 571 = `git rev-list --all --count` exactly.
- **Test counts:** museum shows measured 2,938 (matches the v2.8.0-tag changelog), correctly labeled
"checks that executed"; the internal `failed:1` is not surfaced; the "2951" I chased is a substring
of the footer hash, not a rendered claim.
- **Bug records room (subagent + spot-check):** exactly **10** records (the brief's "11" traces to a
self-contradicting `BACKFILL_REPORT.md`; the generator globs, hardcodes no count). Every cited SHA
resolves in the repo the record attributes it to. Both app bugs correctly IN-FLIGHT vs the v2.8.0
pin. The deliberately-unconfirmed "caught by a human" hedge (silent-flatline) is preserved as
"unconfirmed / not independently corroborated" on the doc page, not flattened.
- **Redirect ledger (subagent + HTTP test):** 389 entries = 363 stubs + 26 skipped; all 363 stub
targets exist on disk; the 26 skipped are all genuinely-removed documents; no orphans. HTTP redirect
executed end-to-end (stub → landed on target page).
- **RITUAL-not-gate (injection):** malformed pin, nonexistent tag, missing app repo, malformed
measurements — all exit 0 and leave the previous site intact; nonexistent-tag and missing-repo abort
loudly and correctly. Thumbnails: "28 cached, 0 to render" — no re-render of committed prototypes.
- **Identity (computed styles, 360 & 412px, dark):** cream `#e8e1cd` on dark slate `#262823`; NO
bezel/chassis (no inset shadows, no CRT overlays, no heavy borders); NO container animation;
phosphor `#14fdce` confined to SVG (0 green container-text elements; container green is sage);
contrast ink 11.4:1 / red 5.4:1 / green 7.0:1; NO horizontal overflow on any view type; search
functional; "DO NOT SERVE" self-marking present.
## Observations (not defects)
- The **committed** `museum/site` is stale vs current archive content: a regen yields 307 modified +
7 new doc pages (new memory/* files and planning/2.8.5/KNOWLEDGE_GRAPH_SPEC). This is by design
(regenerate at a release, not per sync) — but it means the museum a viewer opens today does not
reflect the current archive.
- Rooms **2.5.0 and 2.6.0 each render "1 artifact"** (only 1 planning doc archived for each). Legit
but visually thin next to 2.8.0 (305) / 2.8.5 (274) — the "too sparse" class the owner has flagged.
- Bug **wall cards** omit the `## Provenance` section, so a record's honest in-prose caveats (drift,
absent commit) show only on the full doc page, not the wall.
- Bug promotion (IN-FLIGHT→SEALED) reads only `provenance[0]`; today both app bugs put their fix SHA
there so it works, but a fix commit in a later provenance line would silently never promote. Latent,
not currently triggered.
## Could NOT check
- **file:// auto-redirect** of the stubs: the harness renders out-of-project local files as static
snapshots that don't execute the meta-refresh. HTTP redirect is verified; file:// auto-refresh is
NOT execute-tested. The relative fallback link is present and works on click.
- **Actual pixels:** screenshots timed out; all visual conclusions are computed-style/canvas
measurements. A human should still look.
- **Re-running 2,938 tests** to independently confirm the frozen release measurement — took the
committed measurement provenance as given.
STAMP · generated for RELEASE v2.8.5 commit 06e5180 (06e51801b38a) · archive input-tree hash c07fbfbdd2e1ddeb · 754 files · no wall-clock timestamp (regenerates identically when nothing changed).