/**
* qa-l9-matrix.mjs — the L9 release-candidate QA matrix, in one command.
*
* L9 = the final live keyed end-to-end QA pass
* (P1-5) + the browser tracking gate (P1-7) + a re-confirmation of the release
* bar, run against the release candidate before the repo goes public.
*
* This runner does everything in that matrix that a machine can honestly do:
*
* A · REPO static gates — unit suite, build, the Node-24 allocation gate,
* secret/private-name scans, LAN-safe defaults, public files.
* B · FEED server-side probes — does each keyed proxy actually return
* live data, and does a MISSING key degrade honestly?
* C · APP one real browser session — layers populate, credits list,
* clean-UI keeps attribution, no key leaks into the client.
* D · HARNESS the existing qa-*.mjs fleet, invoked as subprocesses and
* aggregated. This runner never reimplements what they cover.
* M · MANUAL the owner-eyes checks (3 voice mic round trips, the LAN
* warning, the live-vessel transfer, …). Always reported as
* SKIPPED/OWNER-RUN so the coverage math stays honest — the
* steps live in the maintainers' release runbook.
*
* Honest degradation is the core contract: a check that needs a key THIS run
* does not have is SKIPPED with an OWNER-RUN tag, never failed. A FAIL always
* means "the product is wrong", not "my environment was thin".
*
* Run:
* node scripts/qa-l9-matrix.mjs # against :4173
* node scripts/qa-l9-matrix.mjs --url http://localhost:4220
* node scripts/qa-l9-matrix.mjs --cheap # read-only, no heavy harnesses
* node scripts/qa-l9-matrix.mjs --only A,B # groups or ids
* node scripts/qa-l9-matrix.mjs --skip D8,D12 # drop specific checks
* node scripts/qa-l9-matrix.mjs --list # print the matrix and exit
* node scripts/qa-l9-matrix.mjs --json out.json # machine-readable results
* node scripts/qa-l9-matrix.mjs --headful # watch the browser group
*
* Exit codes: 0 = no FAILs · 1 = at least one FAIL · 2 = target unreachable.
*/
import puppeteer from 'puppeteer';
import { spawn } from 'node:child_process';
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { dirname, resolve } from 'node:path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = resolve(__dirname, '..');
// ── CLI ───────────────────────────────────────────────────────────────────
const argv = process.argv.slice(2);
function getOpt(flag, def) {
const i = argv.indexOf(flag);
return i >= 0 && argv[i + 1] ? argv[i + 1] : def;
}
const has = (flag) => argv.includes(flag);
const APP_URL = getOpt('--url', 'http://localhost:4173').replace(/\/$/, '');
const APP_ORIGIN = new URL(APP_URL).origin;
const CHEAP = has('--cheap');
const HEADFUL = has('--headful');
const LIST_ONLY = has('--list');
const JSON_OUT = getOpt('--json', null);
const ONLY = (getOpt('--only', '') || '').split(',').map((s) => s.trim()).filter(Boolean);
const SKIP_IDS = (getOpt('--skip', '') || '').split(',').map((s) => s.trim()).filter(Boolean);
// ── THE GOVERNING PRINCIPLE ───────────────────────────────────────────────
//
// FAIL means the product is wrong. ENV/SKIP must be POSITIVELY identified,
// never a default:
// · connection-refused / target-gone → ENV
// · HTTP 500 or a malformed payload from a
// RESPONSIVE app → PRODUCT FAIL
// · a harness crash → HARNESS-CRASH (its own
// visible category — never ENV, never PASS)
// · a check that could not verify its claim → that check FAILS or
// reports HARNESS-CRASH, never silently passes
//
// Corollary: "no evidence of failure" is not "evidence of success". Every
// check asserts the behaviour its description claims, or it says it could not.
//
// ── result model ──────────────────────────────────────────────────────────
const PASS = 'PASS';
const PASS_SKIPS = 'PASS-WITH-SKIPS'; // green, but the harness left assertions unrun
const FAIL = 'FAIL';
const CRASH = 'HARNESS-CRASH'; // the check itself broke — counts against green
const SKIP = 'SKIPPED';
const results = [];
const C = {
g: (s) => `\x1b[32m${s}\x1b[0m`,
r: (s) => `\x1b[31m${s}\x1b[0m`,
y: (s) => `\x1b[33m${s}\x1b[0m`,
m: (s) => `\x1b[35m${s}\x1b[0m`,
d: (s) => `\x1b[2m${s}\x1b[0m`,
b: (s) => `\x1b[1m${s}\x1b[0m`,
};
const pass = (detail) => ({ status: PASS, detail });
const passWithSkips = (detail, unrun) => ({ status: PASS_SKIPS, detail, unrun });
const fail = (detail) => ({ status: FAIL, detail });
const crash = (detail) => ({ status: CRASH, detail });
const skip = (detail, tag = 'OWNER-RUN') => ({ status: SKIP, detail, tag });
/** The closed set of outcomes. Anything else is a bug in the runner itself. */
const OUTCOMES = new Set([PASS, PASS_SKIPS, FAIL, CRASH, SKIP]);
const SKIP_TAGS = new Set(['OWNER-RUN', 'ENV', 'CHEAP', 'N/A']);
/**
* Every verdict passes through here before it is recorded. A malformed result
* — undefined, a non-object, an unknown status, a SKIP with no tag — used to
* render as `SKIPPED[undefined]`, land in no counter, and leave the run green.
* A runner that cannot classify its own result has verified nothing, so it
* reports HARNESS-CRASH against itself.
* @param {unknown} res The raw verdict a check returned.
* @returns {{status: string, detail: string, tag?: string}} A valid verdict.
*/
function normalizeVerdict(res) {
if (!res || typeof res !== 'object' || Array.isArray(res)) {
return crash(`the runner produced a malformed verdict (${res === undefined ? 'undefined' : JSON.stringify(res)?.slice(0, 80)}) — this check verified nothing`);
}
if (!OUTCOMES.has(res.status)) {
return crash(`the runner produced an unknown outcome "${String(res.status)}" — not one of ${[...OUTCOMES].join(' / ')}; this check verified nothing`);
}
if (res.status === SKIP && !SKIP_TAGS.has(res.tag)) {
return crash(`a SKIPPED verdict carried an invalid tag "${String(res.tag)}" — a skip must name its reason (${[...SKIP_TAGS].join(' / ')}), or it is indistinguishable from a silent pass`);
}
return res;
}
/** Environment facts discovered in preflight; checks read this. */
const env = {
// FIRMS/TOMTOM/AIS/OPENAI/OPENSKY →
// true key positively present
// false key positively ABSENT (the endpoint said so in its own words)
// 'error' the status endpoint is unhealthy — key state UNKNOWN, and any
// check that depends on it FAILS rather than skipping
// null deliberately not probed (--cheap)
keys: {},
node24: null, // { bin, label } for the calibrated allocation runtime
reachable: false, // got ANY HTTP response (even a 500) — vs connection refused
shellStatus: null, // the app shell's HTTP status, for the ENV-vs-FAIL split
browserVersion: null,
boot: null,
};
/**
* Branch on a key's POSITIVELY established state. Returns a verdict to return
* immediately when the state is not usable, or null to continue.
* `'error'` (status endpoint unhealthy on a responsive app) is a product FAIL,
* never a quiet skip; `null` (deliberately unprobed) is an honest skip.
*/
function keyGuard(name, state) {
if (state === true || state === false) return null;
if (state === 'error') {
return fail(`${name} key state UNKNOWN — its status endpoint errored or returned a malformed payload on a responsive server, so this check cannot say whether the key is merely absent`);
}
return skip(`${name} key presence was not probed (--cheap) — this check cannot pick its keyed/keyless branch`, 'CHEAP');
}
/**
* Required attribution per layer id, checked against the credits actually
* registered in `viewer.creditDisplay` (source strings live in
* src/data/dataCredits.js). C12 asserts EVERY enabled layer, and an enabled
* layer that appears in neither this map nor the exemption list FAILS — an
* unmapped layer must never pass silently just because nobody added it here.
*/
const CREDIT_EXPECTATIONS = {
flights: /OpenSky/i,
military: /adsb\.lol/i,
satellites: /CelesTrak/i,
earthquakes: /Geological Survey|USGS/i,
'rocket-launches': /Launch Library|LL2/i,
traffic: /TomTom|OpenStreetMap/i,
cctv: /Austin|Caltrans|Transport for London|TfL/i,
radio: /Radio Browser/i,
bikeshare: /GBFS|bikeshare/i,
'ais-live-vessels': /AISStream/i,
'military-installations': /OpenStreetMap/i,
'local-datacenters': /OpenStreetMap/i,
'local-dams': /OpenStreetMap/i,
'local-firms': /FIRMS/i,
'telegeography-submarine-cables': /TeleGeography/i,
'local-neighborhoods': /DataSF|San Francisco/i,
'weather-effects': /Open-Meteo/i,
};
/**
* Layers that legitimately register no third-party credit, with the reason.
* Anything here is an explicit decision, not an oversight.
*/
const CREDIT_EXEMPT_LAYERS = {
'military-awareness': 'derived view over other layers; it ships no data of its own and its sources carry their own credits',
detection: 'a rendering treatment over already-credited layers, not a data source',
annotations: 'user-drawn marks; no third-party data',
};
/** @returns {{regex: RegExp}|{exempt: string}|null} null = unmapped (fails closed). */
function requiredCreditFor(layerId) {
if (CREDIT_EXPECTATIONS[layerId]) return { regex: CREDIT_EXPECTATIONS[layerId] };
if (CREDIT_EXEMPT_LAYERS[layerId]) return { exempt: CREDIT_EXEMPT_LAYERS[layerId] };
return null;
}
/**
* Evaluate a package.json `engines.node` range against a version, without
* pulling in semver. Supports the comparator forms this repo uses:
* `>=24.14.0 <25 || >=26 <27`.
*
* Checking only the major version passed Node 24.0.0 against a `>=24.14.0`
* floor — the floor exists because the allocation budgets are calibrated, so
* "close enough" is exactly the wrong answer for a release gate.
* @param {string} version e.g. "24.19.0"
* @param {string} range e.g. ">=24.14.0 <25 || >=26 <27"
* @returns {?boolean} null when the range uses syntax this cannot evaluate.
*/
function satisfiesEngines(version, range) {
const parse = (v) => String(v).trim().replace(/^[v=]+/, '').split('.').map((n) => Number.parseInt(n, 10) || 0);
const cmp = (a, b) => {
const [x, y] = [parse(a), parse(b)];
for (let i = 0; i < 3; i += 1) {
if ((x[i] || 0) !== (y[i] || 0)) return (x[i] || 0) < (y[i] || 0) ? -1 : 1;
}
return 0;
};
const ops = { '>=': (c) => c >= 0, '>': (c) => c > 0, '<=': (c) => c <= 0, '<': (c) => c < 0, '=': (c) => c === 0 };
let unsupported = false;
const ok = String(range || '').split('||').some((clause) => {
const parts = clause.trim().split(/\s+/).filter(Boolean);
if (!parts.length) return false;
return parts.every((part) => {
const m = /^(>=|<=|>|<|=)?\s*v?(\d+(?:\.\d+){0,2})$/.exec(part);
if (!m) { unsupported = true; return false; }
return ops[m[1] || '='](cmp(version, m[2]));
});
});
return unsupported && !ok ? null : ok;
}
/**
* Does a `node --version` string name the runtime the allocation budgets are
* calibrated for? A3 pins the binary it actually invoked, because npm can
* re-resolve the interpreter from PATH and hand the gate a different Node than
* the one the check believes it selected.
* @param {string} version e.g. "v24.19.0"
* @returns {boolean} true only for a parseable Node 24.
*/
function isCalibratedAllocationRuntime(version) {
const [maj] = String(version || '').trim().replace(/^v/, '').split('.').map((n) => Number.parseInt(n, 10));
return maj === 24;
}
/**
* Did C10's traffic measurement expire before the flow fetch landed?
*
* The same discrimination C11 makes for the bundled layers: "still loading when
* my budget expired" is not "empty". The discriminator is whether the flow
* request ever completed — NOT whether the answer was empty — so a result that
* landed and is empty keeps failing. That empty-but-landed shape is the
* Overpass-outage signature (no road graph to colour: tiles fetched, nothing
* coloured), and it must stay a FAIL.
* @param {object} stats the traffic layer's getStats() snapshot.
* @returns {boolean} true when the check observed no flow fetch at all.
*/
function trafficFlowInconclusive(stats) {
const s = stats || {};
return s.mode === 'live'
&& !(s.tilesFetched > 0)
&& Boolean(s.loading || s.loadingLabel)
&& !s.error;
}
/** Positively-identified "the target is not there at all" (never an HTTP error). */
const CONNECTION_REFUSED_RE = /ECONNREFUSED|ECONNRESET|EHOSTUNREACH|ENOTFOUND|fetch failed|socket hang up|Connect Timeout/i;
/** Harness preflight messages that positively mean "no server", not "harness broke". */
const HARNESS_ENV_RE = /Dev server (?:not reachable|unavailable)|Dev server unavailable at|not reachable at http/i;
// ── small helpers ─────────────────────────────────────────────────────────
async function jget(path, { method = 'GET', timeoutMs = 25000, body = null } = {}) {
const res = await fetch(`${APP_URL}${path}`, {
method,
signal: AbortSignal.timeout(timeoutMs),
...(body ? { body, headers: { 'Content-Type': 'application/json' } } : {}),
});
const text = await res.text();
let json = null;
try { json = JSON.parse(text); } catch { /* text payload */ }
return { status: res.status, ok: res.ok, headers: res.headers, text, json };
}
function sh(cmd, args, { cwd = REPO_ROOT, env: extraEnv = {}, timeoutMs = 600000 } = {}) {
return new Promise((resolveP) => {
const child = spawn(cmd, args, {
cwd,
env: { ...process.env, ...extraEnv },
stdio: ['ignore', 'pipe', 'pipe'],
// Own process group: killing a timed-out harness must also take its
// Chromium descendants down. An orphaned browser keeps a GPU context and
// a websocket alive and contaminates every later check in the fleet.
detached: true,
});
let out = '';
let err = '';
const killTree = () => {
// Negative pid = the whole process group. Fall back to the bare child if
// the group is already gone.
try { process.kill(-child.pid, 'SIGKILL'); } catch { try { child.kill('SIGKILL'); } catch { /* gone */ } }
};
const timer = setTimeout(killTree, timeoutMs);
child.stdout.on('data', (d) => { out += d.toString(); });
child.stderr.on('data', (d) => { err += d.toString(); });
child.on('close', (code, signal) => {
clearTimeout(timer);
// Sweep the group again on normal exit too: a harness that leaks its
// browser would otherwise leave it running for the rest of the matrix.
try { process.kill(-child.pid, 'SIGKILL'); } catch { /* already reaped */ }
resolveP({ code, signal, out, err, timedOut: signal === 'SIGKILL' });
});
child.on('error', (e) => {
clearTimeout(timer);
resolveP({ code: -1, signal: null, out, err: String(e?.message || e), timedOut: false });
});
});
}
const tail = (s, n = 220) => (s || '').trim().split('\n').slice(-3).join(' | ').slice(-n);
// ── harness adapters ──────────────────────────────────────────────────────
// Exit-code semantics across the fleet are NOT uniform: 1 = assertions failed,
// 2 = environment/preflight (server down, key missing), 3 = harness crash. And
// qa-floor-verify never sets a code at all. So every harness declares how to
// read itself.
// Verdict lines are ANCHORED and matched across the WHOLE transcript, not
// "first hit wins". A parser that accepts the first match will happily read a
// scoreboard that has trailing garbage on it, or take the first of two
// contradictory scoreboards — both of which let a broken harness pass.
const RESULT_RE = /^[^\S\n]*RESULT:[^\S\n]*(\d+)[^\S\n]+passed,[^\S\n]*(\d+)[^\S\n]+failed(?:,[^\S\n]*(\d+)[^\S\n]+(?:skipped|inconclusive))?[^\S\n]*$/gm;
const COCKPIT_RE = /^[^\S\n]*RESULT:[^\S\n]*(READY|NOT_READY)[^\S\n]*\((\d+)[^\S\n]+failures\)[^\S\n]*$/gm;
const FLOOR_RE = /^[^\S\n]*VERDICT:[^\S\n]*(PASS|INCONCLUSIVE|FAIL)[^\S\n]*$/gm;
const OVERLAY_RE = /^[^\S\n]*Summary:[^\S\n]*(\d+)[^\S\n]+measured[^\S\n]*·[^\S\n]*(\d+)[^\S\n]+skipped[^\S\n]*·[^\S\n]*(\d+)[^\S\n]+errors[^\S\n]*$/gm;
/**
* Collect EVERY complete verdict line in a transcript.
*
* A harness must emit exactly one. Zero means it never reported; more than one
* means its output is self-contradictory (two scoreboards) or duplicated, and
* a runner that silently takes the first is choosing which truth to believe.
* @param {RegExp} re A /gm/-flagged, line-anchored verdict pattern.
* @param {string} text The transcript to scan.
* @returns {RegExpExecArray[]} All matches, in order.
*/
function allVerdictLines(re, text) {
re.lastIndex = 0;
return [...String(text || '').matchAll(re)];
}
/**
* Enforce "exactly one complete verdict line" across stdout and stderr.
* @returns {{matches: RegExpExecArray[], verdict: ?object}} verdict set = stop.
*/
function soleVerdict(re, kind, { out, err }) {
const matches = [...allVerdictLines(re, out), ...allVerdictLines(re, err)];
if (matches.length > 1) {
const rendered = matches.map((m) => m[0].trim()).join(' || ');
// Identical duplicates are still a defect (which run is being reported?),
// but contradictory ones are the dangerous case. Both stop the check.
const distinct = new Set(matches.map((m) => m[0].trim()));
return {
matches,
verdict: crash(distinct.size > 1
? `contradictory harness output: ${matches.length} different ${kind} lines — ${rendered}; this check cannot be trusted either way`
: `duplicated harness output: the ${kind} line was emitted ${matches.length} times — ${rendered}; it is unclear which run this reports`),
};
}
return { matches, verdict: null };
}
/**
* Positively classify a non-parseable harness run. A missing scoreboard is a
* HARNESS-CRASH by default; it only becomes ENV when the harness itself said,
* in words, that the server was not there. Exit code 2 is NOT evidence of
* environment — several harnesses use it for arbitrary top-level exceptions.
*/
function classifyNoScoreboard(kind, { code, out, err }) {
const blob = `${err}\n${out}`;
if (HARNESS_ENV_RE.test(blob)) return skip(`harness preflight: target not reachable — ${tail(err) || tail(out)}`, 'ENV');
return crash(`no ${kind} line (exit ${code}) — the harness did not complete: ${tail(err) || tail(out)}`);
}
function readResultLine({ code, out, err, timedOut }) {
if (timedOut) return fail('timed out');
const sole = soleVerdict(RESULT_RE, 'RESULT', { out, err });
if (sole.verdict) return sole.verdict;
const m = sole.matches[0];
if (!m) return classifyNoScoreboard('RESULT', { code, out, err });
const [, p, f, s] = m;
const skipped = Number(s || 0);
const detail = `${p} passed, ${f} failed${skipped ? `, ${skipped} skipped/inconclusive` : ''}`;
if (Number(f) > 0) return fail(detail);
// A scoreboard with no assertions at all means the harness bailed before
// testing anything. It cannot be a pass, and it is not automatically ENV.
if (Number(p) === 0) return classifyNoScoreboard('asserting RESULT', { code, out, err: `${err}\nharness asserted nothing (${detail})` });
// Exit 2/3 alongside a clean scoreboard means it broke AFTER reporting
// (browser teardown, cleanup) — still not a clean pass.
if (code !== 0) return crash(`${detail}, but the harness exited ${code} after reporting: ${tail(err)}`);
// Green, but assertions were left unrun — visible, never silently green.
if (skipped > 0) return passWithSkips(detail, skipped);
return pass(detail);
}
function readCockpit({ code, out, err, timedOut }) {
if (timedOut) return fail('timed out');
const sole = soleVerdict(COCKPIT_RE, 'RESULT', { out, err });
if (sole.verdict) return sole.verdict;
const m = sole.matches[0];
if (!m) return classifyNoScoreboard('RESULT', { code, out, err });
const failures = Number(m[2]);
if (m[1] !== 'READY') return fail(`NOT_READY, ${failures} failures`);
// READY with a nonzero failure count is self-contradictory output. Reading
// only the word and ignoring the number it carries is exactly how a broken
// harness passes a gate.
if (failures > 0) {
return crash(`contradictory harness output: "READY (${failures} failures)" — the verdict and the count disagree, so this check cannot be trusted either way`);
}
if (code !== 0) return crash(`READY, but the harness exited ${code} after reporting: ${tail(err)}`);
return pass('READY, 0 failures');
}
/**
* A check may declare KNOWN CONDITIONS: an evidence-gated one-line
* classification for a non-passing verdict. The note explains a failure; it
* NEVER changes it. A condition only applies when its pattern is actually
* present in the harness transcript, so it cannot become a blanket excuse.
* @param {{status: string}} verdict The verdict to annotate.
* @param {{when: RegExp, note: string}[]} conditions Declared conditions.
* @param {string} transcript The harness stdout+stderr.
* @returns {{status: string}} The same verdict, possibly with `.note`.
*/
function applyKnownConditions(verdict, conditions, transcript) {
if (!verdict || verdict.status === PASS || !Array.isArray(conditions)) return verdict;
const hit = conditions.find((c) => c.when.test(transcript || ''));
if (hit) verdict.note = hit.note;
return verdict;
}
function readFloorVerdict({ code, out, err, timedOut }) {
// qa-floor-verify.mjs never sets an exit code — stdout is the only truth.
if (timedOut) return fail('timed out');
const sole = soleVerdict(FLOOR_RE, 'VERDICT', { out, err });
if (sole.verdict) return sole.verdict;
const m = sole.matches[0];
if (!m) return classifyNoScoreboard('VERDICT', { code, out, err });
if (m[1] === 'FAIL') return fail('VERDICT: FAIL — grounded contacts buried below the mesh floor');
if (m[1] === 'INCONCLUSIVE') {
// The oracle found nothing to measure. That is a failure of ITS
// preconditions — hiding every grounded contact must not silently skip the
// regression it exists to catch.
const counts = /low contacts with plausible mesh readings:\s*(\d+)/.exec(out);
return fail(`VERDICT: INCONCLUSIVE — the floor oracle had no candidates to measure (${counts ? `${counts[1]} plausible low contacts` : 'no count reported'}). Preconditions unmet: expected grounded/low traffic at the test airport`);
}
if (code !== 0 && code !== null) return crash(`VERDICT: PASS, but the harness exited ${code} afterwards: ${tail(err)}`);
return pass('VERDICT: PASS');
}
/**
* qa-overlay-baseline's `Summary:` line only proves SAMPLING completed — a
* scene whose layer never activated still reports `1 measured · 0 errors`. The
* harness's own `--json` carries the proof: `layerActivations[].toggleResult`
* and `.delta` (entities / primitiveLabels / nonemptyLabelText). Read that.
*/
function readOverlaySummary(layerId, jsonPath) {
return ({ code, out, err, timedOut }) => {
if (timedOut) return fail('timed out');
const sole = soleVerdict(OVERLAY_RE, 'Summary', { out, err });
if (sole.verdict) return sole.verdict;
const m = sole.matches[0];
if (!m) return classifyNoScoreboard('Summary', { code, out, err });
const [, measured, skipped, errors] = m;
if (Number(errors) > 0) return fail(`${measured} measured, ${errors} errors`);
if (Number(measured) === 0) {
return fail(`0 measured, ${skipped} skipped — the ${layerId} scene produced nothing to measure, so the layer never activated`);
}
let run = null;
try { run = JSON.parse(readFileSync(jsonPath, 'utf8')); } catch (e) {
return crash(`harness reported ${measured} measured but wrote no readable --json (${String(e?.message || e).slice(0, 80)}); this check cannot prove the ${layerId} overlay was nonempty`);
}
const act = (run.scenes || [])
.flatMap((sc) => sc.layerActivations || [])
.find((a) => a.layerId === layerId);
if (!act) return crash(`no activation record for ${layerId} in the harness JSON — the check cannot verify its claim`);
if (act.toggleResult?.error) return fail(`${layerId} failed to activate: ${String(act.toggleResult.error).slice(0, 120)}`);
if (act.toggleResult?.enabled !== true) return fail(`${layerId} did not report enabled after activation: ${JSON.stringify(act.toggleResult).slice(0, 120)}`);
const d = act.delta || {};
const drawn = (d.entities || 0) + (d.primitiveLabels || 0) + (d.primitiveBillboards || 0) + (d.primitivePoints || 0);
const layerCount = act.state?.stats?.count;
if (!(drawn > 0)) {
return fail(`${layerId} activated but drew nothing (entities=${d.entities ?? 'n/a'} primitiveLabels=${d.primitiveLabels ?? 'n/a'} stats.count=${layerCount ?? 'n/a'}) — an empty overlay is not a baseline`);
}
if (code !== 0) return crash(`${measured} measured, but the harness exited ${code} after reporting: ${tail(err)}`);
return pass(`${measured} measured, 0 errors; ${layerId} activated and drew ${drawn} (entities=${d.entities} labels=${d.primitiveLabels} nonemptyLabelText=${d.nonemptyLabelText ?? 'n/a'} stats.count=${layerCount ?? 'n/a'})`);
};
}
const HARNESS_LOG_DIR = resolve(REPO_ROOT, '.gev-logs', 'qa-l9-matrix');
/** Where D12 asks qa-overlay-baseline to write its machine-readable run. */
const OVERLAY_JSON = resolve(HARNESS_LOG_DIR, 'D12-overlay-baseline.json');
/** Declarative harness runner: reuses the shipped fleet, never reimplements it. */
function harness({ id, script, args = [], parse = readResultLine, timeoutMs = 900000, envExtra = {}, knownConditions = [] }) {
return async () => {
mkdirSync(HARNESS_LOG_DIR, { recursive: true });
const r = await sh(process.execPath, [resolve(REPO_ROOT, 'scripts', script), ...args], {
timeoutMs,
env: { QA_BASE_URL: APP_URL, ...envExtra },
});
const verdict = applyKnownConditions(parse(r), knownConditions, `${r.out}\n${r.err}`);
// A dev server whose dependency optimizer re-runs mid-test answers 504
// "Outdated Optimize Dep" and the module never evaluates. Everything
// downstream is then measured against a broken module graph — on a cold
// cache this turned the geoid module into five bogus height-datum
// "failures". That is a positively identified environment condition (an
// exact Vite marker, not a guess), so it is an ENV skip rather than a false
// accusation against the product. It never rescues a run that passed.
if ((verdict.status === FAIL || verdict.status === CRASH)
&& /Outdated Optimize Dep/.test(`${r.out}\n${r.err}`)) {
verdict.status = SKIP;
verdict.tag = 'ENV';
verdict.detail = `${verdict.detail} — but the dev server re-optimized dependencies mid-run (Vite 504 "Outdated Optimize Dep"), so this ran against a broken module graph. Load the app once to warm the server, then re-run this check.`;
}
// Keep the full transcript of anything that did not pass — otherwise
// diagnosing a harness failure costs a whole second run.
if (verdict.status !== PASS) {
try {
mkdirSync(HARNESS_LOG_DIR, { recursive: true });
const logPath = resolve(HARNESS_LOG_DIR, `${id || script.replace(/\.mjs$/, '')}.log`);
writeFileSync(logPath, `$ node scripts/${script} ${args.join(' ')}\nexit=${r.code} signal=${r.signal}\n\n--- stdout ---\n${r.out}\n--- stderr ---\n${r.err}\n`);
verdict.detail = `${verdict.detail} [log: ${logPath.replace(`${REPO_ROOT}/`, '')}]`;
} catch { /* logging must never change a verdict */ }
}
return verdict;
};
}
// ── the matrix ────────────────────────────────────────────────────────────
// heavy: dropped by --cheap (long, or drives real load against the target)
// costly: dropped by --cheap (spends third-party API credit)
// needsKey: SKIPPED/OWNER-RUN when the target server has no such key
const CHECKS = [];
const check = (spec) => { CHECKS.push(spec); };
// ─── A · REPO GATES ───────────────────────────────────────────────────────
check({
id: 'A1', group: 'A', desc: 'Node runtime satisfies package.json engines (allocation budgets are pinned to Node 24)',
run: async () => {
const pkg = JSON.parse(readFileSync(resolve(REPO_ROOT, 'package.json'), 'utf8'));
const range = pkg.engines?.node || '(unset)';
const satisfied = satisfiesEngines(process.versions.node, range);
if (satisfied === null) {
return crash(`could not evaluate engines range "${range}" against node ${process.versions.node} — this check cannot confirm the runtime is supported`);
}
if (satisfied) return pass(`node ${process.versions.node} satisfies "${range}"`);
// An off-range runtime is an environment problem, not a product defect —
// but it silently disables the allocation gate, so say so loudly. A3 then
// runs that gate under a discovered Node 24.
return env.node24
? skip(`node ${process.versions.node} is OUTSIDE "${range}"; A3 runs the allocation gate under ${env.node24.label}, but prefer running the whole L9 pass on Node 24`, 'ENV')
: fail(`node ${process.versions.node} is OUTSIDE "${range}" and no Node 24 runtime was found — the allocation gate cannot run at all`);
},
});
check({
id: 'A2', group: 'A', desc: 'npm test — unit suite green',
heavy: false,
run: async () => {
const r = await sh('npm', ['test'], { timeoutMs: 600000 });
const m = /ℹ pass (\d+)[\s\S]*?ℹ fail (\d+)/.exec(r.out) || /pass (\d+)[\s\S]*?fail (\d+)/.exec(r.out);
if (!m) return fail(`could not parse test output (exit ${r.code}): ${tail(r.err) || tail(r.out)}`);
const [, p, f] = m;
return Number(f) === 0 && r.code === 0
? pass(`${p} passed, ${f} failed`)
: fail(`${p} passed, ${f} failed (exit ${r.code})`);
},
});
check({
id: 'A3', group: 'A', desc: 'Allocation microbenchmarks actually EXECUTE (they silently skip off Node 24)',
run: async () => {
// npm test prints "[unit] SKIPPED n allocation microbenchmarks" and still
// exits 0 when the runtime is not Node 24. A green suite is therefore NOT
// proof the gate ran. Force it, under Node 24 when one is discoverable.
//
// ALWAYS invoke the Node 24 BINARY directly — never `npm test`. npm
// re-resolves the interpreter from PATH and can land back on the system
// Node even when THIS process is already 24: running the whole matrix under
// `mise exec node@24.19.0 --`, the npm shell-out still re-execed system
// Node 25 and the forced gate refused with "received 25.6.1", which the
// check then reported as a product failure. That silent re-resolution is
// the very thing A3 exists to catch, so both branches now take the same
// route and both PIN the runtime they actually invoked.
const runGate = async (bin, label) => {
const v = await sh(bin, ['--version'], { timeoutMs: 60000 });
const version = (v.out || '').trim();
if (!isCalibratedAllocationRuntime(version)) {
// run-unit-tests.mjs refuses to measure calibrated budgets off Node 24,
// so a wrong binary means the gate never ran. That is this check failing
// to establish its own claim — not evidence about the product.
return crash(`the runtime selected for the allocation gate (${label}) reports ${version || 'no parseable version'}, not Node 24 — the gate would refuse or silently skip, so this check verified nothing`);
}
const r = await sh(bin, [resolve(REPO_ROOT, 'scripts/run-unit-tests.mjs')], {
timeoutMs: 600000, env: { GEV_REQUIRE_ALLOCATION_GATE: '1' },
});
return r.code === 0
? pass(`allocation gate ran under ${label} (${version}) and passed`)
: fail(`allocation gate failed under ${label} (${version}): ${tail(r.out) || tail(r.err)}`);
};
const [maj] = process.versions.node.split('.').map(Number);
if (maj === 24) return runGate(process.execPath, 'this runtime');
if (env.node24) return runGate(env.node24.bin, env.node24.label);
return skip(`no Node 24 runtime found (running ${process.versions.node}); the gate SKIPS silently — install Node 24 and re-run`, 'OWNER-RUN');
},
});
check({
id: 'A4', group: 'A', desc: 'npm run build — production build clean',
run: async () => {
const r = await sh('npm', ['run', 'build'], { timeoutMs: 900000 });
return r.code === 0 ? pass('build succeeded') : fail(`build failed: ${tail(r.err) || tail(r.out)}`);
},
});
check({
id: 'A5', group: 'A',
// Named for what it actually does. It is a KNOWN-PREFIX scan, not a general
// secret detector — a high-entropy blob with no recognised prefix passes it.
desc: 'No tracked .env, and no known-prefix credential literals (OpenAI/Google/AWS/GitHub/Slack/Stripe/private keys)',
run: async () => {
const tracked = await sh('git', ['ls-files'], { timeoutMs: 60000 });
// git ls-files exits non-zero only on real failure — a failed enumeration
// must not read as "no .env files found".
if (tracked.code !== 0) return crash(`git ls-files failed (exit ${tracked.code}): ${tail(tracked.err)}`);
const files = tracked.out.split('\n').filter(Boolean);
if (files.length === 0) return crash('git ls-files returned nothing — cannot claim the tree is clean');
const envFiles = files.filter((f) => /(^|\/)\.env($|\.(?!example))/.test(f));
if (envFiles.length) return fail(`tracked env file(s): ${envFiles.join(', ')}`);
const patterns = [
'sk-[A-Za-z0-9]{20,}', // OpenAI
'AIza[0-9A-Za-z_\\-]{30,}', // Google
'AKIA[0-9A-Z]{16}', // AWS access key id
'ASIA[0-9A-Z]{16}', // AWS session key id
'gh[pousr]_[A-Za-z0-9]{30,}', // GitHub tokens
'xox[baprs]-[A-Za-z0-9-]{10,}', // Slack
'(sk|pk|rk)_(live|test)_[A-Za-z0-9]{16,}', // Stripe
'-----BEGIN (RSA |EC |OPENSSH |PGP )?PRIVATE KEY-----',
];
const grep = await sh('git', ['grep', '-nIE', `(${patterns.join('|')})`, '--', ':!*.md', ':!docs/**'], { timeoutMs: 120000 });
// git grep: 0 = matches found, 1 = no matches (the clean case), >1 = error.
if (grep.code > 1) return crash(`git grep failed (exit ${grep.code}): ${tail(grep.err)}`);
const hits = grep.out.split('\n').filter(Boolean);
return hits.length === 0
? pass(`no tracked .env; ${patterns.length} credential prefixes scanned across ${files.length} tracked files, no hits`)
: fail(`${hits.length} credential literal(s): ${hits.slice(0, 2).join(' | ').slice(0, 200)}`);
},
});
check({
id: 'A6', group: 'A', desc: 'Private-name scan over publicly shipped paths (release checklist)',
run: async () => {
// The public snapshot must not carry the private scenario vocabulary.
// Maintainer-internal directories are stripped at curation, so they are
// excluded here — this scans what would actually ship.
//
// The release checklist also lists two more terms that are dropped as
// blockers because both are legitimately present in the shipping tree: one
// is the name of the auto-detection default view (README, CHANGELOG,
// src/data/*), the other appears inside the bundled public geodata
// (datacenter and submarine-cable landing points). Scanning for them
// produces only false positives — flagged as a stale checklist item in
// the maintainers' release runbook, not silently honoured.
//
// The terms are assembled from fragments so THIS file carries no literal
// copy of the private vocabulary. Spelling them out here would make the
// scanner its own first hit — and this script ships publicly.
const terms = [['horm', 'uz'], ['cease', 'fire'], ['gps-', 'jamming']].map(([a, b]) => a + b);
const grep = await sh('git', ['grep', '-lIiE', terms.join('|'), '--',
':!docs/inter' + 'nal/**', ':!.cla' + 'ude/**', ':!.gev-logs/**', ':!CLA' + 'UDE.md', ':!AGENTS.md'], { timeoutMs: 120000 });
// 0 = matches, 1 = no matches, >1 = the scan itself failed.
if (grep.code > 1) return crash(`git grep failed (exit ${grep.code}): ${tail(grep.err)}`);
const hits = grep.out.split('\n').filter(Boolean);
return hits.length === 0
? pass(`clean for: ${terms.join(', ')}`)
: fail(`${hits.length} file(s) carry private terms: ${hits.slice(0, 4).join(', ')}`);
},
});
check({
id: 'A7', group: 'A', desc: 'Public-facing files present (LICENSE, SECURITY, DATA_SOURCES, README, .env.example)',
run: async () => {
const want = ['LICENSE', 'SECURITY.md', 'DATA_SOURCES.md', 'README.md', '.env.example', 'CHANGELOG.md'];
const missing = want.filter((f) => !existsSync(resolve(REPO_ROOT, f)));
return missing.length === 0 ? pass(want.join(', ')) : fail(`missing: ${missing.join(', ')}`);
},
});
check({
id: 'A8', group: 'A', desc: 'Default launch binds localhost; LAN is an explicit opt-in that warns (release bar #3)',
run: async () => {
const sh_ = readFileSync(resolve(REPO_ROOT, 'scripts/dev-fresh.sh'), 'utf8');
const localDefault = /HOST="\$\{HOST:-localhost\}"/.test(sh_);
const warns = /WARNING: HOST=/.test(sh_) && /brokers your configured API keys/i.test(sh_);
const localBanner = /Local-only mode/.test(sh_);
if (localDefault && warns && localBanner) return pass('HOST defaults to localhost; LAN path prints the key-exposure warning');
return fail(`localhost-default=${localDefault} lan-warning=${warns} local-banner=${localBanner}`);
},
});
check({
id: 'A9', group: 'A', desc: '.env.example documents LAN opt-in + the cost-control throttles',
run: async () => {
const t = readFileSync(resolve(REPO_ROOT, '.env.example'), 'utf8');
const bits = {
lan: /HOST=0\.0\.0\.0/.test(t),
google: /GEV_RATELIMIT_GOOGLE_PER_MIN/.test(t),
openai: /GEV_RATELIMIT_OPENAI_PER_MIN/.test(t),
notBilling: /not.*billing cap|billing cap/i.test(t),
};
const bad = Object.entries(bits).filter(([, v]) => !v).map(([k]) => k);
return bad.length === 0 ? pass('LAN opt-in + both throttles + the not-a-billing-cap caveat') : fail(`missing: ${bad.join(', ')}`);
},
});
// ─── B · FEED PROBES (server side) ────────────────────────────────────────
check({
id: 'B1', group: 'B', desc: 'Target serves the app shell',
run: async () => {
const r = await jget('/');
return r.ok && /
/i.test(r.text)
? pass(`HTTP ${r.status}, ${r.text.length} bytes`)
: fail(`HTTP ${r.status}`);
},
});
check({
id: 'B2', group: 'B', desc: 'Flights proxy returns live contacts (/api/opensky)',
run: async () => {
const r = await jget('/api/opensky?lamin=24&lomin=-125&lamax=50&lomax=-66', { timeoutMs: 45000 });
if (!r.ok) return fail(`HTTP ${r.status}: ${r.text.slice(0, 120)}`);
const n = r.json?.states?.length || 0;
return n > 0 ? pass(`${n} states, cache=${r.headers.get('x-opensky-cache') || 'n/a'}`) : fail('0 states returned');
},
});
check({
id: 'B3', group: 'B', desc: 'OpenSky credentials are actually in use (not the anonymous/fallback path)',
run: async () => {
const r = await jget('/api/opensky?lamin=24&lomin=-125&lamax=50&lomax=-66', { timeoutMs: 45000 });
// Header names are exact: X-OpenSky-Auth-Mode-Used / X-OpenSky-Auth-Reason.
// (An earlier guess at these names made this check pass vacuously.)
const reason = r.headers.get('X-OpenSky-Auth-Reason') || '';
const used = r.headers.get('X-OpenSky-Auth-Mode-Used') || r.headers.get('X-OpenSky-Auth') || '';
if (!r.ok) return fail(`HTTP ${r.status} from a responsive proxy (auth=${used || 'n/a'} reason=${reason || 'n/a'}): ${r.text.slice(0, 120)}`);
if (!used) return fail('proxy answered 200 without the X-OpenSky-Auth headers — cannot verify which auth mode served this');
if (/invalid_credentials|rejected/.test(reason)) return fail(`OpenSky rejected the configured credentials (reason=${reason})`);
if (/missing_.*creds|invalid_or_missing/.test(reason) || used === 'anon') {
return skip(`OpenSky served ANONYMOUSLY (auth=${used}, reason=${reason || 'n/a'}) — the keyed claim needs configured credentials`, 'OWNER-RUN');
}
if (!/^(oauth|basic)$/.test(used)) {
// 'cached'/'unknown'/'adsblol-regional' etc. — real, but not proof that
// credentials are in use right now.
return fail(`served by mode "${used}" (reason=${reason || 'n/a'}) — not a live authenticated OpenSky fetch, so this check cannot confirm credentials are in use`);
}
return pass(`authenticated: auth=${used}, reason=${reason || 'n/a'}, cache=${r.headers.get('X-OpenSky-Cache') || 'n/a'}`);
},
});
check({
id: 'B4', group: 'B', desc: 'CelesTrak TLE proxy serves and caches (/api/celestrak/stations)',
run: async () => {
const r = await jget('/api/celestrak/stations', { timeoutMs: 40000 });
if (!r.ok) return fail(`HTTP ${r.status}`);
const lines = r.text.split('\n').filter((l) => /^1 /.test(l)).length;
const cache = r.headers.get('x-tle-cache');
return lines > 0 ? pass(`${lines} TLE records, x-tle-cache=${cache}`) : fail('no TLE lines in response');
},
});
check({
id: 'B5', group: 'B', desc: 'TLEs are FRESH (epoch under 14 days — a stale catalog silently mis-propagates)',
run: async () => {
const r = await jget('/api/celestrak/stations', { timeoutMs: 40000 });
if (!r.ok) return fail(`HTTP ${r.status}`);
const line1 = r.text.split('\n').find((l) => /^1 /.test(l));
if (!line1) return fail('no TLE line 1 found');
// Columns 19-32: epoch YYDDD.DDDDDDDD
const yy = Number(line1.slice(18, 20));
const ddd = Number(line1.slice(20, 32));
const year = yy < 57 ? 2000 + yy : 1900 + yy;
const epoch = new Date(Date.UTC(year, 0, 1) + (ddd - 1) * 86400000);
const ageDays = (Date.now() - epoch.getTime()) / 86400000;
return ageDays >= 0 && ageDays < 14
? pass(`newest epoch ${epoch.toISOString().slice(0, 10)} (${ageDays.toFixed(1)} d old)`)
: fail(`TLE epoch ${epoch.toISOString().slice(0, 10)} is ${ageDays.toFixed(1)} days old`);
},
});
check({
id: 'B6', group: 'B', desc: 'FIRMS proxy returns live fires', needsKey: 'FIRMS',
run: async () => {
const r = await jget('/api/firms', { timeoutMs: 60000 });
if (!r.ok) return fail(`HTTP ${r.status}: ${r.text.slice(0, 120)}`);
const n = r.json?.count ?? r.json?.fires?.length ?? 0;
return n > 0
? pass(`${n} fires, stale=${r.json?.stale}, sources=${(r.json?.sources || []).length}`)
: fail('0 fires from a keyed FIRMS proxy');
},
});
check({
id: 'B7', group: 'B', desc: 'FIRMS without a key fails HONESTLY (503 no_key, never a healthy-empty)',
run: async () => {
const guard = keyGuard('FIRMS', env.keys.FIRMS);
if (guard) return guard;
if (env.keys.FIRMS === true) return skip('server HAS a FIRMS key — the keyless path needs an unkeyed server', 'N/A');
const r = await jget('/api/firms');
return r.status === 503 && r.json?.error === 'no_key'
? pass('503 {"error":"no_key"}')
: fail(`expected 503 no_key, got ${r.status} ${r.text.slice(0, 120)}`);
},
});
check({
id: 'B8', group: 'B', desc: 'AIS vessel feed is live (/api/ais-live)', needsKey: 'AIS',
run: async () => {
const r = await jget('/api/ais-live', { timeoutMs: 40000 });
const rows = r.json?.rows?.length || 0;
const status = r.json?.status;
if (!r.ok) return fail(`HTTP ${r.status} status=${status}`);
// Rows alone are NOT liveness. The watchdog keeps serving cached vessels
// through stale/reconnecting/down — "the cached vessels on screen are
// exactly what makes an outage invisible" (src/data/aisLiveVessels.js:183).
// A live claim therefore needs status === 'live' AND rows.
// ('open' is the pre-watchdog spelling: still accepted by the client, never
// emitted by this server — aisWatchdog.js:72.)
const healthy = status === 'live' || status === 'open';
if (healthy && rows > 0) {
return pass(`${rows} vessels, status=${status}, newest=${r.json?.newestPositionAt || 'n/a'}, silentFor=${r.json?.silentForMs ?? 'n/a'}ms`);
}
if (status === 'auth-failed') {
// A rejected key is terminal and is the product's problem to report.
return fail(`AISStream rejected the configured key (status=auth-failed, rows=${rows}) — retry is terminal (retryInSec 0)`);
}
if (healthy && rows === 0) {
return skip(`status=live but 0 rows — AISStream connects open-but-silent upstream (their #23/#15); recheck when it wakes`, 'ENV');
}
if (['stale', 'reconnecting', 'down', 'connecting'].includes(status)) {
// Transient/degraded is ENV only because the payload SAYS so — the
// honesty is the evidence. rows>0 here means cached, not live.
return skip(`feed is ${status}${rows > 0 ? ` while still serving ${rows} CACHED rows` : ''} (attempt=${r.json?.reconnectAttempt ?? 'n/a'}, nextAttemptAt=${r.json?.nextAttemptAt ?? 'n/a'}, silentFor=${r.json?.silentForMs ?? 'n/a'}ms) — surfaced honestly, but this is not a live feed`, 'ENV');
}
return fail(`unexpected AIS feed status "${status}" with ${rows} rows — not one of live/stale/reconnecting/down/auth-failed/connecting`);
},
});
check({
id: 'B9', group: 'B', desc: 'AIS without a key fails HONESTLY (503 + missing-key status, no reconnect loop)',
run: async () => {
const guard = keyGuard('AIS', env.keys.AIS);
if (guard) return guard;
if (env.keys.AIS === true) return skip('server HAS an AISStream key', 'N/A');
const r = await jget('/api/ais-live');
return r.status === 503 && r.json?.status === 'missing-key' && Array.isArray(r.json?.rows)
? pass(`503 status=missing-key, rows=[] — "${String(r.json?.error).slice(0, 60)}"`)
: fail(`expected 503/missing-key, got ${r.status} ${r.text.slice(0, 120)}`);
},
});
check({
id: 'B10', group: 'B', desc: 'TomTom traffic reports LIVE mode with budget accounting', needsKey: 'TOMTOM',
run: async () => {
const r = await jget('/api/tomtom/status');
if (!r.ok) return fail(`HTTP ${r.status}`);
return r.json?.hasKey
? pass(`hasKey=true, used ${r.json.dailyCount}/${r.json.budget} tiles today`)
: fail('status says hasKey=false on a server that reported a TomTom key');
},
});
check({
id: 'B11', group: 'B', desc: 'TomTom without a key identifies SIMULATION honestly (200 hasKey:false)',
run: async () => {
const guard = keyGuard('TOMTOM', env.keys.TOMTOM);
if (guard) return guard;
if (env.keys.TOMTOM === true) return skip('server HAS a TomTom key', 'N/A');
const r = await jget('/api/tomtom/status');
const tile = await jget('/api/tomtom/flow/12/1000/1600.pbf');
return r.ok && r.json?.hasKey === false && tile.status === 503 && tile.json?.error === 'no_key'
? pass('status 200 hasKey:false; flow tile 503 no_key')
: fail(`status=${r.status} hasKey=${r.json?.hasKey}; tile=${tile.status} ${tile.text.slice(0, 60)}`);
},
});
check({
id: 'B12', group: 'B', desc: 'CCTV source packs registered (Austin + at least one more city)',
run: async () => {
const r = await jget('/api/cctv/sources', { timeoutMs: 60000 });
if (!r.ok) return fail(`HTTP ${r.status}`);
const src = r.json?.sources || [];
const cities = [...new Set(src.map((s) => s.cityId || s.city))];
const austin = src.some((s) => /austin/i.test(s.cityId || s.city || ''));
return src.length > 0 && austin && cities.length >= 2
? pass(`${src.length} cameras across ${cities.length} packs: ${cities.slice(0, 6).join(', ')}`)
: fail(`${src.length} cameras, austin=${austin}, packs=${cities.join(',')}`);
},
});
check({
id: 'B13', group: 'B', desc: 'CCTV frame proxy returns real image bytes',
run: async () => {
const list = await jget('/api/cctv/sources', { timeoutMs: 60000 });
const first = (list.json?.sources || [])[0];
if (!first) return fail('no CCTV sources to sample');
const res = await fetch(`${APP_URL}/api/cctv/frame/${encodeURIComponent(first.id)}`, { signal: AbortSignal.timeout(45000) });
const ct = res.headers.get('content-type') || '';
const buf = Buffer.from(await res.arrayBuffer());
return res.ok && /^image\//.test(ct) && buf.length > 512
? pass(`${first.id}: ${ct}, ${(buf.length / 1024).toFixed(0)} KB`)
: fail(`HTTP ${res.status} content-type=${ct} bytes=${buf.length}`);
},
});
check({
id: 'B14', group: 'B', desc: 'CCTV health route answers (per-camera upstream status)',
run: async () => {
const r = await jget('/api/cctv/health', { timeoutMs: 45000 });
return r.ok && Array.isArray(r.json?.cameras)
? pass(`cameras[]=${r.json.cameras.length} tracked`)
: fail(`HTTP ${r.status} ${r.text.slice(0, 100)}`);
},
});
check({
id: 'B15', group: 'B', desc: 'Radio directory proxy returns stations (or a labelled degraded state)',
run: async () => {
const r = await jget('/api/radio/stations?limit=20', { timeoutMs: 45000 });
const rows = Array.isArray(r.json) ? r.json.length : (r.json?.stations?.length || 0);
if (r.ok && rows > 0) return pass(`${rows} stations`);
if (r.status === 503 && r.json?.degraded) return skip(`upstream Radio Browser degraded: ${r.json.degradedReason}`, 'ENV');
return fail(`HTTP ${r.status} rows=${rows} ${r.text.slice(0, 100)}`);
},
});
check({
id: 'B16', group: 'B', desc: 'Launch Library proxy returns upcoming missions',
run: async () => {
const r = await jget('/api/launches', { timeoutMs: 45000 });
const n = r.json?.results?.length ?? r.json?.launches?.length ?? (Array.isArray(r.json) ? r.json.length : 0);
if (r.ok && n > 0) return pass(`${n} launches`);
if (r.ok) return skip('proxy up but no upcoming launches listed', 'ENV');
return fail(`HTTP ${r.status}`);
},
});
check({
id: 'B17', group: 'B', desc: 'Terrain height service answers (the height-datum backbone)',
run: async () => {
// Contract: points="lon,lat;lon,lat;…" (longitude first).
const r = await jget('/api/terrain/heights?points=-97.7431,30.2672', { timeoutMs: 45000 });
if (r.status === 502) return skip(`terrain upstream unavailable and no cache: ${r.text.slice(0, 90)}`, 'ENV');
if (!r.ok) return fail(`HTTP ${r.status} ${r.text.slice(0, 100)}`);
const first = r.json?.results?.[0];
return Number.isFinite(first?.elevation) && Number.isFinite(first?.geoid)
? pass(`Austin: elevation ${first.elevation.toFixed(1)} m, geoid ${first.geoid.toFixed(1)} m, ellipsoid ${first.ellipsoid.toFixed(1)} m`)
: fail(`unexpected payload: ${r.text.slice(0, 120)}`);
},
});
check({
id: 'B18', group: 'B', desc: 'Overpass proxy answers a real query (roads, annotations, installations)',
heavy: true,
run: async () => {
// Contract: a form-encoded body with exactly one bounded `data` query.
const query = '[out:json][timeout:25];node(30.26,-97.75,30.27,-97.74)["amenity"="cafe"];out 5;';
const res = await fetch(`${APP_URL}/api/overpass`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({ data: query }).toString(),
signal: AbortSignal.timeout(60000),
});
const text = await res.text();
let json = null; try { json = JSON.parse(text); } catch { /* not json */ }
if (res.ok && Array.isArray(json?.elements)) return pass(`${json.elements.length} elements`);
return res.status === 502
? skip(`Overpass upstream unavailable: ${text.slice(0, 80)}`, 'ENV')
: fail(`HTTP ${res.status} ${text.slice(0, 100)}`);
},
});
check({
id: 'B19', group: 'B', desc: 'Realtime token endpoint mints an EPHEMERAL secret and never the raw key',
needsKey: 'OPENAI', costly: true,
run: async () => {
const r = await jget('/api/realtime/token', { method: 'POST', timeoutMs: 30000 });
if (!r.ok) return fail(`HTTP ${r.status}: ${r.text.slice(0, 120)}`);
const blob = r.text;
if (/\bsk-[A-Za-z0-9]{20,}/.test(blob)) return fail('response contains a raw sk- key');
return /ek_|client_secret|value/.test(blob)
? pass('ephemeral client secret returned; no raw key in the payload')
: fail(`unexpected token payload: ${blob.slice(0, 120)}`);
},
});
check({
id: 'B20', group: 'B', desc: 'Voice without a key fails HONESTLY (503, app unaffected)',
run: async () => {
const guard = keyGuard('OPENAI', env.keys.OPENAI);
if (guard) return guard;
if (env.keys.OPENAI === true) return skip('server HAS an OpenAI key — the keyless path needs an unkeyed server', 'N/A');
const r = await jget('/api/realtime/token', { method: 'POST' });
return r.status === 503 && /OPENAI_API_KEY is not set/.test(r.text)
? pass('503 "OPENAI_API_KEY is not set"')
: fail(`expected 503, got ${r.status} ${r.text.slice(0, 120)}`);
},
});
check({
id: 'B21', group: 'B', desc: 'No proxy echoes credential material back to the client (P1-5 acceptance #4)',
run: async () => {
const paths = ['/api/cctv/sources', '/api/tomtom/status', '/api/firms/status', '/api/celestrak/stations', '/api/ais-live'];
const leaked = [];
const unscannable = [];
for (const p of paths) {
let r;
// A route this check could not read is a route it did not scan. Swallowing
// the exception and still reporting "5 routes scanned" is a false PASS.
try { r = await jget(p, { timeoutMs: 30000 }); } catch (e) {
unscannable.push(`${p} (${String(e?.message || e).slice(0, 60)})`);
continue;
}
// An error page is not a payload. Scanning five 500s and finding no key
// is trivially true and proves nothing — a broken app must not satisfy a
// negative assertion. The one documented exception is the keyless
// 503 {status:'missing-key'} from /api/ais-live, which IS its real shape.
const documentedKeyless = r.status === 503
&& (r.json?.status === 'missing-key' || r.json?.error === 'no_key' || /OPENAI_API_KEY is not set/.test(r.text));
if (!r.ok && !documentedKeyless) {
unscannable.push(`${p} (HTTP ${r.status})`);
continue;
}
const body = r.text.slice(0, 400000);
if (/\bsk-[A-Za-z0-9]{20,}/.test(body)) leaked.push(`${p}: sk- key`);
if (/AIza[0-9A-Za-z_\-]{30,}/.test(body)) leaked.push(`${p}: Google key`);
if (/(client_secret|api_?key|MAP_KEY)["']?\s*[:=]\s*["'][A-Za-z0-9_\-]{16,}/i.test(body)) leaked.push(`${p}: key-shaped assignment`);
}
if (leaked.length) return fail(leaked.join('; '));
if (unscannable.length) {
return fail(`could not read ${unscannable.length}/${paths.length} routes, so this check cannot claim they are clean: ${unscannable.join(', ')}`);
}
return pass(`${paths.length} routes scanned, no credential material`);
},
});
// ─── C · IN-BROWSER PROBES (single shared session) ────────────────────────
// These run inside runBrowserGroup(); each declares only its id/desc here so
// --list and the scoreboard stay complete.
const BROWSER_CHECKS = [
['C1', 'App boots: viewer + dataManager live, first paint under 60 s'],
['C2', 'Photorealistic 3D basemap attached (globe alive on arrival)'],
['C3', 'Boot produces no uncaught page errors'],
['C4', 'Flights layer populates with live contacts'],
['C5', 'Satellites layer propagates the live catalog'],
['C6', 'Earthquakes layer populates'],
['C7', 'CCTV layer populates and its frame loop is healthy'],
['C8', 'Vessels: live rows when keyed, honest UNAVAILABLE when not'],
['C9', 'Fires: live cells when keyed, honest KEY REQUIRED when not'],
['C10', 'Traffic: LIVE mode when keyed, clearly-labelled SIMULATION when not'],
['C11', 'Bundled layers render: datacenters, dams, submarine cables, installations'],
['C12', 'Attribution lightbox lists a credit for every enabled layer'],
['C13', 'Clean-UI keeps the Google/Cesium credit line visible (ToS)'],
['C14', 'No key material reaches browser state, URLs or storage'],
['C15', 'Sensor styles (CRT/NVG/FLIR) apply without moving the camera'],
['C16', 'Reset-to-globe control returns the camera to the global band'],
['C17', 'Voice surface degrades honestly without a key'],
];
for (const [id, desc] of BROWSER_CHECKS) check({ id, group: 'C', desc, browser: true });
// ─── D · EXISTING HARNESS FLEET ───────────────────────────────────────────
check({
id: 'D1', group: 'D', desc: 'track-regression — the tracking/height-datum invariant gate (P1-7)',
heavy: true, run: harness({ id: 'D1', script: 'track-regression.mjs', args: ['--url', APP_URL], timeoutMs: 1200000 }),
});
check({
id: 'D2', group: 'D', desc: 'qa-heading-b3 — path-derived display heading',
heavy: true, run: harness({ id: 'D2', script: 'qa-heading-b3.mjs', args: ['--url', APP_URL], timeoutMs: 900000 }),
});
check({
id: 'D3', group: 'D', desc: 'qa-sprites-b5 — per-class billboard silhouettes',
heavy: true,
run: harness({
id: 'D3',
script: 'qa-sprites-b5.mjs',
args: ['--url', APP_URL],
timeoutMs: 900000,
knownConditions: [{
// Evidence-gated: only when its console assertion is the failing one AND
// the transcript actually shows a 503. Explains, never excuses.
when: /no console errors[\s\S]{0,300}?503/,
note: 'not key-tolerant — its "no console errors" assertion counts the honest keyless 503s (e.g. /api/openai/hud-summary) as errors; expected to PASS on the fully keyed server. Still a FAIL here.',
}],
}),
});
check({
id: 'D4', group: 'D', desc: 'qa-cctv-v2 — camera geometry, projection, ambient cards',
heavy: true, run: harness({ id: 'D4', script: 'qa-cctv-v2.mjs', args: ['--url', APP_URL], timeoutMs: 1500000 }),
});
check({
id: 'D5', group: 'D', desc: 'qa-failstate-b10 — fabricated upstream failures degrade honestly',
run: harness({ id: 'D5', script: 'qa-failstate-b10.mjs', args: ['--url', APP_URL], timeoutMs: 900000 }),
});
check({
id: 'D6', group: 'D', desc: 'qa-attribution-b12 — per-layer credits + clean/recording credit line',
run: harness({ id: 'D6', script: 'qa-attribution-b12.mjs', args: ['--url', APP_URL], timeoutMs: 600000 }),
});
check({
id: 'D7', group: 'D', desc: 'qa-cockpit-utility — cockpit display/radio layout readiness',
heavy: true, parseNote: 'READY/NOT_READY',
run: harness({
id: 'D7',
script: 'qa-cockpit-utility.mjs',
parse: readCockpit,
timeoutMs: 900000,
knownConditions: [{
// Narrow and evidence-gated: the console assertion is the failing one AND
// the noise is an upstream proxy honestly reporting unavailability.
when: /runtime console remains clean[\s\S]{0,400}?503/,
note: 'the only failing assertion is "runtime console remains clean", and the noise is honest 503s from an upstream-backed proxy (e.g. /api/military-installations reporting "temporarily unavailable"). Environmental, but still a FAIL: re-run when the upstream recovers before filing anything.',
}],
}),
});
check({
id: 'D8', group: 'D', desc: 'qa-radio — worldwide radio browse/play surface',
heavy: true, run: harness({ id: 'D8', script: 'qa-radio.mjs', args: ['--url', APP_URL], timeoutMs: 900000 }),
});
check({
id: 'D9', group: 'D', desc: 'qa-floor-verify — grounded contacts sit ON the rendered mesh floor',
heavy: true,
run: harness({
id: 'D9',
script: 'qa-floor-verify.mjs',
parse: readFloorVerdict,
timeoutMs: 600000,
knownConditions: [{
when: /VERDICT:\s*FAIL|buried/i,
note: 'EXPECTED at main 4f9d99b — the below-mesh fix is not landed, so grounded contacts sit under the floor. Annotated, never green. If fix/below-mesh-contacts has landed, PASS is expected instead and any remaining FAIL (jet-bridge / intra-cell relief residual) is a REAL failure that stays FAIL.',
}],
}),
});
check({
id: 'D10', group: 'D', desc: 'qa-voice-routing (behavior layer) — tool behavior without model turns',
heavy: true, run: harness({ id: 'D10', script: 'qa-voice-routing.mjs', args: ['--layer', 'behavior', '--url', APP_URL], timeoutMs: 1500000 }),
});
check({
id: 'D11', group: 'D', desc: 'qa-firms — live fire rendering and interaction', needsKey: 'FIRMS', heavy: true,
run: harness({ id: 'D11', script: 'qa-firms.mjs', args: ['--url', APP_URL], timeoutMs: 900000 }),
});
check({
id: 'D12', group: 'D', desc: 'qa-overlay-baseline (submarine cables scene) — overlay/label baseline',
heavy: true,
run: harness({
id: 'D12',
script: 'qa-overlay-baseline.mjs',
args: ['--url', APP_URL, '--scene', 'cables', '--json', OVERLAY_JSON],
parse: readOverlaySummary('telegeography-submarine-cables', OVERLAY_JSON),
timeoutMs: 900000,
}),
});
// ─── M · OWNER-EYES (never automated; steps in the runbook) ───────────────
const MANUAL = [
['M1', 'Voice mic round trip 1/3 — "when is the next ISS pass?" (next_iss_pass)'],
['M2', 'Voice mic round trip 2/3 — connect/disconnect twice in one tab + keyed set_context_mode and control_cockpit'],
['M3', 'Voice mic round trip 3/3 — adsbdb enrichment readout on a live tracked flight'],
['M4', 'LAN warning path — HOST=0.0.0.0 banner, LAN URL, and a throttled response'],
['M5', 'Live AIS vessel one-click camera transfer — requires status=live, not cached rows (never verified against a live feed)'],
['M6', 'CCTV dense-city interaction — cold fill, hover, select, card removal, monitor plane, coverage, auto-hop suspend'],
['M7', 'Grounded + airborne tracked aircraft from 2-3 headings (DISPLAY 3D ON, non-TR-3B subject)'],
['M8', 'Voice analyst_query: exact unrounded count + scopeLabel, contactsWindow verbatim, follow-up re-filter'],
['M9', 'First-run: the arrival camera feels alive within 30 seconds'],
['M10', 'Sensor styles + Contacts-owned detection (DENSE/75 on activation-from-OFF; Cockpit inert; restore on deactivation)'],
['M11', 'Cancelled cross-mode Context switch rests on Context OFF (contextOff + priorMode, no restoration)'],
];
for (const [id, desc] of MANUAL) check({ id, group: 'M', desc, manual: true });
// ── selection ─────────────────────────────────────────────────────────────
function selected(c) {
if (SKIP_IDS.includes(c.id)) return false;
if (!ONLY.length) return true;
// EXACT id or whole-group only. Prefix matching made `--only D1` quietly
// select D10/D11/D12 as well, so a "single-check rerun" was not one.
return ONLY.some((sel) => c.id === sel || c.group === sel);
}
// ── browser group runner ──────────────────────────────────────────────────
const BOOT_JS = () => window.__godsEyeView?.viewer && window.__godsEyeView?.dataManager;
async function runBrowserGroup(record) {
const ids = BROWSER_CHECKS.map(([id]) => id).filter((id) => selected(CHECKS.find((c) => c.id === id)));
if (!ids.length) return;
const emit = (id, res, ms) => { if (ids.includes(id)) record(CHECKS.find((c) => c.id === id), res, ms); };
const only = (id) => ids.includes(id);
const exe = (() => { try { return puppeteer.executablePath(); } catch { return null; } })();
const browser = await puppeteer.launch({
headless: HEADFUL ? false : 'new',
...(exe ? { executablePath: exe } : {}),
// Heavy layers (CCTV fleet admission, traffic road graphs) can block the
// page's main thread past puppeteer's 180 s default and turn a healthy
// layer into a bogus "probe threw" FAIL.
protocolTimeout: 420000,
args: ['--no-sandbox', '--disable-setuid-sandbox', '--use-gl=angle', '--use-angle=swiftshader',
'--disable-background-timer-throttling', '--disable-renderer-backgrounding',
// C17 drives the keyless voice path, which asks for a microphone before
// it mints a token. A fake device + auto-granted permission keeps the
// failure under test the MISSING KEY, not a missing microphone.
'--use-fake-device-for-media-stream', '--use-fake-ui-for-media-stream'],
});
env.browserVersion = await browser.version();
const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 });
const pageErrors = [];
const consoleErrors = [];
const requestUrls = [];
page.on('pageerror', (e) => pageErrors.push(String(e?.message || e).slice(0, 200)));
page.on('console', (m) => { if (m.type() === 'error') consoleErrors.push(m.text().slice(0, 200)); });
page.on('request', (r) => { requestUrls.push(r.url()); });
// A saturated main thread (SwiftShader + ~20k entities) makes every CDP call
// wait the full protocolTimeout — 7 minutes per call, and a check that never
// returns never reports. Every in-page read is therefore bounded.
//
// evalBounded: for POLL loops — null means "nothing this tick, try again".
const evalBounded = (fn, arg, ms = 8000) => Promise.race([
page.evaluate(fn, arg).catch(() => null),
new Promise((r) => setTimeout(() => r(null), ms)),
]);
// mustEval: for one-shot reads a check depends on. A deadline expiry is a
// positively-identified condition (the page stopped answering), so the check
// reports HARNESS-CRASH — it verified nothing. It never degrades to a pass.
const UNRESPONSIVE = Symbol('page-unresponsive');
const mustEval = async (fn, arg = null, ms = 30000) => {
const outcome = await Promise.race([
page.evaluate(fn, arg).then((value) => ({ ok: true, value }), (e) => ({ ok: false, reason: `page threw: ${String(e?.message || e).slice(0, 140)}` })),
new Promise((r) => setTimeout(() => r({ ok: false, reason: `page did not answer within ${ms} ms`, unresponsive: UNRESPONSIVE }), ms)),
]);
return outcome;
};
const step = async (id, fn) => {
if (!only(id)) return null;
const t0 = Date.now();
try {
const res = await fn();
emit(id, res, Date.now() - t0);
return res;
} catch (e) {
// The probe itself broke — it verified nothing, so it is a crash, not a
// product failure.
emit(id, crash(`probe threw, so this check verified nothing: ${String(e?.message || e).slice(0, 180)}`), Date.now() - t0);
return null;
}
};
// ── C1 boot ─────────────────────────────────────────────────────────────
const t0 = Date.now();
let booted = false;
let bootNote = '';
for (let attempt = 1; attempt <= 3 && !booted; attempt += 1) {
try {
await page.goto(APP_URL, { waitUntil: 'domcontentloaded', timeout: 120000 });
await page.waitForFunction(BOOT_JS, { timeout: 90000, polling: 1000 });
booted = true;
} catch {
// A dev server that re-optimizes deps mid-load answers 504 "Outdated
// Optimize Dep" and the module graph never evaluates. One reload after
// the optimizer settles clears it; three strikes is a real failure.
const stale = consoleErrors.some((e) => /Outdated Optimize Dep|504/.test(e));
bootNote = stale ? 'vite dep re-optimization (504) on attempt ' + attempt : `attempt ${attempt} timed out`;
await new Promise((r) => setTimeout(r, 5000));
}
}
const bootSec = (Date.now() - t0) / 1000;
// The check's stated claim is "live, first paint under 60 s". Both halves are
// asserted: globals existing is not a painted frame, and a boot that took
// three attempts and four minutes is not a 60-second boot.
const BOOT_BUDGET_S = 60;
let paint = null;
if (booted) {
const paintR = await mustEval(async () => {
const g = window.__godsEyeView;
// Wait for Cesium to actually render a frame, then confirm the canvas
// holds non-blank pixels.
const painted = await new Promise((resolve) => {
let done = false;
const stop = g.viewer.scene.postRender.addEventListener(() => {
if (done) return;
done = true;
setTimeout(() => { try { stop(); } catch { /* removed */ } resolve(true); }, 0);
});
g.viewer.scene.requestRender();
setTimeout(() => { if (!done) { done = true; try { stop(); } catch { /* removed */ } resolve(false); } }, 20000);
});
const canvas = g.viewer.scene.canvas;
return { painted, w: canvas?.width ?? 0, h: canvas?.height ?? 0, frames: g.viewer.scene.frameState?.frameNumber ?? null };
}, null, 45000);
paint = paintR.ok ? paintR.value : { probeError: paintR.reason };
}
env.boot = { ok: booted, seconds: bootSec, paint };
const bootDetail = `viewer + dataManager live in ${bootSec.toFixed(1)} s${bootNote ? ` (after ${bootNote})` : ''}; first paint frame=${paint?.frames ?? 'n/a'} canvas=${paint?.w ?? 0}x${paint?.h ?? 0}`;
emit('C1', (() => {
if (!booted) return fail(`app never booted in ${bootSec.toFixed(0)} s — ${bootNote}; if 504, clear node_modules/.vite and restart the dev server`);
if (paint?.probeError) return crash(`booted in ${bootSec.toFixed(1)} s but the first-paint probe failed: ${paint.probeError}`);
if (!paint?.painted) return fail(`${bootDetail} — the scene never rendered a frame, so "first paint" is unproven`);
if (!(paint.w > 0 && paint.h > 0)) return fail(`${bootDetail} — the render canvas has no size`);
if (bootSec > BOOT_BUDGET_S) {
return fail(`${bootDetail} — over the ${BOOT_BUDGET_S} s budget this check states${bootNote ? ` (${bootNote})` : ''}`);
}
return pass(bootDetail);
})(), Date.now() - t0);
if (!booted) {
for (const [id] of BROWSER_CHECKS.slice(1)) {
emit(id, skip('app did not boot — see C1', 'ENV'), 0);
}
await browser.close();
return;
}
// Cancel the intro flyTo: it clobbers any setView issued mid-flight.
await evalBounded(() => { try { window.__godsEyeView.viewer.camera.cancelFlight(); } catch { /* none */ } });
await new Promise((r) => setTimeout(r, 3000));
// Enable a layer, then poll its stats from THIS side. Polling in Node (many
// short evaluates) instead of one long in-page loop keeps every CDP call far
// below the protocol timeout even when a layer stalls the main thread.
const settle = async (layerId, maxSec = 45) => {
const enabled = (await evalBounded(async (id) => {
const dm = window.__godsEyeView.dataManager;
if (!dm.layers.has(id)) return { missing: true };
try {
// setEnabled resolves when the whole lifecycle transaction settles —
// for a viewport-scoped layer over a huge extent that can be minutes.
// Race it: the layer is still enabling, and the poll loop below is the
// real observer. Blocking here just burns the CDP protocol timeout.
await Promise.race([
dm.setEnabled(id, true, { origin: 'user' }),
new Promise((r) => setTimeout(r, 20000)),
]);
} catch (e) { return { enableError: String(e?.message || e) }; }
return { ok: true };
}, layerId, 30000)) || { ok: true, enableUnconfirmed: true };
if (enabled.missing || enabled.enableError) return enabled;
let stats = null;
let lifecycleState = null;
for (let i = 0; i < maxSec; i += 1) {
// eslint-disable-next-line no-await-in-loop
await new Promise((r) => setTimeout(r, 1000));
// eslint-disable-next-line no-await-in-loop
const snap = await evalBounded((id) => {
const dm = window.__godsEyeView.dataManager;
const mod = dm.layers.get(id)?.module;
const s = mod?.getStats ? mod.getStats() : null;
const projected = dm.getAll().find((l) => l.id === id) || {};
return { stats: s, lifecycleState: projected.lifecycleState, enabled: projected.enabled };
}, layerId);
if (!snap) continue;
stats = snap.stats;
lifecycleState = snap.lifecycleState;
if (!stats) continue;
const answered = (stats.count > 0) || stats.error;
// Some layers (CCTV frame fill, traffic road graphs) keep `loading` true
// long after they have data. Wait for a quiet settle for a while, then
// accept "has data" so one progressive layer cannot eat the budget.
if (answered && (!stats.loading || i >= Math.min(12, Math.floor(maxSec / 2)))) break;
}
return { stats, lifecycleState };
};
// The late checks (C16 reset control, C17 voice surface) make claims about
// CONTROLS, not about layer load. By the time they run, ~20k entities and the
// sensor-style post-processing stages have saturated the main thread hard
// enough that a trivial read times out — honest as a CRASH, but useless as a
// verdict. Put the stage back down first. Defined here (not inside C16) so it
// still runs when only one of the late checks is selected.
let quiesced = false;
const quiesce = async () => {
if (quiesced) return;
quiesced = true;
await evalBounded(async () => {
const dm = window.__godsEyeView.dataManager;
const heavy = ['cctv', 'traffic', 'flights', 'satellites', 'telegeography-submarine-cables',
'local-datacenters', 'local-dams', 'military-installations', 'earthquakes'];
for (const id of heavy) {
if (!dm.layers.has(id)) continue;
try {
// eslint-disable-next-line no-await-in-loop
await Promise.race([dm.setEnabled(id, false, { origin: 'user' }), new Promise((r) => setTimeout(r, 3000))]);
} catch { /* teardown is best-effort */ }
}
}, null, 45000);
await new Promise((r) => setTimeout(r, 4000));
};
await step('C2', async () => {
// The claim is PHOTOREALISTIC 3D, so an ordinary imagery layer is not
// evidence: an OSM-only fallback would have satisfied the old OR-chain
// while the headline feature was missing.
const infoR = await mustEval(() => {
const g = window.__godsEyeView;
const prims = g.viewer.scene.primitives;
const tilesets = [];
for (let i = 0; i < prims.length; i += 1) {
const prim = prims.get(i);
if (prim?.constructor?.name !== 'Cesium3DTileset') continue;
tilesets.push({
url: String(prim.resource?.url || prim._url || ''),
ready: prim.ready !== false,
tilesLoaded: prim.tilesLoaded === true,
});
}
return {
hasTileset: !!g.tileset,
tilesets,
imagery: g.viewer.imageryLayers?.length ?? 0,
mapStack: g.styleManager?.getVisualState?.()?.mapStack ?? null,
};
});
if (!infoR.ok) return crash(`could not read the scene graph: ${infoR.reason}`);
const info = infoR.value;
const photoreal = info.tilesets.find((t) => /google|tile\.googleapis|photorealistic|3dtiles/i.test(t.url));
if (!info.tilesets.length) {
return fail(`no Cesium3DTileset attached (imagery layers=${info.imagery}, mapStack=${info.mapStack}) — the photorealistic globe is absent`);
}
if (!photoreal) {
return fail(`a 3D tileset is attached but none resolves to Google Photorealistic tiles (urls: ${info.tilesets.map((t) => t.url.slice(0, 60) || '(no url)').join(' | ')}, mapStack=${info.mapStack})`);
}
if (!photoreal.ready) {
return fail(`the photorealistic tileset is attached but not ready (mapStack=${info.mapStack})`);
}
return pass(`Photorealistic 3D attached and ready (mapStack=${info.mapStack}, ${info.tilesets.length} tileset(s), imagery layers=${info.imagery})`);
});
await step('C3', async () => (pageErrors.length === 0
? pass(`0 uncaught page errors (${consoleErrors.length} console errors, keyless 503s expected)`)
: fail(`${pageErrors.length} uncaught: ${pageErrors.slice(0, 2).join(' | ')}`)));
// Snapshot the voice surface NOW, before the layer probes below saturate the
// main thread. C17 reports from this — a real observation, taken at a moment
// the page can answer. (Under SwiftShader with ~20k entities up, a trivial
// evaluate can starve for minutes.)
const voiceSnapshotR = await mustEval(() => {
const vc = window.__gevVoiceCommands;
if (!vc) return { present: false };
let diag = null;
try { diag = vc.getDiagnostics?.(); } catch { /* never started */ }
return { present: true, active: !!vc.isActive?.(), status: diag?.status ?? null, hasRunner: typeof vc.runner === 'function' };
}, null, 30000);
const voiceSnapshot = voiceSnapshotR.ok ? voiceSnapshotR.value : { probeError: voiceSnapshotR.reason };
await step('C4', async () => {
const r = await settle('flights', 40);
const s = r.stats || {};
if (!(s.count > 0)) return fail(`0 contacts (status=${s.status || ''} error=${s.error || ''})`);
const src = String(s.source || '');
return /adsb\.lol/i.test(src)
? skip(`${s.count} contacts but via the adsb.lol FALLBACK (source=${src}) — OpenSky credentials needed for the live claim`, 'OWNER-RUN')
: pass(`${s.count} contacts, source=${src || 'OpenSky'}, stale=${!!s.stale}`);
});
await step('C5', async () => {
const r = await settle('satellites', 40);
const s = r.stats || {};
return s.count > 0 ? pass(`${s.count} satellites, status=${s.status || 'nominal'}`) : fail(`0 satellites (status=${s.status} error=${s.error || ''})`);
});
await step('C6', async () => {
const r = await settle('earthquakes', 30);
const s = r.stats || {};
return s.count > 0 ? pass(`${s.count} events`) : fail(`0 events (error=${s.error || ''})`);
});
await step('C7', async () => {
const r = await settle('cctv', 45);
// A camera COUNT proves registration, not that the frame loop runs. Poll
// until ambient cards exist AND frames have actually been fetched, then
// assert both — "healthy frame loop" is the claim, so it is the assertion.
let ui = null;
for (let i = 0; i < 30; i += 1) {
// eslint-disable-next-line no-await-in-loop
ui = await evalBounded(() => {
const st = window.__godsEyeView.dataManager.layers.get('cctv')?.module?.getUIState?.();
return st ? { count: st.count, loading: st.loading, ambient: st.ambientCards, error: st.error } : null;
}, null) || ui;
if (ui && ui.count > 0 && (ui.ambient?.count || 0) > 0 && (ui.ambient?.frameFetches || 0) > 0) break;
// eslint-disable-next-line no-await-in-loop
await new Promise((res) => setTimeout(res, 1000));
}
if (!ui) return fail('cctv module exposed no UI state');
const s = r.stats || {};
if (!(ui.count > 0)) return fail(`0 cameras registered (error=${ui.error || s.error || 'none'})`);
const cards = ui.ambient?.count || 0;
const fetches = ui.ambient?.frameFetches || 0;
if (cards === 0) return fail(`${ui.count} cameras registered but 0 ambient cards were produced — nothing is rendering`);
if (fetches === 0) {
return fail(`${ui.count} cameras and ${cards} ambient cards, but frameFetches=0 — the frame loop never ran, so "healthy" is unproven`);
}
return pass(`${ui.count} cameras, ${cards} ambient cards, ${fetches} frame fetches (${ui.ambient?.fetchMode}, ${ui.ambient?.fetchesInFlight} in flight), loading=${ui.loading?.active}`);
});
await step('C8', async () => {
const guard = keyGuard('AIS', env.keys.AIS);
if (guard) return guard;
const r = await settle('ais-live-vessels', 30);
const s = r.stats || {};
// The rendered chip is the honesty claim, so read the chip. An empty layer
// that says nothing is exactly the silent-failure this check must catch —
// count === 0 is NOT evidence of an honest UNAVAILABLE state.
const chipR = await mustEval(() => {
const row = document.querySelector('[data-layer-id="ais-live-vessels"]');
const btn = row?.querySelector('.data-toggle-btn');
return {
text: (btn?.textContent || '').trim(),
feedState: btn?.dataset?.feedState || null,
meta: (row?.textContent || '').replace(/\s+/g, ' ').trim().slice(0, 140),
};
});
if (!chipR.ok) return crash(`could not read the vessels layer row: ${chipR.reason}`);
const chip = chipR.value;
if (!chip) return fail('no [data-layer-id="ais-live-vessels"] row in the DOM — cannot read the surfaced feed state');
if (env.keys.AIS === false) {
const surfaced = chip.feedState === 'unavailable' && /UNAVAILABLE/i.test(chip.text);
if (!surfaced) {
return fail(`keyless vessels did not SURFACE the unavailable state: chip="${chip.text}" feedState=${chip.feedState} (stats: status=${s.status} error=${s.error}) — a silently empty layer is the failure mode this check exists for`);
}
if (s.count > 0) return fail(`chip says UNAVAILABLE but the layer reports ${s.count} vessels`);
return pass(`keyless and honest: chip="${chip.text}" feedState=unavailable, stats.status=${s.status}, error="${String(s.error || '').slice(0, 40)}", count=0`);
}
// getStats().status is ONLY ever 'unavailable' or undefined; the feed state
// rides on transportStatus (src/data/aisLiveVessels.js:646-668). And cached
// rows survive a degraded feed on purpose, so count > 0 is not liveness.
const transport = s.transportStatus;
const live = transport === 'live' || transport === 'open';
if (live && s.count > 0) {
// Chip vocabulary: ON / LOADING / DEGRADED / STALE / FALLBACK /
// UNAVAILABLE (src/data/manager.js:12-19). A live feed with rows reads ON.
return /^ON$/i.test(chip.text)
? pass(`${s.count} vessels live: chip="ON", transport=${transport}, lastMessage=${s.lastMessageAt || 'n/a'}`)
: fail(`transport=${transport} with ${s.count} vessels, but the chip reads "${chip.text}" — a live feed must present as ON`);
}
if (transport === 'auth-failed') {
const surfaced = /UNAVAILABLE/i.test(chip.text) && /key rejected/i.test(String(s.error || ''));
return surfaced
? fail(`AISStream rejected the key — surfaced correctly (chip="${chip.text}", error="${s.error}", retryInSec=${s.retryInSec}) but a rejected key is a product-blocking failure, not an environment condition`)
: fail(`AISStream rejected the key and the UI did not say so: chip="${chip.text}", error="${String(s.error || 'none')}"`);
}
if (['stale', 'reconnecting', 'down'].includes(transport)) {
// Degraded is ENV only when it is SURFACED. Cached rows must read STALE;
// no usable rows must read UNAVAILABLE.
const expected = s.count > 0 ? /STALE|DEGRADED/i : /UNAVAILABLE|DEGRADED/i;
return expected.test(chip.text)
? skip(`feed is ${transport}${s.count > 0 ? ` with ${s.count} CACHED vessels` : ''} and the UI says so (chip="${chip.text}", error="${String(s.error || '').slice(0, 60)}", retryInSec=${s.retryInSec}) — honest degradation, not a live feed`, 'ENV')
: fail(`feed is ${transport} with ${s.count} vessels but the chip reads "${chip.text}" — a degraded feed that presents as healthy is exactly the invisible outage this check exists for`);
}
if (s.count > 0) {
return fail(`${s.count} vessels with transport="${transport}" — neither live nor a recognised degraded state, so this cannot be called a live feed (chip="${chip.text}")`);
}
// Keyed but empty: honest only if the UI says so.
return /UNAVAILABLE|LOADING|DEGRADED|STALE/i.test(chip.text)
? skip(`keyed but 0 vessels and the UI says so (chip="${chip.text}", transport=${transport}, error="${String(s.error || '').slice(0, 60)}") — AISStream connects open-but-silent upstream`, 'ENV')
: fail(`keyed, 0 vessels, and the chip claims "${chip.text}" — the layer is empty without surfacing it`);
});
await step('C9', async () => {
const guard = keyGuard('FIRMS', env.keys.FIRMS);
if (guard) return guard;
const r = await settle('local-firms', 30);
const s = r.stats || {};
if (env.keys.FIRMS === false) {
return s.error === 'KEY REQUIRED'
? pass('keyless and honest: getStats().error === "KEY REQUIRED"')
: fail(`keyless but error=${s.error} count=${s.count} — expected "KEY REQUIRED"`);
}
return s.count > 0 ? pass(`${s.count} fires, cells=${s.cells}`) : fail(`keyed but 0 fires (error=${s.error || ''})`);
});
await step('C10', async () => {
// Traffic is viewport-scoped: enabling it from a global camera asks for a
// planet-sized road graph. Put the camera over a dense city first — that
// is also the only altitude at which "live flow" means anything.
await evalBounded(async () => {
const g = window.__godsEyeView;
g.viewer.camera.cancelFlight();
g.styleManager.applyCameraState({ lat: 30.2672, lon: -97.7431, alt: 2500, heading: 0, pitch: -40 }, 1.2);
await new Promise((r) => setTimeout(r, 3500));
});
const guard = keyGuard('TOMTOM', env.keys.TOMTOM);
if (guard) return guard;
const r = await settle('traffic', 45);
const s = r.stats || {};
if (env.keys.TOMTOM === false) {
const label = String(s.loadingLabel || '');
return s.mode === 'sim' && /SIMULATED/i.test(label)
? pass(`sim mode labelled honestly: "${label.slice(0, 70)}"`)
: fail(`mode=${s.mode} label="${label.slice(0, 70)}" — expected sim + a SIMULATED label`);
}
const colored = (s.flowBuckets?.free || 0) + (s.flowBuckets?.slow || 0) + (s.flowBuckets?.jam || 0);
if (s.mode === 'live' && s.tilesFetched > 0 && colored > 0) {
return pass(`live: ${s.flowCoveragePct}% coverage, ${s.tilesFetched} tiles, ${colored} colored dots`);
}
// Same discrimination C11 already makes for the bundled layers: "still
// loading when my budget expired" is not "empty", and calling it a product
// failure is a false accusation. The discriminator here is whether the FLOW
// FETCH ever completed, not whether the answer was empty:
// · zero tiles + still fetching + no error = the request had not landed,
// so this check never observed live flow at all -> INCONCLUSIVE.
// · tiles fetched but nothing coloured = loaded and empty -> FAIL, which
// is the Overpass-outage signature (no road graph to colour, observed as
// tiles=4 colored=0) and must keep failing.
// Narrow on purpose: it cannot absorb an empty result that actually landed.
// (settle() breaks once the road graph answers, so the flow tiles can still
// be in flight — that is how a full pass produced tiles=0 on a build whose
// isolated re-run coloured 3,891 dots.)
if (trafficFlowInconclusive(s)) {
return crash(`traffic's flow fetch had not landed when the 45 s budget expired: tiles=0, loading=${!!s.loading}, label="${String(s.loadingLabel || '').slice(0, 40)}", road dots=${s.count ?? 0} — this check could not determine whether live flow renders, so it verified nothing`);
}
return fail(`mode=${s.mode} tiles=${s.tilesFetched} coverage=${s.flowCoveragePct} colored=${colored}`);
});
await step('C11', async () => {
// These are GLOBAL datasets and their rendered counts are viewport-scoped.
// C10 leaves the camera at 2,500 m over Austin, where a worldwide
// datacenter/dam set legitimately has nothing in view — inheriting that
// camera made this check report an empty layer that was actually fine.
// Establish the camera this check needs instead of inheriting one.
await evalBounded(async () => {
const g = window.__godsEyeView;
g.viewer.camera.cancelFlight();
g.styleManager.applyCameraState({ lat: 20, lon: 0, alt: 14000000, heading: 0, pitch: -90 }, 1.5);
await new Promise((r) => setTimeout(r, 4000));
}, null, 30000);
await new Promise((r) => setTimeout(r, 2000));
const bundled = ['local-datacenters', 'local-dams', 'telegeography-submarine-cables'];
const out = [];
const stillLoading = [];
let loadNote = '';
for (const id of bundled) {
// eslint-disable-next-line no-await-in-loop
const r = await settle(id, 45);
const s = r.stats || {};
const label = id.replace(/^local-|^telegeography-/, '');
out.push(`${label}=${r.missing ? 'MISSING' : (s.count ?? 0)}`);
// "Still loading when my budget expired" is not "empty". Under full-run
// load these can take longer than an isolated run, and calling that a
// product failure is a false accusation — say the measurement was
// inconclusive instead.
if (!r.missing && !(s.count > 0) && (s.loading || s.loadingLabel) && !s.error) stillLoading.push(label);
}
if (stillLoading.length) {
return crash(`still loading when the ${45}s budget expired: ${stillLoading.join(', ')} [all: ${out.join(', ')}] — this check could not determine whether they render, so it verified nothing`);
}
let zero = out.filter((o) => /=0$|MISSING/.test(o));
if (zero.length) {
// A bundled layer can read 0 while the heavy layers are live (flights,
// CCTV, traffic) — the perf-wave budgets and scope mask legitimately
// suppress work under load. This check claims "bundled layers render",
// not "they render while everything else is on", and it must not guess
// between suppression-by-budget and a real render failure. Put the stage
// down and measure again: that is conclusive either way.
const contested = zero.map((o) => o.split('=')[0]);
await quiesce();
const retried = [];
for (const label of contested) {
const id = bundled.find((b2) => b2.replace(/^local-|^telegeography-/, '') === label);
if (!id) continue;
// eslint-disable-next-line no-await-in-loop
const r2 = await settle(id, 45);
retried.push(`${label}=${r2.stats?.count ?? 0}`);
}
const stillZero = retried.filter((o) => /=0$/.test(o));
if (stillZero.length) {
return fail(`empty bundled layer(s) even on a quiet stage: ${stillZero.join(', ')} [under load: ${out.join(', ')}]`);
}
// Do NOT return here: the installations assertion below is part of this
// check's claim and must still run.
loadNote = ` (under load: ${out.join(', ')}; on a quiet stage: ${retried.join(', ')} — the zero reading was load-related suppression, not a render failure)`;
}
zero = [];
// military-installations is named in this check's description, so it is
// asserted — not quietly excluded. It is viewport-scoped (≤10° span,
// src/data/militaryInstallations.js MAX_VIEWPORT_DEGREES) and returns 0
// from a global camera, so fly to a tight box over a known base cluster
// first, and cross-check the layer against its own API: rows from the API
// but nothing on the map is a PRODUCT failure; nothing from either is a
// positively-identified upstream-data condition.
const box = { name: 'San Diego / Coronado', lat: 32.70, lon: -117.18, span: 0.6 };
const api = await jget(`/api/military-installations?south=${(box.lat - box.span).toFixed(5)}&west=${(box.lon - box.span).toFixed(5)}&north=${(box.lat + box.span).toFixed(5)}&east=${(box.lon + box.span).toFixed(5)}`, { timeoutMs: 60000 })
.catch((e) => ({ status: 0, json: null, text: String(e?.message || e) }));
const apiRows = Array.isArray(api.json?.features) ? api.json.features.length
: (Array.isArray(api.json?.elements) ? api.json.elements.length
: (Array.isArray(api.json) ? api.json.length : null));
// The layer gates on the camera's COMPUTED VIEW RECTANGLE (<=10 degrees,
// MAX_VIEWPORT_DEGREES), not on the request box. An oblique camera sees to
// the horizon and blows past that even from low altitude, so look straight
// down: nadir at 25 km spans well under a degree.
await evalBounded(async (b) => {
const g = window.__godsEyeView;
g.viewer.camera.cancelFlight();
g.styleManager.applyCameraState({ lat: b.lat, lon: b.lon, alt: 25000, heading: 0, pitch: -90 }, 1.2);
await new Promise((r) => setTimeout(r, 4000));
}, box, 30000);
// `zoom-in` is a TRANSIENT: the layer evaluates the viewport at enable time
// and republishes after the camera settles. settle() breaks on the first
// truthy `error`, so it latched that transient and never saw the real load.
// Poll for a definitive outcome instead, and only then judge.
const mi = await settle('military-installations', 5);
let ms = mi.stats || {};
for (let i = 0; i < 40; i += 1) {
if (ms.count > 0) break;
if (ms.error && !/zoom.?in/i.test(String(ms.error))) break;
// eslint-disable-next-line no-await-in-loop
const snap = await evalBounded(() => {
const dm = window.__godsEyeView.dataManager;
// Nudge the viewport-driven reload: the layer reloads on camera settle.
try { dm.layers.get('military-installations')?.module?.refresh?.(); } catch { /* optional */ }
return dm.layers.get('military-installations')?.module?.getStats?.() ?? null;
}, null, 10000);
if (snap) ms = snap;
// eslint-disable-next-line no-await-in-loop
await new Promise((r) => setTimeout(r, 1000));
}
if (mi.missing) return fail(`military-installations layer is not registered [bundled: ${out.join(', ')}]`);
if (ms.count > 0) return pass(`${out.join(', ')}, military-installations=${ms.count} over ${box.name}${loadNote}`);
if (/zoom-in/.test(String(ms.status || ''))) {
return fail(`military-installations refused the ${box.span * 2}° box over ${box.name} as too wide (status=${ms.status}, error="${ms.error}") — the probe camera and the layer's own ≤10° gate disagree`);
}
if (api.status !== 200) {
// Distinguish an honest upstream outage from a broken route: the proxy
// has a documented degraded shape (503 + "temporarily unavailable") for
// when Overpass is down. That is the app degrading correctly, so it is a
// positively identified ENV condition — anything else is a product FAIL.
const honestOutage = api.status === 503 && /temporarily unavailable/i.test(String(api.text || ''));
if (honestOutage) {
return skip(`bundled layers OK (${out.join(', ')}); military-installations could not be checked — its upstream is down and the proxy says so honestly (HTTP 503 "${String(api.json?.error || '').slice(0, 60)}")`, 'ENV');
}
return fail(`military-installations rendered 0 and its API returned HTTP ${api.status} for ${box.name} — a responsive app failing this route is a product failure: ${String(api.text || '').slice(0, 100)}`);
}
if (apiRows === null) return crash(`could not read a row count from /api/military-installations to cross-check the empty layer: ${String(api.text || '').slice(0, 100)}`);
if (apiRows > 0) {
return fail(`/api/military-installations returned ${apiRows} features over ${box.name} but the layer rendered 0 (status=${ms.status}, error=${ms.error || 'none'}) [bundled: ${out.join(', ')}]`);
}
return skip(`bundled layers OK (${out.join(', ')}); military-installations rendered 0 AND its API returned 0 features over ${box.name} — positively an upstream-data condition, not a render failure`, 'ENV');
});
await step('C12', async () => {
// This check reads the credits of whatever THIS run switched on. Run
// standalone (`--only C12`) nothing is on, and it would pass vacuously off
// the static credit list — so self-arm a deterministic set first.
const armed = (await evalBounded(() => [...(window.__godsEyeView.dataManager.getEnabledLayerIds?.() || [])], null, 20000)) || [];
const SELF_ARM = ['flights', 'satellites', 'earthquakes', 'telegeography-submarine-cables'];
if (armed.length === 0) {
for (const id of SELF_ARM) {
// eslint-disable-next-line no-await-in-loop
await settle(id, 25);
}
const nowOn = (await evalBounded(() => [...(window.__godsEyeView.dataManager.getEnabledLayerIds?.() || [])], null, 20000)) || [];
if (nowOn.length === 0) {
return crash('no layers are enabled and self-arming failed — this check has nothing to verify credits against');
}
}
const credR = await mustEval(async () => {
const viewer = window.__godsEyeView.viewer;
const dm = window.__godsEyeView.dataManager;
viewer.scene.requestRender();
await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
const html = (viewer.creditDisplay._staticCredits || []).map((c) => c.html);
viewer.creditDisplay.showLightbox();
viewer.scene.requestRender();
await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
const listCount = document.querySelector('.cesium-credit-lightbox > ul')?.children?.length || 0;
viewer.creditDisplay.hideLightbox();
// getEnabledLayerIds() returns a Set — spread it or it crosses the CDP
// bridge as {}.
return { html, listCount, enabled: [...(dm.getEnabledLayerIds?.() || [])] };
}, null, 60000);
if (!credR.ok) return crash(`could not read the credit display: ${credR.reason}`);
const cred = credR.value;
// EVERY enabled layer is checked. Filtering to a known subset meant a layer
// outside the list — military-installations, which C11 now enables — could
// ship with no attribution while this check claimed full coverage.
const missing = [];
const unmapped = [];
const exempted = [];
for (const id of cred.enabled) {
const expectation = requiredCreditFor(id);
if (!expectation) { unmapped.push(id); continue; }
if (expectation.exempt) { exempted.push(id); continue; }
if (!cred.html.some((h) => expectation.regex.test(h))) missing.push(id);
}
if (missing.length) {
return fail(`enabled layer(s) with NO registered attribution: ${missing.join(', ')} — legal requirement (DATA_SOURCES.md, finding H11); lightbox items=${cred.listCount}`);
}
if (unmapped.length) {
// Fail closed: an unmapped layer is an unchecked layer.
return fail(`enabled layer(s) this check has no attribution expectation for: ${unmapped.join(', ')} — add them to CREDIT_EXPECTATIONS, or to CREDIT_EXEMPT_LAYERS with a reason. Until then their attribution is unverified`);
}
if (!(cred.listCount > 0)) return fail(`the attribution lightbox listed 0 items despite ${cred.html.length} registered credits`);
return pass(`${cred.html.length} credits registered, lightbox lists ${cred.listCount}; all ${cred.enabled.length} enabled layers verified${exempted.length ? ` (${exempted.length} exempt: ${exempted.join(', ')})` : ''}`);
});
await step('C13', async () => {
const stR = await mustEval(async () => {
const viewer = window.__godsEyeView.viewer;
window.__godsEyeView.styleManager.setCleanView(true);
// Cesium paints the credit line during a render — force frames before
// measuring, or a healthy credit reads as 0x0.
for (let i = 0; i < 4; i += 1) {
viewer.scene.requestRender();
// eslint-disable-next-line no-await-in-loop
await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
}
await new Promise((r) => setTimeout(r, 1200));
const el = document.getElementById('cesium-credits');
const cs = el ? getComputedStyle(el) : null;
const rect = el?.getBoundingClientRect();
const out = {
clean: document.body.classList.contains('ui-clean-view'),
present: !!el,
display: cs?.display, visibility: cs?.visibility, opacity: cs?.opacity,
w: rect?.width, h: rect?.height,
text: (el?.textContent || '').trim().slice(0, 80),
hasLogo: !!el?.querySelector('.cesium-credit-logoContainer, img'),
// The container itself can measure 0x0 while its positioned children
// paint — report the largest child box so the number means something.
childBox: [...(el?.querySelectorAll('*') || [])]
.map((n) => n.getBoundingClientRect())
.reduce((best, r) => ((r.width * r.height > best.w * best.h) ? { w: r.width, h: r.height } : best), { w: 0, h: 0 }),
};
window.__godsEyeView.styleManager.setCleanView(false);
return out;
}, null, 60000);
if (!stR.ok) return crash(`could not measure the clean-UI credit line: ${stR.reason}`);
const st = stR.value;
// Same contract the shipped attribution harness pins (qa-attribution-b12):
// not display:none, not visibility:hidden, and the expand link present.
const visible = st.present && st.display !== 'none' && st.visibility !== 'hidden' && Number(st.opacity) !== 0;
const labelled = /Data attribution/i.test(st.text) || st.hasLogo;
const box = `${Math.round(st.w || 0)}x${Math.round(st.h || 0)} (largest child ${Math.round(st.childBox?.w || 0)}x${Math.round(st.childBox?.h || 0)})`;
return visible && labelled && st.clean
? pass(`clean-UI on, #cesium-credits painted ${box} ("${st.text.slice(0, 40)}")`)
: fail(`clean=${st.clean} present=${st.present} display=${st.display} opacity=${st.opacity} size=${st.w}x${st.h} text="${st.text.slice(0, 40)}"`);
});
await step('C14', async () => {
const leaked = [];
const inPageR = await mustEval(() => {
const ls = {};
for (let i = 0; i < localStorage.length; i += 1) {
const k = localStorage.key(i);
ls[k] = String(localStorage.getItem(k)).slice(0, 200);
}
return { storage: JSON.stringify(ls), href: location.href };
});
if (!inPageR.ok) return crash(`could not read browser state for the key-leak scan: ${inPageR.reason}`);
const inPage = inPageR.value;
if (/\bsk-[A-Za-z0-9]{20,}/.test(inPage.storage)) leaked.push('localStorage holds an sk- key');
if (/AIza[0-9A-Za-z_\-]{30,}/.test(inPage.storage)) leaked.push('localStorage holds a Google key');
const keyish = requestUrls.filter((u) => u.startsWith(APP_ORIGIN) && /[?&](key|api_?key|token|client_secret)=[A-Za-z0-9_\-]{12,}/i.test(u));
if (keyish.length) leaked.push(`${keyish.length} same-origin URL(s) carry a key query param: ${keyish[0].slice(0, 90)}`);
return leaked.length === 0
? pass(`${requestUrls.length} requests + localStorage scanned, no credential material`)
: fail(leaked.join('; '));
});
await step('C15', async () => {
// CRT/NVG/FLIR are DISPLAY LABELS; the real style ids are retro /
// surveillance / thermal (src/ui.js STYLE_STATUS_LABELS). Passing the
// labels made every call a silent no-op that still "passed" — so assert
// the returned visual state actually changed to the requested style.
const wanted = [['retro', 'CRT'], ['surveillance', 'NVG'], ['thermal', 'FLIR'], ['normal', 'Normal']];
const rR = await mustEval(async (styles) => {
const g = window.__godsEyeView;
const cam = g.viewer.camera;
const before = { x: cam.position.x, y: cam.position.y, z: cam.position.z };
const seen = [];
for (const [style, label] of styles) {
try {
g.styleManager.applyVisualState({ style });
} catch (e) { seen.push({ style, label, error: String(e?.message || e).slice(0, 80) }); continue; }
// eslint-disable-next-line no-await-in-loop
await new Promise((res) => setTimeout(res, 700));
const vs = g.styleManager.getVisualState?.() ?? null;
seen.push({ style, label, observed: vs?.style ?? null, activeStyle: g.styleManager.activeStyle ?? null });
}
const after = { x: cam.position.x, y: cam.position.y, z: cam.position.z };
return { seen, drift: Math.hypot(after.x - before.x, after.y - before.y, after.z - before.z) };
}, wanted, 90000);
if (!rR.ok) return crash(`could not exercise the style presets: ${rR.reason}`);
const r = rR.value;
const threw = r.seen.filter((s) => s.error);
if (threw.length) return fail(`style application threw for: ${threw.map((s) => `${s.style} (${s.error})`).join('; ')}`);
const noop = r.seen.filter((s) => s.observed !== s.style);
if (noop.length) {
return fail(`style did not take effect for: ${noop.map((s) => `${s.label}/${s.style} → getVisualState().style=${s.observed}`).join('; ')} — the call was a no-op`);
}
if (r.seen.length !== wanted.length) return crash(`only ${r.seen.length}/${wanted.length} styles were exercised`);
return r.drift < 1
? pass(`${r.seen.map((s) => `${s.label}→${s.observed}`).join(', ')} each confirmed in getVisualState(); camera drift ${r.drift.toFixed(3)} m`)
: fail(`styles applied but the camera moved ${r.drift.toFixed(1)} m while switching`);
});
await step('C16', async () => {
await quiesce();
// L6 shipped two entry points into one release route: the map control
// (#reset-globe-view) and the cockpit-native one (#cockpit-reset-globe).
const foundR = await mustEval(() => {
const el = document.getElementById('reset-globe-view');
if (!el) return null;
return {
label: el.getAttribute('aria-label') || el.title || 'reset-globe-view',
cockpitTwin: !!document.getElementById('cockpit-reset-globe'),
};
});
if (!foundR.ok) return crash(`could not look for the reset-to-globe control: ${foundR.reason}`);
const found = foundR.value;
if (!found) return fail('#reset-globe-view is missing from the DOM (L6 shipped it)');
// Drop to a city altitude first so "back to the globe" is a real assertion.
// Uses the app's own camera facade rather than a Cesium global.
//
// BOTH the setup and the click are checked. If the setup silently failed
// and the inherited camera happened to already be above the global
// threshold, this check would "pass" while proving nothing about the reset
// control at all.
const setupR = await mustEval(async () => {
const g = window.__godsEyeView;
g.viewer.camera.cancelFlight();
g.styleManager.applyCameraState({ lat: 30.2672, lon: -97.7431, alt: 3000, heading: 0, pitch: -35 }, 1.5);
await new Promise((r) => setTimeout(r, 3000));
return { altKm: g.viewer.camera.positionCartographic.height / 1000 };
}, null, 60000);
if (!setupR.ok) return crash(`could not put the camera at city altitude to test the reset: ${setupR.reason}`);
const before = setupR.value?.altKm;
if (!Number.isFinite(before)) return crash('the city-altitude setup returned no altitude — cannot establish a starting point');
if (before > 5000) {
return crash(`the camera is still at ${Math.round(before)} km after the city-altitude setup, so "returns to the global band" cannot be tested from here`);
}
const clickR = await mustEval(() => {
const el = document.getElementById('reset-globe-view');
if (!el) return { clicked: false, reason: 'control vanished before the click' };
el.click();
return { clicked: true };
}, null, 45000);
if (!clickR.ok) return crash(`could not click the reset-to-globe control: ${clickR.reason}`);
if (!clickR.value?.clicked) return fail(`the reset control could not be clicked: ${clickR.value?.reason}`);
let altKm = before;
for (let i = 0; i < 15; i += 1) {
// eslint-disable-next-line no-await-in-loop
await new Promise((r) => setTimeout(r, 1000));
// eslint-disable-next-line no-await-in-loop
altKm = (await evalBounded(() => window.__godsEyeView.viewer.camera.positionCartographic.height / 1000, null, 20000)) ?? altKm;
if (altKm > 5000) break;
}
return altKm > 5000
? pass(`"${found.label}" ${Math.round(before)} km → ${Math.round(altKm)} km (global band); cockpit twin present=${found.cockpitTwin}`)
: fail(`reset left the camera at ${Math.round(altKm)} km (from ${Math.round(before)} km)`);
});
await step('C17', async () => {
await quiesce();
const v = voiceSnapshot || {};
// The snapshot failing means this check learned nothing — not that the
// product is wrong.
if (v.probeError) return crash(`voice snapshot failed, so nothing was verified: ${v.probeError}`);
if (!v.present) return fail('__gevVoiceCommands never initialised — the voice surface did not load');
// Route through keyGuard like every other key consumer: an 'error' state
// (status endpoint unhealthy) must FAIL, not slip into an owner-run skip.
const guard = keyGuard('OPENAI', env.keys.OPENAI);
if (guard) return guard;
if (env.keys.OPENAI === true) {
// Never start a session against a keyed server: that is a real Realtime
// connection and it costs money. The keyless claim needs a thin server.
return skip(`voice surface present (status=${v.status}); the keyless-degradation claim needs an UNKEYED server, and a real mic round trip is owner-run — see runbook M1-M3`, 'OWNER-RUN');
}
if (!v.hasRunner) return fail('voice controller present but exposes no runner');
// Actually exercise the failure: with no key the token mint 503s, and the
// product's job is to SAY SO. "A runner function exists" proved nothing.
// (Free: the 503 happens before any session is created.)
const beforeR = await mustEval(() => document.querySelectorAll('#gev-voice-control').length, null, 45000);
if (!beforeR.ok) return crash(`could not look for the voice control: ${beforeR.reason}`);
if (!beforeR.value) return fail('#gev-voice-control is absent — the voice surface never rendered');
const surfacedR = await mustEval(async () => {
const vc = window.__gevVoiceCommands;
try { await vc.start?.(); } catch { /* the rejection is the point */ }
for (let i = 0; i < 20; i += 1) {
// eslint-disable-next-line no-await-in-loop
await new Promise((r) => setTimeout(r, 500));
const status = document.getElementById('gev-voice-status')?.textContent?.trim() || '';
if (status && status !== 'CONNECTING') break;
}
let diag = null;
try { diag = vc.getDiagnostics?.(); } catch { /* not started */ }
return {
status: document.getElementById('gev-voice-status')?.textContent?.trim() || null,
detail: document.getElementById('gev-voice-detail')?.textContent?.trim() || null,
errorDetail: document.getElementById('gev-voice-error-detail')?.textContent?.trim() || null,
dataStatus: document.getElementById('gev-voice-control')?.dataset?.status || null,
recentError: diag?.recentErrors?.[0] ? { source: diag.recentErrors[0].source, message: diag.recentErrors[0].message } : null,
appAlive: !!window.__godsEyeView?.viewer,
};
}, null, 60000);
if (!surfacedR.ok) return crash(`could not drive the keyless voice path: ${surfacedR.reason}`);
const surfaced = surfacedR.value;
const saysKey = /OPENAI_API_KEY is not set/i.test(`${surfaced.errorDetail || ''} ${surfaced.recentError?.message || ''}`);
const saysUnavailable = surfaced.dataStatus === 'error' || /ERROR|UNAVAILABLE/i.test(`${surfaced.status || ''} ${surfaced.detail || ''}`);
if (!surfaced.appAlive) return fail('the app died when voice was started without a key — a missing optional key must never take the globe down');
if (!saysUnavailable) {
return fail(`voice start without a key left the UI at status="${surfaced.status}" detail="${surfaced.detail}" (data-status=${surfaced.dataStatus}) — the 503 never surfaced to the user`);
}
if (!saysKey) {
return fail(`voice surfaced an error state (${surfaced.status}) but never named the cause: errorDetail="${surfaced.errorDetail}" recentError=${JSON.stringify(surfaced.recentError)} — expected the OPENAI_API_KEY reason`);
}
return pass(`keyless voice degrades honestly: status="${surfaced.status}", detail="${surfaced.detail}", reason "${surfaced.recentError?.message}"; globe still alive`);
});
await browser.close();
}
// ── preflight ─────────────────────────────────────────────────────────────
async function preflight() {
// "Reachable" means the target answered AT ALL. An HTTP 500 is a responsive
// app returning an error — a PRODUCT failure for B1 to report, never a
// reason to skip the matrix as an environment problem. Only a refused/failed
// connection is ENV.
try {
const r = await fetch(APP_URL, { signal: AbortSignal.timeout(15000) });
env.reachable = true;
env.shellStatus = r.status;
} catch (e) {
env.reachable = false;
env.shellStatus = null;
env.unreachableReason = String(e?.message || e).slice(0, 120);
}
if (!env.reachable) return;
// Key presence is read from the server's own honest self-report — never by
// reading a key value. "Absent" must be POSITIVELY stated by the endpoint in
// its documented shape; an HTTP error or a malformed payload means the key
// state is UNKNOWN ('error'), and every check that depends on it FAILS
// rather than quietly skipping as OWNER-RUN.
const statusKey = async (path) => {
let r;
try { r = await jget(path); } catch (e) {
return CONNECTION_REFUSED_RE.test(String(e?.message || e)) ? 'error' : 'error';
}
if (r.status !== 200) return 'error';
if (typeof r.json?.hasKey !== 'boolean') return 'error';
return r.json.hasKey;
};
env.keys.FIRMS = await statusKey('/api/firms/status');
env.keys.TOMTOM = await statusKey('/api/tomtom/status');
try {
const ais = await jget('/api/ais-live');
if (ais.status === 503 && ais.json?.status === 'missing-key') env.keys.AIS = false;
else if (ais.status === 200 && ais.json && Array.isArray(ais.json.rows)) env.keys.AIS = true;
else env.keys.AIS = 'error';
} catch { env.keys.AIS = 'error'; }
try {
const os = await jget('/api/opensky?lamin=29&lomin=-99&lamax=31&lomax=-97', { timeoutMs: 40000 });
const reason = os.headers.get('X-OpenSky-Auth-Reason') || '';
const used = os.headers.get('X-OpenSky-Auth-Mode-Used') || os.headers.get('X-OpenSky-Auth') || '';
if (!os.ok) env.keys.OPENSKY = 'error';
else if (/missing_.*creds|invalid_or_missing/.test(reason)) env.keys.OPENSKY = false;
else if (/^(oauth|basic)$/.test(used)) env.keys.OPENSKY = true;
else if (used === 'anon') env.keys.OPENSKY = false;
else env.keys.OPENSKY = 'error';
} catch { env.keys.OPENSKY = 'error'; }
if (CHEAP) {
// Minting a Realtime token is free, but --cheap promises to touch nothing
// cost-bearing; leave OpenAI presence unknown and let its checks skip.
env.keys.OPENAI = null;
} else {
try {
const t = await jget('/api/realtime/token', { method: 'POST' });
if (t.status === 503 && /OPENAI_API_KEY is not set/.test(t.text)) env.keys.OPENAI = false;
else if (t.ok) env.keys.OPENAI = true;
else env.keys.OPENAI = 'error';
} catch { env.keys.OPENAI = 'error'; }
}
// A Node 24 runtime for the allocation gate (mise/nvm), if one exists.
const mise = await sh('mise', ['ls', 'node'], { timeoutMs: 20000 });
const m24 = /node\s+(24\.[0-9.]+)/.exec(mise.out || '');
if (m24) {
const where = await sh('mise', ['where', `node@${m24[1]}`], { timeoutMs: 20000 });
const bin = resolve((where.out || '').trim(), 'bin', 'node');
if (existsSync(bin)) env.node24 = { bin, label: `mise node@${m24[1]}` };
}
if (!env.node24) {
const nvmBin = resolve(process.env.HOME || '', '.nvm/versions/node');
if (existsSync(nvmBin)) {
const listed = await sh('ls', [nvmBin], { timeoutMs: 20000 });
const v24 = (listed.out || '').split('\n').map((s) => s.trim()).find((s) => /^v?24\./.test(s));
const bin = v24 ? resolve(nvmBin, v24, 'bin', 'node') : null;
if (bin && existsSync(bin)) env.node24 = { bin, label: `nvm ${v24}` };
}
}
}
// ── main ──────────────────────────────────────────────────────────────────
function keyLabel(v) { return v === true ? 'present' : v === false ? 'absent' : 'unknown'; }
async function main() {
const started = Date.now();
console.log(`\n${C.b(' L9 RELEASE-CANDIDATE QA MATRIX')}`);
console.log(` target : ${APP_URL}${CHEAP ? C.y(' [--cheap: read-only subset]') : ''}`);
if (LIST_ONLY) {
for (const c of CHECKS.filter(selected)) {
console.log(` ${c.id.padEnd(4)} ${c.group} ${c.desc}${c.heavy ? C.d(' [heavy]') : ''}${c.needsKey ? C.d(` [needs ${c.needsKey}]`) : ''}`);
}
console.log(`\n ${CHECKS.filter(selected).length} checks (${CHECKS.filter((c) => selected(c) && !c.manual).length} automated, ${CHECKS.filter((c) => selected(c) && c.manual).length} owner-run)\n`);
return;
}
await preflight();
if (!env.reachable) {
// Positively identified as "nothing is listening" — the only case that
// justifies aborting as an environment problem.
console.error(C.r(`\n Target not reachable at ${APP_URL} (${env.unreachableReason}) — start the keyed dev server first (./scripts/dev-fresh.sh).\n`));
process.exit(2);
}
if (env.shellStatus >= 400) {
console.log(C.r(` shell : HTTP ${env.shellStatus} — the target is RESPONDING but erroring. Running the matrix anyway; this is a product failure, not an environment one.`));
}
console.log(` node : ${process.versions.node}${env.node24 ? C.d(` (Node 24 available: ${env.node24.label})`) : ''}`);
console.log(` keys : OpenSky ${keyLabel(env.keys.OPENSKY)} · FIRMS ${keyLabel(env.keys.FIRMS)} · TomTom ${keyLabel(env.keys.TOMTOM)} · AISStream ${keyLabel(env.keys.AIS)} · OpenAI ${keyLabel(env.keys.OPENAI)}`);
console.log(C.d(' (key presence is read from each proxy\'s own status report; no key value is ever read or logged)\n'));
const record = (c, rawRes, ms) => {
// Validate before counting: an unrecognised verdict is a runner bug, and a
// runner bug must never be able to leave the scoreboard green.
const res = normalizeVerdict(rawRes);
const row = { id: c.id, group: c.group, desc: c.desc, ...res, ms };
results.push(row);
const tagStr = {
[PASS]: C.g('PASS '),
[PASS_SKIPS]: C.m('PASS* '),
[FAIL]: C.r('FAIL '),
[CRASH]: C.m('CRASH '),
[SKIP]: C.y(`SKIPPED[${res.tag}]`),
}[res.status];
console.log(` ${c.id.padEnd(4)} ${tagStr} ${c.desc}`);
if (res.detail) console.log(` ${C.d(String(res.detail).slice(0, 300))}`);
if (res.note) console.log(` ${C.m(`KNOWN CONDITION: ${String(res.note).slice(0, 260)}`)}`);
};
const runList = CHECKS.filter(selected);
const runSerial = async (c) => {
if (c.manual) { record(c, skip('owner-eyes step — see the maintainers\' release runbook', 'OWNER-RUN'), 0); return; }
if (CHEAP && (c.heavy || c.costly)) { record(c, skip('heavy/cost-bearing check omitted by --cheap', 'CHEAP'), 0); return; }
if (c.needsKey && env.keys[c.needsKey] !== true) {
const state = env.keys[c.needsKey];
if (state === 'error') {
// The key-status endpoint is unhealthy on a responsive app. That is a
// product failure, not a reason to mark the row owner-run.
record(c, fail(`${c.needsKey} key state UNKNOWN: its status endpoint returned an error or a malformed payload on a responsive server — cannot claim the key is merely absent`), 0);
return;
}
record(c, skip(`server reports no ${c.needsKey} key (${keyLabel(state)}) — run on the fully keyed server`, 'OWNER-RUN'), 0);
return;
}
const t0 = Date.now();
try {
const res = await c.run();
record(c, res, Date.now() - t0);
} catch (e) {
record(c, crash(`the check itself threw, so it verified nothing: ${String(e?.message || e).slice(0, 200)}`), Date.now() - t0);
}
};
// A target that dies mid-run (a crashed dev server) otherwise turns every
// later check into a bogus product FAIL — empty layers, "no RESULT line".
// Re-check liveness at each group boundary and degrade honestly instead.
// Liveness = "something answered", NOT "answered 200". A 500 keeps the run
// going so the responsible check reports a product FAIL.
let targetAlive = true;
const recheckTarget = async () => {
if (!targetAlive) return false;
try {
await fetch(APP_URL, { signal: AbortSignal.timeout(15000) });
targetAlive = true;
} catch { targetAlive = false; }
return targetAlive;
};
const wrapRun = runSerial;
const runGuarded = async (c) => {
if (!targetAlive && c.group !== 'A' && c.group !== 'M') {
record(c, skip(`target ${APP_URL} stopped responding mid-run — restart the dev server and re-run this group`, 'ENV'), 0);
return;
}
await wrapRun(c);
};
// Groups run in order. Every puppeteer surface is sequential by design:
// concurrent SwiftShader contexts produce fake failures across this fleet.
for (const g of ['A', 'B']) {
for (const c of runList.filter((x) => x.group === g)) await runGuarded(c);
}
if (runList.some((c) => c.browser)) {
if (!(await recheckTarget())) {
for (const c of runList.filter((x) => x.browser)) {
record(c, skip(`target ${APP_URL} stopped responding before the browser group`, 'ENV'), 0);
}
} else {
const emitted = new Set();
const recordBrowser = (c, res, ms) => { emitted.add(c.id); record(c, res, ms); };
try {
await runBrowserGroup(recordBrowser);
} catch (e) {
// Every selected browser check must appear in the scoreboard. Recording
// only the first one left the rest silently absent, and the totals then
// matched results.length tautologically instead of the selected matrix.
const why = String(e?.message || e).slice(0, 180);
for (const c of runList.filter((x) => x.browser && !emitted.has(x.id))) {
record(c, crash(`browser group aborted before this check could run: ${why}`), 0);
}
}
for (const c of runList.filter((x) => x.browser && !emitted.has(x.id))) {
record(c, crash('browser group finished without reporting this check'), 0);
}
}
}
await recheckTarget();
for (const g of ['D', 'M']) {
for (const c of runList.filter((x) => x.group === g)) await runGuarded(c);
}
// Any selected check that never produced a row is itself a hole.
for (const c of runList.filter((x) => !results.some((r) => r.id === x.id))) {
record(c, crash('the runner never executed this selected check'), 0);
}
// ── scoreboard ──────────────────────────────────────────────────────────
const mins = ((Date.now() - started) / 60000).toFixed(1);
const byStatus = (st) => results.filter((r) => r.status === st);
const p = byStatus(PASS).length;
const ps = byStatus(PASS_SKIPS).length;
const f = byStatus(FAIL).length;
const x = byStatus(CRASH).length;
const s = byStatus(SKIP).length;
console.log(`\n${C.b(' ── L9 SCOREBOARD ' + '─'.repeat(52))}`);
for (const g of ['A', 'B', 'C', 'D', 'M']) {
const rows = results.filter((r) => r.group === g);
if (!rows.length) continue;
const n = (st) => rows.filter((r) => r.status === st).length;
const name = { A: 'REPO GATES', B: 'FEED PROBES', C: 'IN-BROWSER', D: 'HARNESS FLEET', M: 'OWNER-EYES' }[g];
console.log(` ${g} ${name.padEnd(15)} ${C.g(`${n(PASS)} pass`)} ${n(PASS_SKIPS) ? C.m(`${n(PASS_SKIPS)} pass*`) : '0 pass*'} ${n(FAIL) ? C.r(`${n(FAIL)} fail`) : '0 fail'} ${n(CRASH) ? C.m(`${n(CRASH)} crash`) : '0 crash'} ${C.y(`${n(SKIP)} skipped`)} (${rows.length})`);
}
console.log(` ${'─'.repeat(68)}`);
console.log(` ${C.b('TOTAL')} ${C.g(`${p} PASS`)} ${ps ? C.m(`${ps} PASS-WITH-SKIPS`) : '0 PASS-WITH-SKIPS'} ${f ? C.r(`${f} FAIL`) : '0 FAIL'} ${x ? C.m(`${x} HARNESS-CRASH`) : '0 HARNESS-CRASH'} ${C.y(`${s} SKIPPED`)} of ${runList.length} selected ${C.d(`${mins} min wall clock`)}`);
const green = f === 0 && x === 0 && ps === 0;
console.log(` ${green ? C.g('GREEN — every selected check either verified its claim or honestly skipped.')
: C.r('NOT GREEN — a fully green L9 run requires 0 FAIL, 0 HARNESS-CRASH and 0 PASS-WITH-SKIPS.')}`);
if (f) {
console.log(`\n ${C.r('FAILURES — the product is wrong')}`);
for (const r of byStatus(FAIL)) console.log(` ${r.id} ${r.desc}\n ${C.d(String(r.detail).slice(0, 300))}`);
}
if (x) {
console.log(`\n ${C.m('HARNESS-CRASH — the check itself broke; it verified NOTHING')}`);
for (const r of byStatus(CRASH)) console.log(` ${r.id} ${r.desc}\n ${C.d(String(r.detail).slice(0, 300))}`);
}
if (ps) {
console.log(`\n ${C.m('PASS-WITH-SKIPS — green, but assertions were left unrun')}`);
for (const r of byStatus(PASS_SKIPS)) console.log(` ${r.id} ${r.desc}\n ${C.d(String(r.detail).slice(0, 300))}`);
}
const ownerRun = byStatus(SKIP).filter((r) => r.tag === 'OWNER-RUN');
if (ownerRun.length) {
console.log(`\n ${C.y('STILL OWED BY THE OWNER RUN')} (${ownerRun.length})`);
for (const r of ownerRun) console.log(` ${r.id} ${r.desc}`);
}
const envSkips = byStatus(SKIP).filter((r) => r.tag !== 'OWNER-RUN');
if (envSkips.length) {
console.log(`\n ${C.d(`environment/N-A/cheap skips (${envSkips.length}): ${envSkips.map((r) => r.id).join(', ')}`)}`);
}
console.log('');
if (JSON_OUT) {
writeFileSync(resolve(process.cwd(), JSON_OUT), JSON.stringify({
target: APP_URL, startedAt: new Date(started).toISOString(), minutes: Number(mins),
node: process.versions.node, browser: env.browserVersion, keys: env.keys,
shellStatus: env.shellStatus, green,
totals: { pass: p, passWithSkips: ps, fail: f, harnessCrash: x, skipped: s, selected: runList.length },
results,
}, null, 2));
console.log(` JSON: ${resolve(process.cwd(), JSON_OUT)}\n`);
}
// A crashed check verified nothing — it must not exit green.
process.exit(f > 0 || x > 0 ? 1 : 0);
}
// Run only when invoked directly, so the pure verdict logic above can be
// imported and pinned by the unit suite (mirrors scripts/run-unit-tests.mjs).
const invokedPath = process.argv[1] ? pathToFileURL(resolve(process.argv[1])).href : '';
if (import.meta.url === invokedPath) {
main().catch((e) => {
console.error(C.r(`\n qa-l9-matrix crashed: ${e?.stack || e}\n`));
process.exit(1);
});
}
export {
PASS, PASS_SKIPS, FAIL, CRASH, SKIP, OUTCOMES,
normalizeVerdict, classifyNoScoreboard, readResultLine, readCockpit, satisfiesEngines,
isCalibratedAllocationRuntime, trafficFlowInconclusive,
soleVerdict, RESULT_RE, COCKPIT_RE, FLOOR_RE,
readFloorVerdict, keyGuard, applyKnownConditions, requiredCreditFor,
CREDIT_EXPECTATIONS, CREDIT_EXEMPT_LAYERS,
};