MEMORY
memory/project-C--Dev--RobCo--RobCo-Archive/museum-thumb-render-nondeterminism.md
sha256 b432e0dd9a14a8d5 · 2939 bytes ·
original held in the private archive
---
name: museum-thumb-render-nondeterminism
description: "FIXED 2026-07-20: thumbnail re-render nondeterminism was CSS-animation timing drift, not PNG encoder jitter as first guessed — fixed by never re-rendering unchanged prototypes"
metadata:
node_type: memory
type: project
originSessionId: 1c45c406-4f75-4a39-8893-a98aca437eb7
modified: 2026-07-21T02:58:52.705Z
---
FIXED (2026-07-20, commit 43390e6, folded into the path-based-naming + redirect-ledger
session). Originally recorded as: fresh/bare clones cold-render all 28 Playwright
prototype thumbnails, and ~11-13 of `museum/site/assets/thumbs/*.png` come out with a
few dozen-to-hundred differing bytes each, a DIFFERENT subset every time — diagnosed
then as "PNG re-encode jitter," unfixed pending a real cause.
**That diagnosis was wrong, and the correction matters.** 27 of the 28 prototypes carry
`@keyframes`/`animation:` rules, several genuinely infinite
(`coreSpin 9s linear infinite`, `corePulse 2.6s ease-in-out infinite`, a pulsing status
lamp). `generate.mjs`'s capture waits a FIXED 600ms after page load with no
synchronization to animation phase, so ordinary process-scheduling jitter between runs
lands the screenshot at a different rotation angle / glow intensity each time — REAL
pixel content drift, not lossless-encoder nondeterminism on identical pixels. This means
the other candidate fix the previous session named ("force deterministic PNG encoding")
would not have touched the actual cause at all — the encoder was never the problem.
**The fix doesn't need to fully solve animation timing to work.** `screenshotPrototypes`
now checks the already-committed `museum/site/assets/thumbs/<sha>.png` (the PREVIOUS
successful build's output — tracked, not gitignored) BEFORE the local `.cache/thumbs`
and before ever launching Playwright. A clone regenerating an unchanged manifest finds
every thumbnail already sitting in the committed site and re-renders nothing, so the
question of what exactly makes Playwright's capture non-reproducible becomes moot —
rendering, and therefore the opportunity for drift, only ever happens once per distinct
prototype content, ever, matching the "measured once, frozen" treatment
`release-measurements.json` already gets. This was deliberately NOT "commit
`museum/.cache/thumbs` too" (the other named candidate) — that would duplicate, byte for
byte, storage the site already carries at `museum/site/assets/thumbs`.
Verified via fresh GitHub clone AND a bare-clone-derived clone (both with an empty,
untouched gitignored cache): `prototypes: 28 total, 28 cached, 0 to render` in both,
`git status` clean, stamp `80bf9bb · f64fb7397980c9cb` matching the local run and each
other. See [[museum-path-based-naming-and-redirects]] for the session this was folded
into, and [[museum-lf-normalization]] / [[museum-readme-txt-leak]] for the earlier
determinism fixes this one follows the same pattern as.
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).