Six commits into the display fixes, three pages still pointed at /src/

By the sixth commit of a set of display fixes, three pages were loading raw source. The fixes were name alignment, the X’d-out slot spacing, the 8am-plus-orange date change, a sticky left nav driven by a scroll handler, the location pin and arrow icons nudged to vertical center, and the schedule-slots text nudged down a couple pixels to stop descenders clipping. These are small UI fixes, the kind you iterate on by refreshing the browser forty times. To make that fast, the editor page, the schedule-slots page and the schedule-build page had all been pointed straight at their /src/ files instead of the compiled, dated bundles the platform actually ships.

That is a fine way to work. Nobody wants a compile step for a one-pixel nudge. The trouble starts when nobody flips the refs back before the branch goes to develop.

Why the dated bundle exists at all

The platform’s release process has a compile step. It takes a /src/Name.js file and produces Name{YYMMDD}.js next to it, using terser. The comment at the top of that script explains the choice of tool:

regex-based “minifiers” (sed s|//.*||, custom scripts, in-app tools) silently corrupt strings that contain ://, producing files that break the page they ship to. terser is the only safe tool. This script enforces it and verifies the output parses, so a broken compile fails loud at compile time instead of silently shipping to the dated file.

The script also refuses to run unless the source path contains /src/. Output goes to the parent directory, and the parent directory is what production serves. A page loads a specific dated filename, like Name260617e.js, and never Name.js.

That same afternoon, on a completely different ticket, a hotfix session needed the same facts spelled out from scratch: how the dated bundle gets produced, whether the filename date has to bump, where the page references live. Two unrelated tickets, same afternoon, both rediscovering one mechanism. That told us it wasn’t written down anywhere a developer looks at the moment it matters.

The guard that already existed, and already failed

This had happened before. The session log calls it “the recurring forgot-to-compile-bundles-before-release trap.” It had bitten once, been written up in the internal workflow docs as a step to remember, and bitten again anyway. A line in a workflow doc does nothing at the moment a branch is about to merge. You read it once, or you never read it if you didn’t write it.

This ticket almost shipped the same way, with three files still wired to /src/. Someone actually reading the diff before pushing caught it. No check in the pipeline did. Reading the diff carefully works until the day it doesn’t.

What actually stops it

So we stopped relying on anyone to remember, future us included, and put the check where the ticket physically cannot close without passing it. The close-time guard does two things before a ticket is allowed to transition:

  1. It scans every page file touched in the branch for a script reference under /src/. If a shipped page is still loading source instead of a dated bundle, the close fails immediately with the file and line.
  2. For every dated bundle reference that is present, it recompiles from the current /src/ source via the platform’s compile script and diffs the result against what the page actually references. If they differ, the bundle is stale: someone edited the source after the last compile and never regenerated the file the page loads.

The second check matters more. You can remember to flip a reference and still ship stale code, because the bug is compiling once and then continuing to edit. The guard never asks whether anyone remembered to compile. It recompiles and compares what you are about to ship against what the source says.

The display fixes shipped clean, with refs flipped and bundles compiled, and the ticket closed to Staging. The guard now sits in the close path for every ticket that touches a /src/*.js file. The workflow doc still says what it said before. What changed is that something other than a person reading carefully has to agree before the ticket closes.

A release step that lives in a doc is a reminder. A release step that fails the close is a control, and only the second one would have caught this branch.