Browser gates: prove the server is THIS build before believing it
Five gates took their measurement from whatever answered a default localhost port. On this machine that port belongs to whichever worktree started first: :4173 is wt-packet's server, :4898 is its repo root. Measured today — an hour of probing reported on a build that was not on disk here, and the mistake was only caught because a marker string was in the file and absent from the response. "Answers 200" and "is serving this checkout" are different questions, and only the second one licenses a verdict. _serves-this-tree.mjs already asked it (it exists because the gospel-resources gate hit this and spent three runs reporting on the wrong tree) but only three callers used it. Wired into the five that measure a served page and had no such check: check-provider-switch request tally per host — the wrong tree's tally check-maplibre-layer-drops silent layer drops — invisible by nature check-filter-width-stable width divergence — would accuse untouched CSS check-facet-changes-map data flow on facet change check-packet-browser imports the renderer FROM the server Only a genuine MISMATCH skips. "No manifest to compare" is a different precondition (an unbuilt checkout) that each gate already speaks for, and turning that into a skip would silence these on the builds they should run on. A mismatch exits 0, like the unreachable case, because it is a precondition and not a product finding — but it prints which, so nobody reads it as a pass. CONTROLS, each fired, per gate: correct server -> PASS with a real number (provider-switch 19 -> 5 mapbox requests, drops 17/17, filter-width identical, facet 2107 -> 1209 dots, packet-browser headings match); a served tree whose manifest differs by one key -> SKIP naming "serves a DIFFERENT build"; no server -> the pre-existing unreachable SKIP, unchanged. One correction found by running it rather than by reading it: the first wiring passed the LEAF PAGE URL where the helper wants the ORIGIN, so it looked for the manifest under the page's own path and skipped every run for the wrong reason. node --check cannot see that; only running both controls can. KNOWN COST, not hidden: in a wave with no server of this tree running, check:provider-switch and check:packet-browser now SKIP where they used to report a green about another worktree. That is the honest reading, not a regression, and the runner prints "evaluated nothing" for them. Next increment is to let these gates serve this checkout themselves so they measure again.
This commit is contained in:
parent
7fd8e4545c
commit
6602cd1399
5 changed files with 102 additions and 0 deletions
|
|
@ -53,6 +53,26 @@ import { chromium } from 'playwright'
|
|||
// (`bun run serve` on 4173) to run it against a built leaf or the cap-5 shell.
|
||||
const BASE = process.env.BASE_URL || 'http://127.0.0.1:5173'
|
||||
const PATH_ = process.env.PROBE_PATH || '/'
|
||||
|
||||
// ⚠ THE SERVER THAT ANSWERS IS NOT NECESSARILY THIS CHECKOUT. Several worktrees of this repo
|
||||
// run on one machine and a default port belongs to whichever started first — measured
|
||||
// 2026-09-24 on :4173. This gate reports on how a map's source data changes when a facet is
|
||||
// picked, so a run against another tree describes somebody else's data flow. The fingerprint
|
||||
// is public/doxa-maps/manifest.json; a dev server serves it straight off disk, so this stays
|
||||
// quiet in the normal `bun run dev` case and only speaks when the bytes really differ.
|
||||
{
|
||||
const { servesThisTree } = await import('./_serves-this-tree.mjs')
|
||||
const { fileURLToPath } = await import('node:url')
|
||||
const { dirname, resolve } = await import('node:path')
|
||||
const repo = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const tree = await servesThisTree(BASE, repo)
|
||||
if (/DIFFERENT build/.test(tree.why)) {
|
||||
console.log('FACET-CHANGES-MAP: SKIP — the server is not serving THIS build.')
|
||||
console.log(` ${tree.why}`)
|
||||
console.log(' Point BASE_URL at this checkout (bun run dev, or bun run serve).')
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
const TAB = process.env.PROBE_TAB || 'research-dashboard'
|
||||
const SELF_TEST = process.argv.includes('--self-test')
|
||||
// WHICH HALF OF THE FIX TO REVERT in --self-test. Default 'colour' reverts ONLY the paint, leaving
|
||||
|
|
|
|||
|
|
@ -36,9 +36,29 @@
|
|||
* NEGATIVE-TESTED: restoring `flex:1 1 160px; max-width:240px` on .filter-dropdown makes widths
|
||||
* diverge and this fails by name, naming the before/after arrays.
|
||||
*/
|
||||
import { dirname, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { chromium } from 'playwright'
|
||||
import { servesThisTree } from './_serves-this-tree.mjs'
|
||||
|
||||
const REPO = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const BASE = process.env.BASE_URL || 'http://127.0.0.1:4173/doxa-maps'
|
||||
|
||||
// ⚠ "ANSWERS 200" IS NOT "IS THIS BUILD". This machine runs several worktrees of one repo and
|
||||
// the default port belongs to whichever server started first — measured 2026-09-24: :4173 was
|
||||
// another worktree's. This gate compares filter widths BEFORE and AFTER a tab change and fails
|
||||
// on divergence, so a run against someone else's tree can report a width regression in code
|
||||
// that was never touched here. Separate that from the unreachable case below, which is already
|
||||
// a SKIP: both are preconditions, neither is a product finding.
|
||||
{
|
||||
const tree = await servesThisTree(BASE, REPO)
|
||||
if (/DIFFERENT build/.test(tree.why)) {
|
||||
console.log('FILTER-WIDTH: SKIP — the server is not serving THIS build.')
|
||||
console.log(` ${tree.why}`)
|
||||
console.log(' Serve this checkout (`bun run serve`) and pass its port as BASE_URL.')
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
const WALK = `(sel)=>{const o=[],s=new Set();const w=(r)=>{if(!r||s.has(r))return;s.add(r);try{o.push(...r.querySelectorAll(sel))}catch(e){};for(const e of r.querySelectorAll('*'))if(e.shadowRoot)w(e.shadowRoot)};w(document);return o}`
|
||||
|
||||
async function measure(page, label, activateTab) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import { chromium } from 'playwright'
|
|||
import { readFileSync, existsSync } from 'node:fs'
|
||||
import { resolve, join, dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { servesThisTree } from './_serves-this-tree.mjs'
|
||||
|
||||
// Portable by construction — see check-no-absolute-paths.mjs. Never hardcode a worktree.
|
||||
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
|
|
@ -52,6 +53,22 @@ if (!existsSync(MANIFEST)) {
|
|||
console.log('MAPLIBRE-LAYER-DROPS: SKIP — no built manifest (run `bun run tree` first).')
|
||||
process.exit(0)
|
||||
}
|
||||
// ⚠ REACHABLE AND MINE ARE DIFFERENT QUESTIONS. This machine runs several worktrees of one
|
||||
// repo and the default port belongs to whichever server started first — measured 2026-09-24:
|
||||
// :4173 was another worktree's, and this gate reported PASS 16/16 about a build that was not
|
||||
// on disk here. The layer-drop family is silent by nature (MapLibre omits a layer instead of
|
||||
// throwing), so a verdict taken from the wrong tree is exactly the kind nobody can catch by
|
||||
// looking. A mismatch is a precondition, not a product failure: SKIP, but name it.
|
||||
{
|
||||
const tree = await servesThisTree(BASE, ROOT)
|
||||
if (/DIFFERENT build/.test(tree.why)) {
|
||||
console.log('MAPLIBRE-LAYER-DROPS: SKIP — the server is not serving THIS build.')
|
||||
console.log(' ' + tree.why)
|
||||
console.log(' Start `bun run serve` in this checkout and pass its port as BASE_URL.')
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
const manifest = JSON.parse(readFileSync(MANIFEST, 'utf8'))
|
||||
const leaves = []
|
||||
for (const b of manifest.bundles || []) {
|
||||
|
|
|
|||
|
|
@ -56,6 +56,24 @@ try {
|
|||
console.log(' python3 -m http.server 4898 (or set PACKET_ORIGIN)')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
// ⚠ AND IT MUST BE THIS CHECKOUT'S ROOT. Several worktrees of this repo run on one machine,
|
||||
// so a port that answers may belong to another one — measured 2026-09-24 on :4173, where a
|
||||
// browser gate reported on a build that was not on disk here. This gate imports the shared
|
||||
// renderer FROM THE SERVER, so the wrong origin means it verifies someone else's renderer
|
||||
// and says nothing about this change. Precondition, not a product failure: SKIP and name it.
|
||||
{
|
||||
const { servesThisTree } = await import('./_serves-this-tree.mjs')
|
||||
const repo = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const tree = await servesThisTree(ORIGIN + '/public', repo)
|
||||
if (/DIFFERENT build/.test(tree.why)) {
|
||||
await b.close()
|
||||
console.log('PACKET-BROWSER: SKIP — the server is not serving THIS checkout.')
|
||||
console.log(` ${tree.why}`)
|
||||
console.log(' Serve THIS repo root and re-run (PACKET_ORIGIN=http://127.0.0.1:PORT).')
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
const html = await pg.evaluate(async ({RENDER, STRINGS, LANG, ORIGIN, API, ISO3, ZONE}) => {
|
||||
const [{ createPacketRenderer }, strings, norm] = await Promise.all([
|
||||
import(RENDER),
|
||||
|
|
|
|||
|
|
@ -12,7 +12,12 @@
|
|||
// not calling its tile servers, and only the request log shows that.
|
||||
//
|
||||
// Usage: node internal/check-provider-switch.mjs <leafUrl>
|
||||
import { dirname, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { chromium } from 'playwright'
|
||||
import { servesThisTree } from './_serves-this-tree.mjs'
|
||||
|
||||
const REPO = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
|
||||
// ⚠ NOT named `URL` — that shadows the global URL constructor, so every
|
||||
// `new URL(request.url())` below throws and the host tally stays EMPTY while the
|
||||
|
|
@ -39,6 +44,28 @@ const LEAF = process.argv[2] || DEFAULT_LEAF
|
|||
console.log(' python3 -m http.server 4173 --directory public (or set BASE_URL)')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
// ⚠ REACHABLE IS NOT THE SAME QUESTION AS MINE. Several worktrees of this repo run on one
|
||||
// machine and the default port belongs to whichever started first — measured 2026-09-24:
|
||||
// :4173 was another worktree's server, and an hour of probing reported on a build nobody
|
||||
// here had changed. This gate's whole verdict is a request tally from a page; a tally taken
|
||||
// from someone else's page is a confident statement about the wrong code.
|
||||
// A mismatch is a PRECONDITION, not a product failure, so it SKIPs (exit 0) like the
|
||||
// unreachable case above — but it says which, so nobody reads it as a pass.
|
||||
// The helper wants the ORIGIN that serves public/, not the leaf page — passing the page URL
|
||||
// makes it look for the manifest under the page's own path and report "nothing serving it",
|
||||
// which would SKIP every run for the wrong reason. (Measured: it did, on both servers.)
|
||||
const tree = await servesThisTree(new URL(LEAF).origin, REPO)
|
||||
// Only a genuine MISMATCH skips. "No manifest to compare" (an unbuilt checkout) is a
|
||||
// different precondition and the reachable check above already speaks for it — turning
|
||||
// that into a skip here would silence the gate on exactly the builds it should run on.
|
||||
if (/DIFFERENT build/.test(tree.why)) {
|
||||
console.log('PROVIDER-SWITCH: SKIP — the server is not serving THIS build.')
|
||||
console.log(` ${tree.why}`)
|
||||
console.log(' Serve your own tree and re-run, e.g.:')
|
||||
console.log(' bun run serve (then BASE_URL=http://127.0.0.1:PORT)')
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
async function run(provider) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue