Skip to content

fix(build): a repository path cited in served bytes must still exist - #657

Merged
oddharsh merged 3 commits into
mainfrom
fix/stale-paths-and-toolchain-pins
Aug 28, 2026
Merged

oddharsh merged 3 commits into
mainfrom
fix/stale-paths-and-toolchain-pins

Conversation

@oddharsh

Copy link
Copy Markdown
Owner

Three findings salvaged from the parked bun branch (#443) before it is retired.
Each one is independent; the middle is one line.

1. A stale repository path in served bytes now fails the build

Sibling of the link-integrity invariant, and the direction it cannot see. That
one asks whether an href resolves to something the site SERVES. This asks
whether a path in the prose resolves to something the repository HAS.

Re-pointed at the current layout and widened to the staged Worker tree, it finds
ten stale citations on main today, every one left behind by a move that
landed weeks ago:

file cited actual
public/_headers scripts/gen-og-cards.mjs tools/photos/gen-og-cards.ts
public/_headers scripts/gen-feeds.mjs tools/gen-feeds.ts
src/content/md/terminal.md tools/photos/radar-sample.mjs .ts
src/pages/lwe/vigenere.html scripts/gen-quadgram-table.mjs tools/photos/gen-quadgram-table.ts
src/pages/garage/workers.html www/_worker.js/index.js, counter.js .build/src/worker/index.ts, src/worker/counter.ts
src/worker/photos.ts scripts/build-histogram-index.mjs, scripts/hash-thumbnails.sh tools/photos/…
src/worker/lib/photo-grid.ts scripts/build-histogram-index.mjs tools/photos/…ts
src/worker/updates.ts scripts/bump-version.sh tools/photos/bump-version.sh
src/worker/lib/assets.ts scripts/gen-shell-deltas.mjs gone; deltas are build output
src/worker/webmention.ts migrations/0001_init.sql 0001_webmentions.sql

/garage/workers is the worst. It is the page about the Worker, its
wrangler.jsonc excerpt named a directory deleted ten days earlier, and the
page's whole argument is that the config is one checked-in file anybody can
read. Its main and directory are the real ones now.

The Worker tree is scanned beside public/ because a Worker string literal is
served the moment somebody asks for the route that prints it.

/terminal/radar has been printing node tools/photos/radar-sample.mjs since
that file became .ts. The other five are comments, which this repo treats as
documentation. gen-shell-deltas.mjs was stale twice over: the script is gone
AND the deltas are build output, so the sentence says deploy time now.

What keeps it from being a nuisance, which is the difference between a tripwire
and a tripwire somebody comments out: only a token naming a FILE has to resolve,
it anchors on a real top-level entry (so /images/x, an MCP tools/list and
somebody else's src/ do not match), and the one allowlist entry is a file in
another repository cited as attribution, whose URL /lwe/vigenere now carries.

Two controls, because a check that only agrees with itself is decoration.
Reverting one real fix fails the build naming that file; planting a citation to
src/worker/definitely-not-here.ts fails it naming all four staged copies the
page produces. It counts what it scanned and throws below 300.

2. A floor on the /*min*/ CSS pass

Step 5 had none, and every failure it has had was an absence. #443 found the live
version: the marker scan matched nothing after the Worker moved to .ts, so it
printed 0 literals and shipped unminified CSS on every Worker-rendered page.
The extension list is fixed on main; the silence that hid it was not. Seven
literals across seven modules today, so the floor is 7. Same idiom as the
client-edge mirror's mirrored < 32 thirty lines up.

Control: rewriting the sentinel to /*MIN*/ fails with found only 0 /*min*/ literals (expected 7+).

3. rustc does NOT move the histograms, and that is a correction

#443 proposed pinning rustc for the zenc crate on a measured 31.2% of 40,448
bins moving. The claim does not reproduce, and the branch never ran an A/B
between two compilers
— it compared a fresh bake against the COMMITTED set,
ruled out Cargo.lock, the input hashes and nondeterminism, and took rustc as
the last suspect standing. Gotcha 41 found the real cause a week later: #394
re-encoded 316 thumbnails, so the committed histograms described bytes nobody
was served.

Measured here over all 165 stems: rustc 1.93.0, 1.96.0 and 1.98.0 produce
byte-identical histograms
, 0 files differing on either pair, from three
binaries with three distinct sha256s off one --locked lockfile. So no pin was
added and config/tools.json's cargo entry keeps bytes: false.

The control is the finding. The first version of the comparison used sips
to re-encode a tile in place, which sips treats as a no-op, so the "perturbed"
file was byte-identical and the diff was measuring nothing. A null result across
three compilers looked excellent and proved nothing. Re-encoding aside and
copying back moves exactly one stem and no others.

Committed as bun run zenc:reproducible, because this question has now produced
one wrong committed conclusion. 4s warm, workstation-only (needs rustup with
those toolchains, same standing as kitesurf:check).

Independently justified and also here: every cargo build call site passes
--locked. The decoder version is a real variable per histogram.rs's own
header, and without it a build can silently update the committed lockfile.
Twelve call sites, so no copy disagrees.

Validation

lint, typecheck (baseline held, 297 files across 10 programs), 511 tests,
photos:check (165 photos, 660 tiers), pages:check, tools:check,
perf-budget (hard checks green), 149 routes, and a wrangler dry-run at
708.52 KiB / 239.88 KiB gzip. Build 1.8s with the new invariant over 541 staged
files.

The sibling of the link-integrity invariant, and the direction it cannot see.
That one asks whether an href resolves to something the site SERVES. This asks
whether a path in the prose resolves to something the repository HAS, which is
what a rename actually breaks here.

Salvaged from the parked bun branch, where it was written the day before the
www/ split. Re-pointed at the current layout and widened to the staged Worker
tree, it finds TEN stale citations on main today, every one created by a move
that landed weeks ago:

  public/_headers                scripts/gen-og-cards.mjs, scripts/gen-feeds.mjs
  src/content/md/terminal.md     tools/photos/radar-sample.mjs
  src/pages/lwe/vigenere.html    scripts/gen-quadgram-table.mjs
  src/pages/garage/workers.html  www/_worker.js/index.js, www/_worker.js/counter.js
  src/worker/photos.ts           scripts/build-histogram-index.mjs, scripts/hash-thumbnails.sh
  src/worker/lib/photo-grid.ts   scripts/build-histogram-index.mjs
  src/worker/updates.ts          scripts/bump-version.sh
  src/worker/lib/assets.ts       scripts/gen-shell-deltas.mjs
  src/worker/webmention.ts       migrations/0001_init.sql

/garage/workers is the worst of them. It is the page ABOUT the Worker, and its
wrangler.jsonc excerpt named a directory deleted ten days earlier while the
page's whole argument is that the config is one checked-in file anybody can
read. Its "main" and "directory" are the real ones now.

Byte-identity discipline makes this MORE likely rather than less: preserving
bytes means reverting served files and leaving their prose behind. That is
gotcha 40 from the other end, where the same rename left eight scripts writing
into directories that do not exist.

WHY THE WORKER TREE IS SCANNED BESIDE public/. A Worker string literal is served
the moment somebody asks for the route that prints it, and /terminal/radar has
been printing `node tools/photos/radar-sample.mjs` since that file became .ts.
The other five are comments, which this repo treats as documentation rather than
as decoration. scripts/gen-shell-deltas.mjs is stale twice over: the script is
gone AND the deltas are build output now, so the sentence says deploy time.

WHAT KEEPS IT FROM BEING A NUISANCE, which is the difference between a tripwire
and a tripwire somebody comments out. Only a token naming a FILE has to resolve,
so a bare directory mention in prose passes. It anchors on a real top-level
entry, so /images/x, an MCP tools/list and somebody else's src/ do not match.
One allowlist entry remains, for a file in another repository cited as
attribution, and /lwe/vigenere now names that repository's URL beside it.

Verified against two controls rather than against its own agreement: reverting
one real fix fails the build naming that file, and planting a citation to
src/worker/definitely-not-here.ts fails it naming all four staged copies the
page produces. It counts what it scanned and throws below 300, because a scanner
that stops matching reports a pass.

541 staged files in the noise of a 1.8s build. lint, typecheck, 511 tests,
photos:check, pages:check, tools:check, perf-budget, 149 routes and a wrangler
dry-run all green. Bundle 708.52 KiB / 239.88 KiB gzip.
…ip again

Step 5 minifies the static CSS template literals in the Worker modules. It had
no floor, and every failure it has had was an absence.

The parked bun branch found the live version: the marker scan matched nothing at
all after the Worker moved from .js to .ts, so the step printed "0 literals" and
shipped unminified CSS on every Worker-rendered page for as long as nobody read
the line. The extension list was fixed on main when the Worker landed. The
silence that hid it was not.

Seven literals across seven modules today, so the floor is 7. Same idiom as the
client-edge mirror's `mirrored < 32` thirty lines up, which exists because that
tripwire had been set at 25 against a real count of 33.

Control: rewriting the sentinel to /*MIN*/ fails the build with "found only 0
/*min*/ literals (expected 7+)" instead of passing quietly.
…that it does not

The parked bun branch proposed pinning rustc for the zenc crate, on a measured
31.2% of 40,448 histogram bins moving. Went to salvage it and the claim does not
reproduce.

WHAT THE BRANCH ACTUALLY MEASURED. It compared a fresh bake against the
COMMITTED histograms, ruled out Cargo.lock, the input hashes and
nondeterminism, and concluded the remaining variable was the build. It never ran
an A/B between two compilers, so rustc was the last suspect standing rather than
a measured cause. CLAUDE.md gotcha 41 found the real one a week later: #394
re-encoded 316 thumbnails, so the committed set described bytes nobody was being
served. Drift-from-committed is fully explained with no compiler in it.

MEASURED HERE, 2026-08-28, over all 165 stems: rustc 1.93.0, 1.96.0 and 1.98.0
produce BYTE-IDENTICAL histograms. 0 files differ on either pair, from three
binaries with three distinct sha256s built off one --locked Cargo.lock. So no
rust-toolchain.toml was added, and config/tools.json's cargo entry keeps
bytes: false. Its bytes_why asserted this with nothing behind it and now names
the control.

THE CONTROL IS THE FINDING, and skipping it is how the first answer went wrong.
The first version of this comparison used sips to re-encode a tile in place,
which sips treats as a no-op, so the "perturbed" file was byte-identical and the
diff was measuring nothing. A null result across three compilers looked
excellent and proved nothing. Re-encoding aside and copying back moves exactly
one stem's meta file and no others, which is what makes the null result mean
something. Gotcha 15 and the onestep probe are the same lesson from two other
directions: ask what the instrument is structurally incapable of seeing before
trusting it.

COMMITTED as `bun run zenc:reproducible`, because this question has now produced
one wrong committed conclusion and re-deriving it from scratch is exactly what
CLAUDE.md warns about at onestep:probe. It builds each toolchain, runs the
control, refuses to compare two binaries with the same digest, and prints a
verdict naming what to do in either direction. 4s warm. Workstation-only: it
needs rustup with those toolchains, the same standing as kitesurf:check.

Also here, and independently justified: every cargo build call site passes
--locked. The DECODER version is a real variable per histogram.rs's own header,
and without --locked a build can silently update the committed Cargo.lock, which
would move every histogram with no visible cause. Twelve call sites across the
eight shell scripts, the pixel-peeper hint, config/tools.json, CLAUDE.md and
MAINTENANCE.md, so no copy disagrees.

lint, typecheck, 511 tests, tools:check and photos:check green.
@github-actions github-actions Bot added area: content Authored documents and prose area: docs Runbooks and repository prose area: garage The garage pages and the cf-garage Worker area: infra Declared Cloudflare state, wrangler config, pins area: lwe The LWE pages and the lwe-ask Worker area: photos The photo pipeline and everything it emits area: tools Developer tooling and the contract suite area: worker The site Worker: routing, rendering, bindings type: fix Corrects behaviour that was wrong labels Aug 28, 2026
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
aadhar-sh 0499a80 Aug 28 2026, 07:34 PM

@github-actions

Copy link
Copy Markdown
Contributor

Wire-size diff vs merge base

3f9f2f9f → b2d06ca2

Brotli q11, the quality the edge serves. Every number here is deterministic:
an unchanged file produces no row. Advisory — this check fails on nothing.

Client assets

No change. 25 files, 86.35 KiB Brotli total.

Pages

Total Brotli: 571.62 KiB → 571.61 KiB (-0.01 KiB, -0.0%) across 54 files, 1 changed.

No single file moved by 0.13 KiB or more.

Plus 1 file under the 0.13 KiB floor, net -0.01 KiB — usually content-hash churn in /a/ references, counted in the total above.

Worker bundle

No change. 240.26 KiB gzip.

Dictionary deltas (pd/)

110 → 111 deltas, 498.41 KiB → 498.58 KiB (+0.18 KiB).

@oddharsh
oddharsh merged commit 9218ef7 into main Aug 28, 2026
9 checks passed
@oddharsh
oddharsh deleted the fix/stale-paths-and-toolchain-pins branch August 28, 2026 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: content Authored documents and prose area: docs Runbooks and repository prose area: garage The garage pages and the cf-garage Worker area: infra Declared Cloudflare state, wrangler config, pins area: lwe The LWE pages and the lwe-ask Worker area: photos The photo pipeline and everything it emits area: tools Developer tooling and the contract suite area: worker The site Worker: routing, rendering, bindings type: fix Corrects behaviour that was wrong

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant