doxa-maps/internal/_serves-this-tree.mjs
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

48 lines
2.4 KiB
JavaScript

/**
* _serves-this-tree.mjs — a browser gate must prove the server it talks to is THIS build.
*
* THE FAILURE THIS EXISTS FOR, MEASURED. Browser gates here default to
* http://127.0.0.1:4173 and adopt whatever answers 200 on it. On this machine that port was
* held by an unrelated process belonging to a different worktree, and the gospel-resources
* gate spent three runs reporting on a build that was not the one on disk — first a PASS,
* then a mount timeout that looked exactly like a regression in code that had nothing to do
* with it. A gate that can report on the wrong tree is worse than no gate: it produces
* confident findings about code nobody changed, and hides real ones.
*
* "Answers 200" and "is serving this checkout" are different questions. This asks the second.
*
* THE FINGERPRINT is public/doxa-maps/manifest.json, which generate-tree rewrites on every
* build and which names every bundle and profile in the tree. If the bytes served differ
* from the bytes on disk, it is a different build — a different worktree, or a stale server
* someone forgot to restart, both of which produce the same lie.
*
* Deliberately NOT fatal on its own: the caller decides whether to start its own server
* instead, or to skip. What it must never do is quietly continue.
*/
import { readFileSync } from 'node:fs'
import { createHash } from 'node:crypto'
import { resolve } from 'node:path'
const MANIFEST = 'doxa-maps/manifest.json'
/**
* @param {string} base e.g. http://127.0.0.1:4173 (a trailing /doxa-maps/ is tolerated)
* @param {string} repo absolute path to the repo root
* @returns {Promise<{ok:boolean, why:string}>}
*/
export async function servesThisTree(base, repo) {
let local
try {
local = createHash('sha256').update(readFileSync(resolve(repo, 'public', MANIFEST))).digest('hex')
} catch {
return { ok: false, why: `no local public/${MANIFEST} to compare against — build the tree first` }
}
const root = String(base).replace(/\/+$/, '').replace(/\/doxa-maps$/, '')
const r = await fetch(`${root}/${MANIFEST}`).catch(() => null)
if (!r || !r.ok) return { ok: false, why: `nothing serving ${MANIFEST} at ${root}` }
const served = createHash('sha256').update(Buffer.from(await r.arrayBuffer())).digest('hex')
if (served !== local) {
return { ok: false, why: `${root} serves a DIFFERENT build than public/ — another worktree, or a server that needs restarting` }
}
return { ok: true, why: 'same build' }
}