Commit graph

4 commits

Author SHA1 Message Date
doxa-maps-88655c70
59f497eb67 Six more browser gates measure THIS build or nothing
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
a9550858 guarded twenty gates; these six were still unguarded. Each
now exits 75 (NOT MEASURED) rather than grading another tree:
- check-legend-export-reachable, check-vision-card-numbers --url:
  requireThisTree on the URL they are given.
- check-embed-basemap-paints: it picks a RANDOM port, not an
  OS-assigned one, so if another agent holds it, its own server fails
  to start and it would measure theirs. It now checks the leaf server's
  identity, stops its own servers and exits 75. Its "a server did not
  come up" path exited 1 and now exits 75.
- check-tabs-localized, check-poster-prints read library/ from
  DOXA_REPO. Pointing that at another checkout now needs
  DOXA_REPO_MEASURE_OTHER=1 (new requireThisRepo helper).
- check-packet-render refuses a packet file inside a DIFFERENT git
  checkout (new requirePathInThisCheckout helper); a file outside any
  checkout is allowed with a note.

Proven by pointing each at a wrong build: a copy of this public/ whose
manifest differs by one byte, served on its own port, and another
worktree for the file and DOXA_REPO gates. All 8 (these 6, plus
shell-scroll and upg-map-data) exit 75. On this tree they measure:
legend-export, vision-card, upg-map-data, tabs-localized and
poster-prints PASS. packet-render gets past the guard and fails on a
non-packet file, as intended. embed-basemap measures and FAILS: "the
page does NOT paint a basemap on its own baked token". That is a
product finding, not the guard, and is reported to its owner.
2026-09-25 10:03:16 +00:00
doxa-maps-88655c70
a9550858ed Browser gates: measure THIS build, or measure nothing
About thirty browser gates could pass while describing another worktree's build.
This machine runs several checkouts and a default port belongs to whichever
server started first — measured 2026-09-24, :4173 was another worktree's, and an
hour of probing reported confidently on code nobody here had touched. check:sri
cannot see it: a stale tree and its stale leaf agree perfectly.

Twenty gates now call requireThisTree() right after they resolve their target and
exit 75 on a mismatch — EX_TEMPFAIL, the code this repo already uses for "not
measured", which the wave runner reports as ⊘ rather than ✗. Exiting 1 would turn
a mis-pointed probe into a red product gate, which is the failure this whole
family of checks exists to prevent.

★ NARROWER THAN THE PROBLEM STATEMENT, ON PURPOSE. Three classes do NOT get it,
because there it would be wrong rather than missing:
  self-serving gates  start their own server on an OS-assigned port
  file:// gates       read this checkout directly — no server to be wrong about
  remote targets      verify-map-paint defaults to the LIVE site, and "does
                      production match what we built" is a deploy question asked
                      deliberately. MEASURED mid-rollout: it reported NOT
                      MEASURED against the live host, which was the guard being
                      wrong, not the gate. It now enforces on localhost only.

TWO THINGS THE ROLLOUT TAUGHT, both caught by running rather than reading:
  · node --check passes a file that will die on ReferenceError. Adding a ROOT
    constant to sixteen gates that do not import resolve/dirname/fileURLToPath
    parsed perfectly and crashed on first run — the same shape that broke
    check-locale-reachable twice. The imports are added under aliased names so
    they cannot collide with a gate's own.
  · Five gates take their URL from argv with no default and are left for a
    per-file pass rather than patched blind.

CONTROLS: against another worktree's server a guarded gate prints NOT MEASURED
naming the mismatch and exits 75; against this checkout's server it runs and
reports normally; against the live site it proceeds.
2026-09-25 08:20:11 +00:00
doxa-maps-88655c70
9acd4f8865 Queue the browser gates, and let them serve their own tree
Two problems, one change.

