diff --git a/internal/check-facet-changes-map.mjs b/internal/check-facet-changes-map.mjs index c50bab114..eb3a35ed6 100644 --- a/internal/check-facet-changes-map.mjs +++ b/internal/check-facet-changes-map.mjs @@ -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 diff --git a/internal/check-filter-width-stable.mjs b/internal/check-filter-width-stable.mjs index 4748f300c..fb518c521 100644 --- a/internal/check-filter-width-stable.mjs +++ b/internal/check-filter-width-stable.mjs @@ -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) { diff --git a/internal/check-maplibre-layer-drops.mjs b/internal/check-maplibre-layer-drops.mjs index 9147b7e08..32455eafe 100644 --- a/internal/check-maplibre-layer-drops.mjs +++ b/internal/check-maplibre-layer-drops.mjs @@ -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 || []) { diff --git a/internal/check-packet-browser.mjs b/internal/check-packet-browser.mjs index 85042baf8..7d14f43fd 100644 --- a/internal/check-packet-browser.mjs +++ b/internal/check-packet-browser.mjs @@ -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), diff --git a/internal/check-provider-switch.mjs b/internal/check-provider-switch.mjs index 4bd46a4fd..dc721f771 100644 --- a/internal/check-provider-switch.mjs +++ b/internal/check-provider-switch.mjs @@ -12,7 +12,12 @@ // not calling its tile servers, and only the request log shows that. // // Usage: node internal/check-provider-switch.mjs +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) {