LOAD. Seven agents each running a wave put 7+ chrome-headless renders on one box;
measured today it reached load 47 with 8GB of swap, and a browser gate that is
swapping measures the swap, not the product. The wave runner now holds browser
steps while 1-min load is at or above LOAD_MAX (12) and takes a coarse flock
before each one, so they queue instead of dogpiling. Thresholds, cadence and the
20-minute cap are bundler-3's wait-for-quiet.sh verbatim, and BROWSER_GATE_LOCK
selects the rendezvous, so every agent lands on one lock whichever entry point
they use. Static gates are untouched: in gates:post that is 38 free, 4 queued.

The load wait is taken ONCE per wave, not once per gate. Per-step it multiplied
the same hold by the number of browser gates — an hour of a wave doing nothing,
which is how a load fix becomes a reason to stop running gates. The flock is
what serializes; the wait only decides when to join the queue.

Browser steps are identified from the gate FILE (a playwright import), not a
hand-kept list that goes stale the first time someone adds a gate — the one
missing from such a list is exactly the one that rejoins the dogpile. `verify` is
caught too: it imports no playwright itself but spawns three gates that render,
and it already marks them browser:true, so that declaration is honoured rather
than duplicated.

COVERAGE. Yesterday's guard made check:provider-switch and check:packet-browser
SKIP in every wave, because their default ports (4173, 4898) belong to other
worktrees on this machine. Skipping was honest but a gate that skips every time
is a gate nobody runs, so on a mismatch they now start a short-lived server over
THIS checkout and measure that instead — the point was never the port, it was
being able to prove which build answered.

MEASURED: a served tree whose manifest differs by one key but has all the same
pages -> "serves a DIFFERENT build", then "serving this checkout on :28384
instead", then a real verdict (16 -> 5 mapbox requests). packet-browser likewise,
once it re-navigates to the new origin — a dynamic import across origins is
refused by a plain static server, which cost one failed run to learn.
gates:post 40/42, the only skips being the two that genuinely have no input
(packets-all, zone-census); it was 4 before this.

The lock path default is product-named. The shared file several shells export
carries an internal code name, and check:no-codename refuses to let a repo we
hand over carry one — it caught this commit's first draft.
2026-09-24 17:43:32 +00:00
doxa-maps-88655c70
fb7ed4566d Browser gates now prove the server is serving THIS checkout
The gospel-resources gate was found adopting whatever answered on the default port,
which on this machine was an unrelated process from a different worktree. It reported
on a build that was not the one on disk: first a PASS, then a mount timeout that read
exactly like a regression in code nobody had touched. "Answers 200" and "is serving
this checkout" are different questions, and only the second one is the gate's job.

That fix was local to one gate. The same default sits under the rest of them, so it is
now one shared helper, internal/_serves-this-tree.mjs, fingerprinting
public/doxa-maps/manifest.json — which generate-tree rewrites on every build and which
names every bundle and profile in the tree. Different bytes means a different build:
another worktree, or a server someone forgot to restart. Both produce the same lie.

Wired into verify-browser-all, which hands ten gates their base URL and would have
passed the wrong tree to all of them, and into check-a11y-button-names. Both now refuse
with a NOT MEASURED exit rather than producing a confident wrong answer. The gospel
gate keeps its behaviour of starting its own server instead.

Verified in both directions: against the foreign 4173 each prints "serves a DIFFERENT
build than public/" and exits 2; against this tree the aggregator proceeds to its ten
gates and the gospel gate passes.

ONE REPORTED NUMBER WAS WRONG BECAUSE OF THIS. The a11y result recorded earlier in this
flight, "810 buttons, 810 with an accessible name", was measured against the foreign
tree. Re-run against this checkout it is 825 buttons, 825 with an accessible name,
still passing across 21 leaf pages. The conclusion held; the evidence had not been
about this build.

Audited the rest of this flight's browser evidence rather than assuming: the 41 probe
scripts in _qa-cycle all target port 5399, which is served by
serve-strict --directory <this worktree>/public, and the manifest served there is
byte-identical to the local one. Those results stand.
2026-09-24 12:54:35 +00:00