gods-eye-view/scripts/track-regression.mjs

4066 lines
215 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* track-regression.mjs
*
* DETERMINISTIC regression harness for 3D flight TRACKING.
*
* Background: tracked-plane 3D has regressed FOUR times (flicker → freeze →
* jitter → pull-out → cross-layer orphan), each fix sometimes revealing the
* next. This script locks the invariants so they can't silently break again.
*
* It drives the REAL app (http://localhost:4173) in headless Chromium with the
* same WebGL launch flags the existing Cesium render harness uses
* (tools/cesium-render.mjs): --use-gl=angle / --use-angle=swiftshader.
*
* DETERMINISM: it does NOT depend on live OpenSky / adsb.lol / AISStream
* (all optional or rate-limited in local QA). Instead it installs a persistent
* `fetch` shim in the page that intercepts the poll endpoints and returns
* SYNTHETIC aircraft positioned near the camera, in the EXACT upstream payload
* shapes the layers parse:
* - flights → GET /api/opensky → { states: [ <state-vector[]> ] }
* - military → GET /api/adsblol/mil → { ac: [ <adsblol-aircraft{}> ] }
* - vessels → GET /api/ais-live → connected, zero-row snapshot
* The shim stays installed so the layers' setInterval pollers keep the
* synthetic planes alive (under MISSING_POLL_LIMIT=3 so they're never pruned).
*
* The four invariants, each one assertion block:
* 1. NO JITTER — the tracked plane's 3D MODEL position and its
* getDetectableObjects() (HUD/detection) position use
* the SAME per-frame value. We sample both over ~30
* frames and assert max|visual-centredetectable| ≈ 0.
* 2. NO PULL-OUT — tracking plane B while tracking A must not fly the
* camera to a high overview (deselect/switch never
* moves the camera — it stays in the follow band).
* 3. NO CROSS-LAYER — tracking military then commercial (and vice versa)
* ORPHAN clears the FIRST layer (its getTrackedInfo()===null),
* via the per-layer viewer.trackedEntityChanged listener.
* 4. INIT CLEAN — app loads, all 12 layers present, no console errors,
* [Detection] Initialized + [TrackedReadout] Initialized.
*
* Plus two pre-ship-audit (2026-07-01) regressions appended at the end:
* H1. CLICK-OWN-PLANE — the tracked standalone model exposes its pick id,
* and a real mouse click on the tracked plane is a
* NO-OP (no deselect, no camera spike).
* M3. AGE-OUT RELEASE — when the tracked plane's fixes stop arriving
* (3 missed polls via the shim), tracking clears and
* the camera is RELEASED IN PLACE: viewer.trackedEntity
* undefined, NO jump (owner decision 2026-07-02 —
* the old ~80 km overview flyTo is gone).
*
* And the landing-ghost polish (2026-07-02): a LOW+SLOW (landed) plane that
* vanishes from the feed is removed after ONE missed poll, while a cruise
* plane keeps the full 3-poll grace (it absorbs real feed gaps); the tracked
* readout carries a "· STALE" cue while a tracked plane coasts through its
* missed-poll grace, and drops it when the plane reappears.
*
* And the ground-traffic feature (2026-07-03, owner reversal): present-but-
* grounded planes render FULL-STRENGTH in the airborne tint pipeline
* (white / amber-military; the day-1 gray mute was killed the same day) at
* ×0.8 scale and stay detectable; the on_ground flip restyles the SAME
* billboard in place (landing/takeoff transition — never a removal); a
* grounded plane that then vanishes from the feed still fast-culls after one
* missed poll (both layers; military keys off adsb.lol's alt_baro === "ground").
* Ground billboards render depth-test-free (disableDepthTestDistance = ∞) so
* the photoreal tile skin can't bury them up close; takeoff restores the test.
*
* And GROUND 3D (2026-07-03, owner decision LOCKED: "when I have 3D mode —
* proximity or all — I want that respected regardless of whether a plane is
* on the ground or in the air. No distinction."): a synthetic on_ground plane
* is model-ELIGIBLE and gets a model under the existing cap (both layers); its
* model matrix height reads the ONE-SHOT cached ground snap — a stubbed
* scene.sampleHeight (qa-cctv-drift-b9b style) + the per-layer belly offset —
* never the buried/floating feed altitude, and never re-samples per frame;
* the TRACKED grounded plane gets the standalone tracked model too (the
* owner's "tracked SWA143 at 0 kts showed a 2D billboard" case).
*
* And arrival-rotation freshness (2026-07-03 ground-polish): camera.moveEnd
* forces a full rotation pass on the next frame (fly-to settles the
* pose-signature gate can eat), and a billboard flipping INTO view while the
* camera idles re-aims the same tick instead of wearing a stale nose for up
* to ROTATION_REFRESH_MS. Both layers.
*
* Run: npm run test:track (assumes dev server already up on :4173)
* node scripts/track-regression.mjs
*
* Exits non-zero if ANY invariant fails. DOES NOT COMMIT anything.
*
* Flags:
* --url <url> App URL (default http://localhost:4173)
* --headful Show the browser (debugging)
* --keep-open Leave the browser open after the run (debugging)
*/
import fs from 'node:fs';
import puppeteer from 'puppeteer';
import { classifyAircraft, CLASS_SCALE_3D, CLASS_MODEL_REAL } from '../src/data/aircraftClass.js';
import { ensureGeoidReady, geoidHeight } from '../src/data/geoid.js';
// ---------------------------------------------------------------------------
// Args
// ---------------------------------------------------------------------------
const argv = process.argv.slice(2);
const getFlag = (name) => argv.includes(name);
const getOpt = (name, dflt) => {
const i = argv.indexOf(name);
return i >= 0 && argv[i + 1] ? argv[i + 1] : dflt;
};
const APP_URL = getOpt('--url', 'http://localhost:4173');
const APP_ORIGIN = new URL(APP_URL).origin;
const HEADFUL = getFlag('--headful');
const KEEP_OPEN = getFlag('--keep-open');
const CHROME_EXECUTABLE_CANDIDATES = [
process.env.PUPPETEER_EXECUTABLE_PATH,
// Prefer puppeteer's version-pinned Chrome-for-Testing over the system
// Chrome: /Applications auto-updates underneath the harnesses, and its
// software-GL behavior shifts across majors (system Chrome 150 blew the
// tile-gated drain budget under SwiftShader on 2026-07-30 — six
// false-negative qa-cctv-v2 runs against a healthy build). A deterministic
// pinned browser beats the newest one for regression harnesses.
(() => { try { return puppeteer.executablePath(); } catch { return null; } })(),
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
'/Applications/Chromium.app/Contents/MacOS/Chromium',
].filter(Boolean);
function findChromeExecutable() {
for (const candidate of CHROME_EXECUTABLE_CANDIDATES) {
try {
if (fs.existsSync(candidate)) return candidate;
} catch {
// Ignore inaccessible candidates and let Puppeteer fall back to its cache.
}
}
return null;
}
// ---------------------------------------------------------------------------
// Pretty PASS/FAIL reporting
// ---------------------------------------------------------------------------
const results = [];
function record(name, ok, detail) {
results.push({ name, ok, detail });
const tag = ok ? '\x1b[32mPASS\x1b[0m' : '\x1b[31mFAIL\x1b[0m';
console.log(` [${tag}] ${name}${detail ? `${detail}` : ''}`);
}
function skip(name, why) {
results.push({ name, ok: null, detail: why });
console.log(` [\x1b[33mSKIP\x1b[0m] ${name}${why}`);
}
// ---------------------------------------------------------------------------
// Synthetic aircraft (positioned near Austin, the app's load view).
// Commercial ICAOs deliberately NOT in any known-military set so the flights
// layer doesn't suppress them; military hexes are whatever adsb.lol returns and
// the military layer registers them itself on parse.
// ---------------------------------------------------------------------------
const SYNTH = {
// Austin load view is (-97.7431, 30.2672). Spread a few planes a few km apart.
flights: [
// [icao24, callsign, country, time_position, last_contact, lon, lat, baro_alt, on_ground, velocity, true_track]
{ icao: 'aaa001', callsign: 'SYN001', lon: -97.7431, lat: 30.2672, alt: 9000, vel: 230, track: 90 },
{ icao: 'aaa002', callsign: 'SYN002', lon: -97.7600, lat: 30.2800, alt: 9500, vel: 210, track: 45 },
{ icao: 'aaa003', callsign: 'SYN003', lon: -97.7300, lat: 30.2550, alt: 8700, vel: 250, track: 135 },
],
// Two real, well-formed TLEs (ISS + Hubble). SGP4 needs a valid element set;
// these are static public catalog entries, so the propagated positions are
// reproducible run to run.
tle: [
'ISS (ZARYA)',
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9004',
'2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.49814310 12345',
'HST',
'1 20580U 90037B 24001.50000000 .00001250 00000-0 67000-4 0 9992',
'2 20580 28.4700 288.8102 0002613 321.7208 133.2117 15.09299130 12345',
'',
].join('\n'),
// One dense (Starlink-shell) element set, so dense mode has a real subject
// to track. Same orbital elements as the ISS entry with a distinct satnum,
// which keeps SGP4 valid and the propagation reproducible.
denseTle: [
'STARLINK-1007',
'1 44713U 19074A 24001.50000000 .00016717 00000-0 10270-3 0 9004',
'2 44713 53.0000 247.4627 0006703 130.5360 325.0288 15.06000000 12345',
'',
].join('\n'),
military: [
// adsb.lol record fields: hex, flight, lon, lat, alt_baro (ft), track, gs (kt), t, r, ownOp, seen_pos
{ hex: 'bbb101', flight: 'MIL101', lon: -97.7500, lat: 30.2700, altFt: 28000, track: 270, gsKt: 420, t: 'F16', r: 'AF-101' },
{ hex: 'bbb102', flight: 'MIL102', lon: -97.7350, lat: 30.2600, altFt: 26000, track: 315, gsKt: 400, t: 'F18', r: 'AF-102' },
],
};
// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------
async function main() {
console.log(`\n3D Tracking Regression Harness`);
console.log(` App URL : ${APP_URL}`);
console.log(` Mode : ${HEADFUL ? 'headful' : 'headless'}\n`);
// Verify the dev server is up before launching a browser.
try {
const res = await fetch(APP_URL, { method: 'GET' });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
} catch (e) {
console.error(`\x1b[31mDev server not reachable at ${APP_URL} (${e.message}).\x1b[0m`);
console.error(`Start it first: ./scripts/dev-fresh.sh (or: npm run dev)`);
process.exit(2);
}
const chromeExecutable = findChromeExecutable();
if (chromeExecutable) {
console.log(` Browser : ${chromeExecutable}\n`);
}
const browser = await puppeteer.launch({
headless: HEADFUL ? false : 'new',
// This machine intermittently stalls single CDP calls past the 180 s
// default under SwiftShader load (same hardening as qa-focus-evidence).
protocolTimeout: 300_000,
...(chromeExecutable ? { executablePath: chromeExecutable } : {}),
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
// SwiftShader only in headless: forcing it in headful defeats the whole
// point of --headful (real GPU). Diagnosed 2026-08-03: under this
// machine's Chrome 145 SwiftShader, loading the tracked military GLB
// kills frame production entirely (rAF stops while timers/evals stay
// alive), wedging any rAF-awaiting evaluation. Same policy as
// qa-focus-evidence: headful = real GPU.
...(HEADFUL ? [] : ['--use-gl=angle', '--use-angle=swiftshader']),
'--disable-dev-shm-usage',
'--disable-web-security',
'--disable-background-timer-throttling',
'--disable-renderer-backgrounding',
// macOS stops frame production for fully-occluded windows, which kills
// rAF (and thus every rAF-awaiting evaluation) in headful runs whose
// window opens behind others — the qa-focus-evidence bringToFront
// lesson, enforced belt-and-braces here.
'--disable-backgrounding-occluded-windows',
'--window-size=1280,800',
],
});
const consoleErrors = [];
const failedResponses = [];
const sawLog = { detection: false, readout: false };
try {
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
await page.setRequestInterception(true);
page.on('request', (request) => {
const url = new URL(request.url());
if (url.origin === APP_ORIGIN && url.pathname === '/api/openai/hud-summary') {
request.respond({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ summary: 'QA globe ready' }),
});
return;
}
request.continue();
});
page.on('console', (msg) => {
const text = msg.text();
const type = msg.type();
if (text.includes('[Detection] Initialized')) sawLog.detection = true;
if (text.includes('[TrackedReadout] Initialized')) sawLog.readout = true;
if (type === 'error') {
// Ignore benign network resource 404s (e.g. an un-shimmed upstream
// endpoint with no live data, a missing tile/favicon). Those are
// environmental noise, not a tracking-invariant regression. Real JS
// errors (TypeError, unhandled rejection, etc.) are still captured.
const isBenign404 = /Failed to load resource.*404/i.test(text);
const sourceUrl = msg.location()?.url || '';
if (!isBenign404) consoleErrors.push(sourceUrl ? `${text} [${sourceUrl}]` : text);
}
// Surface a trace for debugging, but keep it quiet.
if (process.env.GEV_TEST_VERBOSE) console.log(` [page:${type}] ${text}`);
});
page.on('pageerror', (err) => consoleErrors.push(`pageerror: ${err.message}`));
page.on('response', (response) => {
if (response.status() >= 500) {
failedResponses.push(`HTTP ${response.status()} ${response.url()}`);
}
});
// ---- Install the synthetic-fetch shim BEFORE any app code runs ----------
// Must be in place before the layers' first update() fires fetch(API_URL).
await page.evaluateOnNewDocument((synth, appOrigin) => {
// Stash the planes so the page can mutate them later (e.g. to advance
// positions), and so we can confirm the shim is live.
window.__SYNTH = synth;
window.__SYNTH_HITS = { opensky: 0, mil: 0 };
const realFetch = window.fetch.bind(window);
const jsonResponse = (obj) =>
new Response(JSON.stringify(obj), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
window.fetch = (input, init) => {
const requestUrl = typeof input === 'string' || input instanceof URL
? String(input)
: input?.url;
const url = new URL(requestUrl, window.location.href);
const isAppRequest = url.origin === appOrigin;
// OpenSky (commercial flights): { states: [ state-vector[] ] }
if (isAppRequest && url.pathname === '/api/opensky') {
window.__SYNTH_HITS.opensky++;
// A withheld contact models the ordinary case where the recipient's
// first authoritative refresh does not yet carry the shared aircraft.
const withheld = (() => {
try { return window.sessionStorage.getItem('__gevWithhold') || ''; } catch { return ''; }
})();
const states = window.__SYNTH.flights
.filter((f) => f.icao !== withheld)
.map((f) => ([
f.icao, // 0 icao24
f.callsign, // 1 callsign
'Synthetica', // 2 origin_country
Math.floor(Date.now() / 1000), // 3 time_position
Math.floor(Date.now() / 1000), // 4 last_contact
f.lon, // 5 longitude
f.lat, // 6 latitude
f.alt, // 7 baro_altitude (m)
f.onGround === true, // 8 on_ground (ground-traffic phase flips this live)
f.vel, // 9 velocity (m/s)
f.track, // 10 true_track (deg)
0, null, null, null, false, 0, // padding to match state-vector length
]));
return Promise.resolve(jsonResponse({ time: Math.floor(Date.now() / 1000), states }));
}
// Trail backfill (fires on trackById). Stub with valid-but-empty
// payloads so the deterministic run never 404s against the dev proxy.
// flights: { path: [ [time, lat, lon, baroAlt, true_track, on_ground] ] }
if (isAppRequest && url.pathname === '/api/opensky-track') {
return Promise.resolve(jsonResponse({ path: [] }));
}
// military: { timestamp: <epochSec>, trace: [ [secAfter, lat, lon, ...] ] }
if (isAppRequest && url.pathname === '/api/adsblol/trace') {
return Promise.resolve(jsonResponse({ timestamp: Math.floor(Date.now() / 1000), trace: [] }));
}
// adsbdb enrichment (fires for tracked/model-eligible planes): empty
// object → typeCode stays null → the synthetic planes' class (and so
// their 3D scale + ground-snap belly offset) is DETERMINISTIC, never a
// live-proxy lookup of a fake hex.
if (isAppRequest && /^\/api\/adsbdb\/(?:type|route)\/[^/]+$/.test(url.pathname)) {
return Promise.resolve(jsonResponse({}));
}
// Contacts enables the optional AIS source alongside aircraft. Keep
// this tracking harness independent of local AIS credentials while
// preserving the truthful "awaiting first message" lifecycle.
if (isAppRequest && url.pathname === '/api/ais-live') {
return Promise.resolve(jsonResponse({
status: 'connected',
rows: [],
lastMessageAt: null,
}));
}
// CelesTrak TLE groups. Served from a fixed two-satellite catalog so
// the satellite assertions are deterministic and the run never depends
// on an upstream that rate-limits (it was answering 403 the night this
// was written).
if (isAppRequest && url.pathname.startsWith('/api/celestrak/')) {
const group = url.pathname.slice('/api/celestrak/'.length);
// One named group fails on demand. Failing a group the subject is
// NOT in is the reclassification case: CelesTrak moves satellites
// between groups, so a subject missing from its old group may have
// moved into the one that just failed.
if (window.__SYNTH.failGroup && group === window.__SYNTH.failGroup) {
return Promise.resolve(new Response('upstream unavailable', { status: 503 }));
}
if (group === 'starlink') {
// A dense load that FAILS is the case that erases the dense
// request: settling a failure reverts the catalog mode to core.
if (window.__SYNTH.failDense) {
return Promise.resolve(new Response('upstream unavailable', { status: 503 }));
}
return Promise.resolve(new Response(window.__SYNTH.denseTle, {
status: 200, headers: { 'Content-Type': 'text/plain' },
}));
}
// EVERY core group serves the same catalog. Dedupe keeps the first
// (stations) tag, so the catalog is unchanged — but no group is
// EMPTY, and an empty group counts as failed, which would make an
// `accepted` refresh (and therefore any release) unreachable here.
return Promise.resolve(new Response(window.__SYNTH.tle, {
status: 200, headers: { 'Content-Type': 'text/plain' },
}));
}
// Voice scene context reverse-geocodes the view target and asks Places
// for nearby names. Answer both with empty results: the entity-context
// assertions are about the SELECTED contact, and a live lookup would
// make the run non-hermetic (and bill the owner's Google quota).
if (url.hostname === 'maps.googleapis.com' && url.pathname.startsWith('/maps/api/geocode')) {
return Promise.resolve(jsonResponse({ status: 'ZERO_RESULTS', results: [] }));
}
if (isAppRequest && url.pathname === '/api/google/nearby-places') {
return Promise.resolve(jsonResponse({ places: [] }));
}
// adsb.lol military: { ac: [ aircraft{} ] } (must come AFTER /trace check)
if (isAppRequest && url.pathname === '/api/adsblol/mil') {
window.__SYNTH_HITS.mil++;
const ac = window.__SYNTH.military.map((m) => ({
hex: m.hex,
flight: m.flight,
lon: m.lon,
lat: m.lat,
alt_baro: m.altFt,
track: m.track,
gs: m.gsKt,
t: m.t,
r: m.r,
ownOp: 'SYNTH AF',
seen_pos: 0,
}));
return Promise.resolve(jsonResponse({ msg: 'No error', now: Date.now(), ac }));
}
return realFetch(input, init);
};
}, SYNTH, APP_ORIGIN);
console.log('Loading app...');
await page.goto(APP_URL, { waitUntil: 'domcontentloaded', timeout: 60000 });
if (HEADFUL) await page.bringToFront();
// Wait for the app to expose its globals (Cesium viewer + dataManager).
await page.waitForFunction(
() => window.__godsEyeView && window.__godsEyeView.viewer && window.__godsEyeView.dataManager,
{ timeout: 60000, polling: 200 }
);
console.log(' App globals ready.\n');
// Small helper: run an expression in the page after the next render frame,
// so reads happen on a settled frame.
const evalPage = (fn, ...args) => page.evaluate(fn, ...args);
// ============================================================
// INVARIANT 4: INIT CLEAN (run first — establishes baseline)
// ============================================================
console.log('Invariant 4 — init clean');
// Give the app a moment to finish first-frame init (detection/readout log).
await page.waitForFunction(
() => {
const dm = window.__godsEyeView.dataManager;
return dm && dm.layers && dm.layers.size >= 12;
},
{ timeout: 30000, polling: 200 }
).catch(() => {});
const layerInfo = await evalPage(() => {
const dm = window.__godsEyeView.dataManager;
return {
count: dm.layers.size,
ids: [...dm.layers.keys()],
hasFlights: dm.layers.has('flights'),
hasMilitary: dm.layers.has('military'),
};
});
record('init: >=12 layers registered', layerInfo.count >= 12,
`${layerInfo.count} layers [${layerInfo.ids.join(', ')}]`);
record('init: flights + military layers present',
layerInfo.hasFlights && layerInfo.hasMilitary,
`flights=${layerInfo.hasFlights} military=${layerInfo.hasMilitary}`);
// Detection + TrackedReadout init logs are emitted during app boot.
// Give them a beat in case they fire just after globals appear.
await waitFor(() => sawLog.detection && sawLog.readout, 8000).catch(() => {});
record('init: [Detection] Initialized logged', sawLog.detection);
record('init: [TrackedReadout] Initialized logged', sawLog.readout);
record('init: no console errors during boot', consoleErrors.length === 0,
consoleErrors.length ? `${consoleErrors.length} error(s): ${consoleErrors.slice(0, 3).join(' | ')}` : 'clean');
// Independent GLB capability control. Product model absence cannot prove
// that the browser backend is incapable: that is the condition this
// harness is meant to catch. Load the already-approved airplane asset
// directly through Cesium, outside the Flights/Military model pipelines,
// then remove the control before exercising product behavior.
const glbControlStarted = await evalPage(async () => {
window.__qaGlbControl = null;
window.__qaGlbControlError = null;
const asset = await fetch('/models/airplane.glb');
const assetBytes = asset.ok ? (await asset.arrayBuffer()).byteLength : 0;
if (!asset.ok || assetBytes === 0) {
throw new Error(`GLB control asset unavailable: HTTP ${asset.status}`);
}
const Cesium = await import('/node_modules/cesium/Build/Cesium/index.js');
const viewer = window.__godsEyeView.viewer;
const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(-97.7431, 30.2672, 9000),
);
void Cesium.Model.fromGltfAsync({
url: '/models/airplane.glb',
modelMatrix,
scale: 1,
}).then((model) => {
model.id = 'qa:independent-glb-control';
window.__qaGlbControl = viewer.scene.primitives.add(model);
viewer.scene.requestRender();
}).catch((error) => {
window.__qaGlbControlError = String(error?.message || error);
});
return true;
}).catch((error) => {
throw new Error(`Independent GLB capability control could not start: ${error.message}`);
});
const glbBackendCapable = glbControlStarted && await page.waitForFunction(() => {
const control = window.__qaGlbControl;
window.__godsEyeView.viewer.scene.requestRender();
return Boolean(control?.ready);
}, { timeout: 40000, polling: 250 }).then(() => true).catch(() => false);
const glbControlDetail = await evalPage((capable) => {
const viewer = window.__godsEyeView.viewer;
const control = window.__qaGlbControl;
const error = window.__qaGlbControlError;
if (control) viewer.scene.primitives.remove(control);
delete window.__qaGlbControl;
delete window.__qaGlbControlError;
return capable ? 'ready' : (error || 'did not become ready');
}, glbBackendCapable);
console.log(` GLB capability control: ${glbBackendCapable ? 'ready' : 'unavailable'} (${glbControlDetail})`);
// Hermeticity (round 5, 2026-07-06): the mesh-floor sampler probes the
// REAL scene once per cell per poll. Under headless GL, Google tiles
// sometimes stream at the synthetic-plane coords and sometimes don't, so
// billboard datums varied run-to-run and flaked the ground/arrival
// groups. Stub sampleHeight to "no tiles anywhere" for the whole run; the
// ground-3d group REPLACES this with its counting 187.5 stub, restoring
// the deterministic pre-round-5 datums everywhere else.
await evalPage(() => {
window.__godsEyeView.viewer.scene.sampleHeight = () => undefined;
});
// ============================================================
// Enable flights + military layers and feed synthetic data.
// ============================================================
console.log('\nEnabling flights + military layers (synthetic feed)...');
const enabled = await evalPage(async () => {
const dm = window.__godsEyeView.dataManager;
// setEnabled→toggle→init→enable→update(immediate fetch, shimmed).
await dm.setEnabled('flights', true);
await dm.setEnabled('military', true);
// Drive 3D through the actual DISPLAY-rail control. This preserves the
// user-facing ownership seam and proves that one toggle drives both
// commercial and military layers before model-capacity assertions run.
//
// Since 2026-08-22 the toggle DEFAULTS ON, so the former "click it if it
// is dark" arming step would have become a no-op and this check would
// have quietly degraded into a restatement of the default. Drive a full
// round trip instead — OFF, then back ON — so both directions are proven
// through the real control no matter which way the default points.
const fl = dm.layers.get('flights').module;
const mil = dm.layers.get('military').module;
const models3dButton = document.getElementById('models3d-toggle');
const models3dOff = { button: null, fl: null, mil: null };
if (models3dButton) {
if (!models3dButton.classList.contains('active')) models3dButton.click();
models3dButton.click(); // → OFF: both layers must follow the one control
models3dOff.button = models3dButton.classList.contains('active');
models3dOff.fl = fl.getParams().models3d;
models3dOff.mil = mil.getParams().models3d;
models3dButton.click(); // → ON: the state the rest of the run needs
}
// Force one more update each so freshly-shimmed data is ingested.
await fl.update(window.__godsEyeView.viewer);
await mil.update(window.__godsEyeView.viewer);
return {
flEnabled: dm.isEnabled('flights'),
milEnabled: dm.isEnabled('military'),
flStats: fl.getStats(),
milStats: mil.getStats(),
models3dButtonActive: models3dButton?.classList.contains('active') === true,
flModels3d: fl.getParams().models3d,
milModels3d: mil.getParams().models3d,
models3dOff,
hits: window.__SYNTH_HITS,
};
});
console.log(` flights enabled=${enabled.flEnabled} count=${enabled.flStats.count} | military enabled=${enabled.milEnabled} count=${enabled.milStats.count}`);
console.log(` shim hits: opensky=${enabled.hits.opensky} mil=${enabled.hits.mil}`);
const injectionWorked = enabled.flStats.count > 0 && enabled.milStats.count > 0;
record('inject: synthetic flights ingested (count>0)', enabled.flStats.count > 0,
`flights count=${enabled.flStats.count}`);
record('inject: synthetic military ingested (count>0)', enabled.milStats.count > 0,
`military count=${enabled.milStats.count}`);
record('DISPLAY-rail 3D toggle drives both aircraft layers, both directions',
enabled.models3dButtonActive && enabled.flModels3d && enabled.milModels3d
&& enabled.models3dOff.button === false
&& enabled.models3dOff.fl === false && enabled.models3dOff.mil === false,
`on: button=${enabled.models3dButtonActive} flights=${enabled.flModels3d} military=${enabled.milModels3d}`
+ ` | off: button=${enabled.models3dOff.button} flights=${enabled.models3dOff.fl} military=${enabled.models3dOff.mil}`);
if (!injectionWorked) {
skip('jitter / pull-out / orphan (need synthetic planes)',
'synthetic injection produced 0 planes — see inject failures above');
finishAndExit();
return;
}
// ============================================================
// SHARE LINK V2 — real reload restores the same logical plane.
// ============================================================
console.log('\nShare Link v2 — tracked aircraft survives a full reload');
const shareTracked = await evalPage(() => (
window.__godsEyeView.dataManager.layers
.get('flights').module.trackById('aaa001', { origin: 'user' })
));
await page.waitForFunction(
() => {
const flights = window.__godsEyeView?.dataManager?.layers?.get('flights')?.module;
// `lo=` alone is NOT discriminating — the 3D-models option already
// put an `lo` field in the hash before any aircraft was selected.
// Wait for the tracking assignment itself.
return location.hash.includes('v=2')
&& /[?&#]lo=[^&]*f\.t\.aaa001/.test(location.hash)
&& flights?.getParams?.().selectedFlightsTrackingId === 'aaa001';
},
// Share serialization is driven by the rendered state transition. On a
// saturated headless GPU, ten seconds can expire before that frame even
// though tracking is already accepted; keep the assertion identical but
// give the callback the same 30 s budget as other reload/latch checks.
{ timeout: 30000, polling: 100 },
);
const trackedShareUrl = page.url();
record(
'share-v2: explicit aircraft selection reaches the generated URL',
// Pin the ACTUAL tracking assignment (`f.t.<icao>`), not the mere
// presence of an `lo` field that the 3D-models option already supplies.
shareTracked
&& /[?&#]lo=[^&]*f\.t\.aaa001/.test(trackedShareUrl)
&& !trackedShareUrl.includes('f.t.aaa002'),
trackedShareUrl,
);
await page.reload({ waitUntil: 'domcontentloaded', timeout: 60000 });
await page.waitForFunction(
() => window.__godsEyeView?.dataManager?.layers?.size >= 12,
{ timeout: 60000, polling: 200 },
);
await page.waitForFunction(
() => {
const manager = window.__godsEyeView?.dataManager;
const tracked = manager?.layers?.get('flights')?.module?.getTrackedInfo?.();
return manager?.isEnabled?.('flights')
&& tracked?.icao24 === 'aaa001'
&& window.__godsEyeView.viewer.trackedEntity?.gevTrackedId === 'flights:aaa001';
},
{ timeout: 30000, polling: 100 },
);
const shareReload = await evalPage(() => {
const manager = window.__godsEyeView.dataManager;
const flights = manager.layers.get('flights').module;
return {
flightsEnabled: manager.isEnabled('flights'),
trackedId: flights.getTrackedInfo()?.icao24 || null,
durableId: flights.getParams()?.selectedFlightsTrackingId || null,
viewerTrackedId: window.__godsEyeView.viewer.trackedEntity?.gevTrackedId || null,
};
});
record(
'share-v2: full reload restores the selected logical aircraft',
shareReload.flightsEnabled
&& shareReload.trackedId === 'aaa001'
&& shareReload.durableId === 'aaa001',
JSON.stringify(shareReload),
);
record(
'share-v2: restored aircraft owns the Cesium follow camera',
shareReload.viewerTrackedId === 'flights:aaa001',
`viewerTrackedId=${shareReload.viewerTrackedId}`,
);
// Prove the URL itself owns the result. Remove the same-origin saved
// preference, then open the captured link as a clean recipient would.
await evalPage(() => localStorage.removeItem('gev:layer-state:v2'));
await page.goto(trackedShareUrl, { waitUntil: 'domcontentloaded', timeout: 60000 });
await page.waitForFunction(
() => window.__godsEyeView?.dataManager?.layers?.size >= 12,
{ timeout: 60000, polling: 200 },
);
await page.waitForFunction(
() => {
const manager = window.__godsEyeView?.dataManager;
const tracked = manager?.layers?.get('flights')?.module?.getTrackedInfo?.();
return manager?.isEnabled?.('flights')
&& tracked?.icao24 === 'aaa001'
&& window.__godsEyeView.viewer.trackedEntity?.gevTrackedId === 'flights:aaa001';
},
{ timeout: 30000, polling: 100 },
);
const cleanRecipient = await evalPage(() => {
const manager = window.__godsEyeView.dataManager;
const flights = manager.layers.get('flights').module;
return {
flightsEnabled: manager.isEnabled('flights'),
trackedId: flights.getTrackedInfo()?.icao24 || null,
durableId: flights.getParams()?.selectedFlightsTrackingId || null,
viewerTrackedId: window.__godsEyeView.viewer.trackedEntity?.gevTrackedId || null,
};
});
record(
'share-v2: clean recipient magic link restores the selected aircraft',
cleanRecipient.flightsEnabled
&& cleanRecipient.trackedId === 'aaa001'
&& cleanRecipient.durableId === 'aaa001'
&& cleanRecipient.viewerTrackedId === 'flights:aaa001',
JSON.stringify(cleanRecipient),
);
// ---- Not-yet-arrived shared subject: PENDING, silent, then latches ----
// Reload-from-local always survived a slow first refresh via the layer's
// deferred-restore latch. The shared path used to decide on ONE refresh,
// clear the subject, and post a failure notice seconds into startup.
await evalPage(() => window.sessionStorage.setItem('__gevWithhold', 'aaa001'));
// A goto whose URL differs only by hash is a SAME-DOCUMENT navigation: the
// page would never reload and the app would keep its existing tracking.
// Leave the document first so this is a real cold boot of the shared link.
await page.goto('about:blank', { waitUntil: 'domcontentloaded', timeout: 30000 });
await page.goto(trackedShareUrl, { waitUntil: 'domcontentloaded', timeout: 60000 });
await page.waitForFunction(
() => window.__godsEyeView?.dataManager?.layers?.size >= 12,
{ timeout: 60000, polling: 200 },
);
await page.waitForFunction(
() => document.getElementById('loading-screen')?.classList.contains('hidden'),
{ timeout: 60000, polling: 200 },
);
await new Promise((resolve) => setTimeout(resolve, 6000));
const pendingShare = await evalPage(() => ({
tracked: window.__godsEyeView.dataManager.layers
.get('flights').module.getTrackedInfo()?.icao24 || null,
notice: (document.getElementById('global-loading-label')?.textContent || '').trim(),
noticeShown: !document.getElementById('global-loading-status')?.hidden,
}));
record(
'share-v2: a not-yet-arrived subject is held pending, with no failure notice',
pendingShare.tracked === null
&& !/unavailable|expired|could not be restored/i.test(
pendingShare.noticeShown ? pendingShare.notice : '',
),
JSON.stringify(pendingShare),
);
// The aircraft now arrives on a later poll; the latch must take it.
await evalPage(() => window.sessionStorage.removeItem('__gevWithhold'));
await evalPage(async () => {
const flights = window.__godsEyeView.dataManager.layers.get('flights').module;
for (let i = 0; i < 3; i += 1) {
await flights.update(window.__godsEyeView.viewer);
await new Promise((resolve) => setTimeout(resolve, 600));
}
});
await page.waitForFunction(
() => window.__godsEyeView?.dataManager?.layers?.get('flights')?.module
?.getTrackedInfo?.()?.icao24 === 'aaa001',
{ timeout: 30000, polling: 200 },
).catch(() => {});
const latchedShare = await evalPage(() => ({
tracked: window.__godsEyeView.dataManager.layers
.get('flights').module.getTrackedInfo()?.icao24 || null,
viewerTrackedId: window.__godsEyeView.viewer.trackedEntity?.gevTrackedId || null,
}));
record(
'share-v2: the pending subject latches on when it arrives on a later poll',
latchedShare.tracked === 'aaa001'
&& latchedShare.viewerTrackedId === 'flights:aaa001',
JSON.stringify(latchedShare),
);
// The captured link intentionally contains only the explicitly owned
// Flights layer. Restore the harness-only Military companion before the
// legacy cross-layer invariants continue.
await evalPage(async () => {
const manager = window.__godsEyeView.dataManager;
await manager.setEnabled('military', true);
await manager.layers.get('military').module.update(window.__godsEyeView.viewer);
});
await evalPage(() => {
window.__godsEyeView.viewer.scene.sampleHeight = () => undefined;
});
// ============================================================
// VOICE ENTITY CONTEXT — a click-selected contact IS "the selected
// entity". The aircraft layers publish selection on their own awareness
// lane (the readout card + Contacts subject), and for the whole life of
// the voice tools they never wrote the SHARED context slot that
// `get_entity_context` reads. So with a plane plainly selected on screen,
// `{scope:'selected'}` silently downgraded to `'in_view'` and the model
// answered "there isn't a plane currently selected" (owner field session,
// 2026-08-21). Drives the real tool runner; costs no model turns.
// ============================================================
console.log('\nVoice entity context — a click-selected contact answers scope:selected');
const runnerReady = await evalPage(() => typeof window.__gevVoiceCommands?.runner === 'function');
if (!runnerReady) {
skip('voice-context: click-selected aircraft answers scope:selected',
'voice command runner not exposed on this build');
} else {
const flightSelected = await evalPage(async () => {
const flights = window.__godsEyeView.dataManager.layers.get('flights').module;
// The exact call the canvas click handler makes on a billboard pick.
flights.trackById('aaa001', { origin: 'user' });
const result = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
return {
scope: result?.scope || null,
layerId: result?.selected?.layerId || null,
id: result?.selected?.id || null,
name: result?.selected?.name || null,
latitude: result?.selected?.latitude ?? null,
callsign: result?.selected?.properties?.callsign || null,
};
});
record(
'voice-context: click-selected aircraft answers scope:selected',
flightSelected.scope === 'selected'
&& flightSelected.layerId === 'flights'
&& flightSelected.id === 'aaa001',
JSON.stringify(flightSelected),
);
record(
'voice-context: the selected contact carries its identity and position',
flightSelected.name === 'SYN001'
&& flightSelected.callsign === 'SYN001'
&& Number.isFinite(flightSelected.latitude),
JSON.stringify(flightSelected),
);
// Selecting a different contact must MOVE the subject, not stack a
// second one: a frozen record left behind would be narrated later at a
// position its aircraft has long since left.
const switchedSubject = await evalPage(async () => {
const manager = window.__godsEyeView.dataManager;
manager.layers.get('flights').module.trackById('aaa002', { origin: 'user' });
const result = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
const store = window.__gevContextStore;
const flightRecords = [...store.entities.values()].filter((r) => r.layerId === 'flights');
return {
scope: result?.scope || null,
id: result?.selected?.id || null,
flightRecordIds: flightRecords.map((r) => r.id),
};
});
record(
'voice-context: switching contacts moves the subject and leaves no stale record',
switchedSubject.scope === 'selected'
&& switchedSubject.id === 'aaa002'
&& switchedSubject.flightRecordIds.length === 1
&& switchedSubject.flightRecordIds[0] === 'aaa002',
JSON.stringify(switchedSubject),
);
// A military contact is the same click, on the sibling layer.
const militarySelected = await evalPage(async () => {
const manager = window.__godsEyeView.dataManager;
manager.layers.get('flights').module.stopTracking();
manager.layers.get('military').module.trackById('bbb101', { origin: 'user' });
const result = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
return {
scope: result?.scope || null,
layerId: result?.selected?.layerId || null,
id: result?.selected?.id || null,
name: result?.selected?.name || null,
};
});
record(
'voice-context: click-selected military contact answers scope:selected',
militarySelected.scope === 'selected'
&& militarySelected.layerId === 'military'
&& militarySelected.id === 'bbb101'
&& militarySelected.name === 'MIL101',
JSON.stringify(militarySelected),
);
// Deselecting must give the slot back — a subject that outlives its
// selection is the same bug pointed the other way.
const deselected = await evalPage(async () => {
const manager = window.__godsEyeView.dataManager;
manager.layers.get('military').module.stopTracking();
const result = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
return { scope: result?.scope || null, selected: result?.selected ?? null };
});
record(
'voice-context: deselecting releases the subject back to in_view',
deselected.scope === 'in_view' && deselected.selected === null,
JSON.stringify(deselected),
);
// ============================================================
// SATELLITES — same PRD gap as the aircraft layers: a tracked satellite
// published only its awareness event, so voice could not see it either.
// ============================================================
console.log('\nVoice entity context — a tracked satellite is a selected subject');
const satelliteContext = await evalPage(async () => {
const manager = window.__godsEyeView.dataManager;
await manager.setEnabled('satellites', true);
const satellites = manager.layers.get('satellites').module;
// Wait for the shimmed stations catalog to build its satrecs.
for (let i = 0; i < 80; i += 1) {
if (satellites.getStats?.().count > 0) break;
await new Promise((resolve) => setTimeout(resolve, 250));
}
const tracked = satellites.trackById(25544, { origin: 'user' });
await new Promise((resolve) => setTimeout(resolve, 500));
const selected = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
// Switching subjects must move the slot, not stack a second orbit.
satellites.trackById(20580, { origin: 'user' });
await new Promise((resolve) => setTimeout(resolve, 500));
const switched = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
const satelliteRecordIds = [...window.__gevContextStore.entities.values()]
.filter((record) => record.layerId === 'satellites')
.map((record) => record.id);
// CATALOG REBUILD. The tracked satellite's catalog entry is replaced
// wholesale by a TLE refresh, so a surviving subject must re-resolve
// against the new satrec — and a subject that did NOT survive must
// release the slot rather than linger frozen at its last position.
satellites.trackById(25544, { origin: 'user' });
await new Promise((resolve) => setTimeout(resolve, 500));
await satellites.update(window.__godsEyeView.viewer);
await new Promise((resolve) => setTimeout(resolve, 600));
const afterRebuild = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
// RECLASSIFICATION: the subject vanishes from the catalog while a
// DIFFERENT group — one it could have been moved into — failed to
// load. Its own group loaded fine, so a group-scoped proof would call
// this a disappearance. It is not: absence is only proven when every
// potential carrier loaded.
const fullTle = window.__SYNTH.tle;
const truncatedTle = fullTle.split('\n').slice(3).join('\n');
window.__SYNTH.tle = truncatedTle;
window.__SYNTH.failGroup = 'geo';
await satellites.update(window.__godsEyeView.viewer);
await new Promise((resolve) => setTimeout(resolve, 800));
const afterPartial = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
window.__SYNTH.failGroup = null;
window.__SYNTH.tle = fullTle;
// Recover, so the release case below starts from a healthy subject.
await satellites.update(window.__godsEyeView.viewer);
await new Promise((resolve) => setTimeout(resolve, 800));
// Now the subject vanishes from a COMPLETE catalog — proven absence.
window.__SYNTH.tle = fullTle.split('\n').slice(3).join('\n');
await satellites.update(window.__godsEyeView.viewer);
await new Promise((resolve) => setTimeout(resolve, 800));
const afterSubjectGone = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
window.__SYNTH.tle = fullTle;
// DENSE CARRIER FAILURE. Track a dense-shell satellite, then let the
// dense load fail on the next rebuild. Settling that failure reverts
// the catalog mode to 'core', so anything reading the mode AFTER the
// await no longer sees that dense was ever a potential carrier — and
// would delete a subject the dense catalog might have carried.
satellites.setParams({ catalog: 'dense' });
for (let i = 0; i < 80; i += 1) {
if (satellites.getStats?.().count > 2) break;
await new Promise((resolve) => setTimeout(resolve, 250));
}
const denseTracked = satellites.trackById(44713, { origin: 'user' });
await new Promise((resolve) => setTimeout(resolve, 600));
const denseSelected = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
window.__SYNTH.failDense = true;
await satellites.update(window.__godsEyeView.viewer);
await new Promise((resolve) => setTimeout(resolve, 1200));
const afterDenseFailure = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
const catalogModeAfterFailure = satellites.getParams?.().catalog ?? null;
window.__SYNTH.failDense = false;
satellites.setParams({ catalog: 'core' });
satellites.stopTracking?.();
await new Promise((resolve) => setTimeout(resolve, 400));
satellites.trackById(25544, { origin: 'user' });
await new Promise((resolve) => setTimeout(resolve, 400));
satellites.stopTracking?.();
await new Promise((resolve) => setTimeout(resolve, 400));
const released = await window.__gevVoiceCommands.runner('get_entity_context', { scope: 'selected' });
await manager.setEnabled('satellites', false);
// Following a satellite left the camera in orbit. Hand it back to the
// synthetic fleet so later groups see the view they were written for.
manager.layers.get('flights').module.trackById('aaa001', { origin: 'user' });
await new Promise((resolve) => setTimeout(resolve, 600));
return {
tracked,
scope: selected?.scope ?? null,
layerId: selected?.selected?.layerId ?? null,
id: selected?.selected?.id ?? null,
name: selected?.selected?.name ?? null,
latitude: selected?.selected?.latitude ?? null,
switchedId: switched?.selected?.id ?? null,
satelliteRecordIds,
releasedScope: released?.scope ?? null,
releasedSelected: released?.selected ?? null,
rebuiltScope: afterRebuild?.scope ?? null,
rebuiltId: afterRebuild?.selected?.id ?? null,
rebuiltLatitude: afterRebuild?.selected?.latitude ?? null,
goneScope: afterSubjectGone?.scope ?? null,
goneSelected: afterSubjectGone?.selected ?? null,
partialScope: afterPartial?.scope ?? null,
partialId: afterPartial?.selected?.id ?? null,
denseTracked,
denseSelectedId: denseSelected?.selected?.id ?? null,
denseFailureScope: afterDenseFailure?.scope ?? null,
denseFailureId: afterDenseFailure?.selected?.id ?? null,
catalogModeAfterFailure,
};
});
record(
'voice-context: a tracked satellite answers scope:selected with its identity',
satelliteContext.tracked === true
&& satelliteContext.scope === 'selected'
&& satelliteContext.layerId === 'satellites'
&& satelliteContext.id === '25544'
&& /ISS/.test(satelliteContext.name || '')
&& Number.isFinite(satelliteContext.latitude),
JSON.stringify(satelliteContext),
);
record(
'voice-context: switching satellites moves the subject and leaves no stale orbit',
satelliteContext.switchedId === '20580'
&& satelliteContext.satelliteRecordIds.length === 1
&& satelliteContext.satelliteRecordIds[0] === '20580',
JSON.stringify(satelliteContext),
);
record(
'voice-context: the subject survives a catalog rebuild under the same id',
satelliteContext.rebuiltScope === 'selected'
&& satelliteContext.rebuiltId === '25544'
&& Number.isFinite(satelliteContext.rebuiltLatitude),
JSON.stringify(satelliteContext),
);
record(
'voice-context: a subject missing while ANOTHER potential carrier failed is preserved',
satelliteContext.partialScope === 'selected' && satelliteContext.partialId === '25544',
JSON.stringify(satelliteContext),
);
record(
'voice-context: a subject that does not survive the rebuild releases the slot',
satelliteContext.goneScope === 'in_view' && satelliteContext.goneSelected === null,
JSON.stringify(satelliteContext),
);
record(
'voice-context: a failed DENSE load preserves its subject, even though the mode reverts',
satelliteContext.denseTracked === true
&& satelliteContext.denseSelectedId === '44713'
&& satelliteContext.catalogModeAfterFailure === 'core'
&& satelliteContext.denseFailureScope === 'selected'
&& satelliteContext.denseFailureId === '44713',
JSON.stringify(satelliteContext),
);
record(
'voice-context: deselecting a satellite releases the subject',
satelliteContext.releasedScope === 'in_view' && satelliteContext.releasedSelected === null,
JSON.stringify(satelliteContext),
);
// ============================================================
// PANEL === SPOKEN. Not the shared helper as a stand-in: the REAL
// Contacts pipeline (awareness selects a subject, evaluateSubject fills
// the snapshot, the panel renders it) against the REAL voice tool. A
// divergence introduced at the call site itself — not in the helper —
// has to go red here.
// ============================================================
console.log('\nPanel === spoken — one number, through both real call sites');
const panelVsSpoken = await evalPage(async () => {
const manager = window.__godsEyeView.dataManager;
if (!manager.isEnabled('flights')) await manager.setEnabled('flights', true);
if (!manager.isEnabled('military')) await manager.setEnabled('military', true);
// Enter Contacts the way the operator does, then select a contact so
// awareness has a real subject.
const button = document.getElementById('global-context-flights-btn');
if (button && !window.__godsEyeView.styleManager.getContextModeState?.().mode) button.click();
for (let i = 0; i < 80; i += 1) {
if (window.__godsEyeView.styleManager.getContextModeState?.().mode) break;
await new Promise((resolve) => setTimeout(resolve, 100));
}
manager.layers.get('flights').module.trackById('aaa001', { origin: 'user' });
// Awareness recomputes on its own cadence; wait for a real snapshot.
const awareness = manager.layers.get('military-awareness')?.module;
let snapshot = null;
for (let i = 0; i < 80; i += 1) {
snapshot = awareness?.getContextSnapshot?.() || null;
if (snapshot?.cohorts?.length) break;
await new Promise((resolve) => setTimeout(resolve, 150));
}
if (!snapshot?.subject) return { error: 'awareness produced no subject' };
const countFor = (id) => {
const cohort = snapshot.cohorts.find((entry) => entry?.id === id);
return Number.isFinite(cohort?.count) ? cohort.count : null;
};
// What the PANEL shows, read from the snapshot it renders.
const panelAircraft = (countFor('flights') ?? 0) + (countFor('military') ?? 0);
// What VOICE says, through the real tool runner.
const spoken = await window.__gevVoiceCommands.runner('analyst_query', {
layers: ['flights', 'military'],
scope: { kind: 'radius', km: Math.round((snapshot.radiusM || 250000) / 1000) },
});
return {
subject: snapshot.subject.label || snapshot.subject.id || null,
panelAircraft,
spokenCount: spoken?.count ?? null,
spokenEngine: spoken?.window?.engine ?? null,
spokenCenteredOn: spoken?.window?.centeredOn ?? null,
};
});
record(
'panel===spoken: the Contacts panel and the voice count are one number',
!panelVsSpoken.error
&& panelVsSpoken.spokenEngine === 'contacts-window'
&& panelVsSpoken.spokenCount === panelVsSpoken.panelAircraft,
JSON.stringify(panelVsSpoken),
);
record(
'panel===spoken: the spoken answer names the subject whose window it read',
!panelVsSpoken.error && panelVsSpoken.spokenCenteredOn === panelVsSpoken.subject,
JSON.stringify(panelVsSpoken),
);
// Leave Contacts as the vocabulary group expects to find it.
await evalPage(async () => {
try { await window.__gevVoiceCommands.runner('set_context_mode', { mode: 'off' }); } catch {}
});
// ============================================================
// CONTEXT VOCABULARY — state output must speak the words the tools
// accept. The Contacts mode's internal id is 'flights' while
// `set_context_mode` takes 'contacts', and state surfaces reported the
// internal id: the model read `mode:'flights'`, concluded Contacts was
// off, and refused to answer from the Contacts window counts carried in
// the same payload (owner field session, 2026-08-21).
// ============================================================
console.log('\nContext vocabulary — state output speaks the tools\' own words');
const manualContacts = await evalPage(async () => {
const button = document.getElementById('global-context-flights-btn');
if (!button) return { error: 'Contacts control not found' };
// The MANUAL path is the one that broke silently — voice never set it.
button.click();
for (let i = 0; i < 60; i += 1) {
if (window.__godsEyeView.styleManager.getContextModeState?.().mode) break;
await new Promise((resolve) => setTimeout(resolve, 100));
}
const state = await window.__gevVoiceCommands.runner('get_current_view_state');
return {
internalMode: window.__godsEyeView.styleManager.getContextModeState?.().mode || null,
reportedMode: state?.context?.mode ?? null,
reportedInternal: state?.context?.modeInternal ?? null,
active: state?.context?.active ?? null,
};
});
record(
'context-vocab: a manually activated Contacts reports as "contacts", not its internal id',
manualContacts.internalMode === 'flights'
&& manualContacts.reportedMode === 'contacts'
&& manualContacts.reportedInternal === 'flights'
&& manualContacts.active === true,
JSON.stringify(manualContacts),
);
// Round-trip: whatever state output reports must be a word the tool
// accepts. Feeding the reported mode straight back must not be rejected.
const roundTrip = await evalPage(async (reported) => {
const result = await window.__gevVoiceCommands.runner('set_context_mode', { mode: reported });
const state = await window.__gevVoiceCommands.runner('get_current_view_state');
return {
ok: result?.ok ?? null,
error: result?.error || null,
resultMode: result?.mode ?? null,
resultInternal: result?.modeInternal ?? null,
stateMode: state?.context?.mode ?? null,
};
}, manualContacts.reportedMode);
record(
'context-vocab: the reported mode round-trips back through set_context_mode',
roundTrip.ok === true
&& !roundTrip.error
&& roundTrip.resultMode === 'contacts'
&& roundTrip.resultInternal === 'flights'
&& roundTrip.stateMode === 'contacts',
JSON.stringify(roundTrip),
);
const contextOff = await evalPage(async () => {
const result = await window.__gevVoiceCommands.runner('set_context_mode', { mode: 'off' });
const state = await window.__gevVoiceCommands.runner('get_current_view_state');
return {
resultMode: result?.mode ?? null,
stateMode: state?.context?.mode ?? null,
stateInternal: state?.context?.modeInternal ?? null,
};
});
record(
'context-vocab: no context reports as "off", never a bare null',
contextOff.resultMode === 'off'
&& contextOff.stateMode === 'off'
&& contextOff.stateInternal === null,
JSON.stringify(contextOff),
);
// ============================================================
// ANALYST -> TRACK HANDOFF — the tool instructions tell the model to
// look a contact up with analyst_query and hand that identity to
// track_entity. The analyst's `id` is a DISPLAY label (callsign, else
// registration, else hex) and the lookup matched callsigns and hex
// only, so a callsign-less contact came back as its tail number and
// "Nothing matched" — the model then burned the turn on retries (owner
// field session 2026-08-21, 23:48: three failed track_entity calls
// before a fallback stuck).
// ============================================================
console.log('\nAnalyst handoff — a looked-up contact can actually be tracked');
const handoff = await evalPage(async () => {
const manager = window.__godsEyeView.dataManager;
// This group owns its precondition: earlier groups toggle Contacts,
// which snapshots and restores layer state around itself.
if (!manager.isEnabled('military')) await manager.setEnabled('military', true);
const mil = manager.layers.get('military').module;
const priorFixture = window.__SYNTH.military.slice();
window.__SYNTH.military = [...priorFixture, {
hex: 'bbb777', flight: '', lon: -97.7440, lat: 30.2680,
altFt: 1800, track: 210, gsKt: 130, t: 'UH60', r: '6606',
}];
try {
await mil.update(window.__godsEyeView.viewer);
// Scope is deliberately 'anywhere': what is under test is the
// identity handoff, not spatial filtering, and an earlier group may
// have left the camera somewhere else entirely.
const analyst = await window.__gevVoiceCommands.runner('analyst_query', {
layers: ['military'], scope: { kind: 'anywhere' }, limit: 10,
});
const item = (analyst?.items || []).find((entry) => entry.id === '6606') || null;
const tracked = item
? await window.__gevVoiceCommands.runner('track_entity', { query: item.id, layerId: 'military' })
: null;
return {
militaryEnabled: manager.isEnabled('military'),
militaryCount: mil.getStats?.().count ?? null,
itemCount: (analyst?.items || []).length,
itemFound: Boolean(item),
itemId: item?.id ?? null,
itemIcao: item?.icao24 ?? null,
trackOk: tracked?.ok ?? null,
trackError: tracked?.error ?? null,
trackedIcao: mil.getTrackedInfo()?.icao24 ?? null,
};
} finally {
window.__SYNTH.military = priorFixture;
mil.stopTracking();
await mil.update(window.__godsEyeView.viewer);
}
});
record(
'analyst-handoff: a callsign-less contact is named by the tail number the app shows',
handoff.itemFound && handoff.itemId === '6606',
JSON.stringify(handoff),
);
record(
'analyst-handoff: the identity the analyst returned is trackable, first try',
handoff.trackOk === true
&& !handoff.trackError
&& handoff.trackedIcao === 'bbb777',
JSON.stringify(handoff),
);
record(
'analyst-handoff: the result carries the hex key the tracker keys on',
handoff.itemIcao === 'bbb777',
JSON.stringify(handoff),
);
// Restore the state the downstream invariants were written against:
// flights following aaa001, military idle.
await evalPage(() => {
window.__godsEyeView.dataManager.layers.get('flights').module.trackById('aaa001', { origin: 'user' });
});
await page.waitForFunction(
() => window.__godsEyeView?.dataManager?.layers?.get('flights')?.module
?.getTrackedInfo?.()?.icao24 === 'aaa001',
{ timeout: 15000, polling: 100 },
);
}
// NOTE: we do NOT manually reposition the camera. Tracking sets
// viewer.trackedEntity + a calibrated viewFrom, so the follow camera lands
// in the few-km band (altitude*1.1+2500, clamped 330 km) — far below the
// MODEL_ALT_CEIL_M = 800 km ceiling, so _modelRegimeActive() is true and the
// standalone tracked model renders. That's the exact path the invariants
// protect, so we exercise it rather than a synthetic setView.
// ============================================================
// INVARIANT 1: NO JITTER
// model visual centre === getDetectableObjects() position, per frame.
// ============================================================
console.log('\nInvariant 1 — no jitter (model visual centre === detectable pos)');
// Install a scene-graph model finder in the page FIRST (used by the wait
// below). The tracked model is a standalone Cesium.Model added to a
// PrimitiveCollection under scene.primitives. We locate the shown Model whose
// matrix translation is nearest the tracked display position.
await evalPage(() => {
window.__findTrackedModel = function () {
const v = window.__godsEyeView.viewer;
const prims = v.scene.primitives;
const out = [];
const walk = (coll) => {
const n = coll.length;
for (let i = 0; i < n; i++) {
const p = coll.get(i);
if (!p) continue;
// PrimitiveCollection has .length + .get
if (typeof p.length === 'number' && typeof p.get === 'function') { walk(p); continue; }
// A Cesium.Model has a modelMatrix (Matrix4: column-major Float64Array-like)
if (p.modelMatrix && typeof p.ready !== 'undefined') out.push(p);
}
};
walk(prims);
// Prefer shown+ready models.
const shown = out.filter((m) => m.show && m.ready);
const pool = shown.length ? shown : out;
if (!pool.length) return null;
// If tracking, pick the model nearest the tracked display position.
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
// Prefer the tracked model's explicit H1 pick id. A neighboring fleet
// model can temporarily be nearer while the follow camera/model matrix
// settles after the cross-layer switch sequence, causing this probe to
// report the neighbor's id even though the correct tracked model is up.
const trackedInfo = fl.getTrackedInfo();
const exactPickModel = trackedInfo
? pool.find((model) => String(model.id) === trackedInfo.icao24)
: null;
if (exactPickModel) return exactPickModel;
const ent = window.__godsEyeView.viewer.trackedEntity;
let tracked = null;
if (ent && typeof ent.gevDisplayPosition === 'function') tracked = ent.gevDisplayPosition();
if (!tracked) return pool[0];
let best = null, bestD = Infinity;
for (const m of pool) {
const mm = m.modelMatrix;
const dx = mm[12] - tracked.x, dy = mm[13] - tracked.y, dz = mm[14] - tracked.z;
const d = dx * dx + dy * dy + dz * dz;
if (d < bestD) { bestD = d; best = m; }
}
// The tracked model rides AT the display position. While the tracked
// GLB is still loading, the nearest ready model is some OTHER plane's
// fleet model km away — returning it made the model-up waits resolve
// spuriously and H1 read a neighbor's pick id. Anything beyond 1 km
// is "tracked model not up yet", not a match.
return bestD < 1000 * 1000 ? best : null;
};
});
// Track a synthetic commercial plane. Tracking sets viewer.trackedEntity +
// viewFrom, so the follow camera lands in the few-km band and the standalone
// 3D model renders (model regime active below the 800 km ceiling).
const trackedIcao = SYNTH.flights[0].icao;
await evalPage((icao) => {
window.__godsEyeView.dataManager.layers.get('flights').module.trackById(icao);
}, trackedIcao);
await sleep(1500); // let the follow camera settle + the GLB load kick off
// Wait until the tracked Cesium.Model primitive exists, is ready & shown.
const modelUp = await page.waitForFunction((icao) => {
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const ti = fl.getTrackedInfo();
if (!ti || ti.icao24 !== icao) return false;
const found = window.__findTrackedModel ? window.__findTrackedModel() : null;
return !!(found && found.ready && found.show && String(found.id) === icao);
}, { timeout: 60000, polling: 250 }, trackedIcao).then(() => true).catch(() => false);
record('3D: tracked commercial model becomes ready through the DISPLAY toggle', modelUp,
modelUp ? `ready+shown id=${trackedIcao}` : 'tracked product model never became ready+shown');
let jitterResult;
if (!modelUp) {
// Model didn't come up — still test the underlying invariant: the tracked
// entity's exposed display position (what the model uses) must equal the
// getDetectableObjects() position. This is the exact shared-source contract.
jitterResult = await sampleFrames(page, 30, (icao) => {
const dm = window.__godsEyeView.dataManager;
const fl = dm.layers.get('flights').module;
const ent = window.__godsEyeView.viewer.trackedEntity;
const disp = ent && typeof ent.gevDisplayPosition === 'function' ? ent.gevDisplayPosition() : null;
const dets = fl.getDetectableObjects({ maxCount: 1000 });
const me = dets.find((d) => d.id === icao || d.id === (fl.getTrackedInfo() && fl.getTrackedInfo().callsign));
if (!disp || !me || !me.position) return null;
const dx = disp.x - me.position.x, dy = disp.y - me.position.y, dz = disp.z - me.position.z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}, trackedIcao);
console.log(' (3D model did not render under SwiftShader; testing the shared display-position contract directly)');
} else {
// Full check: independently transform airplane.glb's measured AABB centre
// through the actual 3D model matrix, then compare it with detection.
// glTF [x,y,z] → Cesium-local [x,-z,y]. The effective rendered
// computedScale is separate from modelMatrix and includes any
// minimumPixelSize enlargement, so include it just as the renderer does.
jitterResult = await sampleFrames(page, 30, (icao) => {
const dm = window.__godsEyeView.dataManager;
const fl = dm.layers.get('flights').module;
const ti = fl.getTrackedInfo();
const model = window.__findTrackedModel();
if (!model) return null;
const mm = model.modelMatrix;
const scale = Number.isFinite(model.computedScale)
? model.computedScale
: (Number.isFinite(model.scale) ? model.scale : 1);
// airplane.glb is now bounding-box centred with transforms applied.
const x = 0 * scale;
const y = 0 * scale;
const z = 0 * scale;
const visual = {
x: mm[0] * x + mm[4] * y + mm[8] * z + mm[12],
y: mm[1] * x + mm[5] * y + mm[9] * z + mm[13],
z: mm[2] * x + mm[6] * y + mm[10] * z + mm[14],
};
const dets = fl.getDetectableObjects({ maxCount: 1000 });
const me = dets.find((d) => d.skipLabel) // tracked entry is skipLabel:true
|| dets.find((d) => d.id === (ti && ti.callsign))
|| dets.find((d) => d.id === icao);
if (!me || !me.position) return null;
const dx = visual.x - me.position.x;
const dy = visual.y - me.position.y;
const dz = visual.z - me.position.z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}, trackedIcao);
}
// Tolerance: the model and detectable both read _cachedDRPosition, so the
// delta should be ~0. A regression (model recomputing dead-reckon on a later
// frameNumber) produced a visible front-back jitter = tens to hundreds of m.
// Allow 5 m for float noise / partial-frame sampling.
const JITTER_TOL_M = 5;
const samples = jitterResult.values.filter((v) => v != null);
if (samples.length < 5) {
skip('jitter: model visual centre === detectable pos', `only ${samples.length} usable samples (positions unavailable)`);
} else {
const maxDelta = Math.max(...samples);
record('jitter: max|visual centre detectable| ≈ 0 over frames', maxDelta <= JITTER_TOL_M,
`max=${maxDelta.toFixed(3)} m over ${samples.length} frames (tol ${JITTER_TOL_M} m, mode=${modelUp ? 'model-matrix' : 'display-contract'})`);
}
// ============================================================
// INVARIANT 2: NO PULL-OUT on a track switch
// tracking B while tracking A must not fly to ~80 km overview.
// ============================================================
console.log('\nInvariant 2 — no pull-out on track switch');
// We're currently tracking SYN001. Record camera height, then switch to
// SYN002 and watch the camera height across frames. A pull-out = the
// deselect flyTo to an ~80 km overview; it should be skipped on a switch.
const planeA = SYNTH.flights[0].icao;
const planeB = SYNTH.flights[1].icao;
// Ensure we are tracking A and have a settled (low) follow height first.
await evalPage((icao) => {
window.__godsEyeView.dataManager.layers.get('flights').module.trackById(icao);
}, planeA);
await sleep(1500);
const heightBefore = await evalPage(() => window.__godsEyeView.viewer.camera.positionCartographic.height);
// Switch to B and immediately start sampling camera height every frame.
const switchSamples = await page.evaluate(async (icao, frames) => {
const v = window.__godsEyeView.viewer;
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const heights = [];
const onTick = () => { heights.push(v.camera.positionCartographic.height); };
const remove = v.scene.postRender.addEventListener(onTick);
fl.trackById(icao); // the SWITCH — must NOT trigger the deselect pull-out flyTo
await new Promise((res) => {
let n = 0;
let settled = false;
const finish = () => {
if (settled) return;
settled = true;
clearTimeout(timer);
stop();
res();
};
const stop = v.scene.postRender.addEventListener(() => {
if (++n >= frames) {
finish();
return;
}
v.scene.requestRender();
});
const timer = setTimeout(finish, Math.max(15000, frames * 1500));
v.scene.requestRender();
});
remove();
return heights;
}, planeB, 45);
const maxHeight = Math.max(heightBefore, ...switchSamples);
// The follow camera for these planes sits a few km up (altitude*1.1+2500,
// clamped 3-30 km). The "pull-out" bug flew to ~80 km. Fail if the camera
// ever climbs past 50 km — comfortably above the legit follow band, well
// below the 80 km overview.
const PULLOUT_CEIL_M = 50000;
record('pull-out: camera stays in follow band on switch (no ~80 km spike)',
maxHeight < PULLOUT_CEIL_M,
`maxHeight=${(maxHeight / 1000).toFixed(1)} km (before=${(heightBefore / 1000).toFixed(1)} km, ceil ${PULLOUT_CEIL_M / 1000} km)`);
// Confirm the switch actually took effect (we are now tracking B).
const nowTrackingB = await evalPage((icao) => {
const ti = window.__godsEyeView.dataManager.layers.get('flights').module.getTrackedInfo();
return !!(ti && ti.icao24 === icao);
}, planeB);
record('pull-out: track switch actually landed on plane B', nowTrackingB,
nowTrackingB ? 'tracking B' : 'switch did not land');
// ============================================================
// INVARIANT 3: NO CROSS-LAYER ORPHAN
// track military, then commercial → military.getTrackedInfo()===null,
// and the reverse.
// ============================================================
console.log('\nInvariant 3 — no cross-layer orphan');
const milHex = SYNTH.military[0].hex;
const comIcao = SYNTH.flights[2].icao;
// (a) military first, then commercial → military must clear.
const cross1 = await evalPage(async (hex, icao) => {
const dm = window.__godsEyeView.dataManager;
const mil = dm.layers.get('military').module;
const fl = dm.layers.get('flights').module;
mil.trackById(hex);
await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
const milTrackedBefore = !!mil.getTrackedInfo();
fl.trackById(icao); // tracking commercial flips viewer.trackedEntity → military listener fires
await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
return {
milTrackedBefore,
milTrackedAfter: !!mil.getTrackedInfo(),
flTrackedAfter: !!fl.getTrackedInfo(),
};
}, milHex, comIcao);
record('orphan: military clears when commercial is tracked',
cross1.milTrackedBefore && cross1.milTrackedAfter === false && cross1.flTrackedAfter === true,
`mil before=${cross1.milTrackedBefore} mil after=${cross1.milTrackedAfter} fl after=${cross1.flTrackedAfter}`);
// (b) commercial first, then military → commercial must clear.
const cross2 = await evalPage(async (hex, icao) => {
const dm = window.__godsEyeView.dataManager;
const mil = dm.layers.get('military').module;
const fl = dm.layers.get('flights').module;
fl.trackById(icao);
await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
const flTrackedBefore = !!fl.getTrackedInfo();
mil.trackById(hex);
await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
return {
flTrackedBefore,
flTrackedAfter: !!fl.getTrackedInfo(),
milTrackedAfter: !!mil.getTrackedInfo(),
};
}, milHex, comIcao);
record('orphan: commercial clears when military is tracked',
cross2.flTrackedBefore && cross2.flTrackedAfter === false && cross2.milTrackedAfter === true,
`fl before=${cross2.flTrackedBefore} fl after=${cross2.flTrackedAfter} mil after=${cross2.milTrackedAfter}`);
// No console errors should have accumulated during the tracking exercises.
record('no console errors during tracking exercises', consoleErrors.length === 0,
consoleErrors.length ? `${consoleErrors.length}: ${consoleErrors.slice(0, 3).join(' | ')}` : 'clean');
// ============================================================
// REGRESSION H1 (pre-ship audit 2026-07-01): clicking the very plane
// you're tracking (3D on) must be a NO-OP — no deselect, no 80 km
// pull-out. The tracked standalone model previously carried NO pick id,
// so scene.pick read the click as empty space → the deselect flyTo.
// ============================================================
console.log('\nRegression H1 — click on the tracked plane is a no-op');
const h1Icao = SYNTH.flights[0].icao;
await evalPage((icao) => {
window.__godsEyeView.dataManager.layers.get('flights').module.trackById(icao);
}, h1Icao);
await sleep(1500); // follow camera settles; tracked GLB load kicks off
// (i) The tracked standalone model must expose its pick id (= the icao).
const h1ModelUp = await page.waitForFunction((icao) => {
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const ti = fl.getTrackedInfo();
if (!ti || ti.icao24 !== icao) return false;
const found = window.__findTrackedModel ? window.__findTrackedModel() : null;
return !!(found && found.ready && found.show && String(found.id) === icao);
}, { timeout: 60000, polling: 250 }, h1Icao).then(() => true).catch(() => false);
if (h1ModelUp) {
const modelPickId = await evalPage(() => {
const m = window.__findTrackedModel();
return m && m.id !== undefined && m.id !== null ? String(m.id) : null;
});
record('H1: tracked standalone model exposes its pick id', modelPickId === h1Icao,
`model.id=${JSON.stringify(modelPickId)} (want "${h1Icao}")`);
} else if (!glbBackendCapable) {
skip('H1: tracked standalone model exposes its pick id',
`independent GLB control unavailable (${glbControlDetail})`);
} else {
record('H1: tracked standalone model exposes its pick id', false,
'independent GLB control rendered, but the product tracked model did not');
}
// (ii) Synthetic click at the tracked plane's screen position. Search a
// small grid around the projected display position for a point where
// scene.pick actually returns the tracked plane (its model's icao pick id
// or the tracked entity) so the click is deterministic — a miss would be
// a LEGIT empty-space deselect, not the H1 signature.
const h1ClickPoint = await evalPage(() => {
const v = window.__godsEyeView.viewer;
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const ti = fl.getTrackedInfo();
if (!ti) return null;
const ent = v.trackedEntity;
const disp = ent && typeof ent.gevDisplayPosition === 'function' ? ent.gevDisplayPosition() : null;
const pos = disp || ti.position;
if (!pos) return null;
const center = v.scene.cartesianToCanvasCoordinates(pos);
if (!center) return null;
const isTrackedPick = (picked) => {
if (!picked) return null;
if (picked.id === ent) return 'entity';
const raw = typeof picked.id === 'string' ? picked.id : (picked.primitive && picked.primitive.id);
return raw === ti.icao24 ? 'icao-pick' : null;
};
const offsets = [[0, 0]];
for (const r of [3, 6, 10, 16, 24]) {
for (const [dx, dy] of [[r, 0], [-r, 0], [0, r], [0, -r], [r, r], [-r, -r], [r, -r], [-r, r]]) {
offsets.push([dx, dy]);
}
}
for (const [dx, dy] of offsets) {
const pt = { x: center.x + dx, y: center.y + dy };
let picked = null;
try { picked = v.scene.pick(pt); } catch { picked = null; }
const via = isTrackedPick(picked);
if (via) return { x: pt.x, y: pt.y, via };
}
return { x: center.x, y: center.y, via: null };
});
if (!h1ClickPoint || !h1ClickPoint.via) {
skip('H1: click on tracked plane keeps tracking (no deselect)',
'scene.pick could not resolve the tracked plane at its screen position (GL backend picking)');
skip('H1: click on tracked plane does not pull the camera out',
'scene.pick could not resolve the tracked plane at its screen position (GL backend picking)');
} else {
const h1HeightBefore = await evalPage(() => window.__godsEyeView.viewer.camera.positionCartographic.height);
// Trusted mouse click through the browser event pipeline → the layer's
// ScreenSpaceEventHandler LEFT_CLICK path (the exact H1 code path).
await page.mouse.click(h1ClickPoint.x, h1ClickPoint.y);
const h1Heights = await page.evaluate(async (frames) => {
const v = window.__godsEyeView.viewer;
const heights = [];
await new Promise((res) => {
let n = 0;
let settled = false;
const finish = () => {
if (settled) return;
settled = true;
clearTimeout(timer);
stop();
res();
};
const stop = v.scene.postRender.addEventListener(() => {
heights.push(v.camera.positionCartographic.height);
if (++n >= frames) {
finish();
return;
}
v.scene.requestRender();
});
const timer = setTimeout(finish, Math.max(15000, frames * 1500));
v.scene.requestRender();
});
return heights;
}, 45);
const h1StillTracking = await evalPage((icao) => {
const ti = window.__godsEyeView.dataManager.layers.get('flights').module.getTrackedInfo();
return !!(ti && ti.icao24 === icao) && !!window.__godsEyeView.viewer.trackedEntity;
}, h1Icao);
record('H1: click on tracked plane keeps tracking (no deselect)', h1StillTracking,
`picked via ${h1ClickPoint.via}; still tracking=${h1StillTracking}`);
const h1MaxHeight = Math.max(h1HeightBefore, ...h1Heights);
record('H1: click on tracked plane does not pull the camera out', h1MaxHeight < PULLOUT_CEIL_M,
`maxHeight=${(h1MaxHeight / 1000).toFixed(1)} km (before=${(h1HeightBefore / 1000).toFixed(1)} km, ceil ${PULLOUT_CEIL_M / 1000} km)`);
}
// ============================================================
// REGRESSION M3 (rewritten 2026-07-02 — deliberate behavior change):
// when the TRACKED plane ages out (3 missed polls), tracking must clear
// and the camera must be RELEASED IN PLACE — viewer.trackedEntity
// undefined and NO jump (the old contract flew an ~80 km overview; the
// owner field-ruled that wrong: "it randomly zooms way up and loses my
// context"). The M3 ordering fix stays: tracking is cleared BEFORE the
// removal loop deletes the plane's state, so we never sit mid-follow
// with stale tracking state.
// ============================================================
console.log('\nRegression M3 — tracked plane age-out releases the camera in place');
const m3Icao = SYNTH.flights[0].icao;
await evalPage((icao) => {
window.__godsEyeView.dataManager.layers.get('flights').module.trackById(icao);
}, m3Icao);
await sleep(1200); // settle in the low follow band
const m3 = await evalPage(async (icao) => {
const v = window.__godsEyeView.viewer;
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const beforeTracking = !!fl.getTrackedInfo();
// Simulate the age-out via the shim: the plane stops arriving.
window.__SYNTH.flights = window.__SYNTH.flights.filter((f) => f.icao !== icao);
// MISSING_POLL_LIMIT = 3 consecutive absent polls → removal + clear.
// Capture the camera pose right BEFORE the removing poll — the follow
// camera drifts with the coasting plane until the instant of release,
// so this is the "where the user was looking" reference.
await fl.update(v);
await fl.update(v);
const c0 = v.camera.positionCartographic;
const atAgeOut = {
lonDeg: (c0.longitude * 180) / Math.PI,
latDeg: (c0.latitude * 180) / Math.PI,
height: c0.height,
};
await fl.update(v); // third miss → removal + clear + in-place release
return {
beforeTracking,
atAgeOut,
stillTrackedAfter: !!fl.getTrackedInfo(),
viewerStillTracking: !!v.trackedEntity,
};
}, m3Icao);
record('M3: tracking cleared after the tracked plane ages out (getTrackedInfo null)',
m3.beforeTracking && !m3.stillTrackedAfter,
`before=${m3.beforeTracking} trackedAfter=${m3.stillTrackedAfter}`);
record('M3: camera released after age-out (viewer.trackedEntity undefined)',
!m3.viewerStillTracking,
`viewerTracked=${m3.viewerStillTracking}`);
// The camera must NOT move after the release: no overview flyTo, no
// snap — it stays where the follow left it. Sample heights across frames
// (any transient flyTo would show up here), then read the settled pose.
const m3Heights = await page.evaluate(async (frames) => {
const v = window.__godsEyeView.viewer;
const heights = [];
await new Promise((res) => {
let n = 0;
let settled = false;
const finish = () => {
if (settled) return;
settled = true;
clearTimeout(timer);
stop();
res();
};
const stop = v.scene.postRender.addEventListener(() => {
heights.push(v.camera.positionCartographic.height);
if (++n >= frames) {
finish();
return;
}
v.scene.requestRender();
});
const timer = setTimeout(finish, Math.max(15000, frames * 1500));
v.scene.requestRender();
});
return heights;
}, 90);
await sleep(800); // any (regressed) 0.6 s flyTo would have finished by now
const m3Final = await evalPage(() => {
const c = window.__godsEyeView.viewer.camera.positionCartographic;
return {
lonDeg: (c.longitude * 180) / Math.PI,
latDeg: (c.latitude * 180) / Math.PI,
height: c.height,
};
});
// Tolerances: the release must hold the camera within ~2 km of where it
// was at age-out time (the follow band sits a few km up; the old overview
// flyTo climbed +80 km, orders of magnitude outside this budget).
const M3_STAY_TOL_M = 2000;
const m3AltDeltaM = Math.max(
Math.abs(m3Final.height - m3.atAgeOut.height),
...m3Heights.map((h) => Math.abs(h - m3.atAgeOut.height)),
);
const m3HorizDeltaM = haversineMeters(
m3.atAgeOut.latDeg, m3.atAgeOut.lonDeg, m3Final.latDeg, m3Final.lonDeg,
);
record('M3: camera stayed in place after age-out — altitude Δ < 2 km',
m3AltDeltaM < M3_STAY_TOL_M,
`Δalt=${(m3AltDeltaM / 1000).toFixed(2)} km (tol ${M3_STAY_TOL_M / 1000} km; ageOut=${(m3.atAgeOut.height / 1000).toFixed(1)} km, final=${(m3Final.height / 1000).toFixed(1)} km)`);
record('M3: camera stayed in place after age-out — horizontal Δ < 2 km',
m3HorizDeltaM < M3_STAY_TOL_M,
`Δhoriz=${(m3HorizDeltaM / 1000).toFixed(2)} km (tol ${M3_STAY_TOL_M / 1000} km)`);
// ============================================================
// CHANGE 2a (2026-07-02): landing-ghost fast cull. A plane whose last
// fix is LOW + SLOW (landed — the feed's ground flag lags the actual
// landing) is removed after ONE missed poll, not the 3-poll grace; a
// cruise plane that misses a poll keeps the full grace (it absorbs real
// feed gaps — owner-confirmed important). Both layers.
// ============================================================
console.log('\nChange 2a — landing-ghost fast cull (1 missed poll; cruise grace intact)');
const fastCull = await evalPage(async () => {
const v = window.__godsEyeView.viewer;
const dm = window.__godsEyeView.dataManager;
const fl = dm.layers.get('flights').module;
const mil = dm.layers.get('military').module;
const has = (mod, id) => mod.getAllPositions(2000).some((p) => p.id === id);
// Landed commercial plane: 120 m baro, 18 m/s (~35 kt) — under both
// fast-cull gates (LANDED_ALT_MAX_M=150 m, LANDED_SPEED_MAX_MPS=23).
window.__SYNTH.flights.push({ icao: 'aaa044', callsign: 'SYN044', lon: -97.7420, lat: 30.2660, alt: 120, vel: 18, track: 180 });
// Landed military plane: 300 ft (~91 m) baro, 20 kt (~10 m/s).
window.__SYNTH.military.push({ hex: 'bbb103', flight: 'MIL103', lon: -97.7480, lat: 30.2680, altFt: 300, track: 90, gsKt: 20, t: 'C130', r: 'AF-103' });
await fl.update(v);
await mil.update(v);
const ingested = { fl: has(fl, 'aaa044'), mil: has(mil, 'bbb103') };
// Both landed planes AND the cruise control (aaa002: 9500 m, 210 m/s)
// vanish from the feed in the SAME poll.
const cruise = window.__SYNTH.flights.find((f) => f.icao === 'aaa002');
window.__SYNTH.flights = window.__SYNTH.flights.filter((f) => f.icao !== 'aaa044' && f.icao !== 'aaa002');
window.__SYNTH.military = window.__SYNTH.military.filter((m) => m.hex !== 'bbb103');
await fl.update(v); // missed poll #1
await mil.update(v); // missed poll #1
const afterOneMiss = {
landedGone: !has(fl, 'aaa044'),
milLandedGone: !has(mil, 'bbb103'),
cruiseStillThere: has(fl, 'aaa002'),
};
// Put the cruise plane back so any later polls aren't disturbed.
if (cruise) window.__SYNTH.flights.push(cruise);
await fl.update(v);
return { ingested, afterOneMiss };
});
record('fast-cull: landed low+slow synthetics ingested (both layers)',
fastCull.ingested.fl && fastCull.ingested.mil,
`flights=${fastCull.ingested.fl} military=${fastCull.ingested.mil}`);
record('fast-cull: landed plane removed after ONE missed poll (flights)',
fastCull.afterOneMiss.landedGone,
`gone=${fastCull.afterOneMiss.landedGone} (grace skipped, was 3 polls)`);
record('fast-cull: landed plane removed after ONE missed poll (military)',
fastCull.afterOneMiss.milLandedGone,
`gone=${fastCull.afterOneMiss.milLandedGone} (grace skipped, was 3 polls)`);
record('fast-cull: cruise plane keeps the 3-poll grace (present after 1 miss)',
fastCull.afterOneMiss.cruiseStillThere,
`present=${fastCull.afterOneMiss.cruiseStillThere}`);
// ============================================================
// CHANGE 2b (2026-07-02): honest readout. While the TRACKED plane is in
// its missed-poll grace (rendered but absent from the latest poll), the
// tracked label/readout must carry the "· STALE" cue — and drop it the
// moment the plane reappears in the feed.
// ============================================================
console.log('\nChange 2b — tracked readout STALE cue during missed-poll grace');
const staleCheck = await evalPage(async () => {
const v = window.__godsEyeView.viewer;
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const labelText = () => {
const ent = v.trackedEntity;
if (!ent) return null;
// Post overlay-unification the tracked text lives in the host
// presentation model (entities are asserted native-label-free);
// the native read stays as a fallback so this probe still fails
// loudly if BOTH surfaces are ever absent.
const model = ent.gevLabelModel;
if (model) return [model.title, ...(model.details || [])].filter(Boolean).join('\n');
if (!ent.label || !ent.label.text) return null;
const t = ent.label.text;
return typeof t === 'string' ? t : (t.getValue ? String(t.getValue(v.clock.currentTime)) : null);
};
// Track a cruise plane that IS in the feed (aaa003: 8700 m, 250 m/s —
// normal grace, so one missed poll leaves it rendered-but-stale).
fl.trackById('aaa003');
await fl.update(v); // plane present → fresh label
const freshLabel = labelText();
const syn3 = window.__SYNTH.flights.find((f) => f.icao === 'aaa003');
window.__SYNTH.flights = window.__SYNTH.flights.filter((f) => f.icao !== 'aaa003');
await fl.update(v); // missed poll #1 → grace → label refreshed with cue
const staleLabel = labelText();
if (syn3) window.__SYNTH.flights.push(syn3);
await fl.update(v); // plane back → label rebuilt without the cue
const recoveredLabel = labelText();
fl.stopTracking(); // leave nothing tracked
return { freshLabel, staleLabel, recoveredLabel };
});
record('stale-readout: tracked label carries STALE cue during grace',
!!staleCheck.staleLabel && staleCheck.staleLabel.includes('STALE')
&& !!staleCheck.freshLabel && !staleCheck.freshLabel.includes('STALE'),
`fresh="${staleCheck.freshLabel && staleCheck.freshLabel.split('\n')[0]}" stale="${staleCheck.staleLabel && staleCheck.staleLabel.split('\n')[0]}"`);
record('stale-readout: STALE cue clears when the plane reappears',
!!staleCheck.recoveredLabel && !staleCheck.recoveredLabel.includes('STALE'),
`recovered="${staleCheck.recoveredLabel && staleCheck.recoveredLabel.split('\n')[0]}"`);
// ============================================================
// CHANGE 3 (2026-07-03): ground traffic is a FEATURE. Present-but-
// grounded planes render FULL-STRENGTH in the airborne tint pipeline
// (white / amber-military — owner verdict, same-day reversal of the
// day-1 gray 50%-alpha muted style: "just leave them as white … in NYC
// I can barely see them") at ×0.8 scale; "on the ground" reads from
// scale + no trail, never from a fade, so the 45%-alpha stale fade
// stays unambiguous. The on_ground flip restyles the SAME billboard in
// place (landing/takeoff transition, never a removal); a grounded plane
// that then VANISHES from the feed still fast-culls after ONE missed
// poll. Military mirror keys off adsb.lol's alt_baro === "ground".
// ============================================================
console.log('\nChange 3 — ground traffic: full-alpha style, in-place transitions, fast cull');
const ground = await evalPage(async () => {
const v = window.__godsEyeView.viewer;
const dm = window.__godsEyeView.dataManager;
const fl = dm.layers.get('flights').module;
const mil = dm.layers.get('military').module;
const findBB = (id) => {
let found = null;
const walk = (coll) => {
const n = coll.length;
for (let i = 0; i < n; i++) {
let p;
try { p = coll.get(i); } catch { continue; }
if (!p) continue;
if (typeof p.length === 'number' && typeof p.get === 'function') { walk(p); continue; }
if (p.image !== undefined && p.alignedAxis !== undefined && p.id === id) found = p;
}
};
walk(v.scene.primitives);
return found;
};
const snap = (id) => {
const bb = findBB(id);
if (!bb) return null;
const c = bb.color;
return {
show: bb.show, scale: bb.scale, alpha: c.alpha, red: c.red, green: c.green, blue: c.blue,
// Infinity doesn't survive puppeteer's JSON transport — encode it.
ddtd: bb.disableDepthTestDistance === Number.POSITIVE_INFINITY ? 'inf' : bb.disableDepthTestDistance,
};
};
// 1. On-ground planes ingest + render full-strength (both layers).
window.__SYNTH.flights.push({ icao: 'aaa066', callsign: 'GND066', lon: -97.7425, lat: 30.2665, alt: 150, vel: 7, track: 45, onGround: true });
window.__SYNTH.military.push({ hex: 'bbb166', flight: 'MILGND1', lon: -97.7490, lat: 30.2690, altFt: 'ground', track: 120, gsKt: 12, t: 'C130', r: 'AF-166' });
await fl.update(v);
await mil.update(v);
const groundSnap = snap('aaa066');
const milGroundSnap = snap('bbb166');
const detectable = fl.getDetectableObjects({ maxCount: 1000 }).some((d) => d.id === 'GND066');
// 2. Takeoff: the flag flips false — same billboard, airborne style.
const gnd = window.__SYNTH.flights.find((f) => f.icao === 'aaa066');
gnd.onGround = false; gnd.alt = 900; gnd.vel = 75;
await fl.update(v);
const airSnap = snap('aaa066');
// 3. Landing: the flag flips back true — ground scale again, still in place.
gnd.onGround = true; gnd.alt = 150; gnd.vel = 9;
await fl.update(v);
const groundAgainSnap = snap('aaa066');
// 4. Feed-dropped grounded planes (re-pinned round 7, owner field data
// "parked planes churn/never heal"): the fast cull now requires
// AIRBORNE history this session. aaa066 flew (step 2) then landed
// then dropped → the landing-ghost fast-cull still fires after ONE
// missed poll. bbb166 was BORN grounded (parked class) → it rides
// the normal MISSING_POLL_LIMIT grace and must SURVIVE the first
// missed poll, keeping its identity/floor state across feed flaps.
window.__SYNTH.flights = window.__SYNTH.flights.filter((f) => f.icao !== 'aaa066');
window.__SYNTH.military = window.__SYNTH.military.filter((m) => m.hex !== 'bbb166');
await fl.update(v);
await mil.update(v);
return {
groundSnap, milGroundSnap, detectable, airSnap, groundAgainSnap,
droppedGone: !snap('aaa066'),
milDroppedGone: !snap('bbb166'),
};
});
const fmtSnap = (s) => (s ? `show=${s.show} scale=${s.scale.toFixed(3)} rgba=(${s.red.toFixed(2)},${s.green.toFixed(2)},${s.blue.toFixed(2)},${s.alpha.toFixed(2)})` : 'missing');
// Ground style (owner verdict 2026-07-03): FULL-ALPHA airborne tint —
// white in the flights layer, amber (#FFB800) in the military layer —
// never the 45%-alpha stale fade, never the retired gray mute. The
// ground cue is the ×0.8 scale (klass default ⇒ base 1.0).
const isFullWhite = (s) => !!s && s.show && s.alpha === 1 && s.red === 1 && s.green === 1 && s.blue === 1;
const isFullAmber = (s) => !!s && s.show && s.alpha === 1 && s.red === 1 && s.blue === 0 && Math.abs(s.green - 0xB8 / 255) < 0.02;
record('ground: on-ground plane renders full-alpha white at ground scale + detectable (flights)',
isFullWhite(ground.groundSnap) && Math.abs(ground.groundSnap.scale - 0.8) < 1e-6 && ground.detectable,
`${fmtSnap(ground.groundSnap)} detectable=${ground.detectable}`);
record('ground: military mirror — alt_baro "ground" renders full-alpha amber',
isFullAmber(ground.milGroundSnap),
fmtSnap(ground.milGroundSnap));
record('ground: takeoff flip restyles in place (white, full alpha, full scale)',
isFullWhite(ground.airSnap) && Math.abs(ground.airSnap.scale - 1) < 1e-6,
fmtSnap(ground.airSnap));
record('ground: landing flip returns to ground scale in place (no removal, still full alpha)',
isFullWhite(ground.groundAgainSnap) && Math.abs(ground.groundAgainSnap.scale - 0.8) < 1e-6,
fmtSnap(ground.groundAgainSnap));
record('ground: landing ghost fast-culls after ONE missed poll; born-parked contact survives the flap (round 7)',
ground.droppedGone && !ground.milDroppedGone,
`flights(landed ghost) gone=${ground.droppedGone} military(born parked) gone=${ground.milDroppedGone} (want true/false)`);
// Fix 2 (2026-07-03 field test): ground planes VANISHED when zooming into
// airports — grounded altitudes sit at/below the photoreal tile skin, so the
// depth test buried the billboard up close (log-depth imprecision let it win
// from orbit). RE-PINNED for round 5 (owner directive 2026-07-06: "I just
// want the planes and their lines to ALWAYS be visible... evenly
// applied"): EVERY billboard — grounded, airborne, before and after a
// ground flip — renders with disableDepthTestDistance = +Infinity. The
// old grounded-only rule kept leaving classes of contacts buried (Austin
// QNH-below-field traffic not yet flagged on_ground). Far-side contacts
// are removed by the fleet tick's horizon occluder, which never depended
// on the depth test. A real-machine eyeball should confirm: zooming from
// orbit to street level, NO aircraft icon ever vanishes into the mesh.
record('ground: depth test disabled for EVERY contact (always visible), incl. across ground flips',
ground.groundSnap?.ddtd === 'inf' && ground.milGroundSnap?.ddtd === 'inf'
&& ground.airSnap?.ddtd === 'inf' && ground.groundAgainSnap?.ddtd === 'inf',
`flights=${ground.groundSnap?.ddtd} mil=${ground.milGroundSnap?.ddtd} takeoff=${ground.airSnap?.ddtd} landing=${ground.groundAgainSnap?.ddtd}`);
// ============================================================
// GROUND 3D (2026-07-03, owner decision LOCKED): "when I have 3D mode —
// proximity or all — I want that respected regardless of whether a plane
// is on the ground or in the air. No distinction."
// (a) a synthetic on_ground plane is model-ELIGIBLE (not skipped),
// (b) it gets a model under the existing cap (both layers),
// (c) the model matrix height = stubbed scene.sampleHeight + the layer's
// belly offset — the one-shot cached ground snap — NOT the buried/
// floating feed altitude (flights alt 150 m / military "ground" → 0 m),
// (d) the TRACKED grounded plane gets the standalone tracked model,
// (e) the snap is ONE-SHOT cached: sample count stays flat across frames.
// Height probe: |modelMatrix translation| |billboard position| — at one
// lat/lon a geodetic height change moves the point along the ellipsoid
// normal, whose angle to the radial at Austin's latitude costs < 0.001%.
//
// RETARGETED 2026-08-03 (weld). (c) still pins exactly what it always did —
// the MODEL rides the sampled skin while the BILLBOARD stays at the reported
// altitude — and that split is by design and unchanged. What changed is the
// CONSUMER anchor: detection brackets/labels and the tracked card used to
// follow the billboard, so on a grounded plane they sat ~100 m below the
// aircraft you can see and rose only as the coarse ground-floor cell warmed
// ("the buoy"), sometimes never converging. They now follow whatever owns the
// visual. So do NOT read the non-zero Δ below as "the anchor is the
// billboard" — it is the model-vs-billboard split, and the weld group that
// follows pins the anchor itself.
// ============================================================
console.log('\nGround 3D — grounded planes are model-eligible + snapped to the sampled skin');
const GROUND3D_STUB_H = 187.5; // stubbed tile-skin height (m, ellipsoid)
// Expected belly offsets (m): native origin-above-lowest-vertex × MODEL_SCALE
// × CLASS_SCALE_3D[klass] — constants match the layers' MODEL_BELLY_OFFSET_NATIVE
// / MODEL_SCALE pairs, which modelScale.test.mjs locks against the GLBs.
// Class is computed with the REAL classifier on the synthetic feed fields.
const g3dFlKlass = classifyAircraft({ typeCode: null, category: null });
const g3dMilKlass = classifyAircraft({ typeCode: 'C130', category: undefined });
const g3dFlOffset = 6.719 * 1 * (CLASS_SCALE_3D[g3dFlKlass] || 1); // airplane.glb, flights
// Hangar fleet (2026-08-16): military C130 → turboprop → the real atr72.glb,
// whose belly offset is the registry's measured bellyM (meters, scale 1) —
// NOT the jet.glb 5.631 × class formula. Pinned by modelScale.test.mjs.
const g3dMilOffset = CLASS_MODEL_REAL[g3dMilKlass]?.bellyM
?? 5.631 * 1 * (CLASS_SCALE_3D[g3dMilKlass] || 1); // jet.glb fallback classes
// Height-datum fix (Task 6): the flights-layer billboard for a grounded synthetic
// (no geo_altitude in this stub feed, no warm terrain-height cache in a headless
// run) now renders at baroM + geoidHeight(lat, lon) rather than the raw baro
// value verbatim — pickRenderAltitudeM's documented visual-fallback branch.
// Height-datum fix (Task 7): militaryFlights.js now runs the pickRenderAltitudeM
// chain too, but DELIBERATELY passes surfaceM=null for the on-ground billboard
// (brief item 3, "don't double-correct"): a grounded plane's MODEL already rides
// groundSnap.js's one-shot tileset sample, and its billboard is depth-test-free,
// so re-correcting the billboard to the ellipsoidal surface would (a) double-
// correct the same grounded plane and (b) — because military ground rows carry
// NO baro ("alt_baro":"ground") — jump the billboard 0 -> ~surface between polls,
// dragging the model's ground-snap input past groundSnap's 50 m move threshold
// and forcing a re-sample (breaks the ONE-SHOT invariant asserted below).
// So bbb177 (on-ground, no alt_geom in the stub feed, no numeric alt_baro,
// surfaceM forced null) makes pickRenderAltitudeM return its null sentinel and
// the military layer falls through to its SAME pre-Task-7 default (`altitudeM` —
// 0 m for an on-ground record with no sticky prior). Expected value unchanged
// (0 m), but now the documented Task-7 code path rather than "untouched by Task 7".
await ensureGeoidReady();
const g3dFlGeoidN = geoidHeight(30.2668, -97.7445); // aaa077's lat/lon (Austin)
let g3dSetup = null;
let g3dPrimaryFailure = null;
let g3dCleanupFailure = null;
try {
g3dSetup = await evalPage(() => {
const gev = window.__godsEyeView;
const scene = gev.viewer.scene;
const dm = gev.dataManager;
const flights = dm.layers.get('flights').module;
const military = dm.layers.get('military').module;
const priorModels3d = {
flights: flights.getParams().models3d,
military: military.getParams().models3d,
};
const priorSampleHeight = scene.sampleHeight;
// Keep the previous run-wide no-height seam in the page. Functions cannot
// cross the Puppeteer serialization boundary, so cleanup restores it from
// this private slot instead of deleting the scene's own property.
window.__g3dPriorSampleHeight = priorSampleHeight;
window.__g3dPriorTilesLoadedDescriptor = gev.tileset
? Object.getOwnPropertyDescriptor(gev.tileset, 'tilesLoaded')
: null;
try {
// 3D models on (QA param) — the owner decision under test.
flights.setParams({ models3d: true });
military.setParams({ models3d: true });
// Force the ground snap's tiles-ready gate open (b9b pattern): headless the
// Google tileset never finishes streaming, so tilesLoaded stays false.
let tilesForced = false;
try {
if (gev.tileset) {
Object.defineProperty(gev.tileset, 'tilesLoaded', { value: true, configurable: true });
tilesForced = gev.tileset.tilesLoaded === true;
} else {
tilesForced = true; // no tileset → groundSnap treats tiles as ready
}
} catch { tilesForced = false; }
// Deterministic sampleHeight stub + call counter (headless has no real skin).
window.__g3dSampleCalls = 0;
window.__g3dSampleHits = { flights: 0, military: 0 };
const fixturePoints = {
flights: { lat: 30.2668, lon: -97.7445 },
military: { lat: 30.2685, lon: -97.7470 },
};
scene.sampleHeight = function (cartographic) {
window.__g3dSampleCalls += 1;
// Attribute each sample to the fixture's distinct ~111 m mesh cell.
// This prevents one successfully sampled contact from satisfying the
// two-contact integrity assertion below.
const lat = Number(cartographic?.latitude) * 180 / Math.PI;
const lon = Number(cartographic?.longitude) * 180 / Math.PI;
if (Number.isFinite(lat) && Number.isFinite(lon)) {
for (const [layer, target] of Object.entries(fixturePoints)) {
const dLat = lat - target.lat;
const dLon = (lon - target.lon) * Math.cos(target.lat * Math.PI / 180);
// 0.0008° encloses the fixture's rounded 0.001° mesh-cell
// sample but cannot overlap the other fixture ~300 m away.
if (Math.hypot(dLat, dLon) <= 0.0008) {
window.__g3dSampleHits[layer] += 1;
}
}
}
return 187.5;
};
return { tilesForced, priorModels3d };
} catch (error) {
// Setup is transactional: once the first fixture mutation lands, every
// later setup failure restores each owned seam independently. Return
// both outcomes across the page boundary so rollback cannot hide or
// replace the primary setup error.
const rollbackFailures = [];
const attemptRollback = (label, operation) => {
try { operation(); } catch (rollbackError) {
rollbackFailures.push(`${label}: ${rollbackError?.message || rollbackError}`);
}
};
attemptRollback('restore sampleHeight seam', () => {
scene.sampleHeight = priorSampleHeight;
});
attemptRollback('restore tilesLoaded seam', () => {
if (!gev.tileset) return;
const prior = window.__g3dPriorTilesLoadedDescriptor;
if (prior) Object.defineProperty(gev.tileset, 'tilesLoaded', prior);
else delete gev.tileset.tilesLoaded;
});
attemptRollback('restore flights models3d', () => {
flights.setParams({ models3d: priorModels3d.flights });
});
attemptRollback('restore military models3d', () => {
military.setParams({ models3d: priorModels3d.military });
});
attemptRollback('delete fixture globals', () => {
delete window.__g3dPriorSampleHeight;
delete window.__g3dPriorTilesLoadedDescriptor;
delete window.__g3dSampleCalls;
delete window.__g3dSampleHits;
});
return {
setupFailure: error?.message || String(error),
rollbackFailures,
priorModels3d,
};
}
});
if (g3dSetup.setupFailure) {
g3dPrimaryFailure = new Error(`ground-3d setup failed: ${g3dSetup.setupFailure}`);
if (g3dSetup.rollbackFailures.length > 0) {
g3dCleanupFailure = new Error(
`ground-3d setup rollback failed: ${g3dSetup.rollbackFailures.join(' | ')}`,
);
}
// Setup rollback already attempted every owned seam. Prevent the
// post-setup cleanup from running against deleted fixture globals.
g3dSetup = null;
throw g3dPrimaryFailure;
}
record('ground-3d: sampleHeight stub installed + tiles-ready forced', g3dSetup.tilesForced,
JSON.stringify(g3dSetup));
// Ingest one grounded plane per layer, then park the camera 8 km above them
// (inside the model regime + add radius; on-screen so they win cap slots).
const g3dIngest = await evalPage(async () => {
const v = window.__godsEyeView.viewer;
const dm = window.__godsEyeView.dataManager;
const fl = dm.layers.get('flights').module;
const mil = dm.layers.get('military').module;
window.__SYNTH.flights.push({ icao: 'aaa077', callsign: 'GND077', lon: -97.7445, lat: 30.2668, alt: 150, vel: 0, track: 45, onGround: true });
window.__SYNTH.military.push({ hex: 'bbb177', flight: 'MILGND7', lon: -97.7470, lat: 30.2685, altFt: 'ground', track: 120, gsKt: 0, t: 'C130', r: 'AF-177' });
await fl.update(v);
await mil.update(v);
const findBB = (id) => {
let found = null;
const walk = (coll) => {
const n = coll.length;
for (let i = 0; i < n; i++) {
let p;
try { p = coll.get(i); } catch { continue; }
if (!p) continue;
if (typeof p.length === 'number' && typeof p.get === 'function') { walk(p); continue; }
if (p.image !== undefined && p.alignedAxis !== undefined && p.id === id) found = p;
}
};
walk(v.scene.primitives);
return found;
};
const flBB = findBB('aaa077');
const milBB = findBB('bbb177');
if (!flBB || !milBB) return { error: `ground billboards missing (fl=${!!flBB} mil=${!!milBB})` };
const radius = (pos) => Math.hypot(pos.x, pos.y, pos.z);
// Park the camera 8 km radially above the flights plane (both in view nadir-ish).
const p = flBB.position;
const r = Math.hypot(p.x, p.y, p.z);
const k = (r + 8000) / r;
v.camera.cancelFlight();
v.camera.setView({
destination: { x: p.x * k, y: p.y * k, z: p.z * k },
orientation: { heading: 0, pitch: -Math.PI / 2, roll: 0 },
});
return { flBBRadius: radius(flBB.position), milBBRadius: radius(milBB.position) };
});
if (g3dIngest.error) {
record('ground-3d: grounded synthetics ingested', false, g3dIngest.error);
} else {
record('ground-3d: grounded synthetics ingested', true,
`bb radii fl=${g3dIngest.flBBRadius.toFixed(1)} mil=${g3dIngest.milBBRadius.toFixed(1)}`);
// In-page model finder by pick id (fleet AND tracked standalone models carry it).
await evalPage(() => {
window.__g3dFindModel = function (id) {
const v = window.__godsEyeView.viewer;
let found = null;
const walk = (coll) => {
const n = coll.length;
for (let i = 0; i < n; i++) {
let p;
try { p = coll.get(i); } catch { continue; }
if (!p) continue;
if (typeof p.length === 'number' && typeof p.get === 'function') { walk(p); continue; }
if (p.modelMatrix && typeof p.ready !== 'undefined' && p.id === id) found = p;
}
};
walk(v.scene.primitives);
return found;
};
});
// (a)+(b): both grounded planes become models under the cap (the old code
// `continue`d past them in the eligibility pre-pass — no model would EVER
// appear). Wait for ready+shown so the handoff assert below is meaningful.
const g3dModelsUp = await page.waitForFunction(() => {
const fm = window.__g3dFindModel('aaa077');
const mm = window.__g3dFindModel('bbb177');
return !!(fm && fm.ready && fm.show && mm && mm.ready && mm.show);
}, { timeout: 40000, polling: 250 }).then(() => true).catch(() => false);
if (!glbBackendCapable && !g3dModelsUp) {
skip('ground-3d: grounded planes are model-eligible and modeled (both layers)',
`independent GLB control unavailable (${glbControlDetail}); grounded GLB readiness is not observable`);
} else {
record('ground-3d: grounded planes are model-eligible and modeled (both layers)', g3dModelsUp,
g3dModelsUp ? 'fleet models up (ready+shown)' : 'models never became ready+shown');
}
if (g3dModelsUp) {
// (c) + handoff + (e): heights snapped, billboards handed off, snap one-shot.
const g3dState = await evalPage(() => {
const v = window.__godsEyeView.viewer;
const findBB = (id) => {
let found = null;
const walk = (coll) => {
const n = coll.length;
for (let i = 0; i < n; i++) {
let p;
try { p = coll.get(i); } catch { continue; }
if (!p) continue;
if (typeof p.length === 'number' && typeof p.get === 'function') { walk(p); continue; }
if (p.image !== undefined && p.alignedAxis !== undefined && p.id === id) found = p;
}
};
walk(v.scene.primitives);
return found;
};
const modelRadius = (id) => {
const m = window.__g3dFindModel(id);
return m ? Math.hypot(m.modelMatrix[12], m.modelMatrix[13], m.modelMatrix[14]) : null;
};
return {
flModelRadius: modelRadius('aaa077'),
milModelRadius: modelRadius('bbb177'),
flBBShown: findBB('aaa077')?.show ?? null,
milBBShown: findBB('bbb177')?.show ?? null,
sampleCalls: window.__g3dSampleCalls,
sampleHits: { ...window.__g3dSampleHits },
};
});
// Expected radial delta = (stub + offset) billboard's rendered altitude.
// Flights billboard altitude is baroM + geoidN (height-datum fix, Task 6 —
// no geo_altitude/warm terrain-cache in this synthetic run, so the
// baro-fallback branch of pickRenderAltitudeM applies). Military (Task 7)
// runs pickRenderAltitudeM too but forces surfaceM=null for on-ground
// billboards (don't double-correct the grounded model's tileset snap — see
// the block above), and this synthetic has no alt_geom/alt_baro, so its
// billboard stays at the pre-Task-7 "ground" -> 0 m default.
const flWantDelta = (GROUND3D_STUB_H + g3dFlOffset) - (150 + g3dFlGeoidN);
const milWantDelta = (GROUND3D_STUB_H + g3dMilOffset) - 0; // "ground" (no alt_geom/alt_baro, surfaceM forced null) → 0 m default
const flDelta = g3dState.flModelRadius - g3dIngest.flBBRadius;
const milDelta = g3dState.milModelRadius - g3dIngest.milBBRadius;
const HEIGHT_TOL_M = 1.0;
record(`ground-3d: flights model height = sampled skin + belly offset (${g3dFlKlass})`,
Math.abs(flDelta - flWantDelta) <= HEIGHT_TOL_M,
`Δradial=${flDelta.toFixed(2)} m want=${flWantDelta.toFixed(2)} m (stub ${GROUND3D_STUB_H} + offset ${g3dFlOffset.toFixed(2)} alt ${(150 + g3dFlGeoidN).toFixed(2)} [150 baro + ${g3dFlGeoidN.toFixed(2)} geoidN])`);
record(`ground-3d: military model height = sampled skin + belly offset (${g3dMilKlass})`,
Math.abs(milDelta - milWantDelta) <= HEIGHT_TOL_M,
`Δradial=${milDelta.toFixed(2)} m want=${milWantDelta.toFixed(2)} m (stub ${GROUND3D_STUB_H} + offset ${g3dMilOffset.toFixed(2)} alt 0)`);
record('ground-3d: billboard→model handoff holds on the ground (icons hidden once models render)',
g3dState.flBBShown === false && g3dState.milBBShown === false,
`fl bb.show=${g3dState.flBBShown} mil bb.show=${g3dState.milBBShown}`);
const bothGroundContactsSampled = g3dState.sampleHits?.flights > 0
&& g3dState.sampleHits?.military > 0;
record('ground-3d: both grounded synthetic contacts reached the sampling seam',
bothGroundContactsSampled,
`sample hits near distinct fixture cells: flights=${g3dState.sampleHits?.flights ?? 0}, military=${g3dState.sampleHits?.military ?? 0}`);
// ============================================================
// WELD (2026-08-03): the detection anchor follows the RENDERED aircraft.
// With a model owning the visual, getDetectableObjects must return the
// model's actual rendered translation, not the billboard position — the
// two are ~100 m apart on a grounded plane. Sampled every frame for 20
// frames because the failure this replaces was TEMPORAL: the bracket used
// to converge slowly (or never) as the coarse floor cell warmed, so a
// single-frame probe could pass while the live behaviour still drifted.
// ============================================================
const WELD_TOL_M = 2.0;
// This guard proves the display and visual accessors have not collapsed
// into the same position. Do not reuse WELD_TOL_M here: the measured
// split includes wall-clock dead reckoning and can validly be only the
// 1.51 m airliner belly offset on a faster runtime.
const ACCESSOR_SEPARATION_EPSILON_M = 0.25;
const weld = await page.evaluate(async (frames) => {
const gev = window.__godsEyeView;
const v = gev.viewer;
const dm = gev.dataManager;
const targets = [
{ layer: 'flights', id: 'aaa077', center: [0, 0, 0] },
{ layer: 'military', id: 'bbb177', center: [0, 0, 0] },
];
const out = {};
for (const t of targets) out[t.layer] = { maxDelta: 0, samples: 0, missing: 0 };
await new Promise((res) => {
let n = 0;
let settled = false;
const finish = () => {
if (settled) return;
settled = true;
clearTimeout(timer);
stop();
res();
};
const stop = v.scene.postRender.addEventListener(() => {
for (const t of targets) {
const rec = out[t.layer];
const mod = dm.layers.get(t.layer)?.module;
const model = window.__g3dFindModel(t.id);
const objects = mod?.getDetectableObjects?.({
mode: 'DENSE', maxCount: 5000, seed: 0,
}) || [];
const object = objects.find((o) => o && o.sourceId === t.id);
if (!object || !object.position || !model || !model.show) {
rec.missing++;
continue;
}
const matrix = model.modelMatrix;
const scale = Number.isFinite(model.computedScale)
? model.computedScale
: (Number.isFinite(model.scale) ? model.scale : 1);
const x = t.center[0] * scale;
const y = t.center[1] * scale;
const z = t.center[2] * scale;
const visual = {
x: matrix[0] * x + matrix[4] * y + matrix[8] * z + matrix[12],
y: matrix[1] * x + matrix[5] * y + matrix[9] * z + matrix[13],
z: matrix[2] * x + matrix[6] * y + matrix[10] * z + matrix[14],
};
const d = Math.hypot(
object.position.x - visual.x,
object.position.y - visual.y,
object.position.z - visual.z,
);
if (d > rec.maxDelta) rec.maxDelta = d;
rec.samples++;
}
if (++n >= frames) {
finish();
return;
}
v.scene.requestRender();
});
const timer = setTimeout(finish, Math.max(15000, frames * 1500));
v.scene.requestRender();
});
return out;
}, 20);
for (const layer of ['flights', 'military']) {
const w = weld[layer] || { samples: 0, missing: -1, maxDelta: Infinity };
record(`weld: ${layer} grounded detection anchor === rendered model visual centre (20 frames)`,
w.samples >= 15 && w.missing === 0 && w.maxDelta <= WELD_TOL_M,
`samples=${w.samples} missing=${w.missing} maxΔ=${w.maxDelta.toFixed(3)} m (tol ${WELD_TOL_M} m)`);
}
// (e) one-shot: drive 60 verified render frames. Correct placement above
// proves the deterministic sample landed; the exact initial call total is
// NOT a contract. A successful ground snap publishes the validated height
// into the shared mesh-floor cell, so the later poll-time sampler may
// legitimately skip that cell. The load-bearing invariant is bounded
// growth across frames, with an explicit guard against a timed-out driver
// falsely looking flat.
const callsBefore = g3dState.sampleCalls;
const fleetSampleWindow = await sampleFrames(
page, 60, () => window.__g3dSampleCalls,
);
const callsAfter = await evalPage(() => window.__g3dSampleCalls);
const fleetFramesComplete = !fleetSampleWindow.timedOut
&& fleetSampleWindow.values.length === 60;
record('ground-3d: fleet sampling window completed all 60 requested frames',
fleetFramesComplete,
`frames=${fleetSampleWindow.values.length}/60 timedOut=${fleetSampleWindow.timedOut}`);
record('ground-3d: fleet ground sampling is one-shot/per-poll bounded (no per-frame sampling)',
fleetFramesComplete && bothGroundContactsSampled && (callsAfter - callsBefore) <= 8,
`sampleHeight calls: before=${callsBefore}, growth over 60 verified frames=${callsAfter - callsBefore} (per-frame would be ~60+)`);
// (d) TRACKED grounded plane → the standalone tracked model (the owner's
// "tracked SWA143 at 0 kts stayed a 2D cyan billboard" case).
// Start the counter BEFORE ownership changes. The previous guard began
// only after ready+shown and could miss a regression that sampled every
// render frame while the standalone model was loading.
const trackedTransitionCallsBefore = callsAfter;
await evalPage(() => {
window.__godsEyeView.dataManager.layers.get('flights').module.trackById('aaa077');
});
const trackedTransitionWindow = await sampleFrames(
page, 30, () => window.__g3dSampleCalls,
);
const trackedTransitionCallsAfter = await evalPage(() => window.__g3dSampleCalls);
const trackedTransitionFramesComplete = !trackedTransitionWindow.timedOut
&& trackedTransitionWindow.values.length === 30;
record('ground-3d: tracked loading/ownership sampling window completed all 30 requested frames',
trackedTransitionFramesComplete,
`frames=${trackedTransitionWindow.values.length}/30 timedOut=${trackedTransitionWindow.timedOut}`);
record('ground-3d: tracked loading/ownership ground sampling is bounded (no per-frame sampling)',
trackedTransitionFramesComplete
&& (trackedTransitionCallsAfter - trackedTransitionCallsBefore) <= 8,
`sampleHeight growth from before trackById across 30 verified frames=${trackedTransitionCallsAfter - trackedTransitionCallsBefore} (per-frame would be ~30+)`);
const g3dTrackedUp = await page.waitForFunction(() => {
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const ti = fl.getTrackedInfo();
if (!ti || ti.icao24 !== 'aaa077') return false;
const m = window.__g3dFindModel('aaa077');
return !!(m && m.ready && m.show);
}, { timeout: 25000, polling: 250 }).then(() => true).catch(() => false);
let trackedDetail = 'tracked model never became ready+shown';
let trackedHeightOk = false;
if (g3dTrackedUp) {
const trackedRadius = await evalPage(() => {
const m = window.__g3dFindModel('aaa077');
return m ? Math.hypot(m.modelMatrix[12], m.modelMatrix[13], m.modelMatrix[14]) : null;
});
const tDelta = trackedRadius - g3dIngest.flBBRadius;
trackedHeightOk = Math.abs(tDelta - flWantDelta) <= HEIGHT_TOL_M;
trackedDetail = `tracked model up; Δradial=${tDelta.toFixed(2)} m want=${flWantDelta.toFixed(2)} m`;
}
record('ground-3d: TRACKED grounded plane gets the standalone tracked model, ground-snapped',
g3dTrackedUp && trackedHeightOk, trackedDetail);
if (g3dTrackedUp) {
const trackedReadyCallsBefore = await evalPage(() => window.__g3dSampleCalls);
const trackedReadyWindow = await sampleFrames(
page, 30, () => window.__g3dSampleCalls,
);
const trackedReadyCallsAfter = await evalPage(() => window.__g3dSampleCalls);
const trackedReadyFramesComplete = !trackedReadyWindow.timedOut
&& trackedReadyWindow.values.length === 30;
record('ground-3d: tracked ready-state sampling window completed all 30 requested frames',
trackedReadyFramesComplete,
`frames=${trackedReadyWindow.values.length}/30 timedOut=${trackedReadyWindow.timedOut}`);
record('ground-3d: tracked ready-state ground sampling is bounded (no per-frame sampling)',
trackedReadyFramesComplete
&& (trackedReadyCallsAfter - trackedReadyCallsBefore) <= 8,
`sampleHeight growth over 30 verified ready-state frames=${trackedReadyCallsAfter - trackedReadyCallsBefore} (per-frame would be ~30+)`);
} else {
record('ground-3d: tracked ready-state sampling window completed all 30 requested frames',
false, 'tracked model never became ready+shown');
record('ground-3d: tracked ready-state ground sampling is bounded (no per-frame sampling)',
false, 'tracked model never became ready+shown');
}
// WELD (tracked): the tracked CARD anchors to the model you can see.
// `gevVisualPosition` is a SEPARATE accessor from `gevDisplayPosition` on
// purpose — the latter carries the follow-camera anti-jitter contract and
// must keep returning the cached dead-reckoned value the camera settled
// on. So this asserts both halves: the visual accessor is welded to the
// rendered model, AND the display accessor still reports the (different)
// dead-reckoned position rather than having been quietly repurposed.
if (g3dTrackedUp) {
const trackedWeld = await evalPage(() => {
const ent = window.__godsEyeView.viewer.trackedEntity;
const m = window.__g3dFindModel('aaa077');
if (!m) return { error: 'no tracked model' };
const matrix = m.modelMatrix;
const scale = Number.isFinite(m.computedScale)
? m.computedScale
: (Number.isFinite(m.scale) ? m.scale : 1);
// airplane.glb is now bounding-box centred with transforms applied.
const x = 0 * scale;
const y = 0 * scale;
const z = 0 * scale;
const anchor = {
x: matrix[0] * x + matrix[4] * y + matrix[8] * z + matrix[12],
y: matrix[1] * x + matrix[5] * y + matrix[9] * z + matrix[13],
z: matrix[2] * x + matrix[6] * y + matrix[10] * z + matrix[14],
};
const at = (p) => (p ? Math.hypot(
p.x - anchor.x, p.y - anchor.y, p.z - anchor.z,
) : null);
const visual = typeof ent?.gevVisualPosition === 'function' ? ent.gevVisualPosition() : null;
const display = typeof ent?.gevDisplayPosition === 'function' ? ent.gevDisplayPosition() : null;
return {
hasVisualAccessor: typeof ent?.gevVisualPosition === 'function',
visualDelta: at(visual),
displayDelta: at(display),
};
});
const visualOk = trackedWeld.hasVisualAccessor
&& Number.isFinite(trackedWeld.visualDelta)
&& trackedWeld.visualDelta <= WELD_TOL_M;
record('weld: TRACKED card anchor === rendered tracked model visual centre',
visualOk,
trackedWeld.error
|| `visualΔ=${Number(trackedWeld.visualDelta).toFixed(3)} m (tol ${WELD_TOL_M} m), accessor=${trackedWeld.hasVisualAccessor}`);
// Separation guard: if displayDelta ever collapses to visualDelta, the
// anti-jitter accessor has been repurposed and the follow camera is at
// risk. Skipped (not failed) when the DR cache is momentarily invalid.
const displayDelta = trackedWeld.displayDelta;
record('weld: gevDisplayPosition still reports the dead-reckoned position (anti-jitter intact)',
!Number.isFinite(displayDelta) || displayDelta > ACCESSOR_SEPARATION_EPSILON_M,
Number.isFinite(displayDelta)
? `displayΔ=${displayDelta.toFixed(3)} m (must stay > ${ACCESSOR_SEPARATION_EPSILON_M} m — the ground-snap split)`
: 'display accessor returned null this frame (DR cache invalid) — separation not evaluated');
}
}
}
} catch (error) {
// Contain the scenario so a primary fixture failure survives cleanup and
// later groups plus the run-wide report still execute.
g3dPrimaryFailure = error;
} finally {
// This group temporarily owns the sampling seam, model toggle, synthetics,
// tracking state, and page globals. Release every one on error/timeout as
// well as on the happy path so later height-datum scenarios cannot inherit
// a deterministic skin or a tracked model from this fixture.
if (g3dSetup) {
try {
const cleanupFailures = await evalPage(async (priorModels3d) => {
const gev = window.__godsEyeView;
const v = gev.viewer;
const dm = gev.dataManager;
const fl = dm.layers.get('flights').module;
const mil = dm.layers.get('military').module;
const failures = [];
const attempt = async (label, operation) => {
try { await operation(); } catch (error) {
failures.push(`${label}: ${error?.message || error}`);
}
};
await attempt('stop tracking', () => fl.stopTracking());
await attempt('remove flights synthetic', () => {
window.__SYNTH.flights = window.__SYNTH.flights.filter((f) => f.icao !== 'aaa077');
});
await attempt('remove military synthetic', () => {
window.__SYNTH.military = window.__SYNTH.military.filter((m) => m.hex !== 'bbb177');
});
await attempt('refresh flights', () => fl.update(v));
await attempt('refresh military', () => mil.update(v));
await attempt('restore sampleHeight seam', () => {
v.scene.sampleHeight = window.__g3dPriorSampleHeight;
});
await attempt('restore tilesLoaded seam', () => {
if (!gev.tileset) return;
const prior = window.__g3dPriorTilesLoadedDescriptor;
if (prior) Object.defineProperty(gev.tileset, 'tilesLoaded', prior);
else delete gev.tileset.tilesLoaded;
});
await attempt('restore flights models3d', () => {
fl.setParams({ models3d: priorModels3d.flights });
});
await attempt('restore military models3d', () => {
mil.setParams({ models3d: priorModels3d.military });
});
await attempt('delete fixture globals', () => {
delete window.__g3dPriorSampleHeight;
delete window.__g3dPriorTilesLoadedDescriptor;
delete window.__g3dFindModel;
delete window.__g3dSampleCalls;
delete window.__g3dSampleHits;
});
return failures;
}, g3dSetup.priorModels3d);
if (cleanupFailures.length > 0) {
g3dCleanupFailure = new Error(`ground-3d cleanup failed: ${cleanupFailures.join(' | ')}`);
}
} catch (error) {
// A page-evaluation failure is itself cleanup evidence, but it must
// not replace the primary error or abort the remaining harness.
g3dCleanupFailure = error;
}
}
}
record('ground-3d: scenario completed without an unhandled fixture error',
g3dPrimaryFailure === null,
g3dPrimaryFailure
? `primary failure: ${g3dPrimaryFailure?.message || g3dPrimaryFailure}`
: 'primary path completed');
record('ground-3d: fixture cleanup completed without errors',
g3dCleanupFailure === null,
g3dCleanupFailure
? `cleanup failure: ${g3dCleanupFailure?.message || g3dCleanupFailure}`
: (g3dSetup ? 'all owned fixture state released' : 'post-setup cleanup not required'));
// ============================================================
// CHANGE 4 (2026-07-03): arrival rotation freshness. Field test: "planes
// look weird when you first come to them — rotations are weird". Two
// repaired holes, both layers:
// (a) SETTLE PASS — camera.moveEnd forces a full rotation pass on the
// next frame (the pose-signature gate can eat a fly-to's settle:
// the final easing frames land inside one 10 m/0.06° quantization
// bucket, leaving mid-flight noses for up to ROTATION_REFRESH_MS).
// (b) REVEAL PASS — a billboard flipping INTO view while the camera
// idles gets its rotation refreshed the same tick (it used to
// reappear wearing its stale/creation-north nose for up to 1 s).
// Staged deterministically: park the camera nadir over the synthetic
// cluster, let rotations settle, TAMPER a billboard's rotation, then
// trigger each path with the camera idle. The idle-drift catch-up
// (ROTATION_REFRESH_MS = 1 s) can coincidentally mask a regression in a
// ~300 ms SwiftShader frame window, so a regression shows as an
// intermittent (not guaranteed) failure — never a false failure.
// ============================================================
console.log('\nChange 4 — arrival rotation: moveEnd settle pass + horizon-reveal pass');
const arrival = await evalPage(async () => {
const v = window.__godsEyeView.viewer;
const dm = window.__godsEyeView.dataManager;
const { screenProjectedRotation } = await import('/src/data/iconOrientation.js');
// 3D models OFF for this phase: a model-handed-off billboard is hidden
// and skips rotation updates entirely — the probes need live billboards
// (this is also the app's default state the field report came from).
dm.layers.get('flights').module.setParams({ models3d: false });
dm.layers.get('military').module.setParams({ models3d: false });
const findBB = (id) => {
let found = null;
const walk = (coll) => {
const n = coll.length;
for (let i = 0; i < n; i++) {
let p;
try { p = coll.get(i); } catch { continue; }
if (!p) continue;
if (typeof p.length === 'number' && typeof p.get === 'function') { walk(p); continue; }
if (p.image !== undefined && p.alignedAxis !== undefined && p.id === id) found = p;
}
};
walk(v.scene.primitives);
return found;
};
const nextFrames = (n) => new Promise((res) => {
let count = 0;
let settled = false;
const finish = () => {
if (settled) return;
settled = true;
clearTimeout(timer);
rm();
res();
};
const rm = v.scene.postRender.addEventListener(() => {
if (++count >= n) {
finish();
return;
}
v.scene.requestRender();
});
const timer = setTimeout(finish, Math.max(10000, n * 1500));
v.scene.requestRender();
});
// Park the camera straight above the flights cluster (lift a live
// billboard's position radially — no Cesium global needed in-page) so
// every probe plane projects on-screen, then let rotations settle at
// the new pose (the setView pose change forces a pass on the next tick).
// aaa002 — aaa001 was evicted for good by the M3 age-out phase.
const anchor = findBB('aaa002');
if (!anchor) return { error: 'anchor aaa002 missing' };
const p = anchor.position;
const r = Math.hypot(p.x, p.y, p.z);
const k = (r + 25000) / r;
v.camera.cancelFlight();
v.camera.setView({
destination: { x: p.x * k, y: p.y * k, z: p.z * k },
orientation: { heading: 0, pitch: -Math.PI / 2, roll: 0 },
});
await nextFrames(3);
const angDiff = (a, b) => Math.abs(Math.atan2(Math.sin(a - b), Math.cos(a - b)));
const probe = async (id, course) => {
const bb = findBB(id);
if (!bb || !bb.show) return { error: `${id} missing/hidden` };
const r0 = bb.rotation; // settled tamper origin; correctness uses a fresh projection below
// (a) settle pass: tamper, then raise moveEnd with the camera IDLE —
// the pose signature is unchanged, so only the moveEnd hook can fix
// this before the 1 s catch-up.
bb.rotation = r0 + 1.5;
v.camera.moveEnd.raiseEvent();
await nextFrames(2);
const afterMoveEnd = bb.rotation;
// A real-GPU fleet tick can land near the edge of the frame budget and
// advance the contact before the probe reads it. Compare with the
// production projection at the CURRENT position, not the now-stale r0.
const expectedMoveEnd = screenProjectedRotation(v.scene, bb.position, course, null);
// (b) reveal pass: tamper + hide — the next fleet tick must flip it
// visible AND correct the nose in that same tick (camera still idle,
// no moveEnd raised). Diagnostic fields (round 5): record WHICH frame
// the flip landed on (flipFrame; -1 = never within the extended
// window) and whether a 3D model owns this id — distinguishes "tick
// slow under load" from "occluder says hidden" from "model handoff".
bb.rotation = r0 + 1.5;
bb.show = false;
let flipFrame = -1;
for (let f = 1; f <= 6; f++) {
await nextFrames(1);
if (bb.show && flipFrame === -1) flipFrame = f;
if (f >= 2 && flipFrame !== -1) break;
}
const expectedReveal = screenProjectedRotation(v.scene, bb.position, course, null);
const hasModel = !!(window.__g3dFindModel && window.__g3dFindModel(id));
return {
r0,
dMoveEnd: angDiff(afterMoveEnd, expectedMoveEnd),
dReveal: angDiff(bb.rotation, expectedReveal),
shown: bb.show, flipFrame, hasModel,
};
};
const flightCourse = window.__SYNTH.flights.find((f) => f.icao === 'aaa002')?.track ?? 0;
const militaryCourse = window.__SYNTH.military.find((m) => m.hex === 'bbb101')?.track ?? 0;
return {
flights: await probe('aaa002', flightCourse),
military: await probe('bbb101', militaryCourse),
};
});
const fmtArr = (a) => (!a ? `no result (${arrival?.error || 'phase error'})` : a.error ? a.error
: `settle-err=${(a.dMoveEnd * 180 / Math.PI).toFixed(1)}° reveal-err=${(a.dReveal * 180 / Math.PI).toFixed(1)}° shown=${a.shown} flipFrame=${a.flipFrame} hasModel=${a.hasModel}`);
const TAMPER_DEG = 1.5 * 180 / Math.PI; // ≈ 86° — an uncorrected nose stays this far off
// Reveal budget re-pinned 2 → 4 frames (round 5): the diagnostic probe
// shows the military flip consistently lands on frame 2 — the exact edge
// of the old budget — so any load hiccup flaked it (flights lands frame
// 1). The regression this protects against is a reveal that waits for
// the 1 s idle catch-up (~30-60 frames) or never re-aims; 4 frames still
// catches that with a wide margin, with zero-headroom flakes gone.
const arrOk = (a) => !!a && !a.error && a.shown
&& (a.flipFrame === -1 ? false : a.flipFrame <= 4)
&& a.dMoveEnd * 180 / Math.PI < 10 && a.dReveal * 180 / Math.PI < 10;
record(`arrival: moveEnd + reveal both re-aim within 4 frames, flights (tamper was ${TAMPER_DEG.toFixed(0)}°)`,
arrOk(arrival.flights), fmtArr(arrival.flights));
record(`arrival: moveEnd + reveal both re-aim within 4 frames, military (tamper was ${TAMPER_DEG.toFixed(0)}°)`,
arrOk(arrival.military), fmtArr(arrival.military));
// ============================================================
// DISPLAY FLOOR (2026-08-19): a grounded contact must never render below
// the floor of the cell it is DISPLAYED over.
//
// `renderAltitudeM` is picked once per poll from the floor of the FIX's
// coarse cell, but what renders is the dead-reckoned position — which
// drifts across cells for the whole 30 s segment and, while a ground
// contact coasts on a stale feed, for hundreds of metres more. On a graded
// apron (KAUS spans ~119140 m ellipsoidal) the sprite ends up under the
// mesh it taxied over; qa-floor-verify measured 15.5 m and reported
// VERDICT: FAIL on main.
//
// Staged so ONLY the display path can produce the lift: the contact's own
// fix cell is left COLD and the seeded floor is planted on the cells the
// display has drifted onto. A poll-path fix would read the fix cell and
// find nothing there, so a pass here cannot come from anywhere else.
// ============================================================
console.log('\nDisplay floor — grounded contacts never render below the cell they drifted onto');
const DISPLAY_FLOOR_LIFT_M = 1.5; // GROUND_FLOOR_LIFT_M
const DF_LAT = 30.2600, DF_LON = -97.7500;
const DF_SEED_M = 400; // identity-probe floor for the fix cell
const dfSetup = await evalPage(async () => {
const Cesium = await import('/node_modules/cesium/Build/Cesium/index.js');
const gev = window.__godsEyeView;
const v = gev.viewer;
const fl = gev.dataManager.layers.get('flights').module;
// Hermetic: the ground-3d group's cleanup restored the REAL sampleHeight,
// which would let the mesh sampler latch whatever headless GL streams.
//
// `__dfSkinM` is the switch, and it is load-bearing rather than tidy. A
// permanently-missing stub means groundSnap can never resolve, and a
// grounded MODEL cannot be placed without a ground height — so every
// grounded-model assertion in this group becomes unreachable and reports
// as a skip about GLB backends instead of as the contract it is. null is
// the group default (the honest "no tiles here" the earlier scenarios
// need, and the COLD case in its own right); a number opens a
// DETERMINISTIC skin for the scenarios that need a model to draw.
window.__dfSkinM = null;
window.__dfSkinSamples = [];
window.__dfPriorTilesLoadedDescriptor = gev.tileset
? Object.getOwnPropertyDescriptor(gev.tileset, 'tilesLoaded')
: null;
if (gev.tileset) {
Object.defineProperty(gev.tileset, 'tilesLoaded', { value: true, configurable: true });
}
v.scene.sampleHeight = (cartographic) => {
if (window.__dfSkinM == null) return undefined;
const lat = Cesium.Math.toDegrees(Number(cartographic?.latitude));
const lon = Cesium.Math.toDegrees(Number(cartographic?.longitude));
if (Number.isFinite(lat) && Number.isFinite(lon)) {
window.__dfSkinSamples.push({ lat, lon, h: window.__dfSkinM });
if (window.__dfSkinSamples.length > 512) window.__dfSkinSamples.shift();
}
return window.__dfSkinM;
};
fl.setParams({ models3d: false }); // billboards own the visual (T7 gate open)
window.__dfFindBB = (id) => {
let found = null;
const walk = (coll) => {
const n = coll.length;
for (let i = 0; i < n; i++) {
let p; try { p = coll.get(i); } catch { continue; }
if (!p) continue;
if (typeof p.length === 'number' && typeof p.get === 'function') { walk(p); continue; }
if (p.image !== undefined && p.alignedAxis !== undefined && p.id === id) found = p;
}
};
walk(v.scene.primitives);
return found;
};
window.__dfCarto = (pos) => {
const c = Cesium.Cartographic.fromCartesian(pos, Cesium.Ellipsoid.WGS84);
return { lat: Cesium.Math.toDegrees(c.latitude), lon: Cesium.Math.toDegrees(c.longitude), h: c.height };
};
// The fleet pass is rate-limited, so counting raw frames under-waits.
window.__dfSettle = (ms) => new Promise((res) => {
let done = false;
const tick = () => { if (done) return; v.scene.requestRender(); setTimeout(tick, 30); };
tick();
setTimeout(() => { done = true; res(); }, ms);
});
// Cesium Models in the scene, split by visibility (duck-typed the same
// way the harness excludes them from height probes).
//
// Pass an `icao` to count ONLY that contact's model. Both the fleet loader
// and the standalone tracked loader stamp `model.id` with the icao (the
// pick identity click-to-track depends on), and the fleet pass never
// models the tracked contact — so an id match for the tracked icao is
// unambiguously ITS model. Counting every model in the scene instead let
// an unrelated fleet, military, or control model satisfy "the model owns
// the visual" while the contact under test never rendered at all.
// `rendering` is the pair the production handoff consults (`ready &&
// show`): a model registered with Cesium's default `show === true` the
// instant its glTF resolves is NOT yet the visual.
window.__dfCountModels = (icao) => {
let shown = 0;
let hidden = 0;
let rendering = 0;
const walk = (coll) => {
const n = coll.length;
for (let i = 0; i < n; i++) {
let p; try { p = coll.get(i); } catch { continue; }
if (!p) continue;
if (typeof p.length === 'number' && typeof p.get === 'function') { walk(p); continue; }
if (p.activeAnimations !== undefined && p.minimumPixelSize !== undefined) {
if (icao !== undefined && p.id !== icao) continue;
if (p.show) {
shown += 1;
if (p.ready === true) rendering += 1;
} else hidden += 1;
}
}
};
walk(v.scene.primitives);
return { shown, hidden, rendering };
};
// Ellipsoid height of the point a contact's MODEL is actually drawn at.
// The counters above answer "is a model the visual"; this answers "and is
// it standing on the ground", which is the half a rendering count cannot
// see — a model placed at the raw feed altitude renders exactly as
// enthusiastically as one placed on the tile skin, ~240 m underground.
window.__dfModelHeight = (icao) => {
let h = null;
const walk = (coll) => {
const n = coll.length;
for (let i = 0; i < n; i++) {
let p; try { p = coll.get(i); } catch { continue; }
if (!p) continue;
if (typeof p.length === 'number' && typeof p.get === 'function') { walk(p); continue; }
if (p.activeAnimations !== undefined && p.minimumPixelSize !== undefined
&& p.id === icao && p.modelMatrix) {
const m = p.modelMatrix;
// Cesium's default is the IDENTITY matrix — translation (0,0,0),
// the Earth's centre, which `Cartographic.fromCartesian` refuses.
// An admitted-but-never-placed model reads as "no height", which
// is the truth about it.
if (m[12] || m[13] || m[14]) {
const c = Cesium.Cartographic.fromCartesian(
new Cesium.Cartesian3(m[12], m[13], m[14]), Cesium.Ellipsoid.WGS84,
);
h = c ? c.height : null;
}
}
}
};
walk(v.scene.primitives);
return h;
};
// Tracked-contact model regime (2026-08-20). The tracked contact's model
// is NOT governed by the DISPLAY-rail 3D toggle — that toggle owns the
// FLEET's draw-call budget. The tracked model is default-on and driven by
// camera distance, entering below TRACKED_MODEL_ENTER_ALT_M and handing
// back to the billboard only above TRACKED_MODEL_EXIT_ALT_M (the
// anti-flap band). The CAMERA is therefore what decides whether a model
// or a billboard is the visual for a tracked contact, which is exactly
// what the display floor stands aside for — so these pins drive the
// camera explicitly instead of the toggle.
//
// Read the thresholds from the app's own policy module so a later retune
// of the swap distance moves these pins with it rather than stranding
// them on stale numbers.
const reg = await import('/src/data/trackedModelRegime.js');
window.__dfRegime = {
enter: reg.TRACKED_MODEL_ENTER_ALT_M,
exit: reg.TRACKED_MODEL_EXIT_ALT_M,
};
// Zooming while following is safe: the tracked-camera framer positions
// the camera ONCE per selection and is deliberately read-only on normal
// frames (EntityView is the sole continuous writer, and the only
// correction is a minimum-range clamp that guards zooming IN, not out),
// so a programmatic zoom persists instead of being fought every frame.
window.__dfCamH = () => v.camera.positionCartographic.height;
// Both walkers bail on a STALLED step as well as on reaching the target:
// the controller enforces a minimum range when following, so a zoom-in
// that has bottomed out would otherwise spin the full iteration budget.
window.__dfZoomAbove = async (targetH) => {
let last = window.__dfCamH();
for (let i = 0; i < 80 && window.__dfCamH() <= targetH; i++) {
v.camera.zoomOut(Math.max(15000, (targetH - window.__dfCamH()) * 0.9));
await window.__dfSettle(100);
const now = window.__dfCamH();
if (i > 0 && Math.abs(now - last) < 1) break;
last = now;
}
return window.__dfCamH();
};
window.__dfZoomBelow = async (targetH) => {
let last = window.__dfCamH();
for (let i = 0; i < 80 && window.__dfCamH() >= targetH; i++) {
v.camera.zoomIn(Math.max(250, (window.__dfCamH() - targetH) * 0.5));
await window.__dfSettle(100);
const now = window.__dfCamH();
if (i > 0 && Math.abs(now - last) < 1) break;
last = now;
}
return window.__dfCamH();
};
// Wait for THIS contact's tracked model to actually RENDER (loaded AND
// shown) — ownership means drawing, not existing, and it means the model
// that carries this icao's pick id, not whichever model happened to be up.
window.__dfAwaitTrackedModel = async (icao, ms) => {
const deadline = Date.now() + ms;
while (Date.now() < deadline && window.__dfCountModels(icao).rendering === 0) {
await window.__dfSettle(500);
}
return window.__dfCountModels(icao);
};
// Vite serves an edited source file as `…/groundFloor.js?t=<hmr stamp>`;
// importing the PLAIN path then hands back a second, unrelated module
// instance whose cells the app never reads. Offer the URL the app itself
// loaded first, then the plain path (clean, never-hot-reloaded server).
const seen = performance.getEntriesByType('resource')
.map((e) => e.name)
.filter((n) => /\/src\/data\/groundFloor\.js(\?|$)/.test(n));
window.__dfCandidates = [...new Set([...seen.reverse(), '/src/data/groundFloor.js'])];
return { candidates: window.__dfCandidates.length };
});
record('display-floor: groundFloor module URL candidates found', dfSetup.candidates > 0,
JSON.stringify(dfSetup));
// Identity probe. Seed a contact's FIX cell BEFORE its first fix arrives,
// then poll: the grounded surfaceM chain reads cachedGroundFloor, so the
// sprite renders at the seeded floor if and only if the app shares this
// module instance. (It must be the FIRST fix — the display runs `now 30 s`,
// which for a new contact extrapolates history[0].) This exercises the POLL
// path only; the clamp under test reads the DISPLAY cell, which stays cold
// here, so a broken fix cannot fake a pass.
const dfIdentity = await evalPage(async (lat, lon, seedM) => {
const v = window.__godsEyeView.viewer;
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const tried = [];
for (let i = 0; i < window.__dfCandidates.length; i++) {
const url = window.__dfCandidates[i];
let gf;
try { gf = await import(/* @vite-ignore */ url); } catch { tried.push({ url, h: null }); continue; }
if (typeof gf.reportMeshFloorCell !== 'function') { tried.push({ url, h: null }); continue; }
gf.setMeshFloorPreferred(true);
gf._clearMeshFloorCellsForTest();
gf.reportMeshFloorCell(lat, lon, seedM);
// A fresh icao per attempt: a contact that already exists keeps the
// history[0] the warm-up dead-reckon renders, so it could never show a
// floor seeded afterwards.
const icao = `aaa09${i}`;
window.__SYNTH.flights.push({ icao, callsign: `TAXI9${i}`, lon, lat, alt: 150, vel: 12, track: 90, onGround: true });
await fl.update(v);
await window.__dfSettle(400);
const bb = window.__dfFindBB(icao);
const h = bb ? window.__dfCarto(bb.position).h : null;
tried.push({ url, h });
gf._clearMeshFloorCellsForTest();
if (Number.isFinite(h) && Math.abs(h - seedM) < 5) {
window.__dfGf = gf; window.__dfIcao = icao;
return { picked: { url, h }, tried };
}
window.__SYNTH.flights = window.__SYNTH.flights.filter((f) => f.icao !== icao);
}
return { picked: null, tried };
}, DF_LAT, DF_LON, DF_SEED_M);
const identityOk = !!dfIdentity.picked;
record('display-floor: harness reached the app\'s own groundFloor module instance',
identityOk,
identityOk
? `a ${DF_SEED_M} m fix-cell seed put the sprite at ${Number(dfIdentity.picked.h).toFixed(1)} m (${dfIdentity.picked.url})`
: `no candidate module was the app's: ${JSON.stringify(dfIdentity.tried)}`);
if (!identityOk) {
skip('display-floor: drift clamp (harness could not seed the shared floor cache)',
'the identity probe above failed — assertions would be meaningless');
} else {
const dfDrift = await evalPage(async (lat, lon) => {
const v = window.__godsEyeView.viewer;
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const gf = window.__dfGf;
const icao = window.__dfIcao;
const cell = (x) => Number(x.toFixed(3));
// Fix cell COLD from here on. The contact keeps the seeded render
// altitude in its history, and its DISPLAYED position sits one render
// delay of taxi behind the fix — several cells away.
gf._clearMeshFloorCellsForTest();
// Airborne control at the same coordinates, ingested while every cell
// is cold so its own fix-time clamp finds nothing: it drifts over the
// same cells and must NOT be lifted.
const airIcao = 'aaa095';
window.__SYNTH.flights.push({ icao: airIcao, callsign: 'AIR95', lon, lat, alt: 150, vel: 12, track: 90 });
await new Promise((r) => setTimeout(r, 1200)); // fix epochs are second-resolution
await fl.update(v);
await window.__dfSettle(400);
const bb = window.__dfFindBB(icao);
if (!bb) return { error: `${icao} billboard missing` };
const d0 = window.__dfCarto(bb.position);
const driftedCells = cell(d0.lat) !== cell(lat) || cell(d0.lon) !== cell(lon);
const driftM = Math.hypot((d0.lat - lat) * 111320,
(d0.lon - lon) * 111320 * Math.cos(lat * Math.PI / 180));
// Plant a floor 30 m above where the sprite is DISPLAYED, across the
// 3×3 cell block it can move within during the assertion window.
const seeded = d0.h + 30;
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
gf.reportMeshFloorCell(cell(d0.lat) + dy * 0.001, cell(d0.lon) + dx * 0.001, seeded);
}
}
// The fleet clamp runs on its throttled render pass. Under a loaded QA
// machine a fixed 1.2 s sleep can sample just before that pass, so wait
// for the observable clamp with a hard deadline instead of weakening
// the assertion or assuming one scheduler cadence.
const clampDeadline = Date.now() + 5000;
let bb2 = null;
let d1 = null;
do {
await window.__dfSettle(250);
bb2 = window.__dfFindBB(icao);
d1 = bb2 ? window.__dfCarto(bb2.position) : null;
} while (Date.now() < clampDeadline && (!d1 || d1.h < seeded + 1));
const air = window.__dfFindBB(airIcao);
const a1 = air ? window.__dfCarto(air.position) : null;
return {
driftedCells, driftM, seeded,
beforeH: d0.h,
afterH: d1 ? d1.h : null,
floorUnderSprite: d1 ? gf.cachedGroundFloor(d1.lat, d1.lon) : null,
fixCellMesh: gf.cachedMeshFloor(lat, lon),
fixCellFloor: gf.cachedGroundFloor(lat, lon),
airborneH: a1 ? a1.h : null,
airborneFound: !!air,
};
}, DF_LAT, DF_LON);
record('display-floor: the displayed position really has drifted off the fix cell',
dfDrift.driftedCells === true,
dfDrift.error || `displayed ${Number(dfDrift.driftM).toFixed(0)} m from the fix (render delay × taxi speed)`);
const clampOk = Number.isFinite(dfDrift.afterH) && Number.isFinite(dfDrift.floorUnderSprite)
&& dfDrift.afterH >= dfDrift.floorUnderSprite + DISPLAY_FLOOR_LIFT_M - 0.5;
record('display-floor: a grounded sprite never renders below the cell it drifted onto',
clampOk,
dfDrift.error || `${Number(dfDrift.beforeH).toFixed(1)} m → ${Number(dfDrift.afterH).toFixed(1)} m against a ${Number(dfDrift.floorUnderSprite).toFixed(1)} m floor (needs >= floor + ${DISPLAY_FLOOR_LIFT_M} m)`);
// Discriminator: the poll path had nothing to read, so the lift can only
// have come from the display path.
const fixCellCold = dfDrift.fixCellMesh == null
&& (dfDrift.fixCellFloor == null || dfDrift.fixCellFloor < dfDrift.seeded - 10);
record('display-floor: the lift came from the display path (fix cell still cold)',
fixCellCold,
`fix cell mesh=${dfDrift.fixCellMesh} floor=${dfDrift.fixCellFloor} vs seeded ${Number(dfDrift.seeded).toFixed(1)} m`);
// Grounded-only: an AIRBORNE contact drifting over the same seeded cells
// keeps its reported altitude — the fix-time clamp owns airborne heights.
record('display-floor: an AIRBORNE contact over the same cells is not lifted',
dfDrift.airborneFound === true && Number.isFinite(dfDrift.airborneH)
&& dfDrift.airborneH < dfDrift.seeded - 10,
`airborne renders at ${Number(dfDrift.airborneH).toFixed(1)} m (seeded floor ${Number(dfDrift.seeded).toFixed(1)} m)`);
// ---- Corridor wiring, WITHOUT pre-seeding ----------------------------
// The scenario above plants the floor by hand, so it still passes if the
// corridor collection is deleted, aimed at the wrong end, or starved.
// This one seeds NOTHING: the contact's DISPLAY cell can only get a floor
// if the poll actually collects the ground it is rendering over and warms
// it through the real DEM resolve. A control cell the same distance away,
// which no corridor covers, must stay cold.
const dfCorridor = await evalPage(async (lat, lon) => {
const v = window.__godsEyeView.viewer;
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const gf = window.__dfGf;
const cell = (x) => Number(x.toFixed(3));
gf._clearMeshFloorCellsForTest(); // DEM only — sampleHeight is stubbed off
const key = (c) => `${c.lat},${c.lon}`;
// Control: the same distance from the fix, perpendicular to the track,
// so it is equally "near the airport" but on no contact's path.
const controlCell = { lat: cell(lat + 0.02), lon: cell(lon) };
// ~250 m PAST the fix along the track (090). The display sits behind the
// fix and is extrapolating toward it, so this ground is only reachable
// if the corridor follows the direction of travel instead of stopping
// at the fix — the coasting-away defect, observable without waiting for
// a real coast.
const aheadCell = {
lat: cell(lat),
lon: cell(lon + 250 / (111320 * Math.cos(lat * Math.PI / 180))),
};
// Snapshot the whole neighbourhood BEFORE this contact exists. The
// display cell's identity is only knowable after a second fix has aged
// the display head off the fix — and by then the corridor has already
// run and (correctly) warmed it, so a read at that point can never show
// it cold. `_clearMeshFloorCellsForTest()` does not help: the DEM half
// of `cachedGroundFloor` lives in terrainHeights' own cache. So the
// cold state is captured up front and looked up afterwards. A display
// cell outside this grid reports `out-of-snapshot`, which fails the
// assertion rather than passing it quietly.
const coldBefore = new Map();
for (let dy = -3; dy <= 3; dy++) {
for (let dx = -8; dx <= 8; dx++) {
const c = { lat: cell(lat + dy * 0.001), lon: cell(lon + dx * 0.001) };
coldBefore.set(key(c), gf.cachedGroundFloor(c.lat, c.lon));
}
}
const startCold = {
control: gf.cachedGroundFloor(controlCell.lat, controlCell.lon),
};
// Baro 0 puts it at the geoid (~-27 m here), ~150 m under the real
// Austin surface, so any lift is unambiguous.
window.__SYNTH.flights.push({ icao: 'aaa097', callsign: 'COAST97', lon, lat, alt: 0, vel: 12, track: 90, onGround: true });
await fl.update(v);
await window.__dfSettle(600);
// AGE A SECOND FIX before sampling. With a single fix the display has
// no path to run and renders AT the fix, which would make the whole
// scenario vacuous — ordinary fix-cell warming could then satisfy the
// display-cell assertion below. The second fix (epochs are
// second-resolution) gives the `now 30 s` display head a segment to
// extrapolate back along, putting it ~360 m of taxi behind the fix.
await new Promise((r) => setTimeout(r, 1200));
await fl.update(v);
await window.__dfSettle(600);
const bb0 = window.__dfFindBB('aaa097');
if (!bb0) return { error: 'aaa097 billboard missing' };
const d0 = window.__dfCarto(bb0.position);
const displayCell = { lat: cell(d0.lat), lon: cell(d0.lon) };
const fixCell = { lat: cell(lat), lon: cell(lon) };
startCold.display = coldBefore.has(key(displayCell))
? coldBefore.get(key(displayCell))
: 'out-of-snapshot';
// Give the fire-and-forget DEM resolve time to land, then let a couple
// more polls run the corridor again.
for (let i = 0; i < 3; i++) {
await new Promise((r) => setTimeout(r, 1400));
await fl.update(v);
await window.__dfSettle(600);
}
const bb1 = window.__dfFindBB('aaa097');
const d1 = bb1 ? window.__dfCarto(bb1.position) : null;
return {
startCold,
displayCell,
fixCell,
sameCellAsFix: displayCell.lat === fixCell.lat && displayCell.lon === fixCell.lon,
displayFloor: gf.cachedGroundFloor(displayCell.lat, displayCell.lon),
controlFloor: gf.cachedGroundFloor(controlCell.lat, controlCell.lon),
aheadCell,
aheadFloor: gf.cachedGroundFloor(aheadCell.lat, aheadCell.lon),
spriteH: d1 ? d1.h : null,
spriteFloor: d1 ? gf.cachedGroundFloor(d1.lat, d1.lon) : null,
beforeH: d0.h,
};
}, 30.3000, -97.8000);
// The whole scenario is only meaningful if the cell being warmed is one
// the ordinary fix-cell batch could NOT have produced. Two conditions
// make that true, and both are asserted here rather than assumed: the
// display head really left the fix cell (the second fix aged it there),
// and that cell was COLD when the measurement started.
record('display-floor/corridor: the display cell is not the fix cell, and started cold',
dfCorridor.sameCellAsFix === false && dfCorridor.startCold?.display == null,
dfCorridor.error
|| `display ${JSON.stringify(dfCorridor.displayCell)} vs fix ${JSON.stringify(dfCorridor.fixCell)}, started at ${dfCorridor.startCold?.display} — the fix-cell collection cannot reach the display cell`);
record('display-floor/corridor: polling warms the ground the contact is DISPLAYED over',
Number.isFinite(dfCorridor.displayFloor),
dfCorridor.error
|| `display-cell floor = ${dfCorridor.displayFloor} (nothing was pre-seeded — only corridor collection can produce this)`);
// The beyond-fix probe carries its own arithmetic precondition: a cell
// that collapsed onto the fix cell would be warmed by the fix batch and
// prove nothing about the direction of travel.
const distinctAheadCell = dfCorridor.aheadCell?.lat !== dfCorridor.fixCell?.lat
|| dfCorridor.aheadCell?.lon !== dfCorridor.fixCell?.lon;
record('display-floor/corridor: the corridor reaches PAST the fix, along the direction of travel',
distinctAheadCell && Number.isFinite(dfCorridor.aheadFloor),
dfCorridor.error
|| `cell ~250 m beyond the fix (${JSON.stringify(dfCorridor.aheadCell)}, distinct from fix ${JSON.stringify(dfCorridor.fixCell)}: ${distinctAheadCell}) floor = ${dfCorridor.aheadFloor} — a fix-aimed corridor never offers it`);
record('display-floor/corridor: an off-path control cell stays cold (not ambient warming)',
dfCorridor.controlFloor == null,
`control cell floor = ${dfCorridor.controlFloor}`);
record('display-floor/corridor: the sprite rides the corridor-warmed floor',
Number.isFinite(dfCorridor.spriteH) && Number.isFinite(dfCorridor.spriteFloor)
&& dfCorridor.spriteH >= dfCorridor.spriteFloor + DISPLAY_FLOOR_LIFT_M - 0.5,
dfCorridor.error
|| `${Number(dfCorridor.beforeH).toFixed(1)} m → ${Number(dfCorridor.spriteH).toFixed(1)} m on a ${Number(dfCorridor.spriteFloor).toFixed(1)} m floor`);
// ---- Tracked contact gets the same floor ----------------------------
// The fleet pass skips the tracked icao and the tracked entity draws from
// _trackedDisplayPosition, so selecting a correctly floored grounded
// billboard used to swap it for an unfloored cyan target under the mesh.
const dfTracked = await evalPage(async () => {
const v = window.__godsEyeView.viewer;
const Cesium = await import('/node_modules/cesium/Build/Cesium/index.js');
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const gf = window.__dfGf;
const cell = (x) => Number(x.toFixed(3));
const bbBefore = window.__dfFindBB('aaa097');
if (!bbBefore) return { error: 'aaa097 billboard missing' };
const d0 = window.__dfCarto(bbBefore.position);
// Plant a floor well ABOVE where it currently renders, across the block
// it can move within, so an UNFLOORED tracked entity is unmistakable.
const seeded = d0.h + 40;
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
gf.reportMeshFloorCell(cell(d0.lat) + dy * 0.001, cell(d0.lon) + dx * 0.001, seeded);
}
}
const fleetClampDeadline = Date.now() + 5000;
let bbLifted = null;
let fleetH = null;
do {
await window.__dfSettle(250);
bbLifted = window.__dfFindBB('aaa097');
fleetH = bbLifted ? window.__dfCarto(bbLifted.position).h : null;
} while (Date.now() < fleetClampDeadline
&& (!Number.isFinite(fleetH) || fleetH < seeded + 1));
if (!fl.trackById('aaa097')) return { error: 'trackById(aaa097) failed' };
await window.__dfSettle(1500);
// Read the tracked entity's rendered height plus the floor under it and
// the sensor value the data APIs report, at whatever regime the camera
// is currently in.
const readTracked = () => {
const pos = v.trackedEntity?.position?.getValue(Cesium.JulianDate.now());
if (!pos) return null;
const c = window.__dfCarto(pos);
const info = fl.getTrackedInfo();
const subject = fl.getTrackedSubject();
return {
h: c.h,
floor: gf.cachedGroundFloor(c.lat, c.lon),
reportedAltM: info?.altitudeM,
subjectH: subject?.position ? window.__dfCarto(subject.position).h : null,
camH: window.__dfCamH(),
// THIS contact's model, not any model in the scene: the ownership
// side of the assertion has to be about aaa097 or it proves nothing
// about who drew aaa097.
models: window.__dfCountModels('aaa097'),
};
};
// --- Regime IN, COLD ground: the model is WITHHELD ------------------
// trackById re-frames the camera to the close follow range, so the
// tracked model regime is already active. `__dfSkinM` is still null, so
// groundSnap has never resolved for this contact: there is no evidence
// of where the ground is, and a depth-tested glTF placed at the feed
// altitude (baro 0 → ~-27 m at Austin) renders ~240 m INSIDE the mesh.
// The only honest answer is not to draw it — which also means the
// billboard is still the visual and must still be FLOORED.
await window.__dfSettle(2500);
const coldModels = window.__dfCountModels('aaa097');
// `shown` as well as `rendering`: a model parked at scale 0 with
// show=true would satisfy "nothing renders" while still being a shown
// primitive claiming the visual, which is the shape this rejects.
const coldTracked = readTracked();
const coldModelH = window.__dfModelHeight('aaa097');
// --- Regime IN, WARM ground: the model takes over, ON the floor ------
// Open a deterministic tile skin AT the planted floor. groundSnap
// resolves, the model is placed on it (plus the class belly offset) and
// takes the visual; the display clamp must then STAND ASIDE (T7),
// leaving the ENTITY at its raw dead-reckon while the MODEL carries the
// ground truth. Both halves are asserted — a rendering count alone
// cannot tell a model standing on the apron from one buried under it.
//
// The open skin is HANDED to the retained-model scenario below, which
// closes it once its own model is up. Every other way out of this block
// — an early error return, a throw — has to close it here instead: a
// skin left open lets a live sample latch into the floor cells the
// planted seeds below are about to own, and the damage would then
// surface as a failure in an unrelated scenario.
window.__dfSkinM = seeded;
let handOffSkin = false;
try {
const modelsIn = await window.__dfAwaitTrackedModel('aaa097', 20000);
const warmModelH = window.__dfModelHeight('aaa097');
// Scene-wide count, used only to tell two very different states apart:
// NO model rendered at all (this browser has no usable GLB backend — a
// legitimate skip) versus models rendered but none of them carried
// aaa097's pick id (a real defect, and the case the old scene-wide
// probe reported as a pass).
const anyModelsIn = window.__dfCountModels();
await window.__dfSettle(600);
const zoomedIn = readTracked();
if (!zoomedIn) return { error: 'tracked entity has no position (zoomed in)' };
// --- Regime OUT: camera above the exit ceiling ----------------------
// Climb past the anti-flap band and the model hands the visual back to
// the billboard — which MUST be floored, or a tracked grounded contact
// renders buried at any distance the operator pulls out to. This is the
// coverage the toggle used to reach; the zoom regime reaches it now.
const achievedOut = await window.__dfZoomAbove(window.__dfRegime.exit + 5000);
await window.__dfSettle(1500);
const zoomedOut = readTracked();
if (!zoomedOut) return { error: 'tracked entity has no position (zoomed out)' };
const out = {
rawH: d0.h,
seeded,
fleetH,
enter: window.__dfRegime.enter,
exit: window.__dfRegime.exit,
modelsRenderingIn: modelsIn.rendering,
anyModelsRenderingIn: anyModelsIn.rendering,
achievedOut,
coldModelsRendering: coldModels.rendering,
coldModelsShown: coldModels.shown,
coldModelH,
coldEntityH: coldTracked ? coldTracked.h : null,
coldFloor: coldTracked ? coldTracked.floor : null,
warmModelH,
zoomedIn,
zoomedOut,
};
fl.stopTracking();
await window.__dfSettle(400);
handOffSkin = true;
return out;
} finally {
if (!handOffSkin) window.__dfSkinM = null;
}
});
record('display-floor: the fleet billboard lifts onto the planted floor (control for the tracked check)',
!dfTracked.error && Number.isFinite(dfTracked.fleetH)
&& dfTracked.fleetH >= dfTracked.seeded + DISPLAY_FLOOR_LIFT_M - 0.5,
dfTracked.error
|| `billboard ${Number(dfTracked.rawH).toFixed(1)} m → ${Number(dfTracked.fleetH).toFixed(1)} m (floor ${Number(dfTracked.seeded).toFixed(1)} m)`);
// The tracked contact is floored exactly when the BILLBOARD is what the
// operator sees, and stands aside exactly when the MODEL is. "Exactly
// when" needs BOTH halves, so both are asserted: floored on the way out,
// NOT floored on the way in. Since the tracked model became zoom-driven
// (2026-08-20), the camera is what picks between the two, so this pin
// drives both sides of the hysteresis band in one scenario.
//
// The negative half is what a height read alone cannot establish —
// groundSnap can land at the same number as the clamp — so it is paired
// with an OWNERSHIP probe rather than inferred from height. The probe is
// aaa097's OWN model (exact pick id) in the `ready && show` state
// `_modelOwnsVisual` consults: rendering while zoomed in, not rendering
// while zoomed out. That distinguishes the two sources by WHO DREW IT,
// which is the actual contract:
// - IN: aaa097's model renders ⇒ `_floorGroundedDisplayPosition` returns
// early, so the tracked ENTITY sits at its raw dead-reckon (baro 0,
// ~150 m under the planted floor) while groundSnap positions the model.
// - OUT: no model of aaa097 renders ⇒ the billboard is the visual and
// MUST be lifted, or a tracked grounded contact renders buried at
// whatever distance the operator has pulled out to.
const dfIn = dfTracked.zoomedIn || {};
const dfOut = dfTracked.zoomedOut || {};
const dfOutFloored = Number.isFinite(dfOut.h) && Number.isFinite(dfOut.floor)
&& dfOut.h >= dfOut.floor + DISPLAY_FLOOR_LIFT_M - 0.5;
const dfInStandsAside = Number.isFinite(dfIn.h) && Number.isFinite(dfIn.floor)
&& dfIn.h < dfIn.floor + DISPLAY_FLOOR_LIFT_M - 0.5;
const dfInModelOwns = dfIn.models?.rendering > 0;
const dfOutBillboardOwns = dfOut.models?.rendering === 0;
const dfRegimeName = 'display-floor/regime: the TRACKED grounded contact is floored exactly when the billboard is the visual';
// COLD ground, camera IN: the gate. A grounded model with no resolved
// ground is not drawn at all, and the billboard it did not replace is
// still floored. Before this pin the same run reported "1 aaa097 model(s)
// rendering, entity left at -26.8 m under a 215.1 m floor" as a PASS —
// the model was rendering 242 m under the apron and nothing said so.
const dfColdFloored = Number.isFinite(dfTracked.coldEntityH)
&& Number.isFinite(dfTracked.coldFloor)
&& dfTracked.coldEntityH >= dfTracked.coldFloor + DISPLAY_FLOOR_LIFT_M - 0.5;
record('display-floor/gate: with NO resolved ground the grounded model is withheld and the billboard is floored',
!dfTracked.error && dfTracked.coldModelsRendering === 0
&& dfTracked.coldModelsShown === 0 && dfColdFloored,
dfTracked.error
|| `cold skin: ${dfTracked.coldModelsRendering} aaa097 model(s) rendering / ${dfTracked.coldModelsShown} shown (placed height ${dfTracked.coldModelH == null ? 'none — never placed' : Number(dfTracked.coldModelH).toFixed(1) + ' m'}), billboard at ${Number(dfTracked.coldEntityH).toFixed(1)} m on a ${Number(dfTracked.coldFloor).toFixed(1)} m floor`);
// WARM ground, camera IN: the placement. The model is not merely visible,
// it is standing ON the floor — within one class belly offset above it,
// never under it. MAX_BELLY_M clears the largest offset any class adds
// (widebody b789, 7.81 m in CLASS_MODEL_REAL); the floor itself is the
// hard lower bound, and a model placed at the raw feed altitude is ~240 m
// under it.
const MAX_BELLY_M = 12;
const dfWarmOnFloor = Number.isFinite(dfTracked.warmModelH)
&& dfTracked.warmModelH >= dfTracked.seeded
&& dfTracked.warmModelH <= dfTracked.seeded + MAX_BELLY_M;
record('display-floor/placement: a resolved grounded model stands ON the floor, not under it and not hidden',
!dfTracked.error && dfTracked.modelsRenderingIn > 0 && dfWarmOnFloor,
dfTracked.error
|| `warm skin: ${dfTracked.modelsRenderingIn} aaa097 model(s) rendering at ${Number(dfTracked.warmModelH).toFixed(1)} m on a ${Number(dfTracked.seeded).toFixed(1)} m floor (belly headroom ${MAX_BELLY_M} m; raw feed altitude was ${Number(dfTracked.rawH).toFixed(1)} m)`);
// Skip only when NO model rendered anywhere — that is a browser without a
// usable GLB backend. Models rendering while none of them is aaa097's is
// a defect, and falls through to the record below so it reports RED.
if (!dfTracked.error && !dfTracked.modelsRenderingIn && !dfTracked.anyModelsRenderingIn) {
skip(dfRegimeName,
'no tracked model rendered in this browser — the zoomed-in half has no model to own the visual');
} else {
record(dfRegimeName,
!dfTracked.error
&& dfInModelOwns && dfInStandsAside
&& dfOutBillboardOwns && dfOutFloored
&& Number.isFinite(dfIn.camH) && dfIn.camH < dfTracked.enter
&& Number.isFinite(dfOut.camH) && dfOut.camH > dfTracked.exit,
dfTracked.error
|| `IN @ ${(dfIn.camH / 1000).toFixed(0)} km (< ${(dfTracked.enter / 1000).toFixed(0)} km enter): ${dfIn.models?.rendering} aaa097 model(s) rendering, entity left at ${Number(dfIn.h).toFixed(1)} m under a ${Number(dfIn.floor).toFixed(1)} m floor (groundSnap owns it); `
+ `OUT @ ${(dfOut.camH / 1000).toFixed(0)} km (> ${(dfTracked.exit / 1000).toFixed(1)} km exit): ${dfOut.models?.rendering} aaa097 model(s) rendering, billboard owns it again, ${Number(dfIn.h).toFixed(1)} m → ${Number(dfOut.h).toFixed(1)} m on a ${Number(dfOut.floor).toFixed(1)} m floor`);
}
// The visual/data split is INTENTIONAL: pixels are floored, measurements
// are not. Pinned so a later "floor everything" pass has to argue with it.
// Asserted in BOTH regimes — who owns the visual must never change what a
// query, the cockpit altimeter, or a proximity count reports.
record('display-floor/regime: data APIs report sensor truth in BOTH regimes, floored or not',
!dfTracked.error
&& Number.isFinite(dfIn.reportedAltM) && Math.abs(dfIn.reportedAltM) < 1
&& Number.isFinite(dfOut.reportedAltM) && Math.abs(dfOut.reportedAltM) < 1
&& Math.abs(dfOut.reportedAltM - dfOut.h) > 100,
dfTracked.error
|| `getTrackedInfo().altitudeM = ${dfIn.reportedAltM} zoomed in / ${dfOut.reportedAltM} zoomed out (feed baro), while the floored visual reads ${Number(dfOut.h).toFixed(1)} m — the split is deliberate`);
// ---- F4: a RETAINED-but-hidden tracked model must not suppress the floor
// Climbing past the tracked model's EXIT ceiling leaves `_trackedModel`
// alive with show=false (the driver hides it, it is not destroyed), and
// the tracked billboard becomes the visual again. Gating the clamp on
// model EXISTENCE put the burial straight back in exactly that state.
//
// This scenario also pins the toggle contract itself. The DISPLAY-rail
// "3D" toggle stays OFF for the whole block on purpose: it governs the
// FLEET's draw-call budget only, and the tracked contact must still take
// its model on zoom without the operator arming anything.
const dfRetained = await evalPage(async () => {
const v = window.__godsEyeView.viewer;
const Cesium = await import('/node_modules/cesium/Build/Cesium/index.js');
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const gf = window.__dfGf;
const cell = (x) => Number(x.toFixed(3));
// This scenario INHERITS the open deterministic skin from the block
// above and closes it partway through, once its own model is up. The
// close is repeated in a finally because the skip return between here
// and there would otherwise hand an open skin to the seeded scenarios
// that follow; closing an already-closed skin is inert.
try {
// Toggle OFF throughout — the tracked model must not need it.
fl.setParams({ models3d: false });
const toggleOff = fl.getParams().models3d === false;
if (!fl.trackById('aaa097')) return { error: 'trackById(aaa097) failed' };
await window.__dfSettle(600);
// Below the ENTER ceiling (trackById re-frames to the close follow
// range): the tracked model arrives on zoom alone, toggle still off.
const belowH = await window.__dfZoomBelow(window.__dfRegime.enter - 20000);
const withModel = await window.__dfAwaitTrackedModel('aaa097', 20000);
// Same split as the regime scenario: a browser with no usable GLB
// backend skips; models rendering under someone else's pick id must
// reach the assertions and fail there.
if (!withModel.rendering && !window.__dfCountModels().rendering) {
fl.stopTracking();
return { skipped: 'no tracked model rendered in this browser' };
}
// While the model IS the visual the clamp must stand aside (T7).
const entWith = v.trackedEntity?.position?.getValue(Cesium.JulianDate.now());
const withModelH = entWith ? window.__dfCarto(entWith).h : null;
// Close the deterministic skin again for the rest of the group. The
// model is up on a snap that is already cached, so it stays up until the
// regime hides it; what this prevents is a live sample latching into the
// floor cells that the planted seeds below are about to own.
window.__dfSkinM = null;
// Now climb past the EXIT ceiling: the model object is RETAINED but
// hidden, and the billboard is the visual again.
const aboveH = await window.__dfZoomAbove(window.__dfRegime.exit + 5000);
await window.__dfSettle(1500);
// aaa097's own model only: "retained but hidden" is a claim about THIS
// contact's primitive, and an unrelated model in the scene must not be
// able to answer it either way.
const afterOut = window.__dfCountModels('aaa097');
const ent = v.trackedEntity?.position?.getValue(Cesium.JulianDate.now());
const c = ent ? window.__dfCarto(ent) : null;
// Plant a floor above wherever it now renders so "floored" is decisive.
// Mesh cells latch ONE-SHOT, so the earlier scenario's seed would win
// this block silently — clear first, then plant.
gf._clearMeshFloorCellsForTest();
const seeded = (c ? c.h : 0) + 35;
if (c) {
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
gf.reportMeshFloorCell(cell(c.lat) + dy * 0.001, cell(c.lon) + dx * 0.001, seeded);
}
}
}
// The viewer is request-render driven. Directly seeding the test seam
// does not itself schedule a frame, so explicitly request one before
// reading the CallbackProperty again. Production floor warming already
// runs inside the app's render/update lifecycle; this keeps the harness
// from mistaking a cached same-frame position for a failed clamp.
v.scene.requestRender();
await window.__dfSettle(900);
const ent2 = v.trackedEntity?.position?.getValue(Cesium.JulianDate.now());
const c2 = ent2 ? window.__dfCarto(ent2) : null;
const out = {
toggleOff,
enter: window.__dfRegime.enter,
exit: window.__dfRegime.exit,
belowH,
aboveH,
modelsRenderingBelow: withModel.rendering,
withModelH,
hiddenModelsAbove: afterOut.hidden,
shownModelsAbove: afterOut.shown,
beforeSeedH: c ? c.h : null,
seeded,
afterSeedH: c2 ? c2.h : null,
};
// Hand the camera back to the CLOSE follow range before releasing. The
// LOADING scenario below needs BOTH an active tracked regime and a
// fleet model for this contact, and the fleet only admits models within
// MODEL_PROX_ADD_M of the camera — parking just inside the enter
// ceiling satisfies the regime but sits outside that add radius, which
// silently starved the fleet half into a skip.
await window.__dfZoomBelow(belowH + 500);
fl.stopTracking();
await window.__dfSettle(300);
return out;
} finally {
window.__dfSkinM = null;
}
});
if (dfRetained.skipped) {
skip('display-floor: retained-but-hidden tracked model still floors the billboard',
dfRetained.skipped);
} else {
record('display-floor/T7: while the tracked MODEL is the visual, the clamp stands aside',
!dfRetained.error && dfRetained.modelsRenderingBelow > 0,
dfRetained.error
|| `${dfRetained.modelsRenderingBelow} aaa097 model(s) rendering at ${(dfRetained.belowH / 1000).toFixed(0)} km with the 3D toggle OFF; entity at ${Number(dfRetained.withModelH).toFixed(1)} m (ground-snap owns it)`);
// The toggle contract after auto-3D (2026-08-20): the DISPLAY-rail "3D"
// switch owns the FLEET only. The tracked contact's model is default-on
// and decided purely by camera distance, so with the toggle OFF it is
// SHOWN below the enter ceiling and handed back above the exit ceiling —
// and handed back by HIDING, not destroying, which is the retained state
// the floor pin below depends on.
record('display-floor/regime: the 3D toggle governs the FLEET only — the tracked model follows the zoom',
!dfRetained.error && dfRetained.toggleOff === true
&& dfRetained.modelsRenderingBelow > 0
&& dfRetained.belowH < dfRetained.enter
&& dfRetained.shownModelsAbove === 0
&& dfRetained.hiddenModelsAbove > 0
&& dfRetained.aboveH > dfRetained.exit,
dfRetained.error
|| `toggle OFF throughout: at ${(dfRetained.belowH / 1000).toFixed(0)} km (< ${(dfRetained.enter / 1000).toFixed(0)} km enter) ${dfRetained.modelsRenderingBelow} aaa097 model(s) rendering; at ${(dfRetained.aboveH / 1000).toFixed(0)} km (> ${(dfRetained.exit / 1000).toFixed(1)} km exit) ${dfRetained.shownModelsAbove} shown / ${dfRetained.hiddenModelsAbove} retained-hidden`);
record('display-floor: a retained-but-hidden tracked model does NOT suppress the floor',
Number.isFinite(dfRetained.afterSeedH)
&& dfRetained.afterSeedH >= dfRetained.seeded + DISPLAY_FLOOR_LIFT_M - 0.5,
`${Number(dfRetained.beforeSeedH).toFixed(1)} m → ${Number(dfRetained.afterSeedH).toFixed(1)} m on a ${Number(dfRetained.seeded).toFixed(1)} m floor (${dfRetained.hiddenModelsAbove} model object(s) still retained, hidden by the zoom regime)`);
}
// ---- F3: the LOADING window is billboard-owned, not model-owned ------
// A fleet model is registered with Cesium's default show=true the instant
// its glTF resolves, but the handoff waits for `ready`; and a tracked
// model is null for the whole load even though the regime is already
// active. Both windows leave the BILLBOARD as the visual, so both must
// stay floored — ownership means actually rendering.
const dfLoading = await evalPage(async () => {
const v = window.__godsEyeView.viewer;
const Cesium = await import('/node_modules/cesium/Build/Cesium/index.js');
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
const gf = window.__dfGf;
const cell = (x) => Number(x.toFixed(3));
const floorAround = (c, seeded) => {
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
gf.reportMeshFloorCell(cell(c.lat) + dy * 0.001, cell(c.lon) + dx * 0.001, seeded);
}
}
};
const out = {};
// (a) FLEET: reach the real admitted-but-not-ready window. A fleet model
// is registered in `_models` with Cesium's default show=true the moment
// its glTF resolves, while the billboard handoff waits for `ready` — so
// for a tick the model claims the visual it is not drawing. That window
// is ~one fleet tick wide, so hold the state open by shadowing the two
// flags on the instance (the same defineProperty trick the ground-3d
// group uses on `tilesLoaded`).
const findFleetModel = (id) => {
let found = null;
const walk = (coll) => {
const len = coll.length;
for (let i = 0; i < len; i++) {
let p; try { p = coll.get(i); } catch { continue; }
if (!p) continue;
if (typeof p.length === 'number' && typeof p.get === 'function') { walk(p); continue; }
if (p.activeAnimations !== undefined && p.minimumPixelSize !== undefined && p.id === id) found = p;
}
};
walk(v.scene.primitives);
return found;
};
fl.setParams({ models3d: true });
const fleetDeadline = Date.now() + 20000;
let fleetModel = null;
while (Date.now() < fleetDeadline && !(fleetModel = findFleetModel('aaa097'))) {
await window.__dfSettle(500);
}
if (!fleetModel) {
fl.setParams({ models3d: false });
return { skipped: 'no fleet model for aaa097 in this browser' };
}
// Accessors with SWALLOWING setters, not data properties: the fleet tick
// assigns `model.show = false` for a not-ready model, and assigning to a
// non-writable own property throws in strict mode — which lands inside
// Cesium's render loop and stops rendering for the rest of the run.
Object.defineProperty(fleetModel, 'ready', { get: () => false, set: () => {}, configurable: true });
Object.defineProperty(fleetModel, 'show', { get: () => true, set: () => {}, configurable: true });
const bb = window.__dfFindBB('aaa097');
if (!bb) return { error: 'aaa097 billboard missing' };
bb.show = true; // the handoff would not have hidden it: the model is not ready
const d0 = window.__dfCarto(bb.position);
gf._clearMeshFloorCellsForTest();
// Earlier display-floor scenarios deliberately leave this contact's
// sticky-cell/rebuild cache populated. Reset that test-owned cache
// before planting a different artificial floor in the same area, so
// this case measures loading ownership instead of prior-scenario
// hysteresis.
fl._clearDisplayFloorStateForTest();
const seededFleet = d0.h + 45;
floorAround(d0, seededFleet);
// reportMeshFloorCell is a direct test seam and does not schedule a
// Cesium frame. Force the CallbackProperty to re-evaluate before the
// assertion, matching the request-render fix in the retained-model
// scenario above.
v.scene.requestRender();
await window.__dfSettle(900);
const bbAfter = window.__dfFindBB('aaa097');
out.fleetModelReady = fleetModel.ready;
out.fleetModelShow = fleetModel.show;
out.fleetBillboardVisible = !!bbAfter?.show;
out.fleetSeeded = seededFleet;
out.fleetH = bbAfter ? window.__dfCarto(bbAfter.position).h : null;
delete fleetModel.ready;
delete fleetModel.show;
fl.setParams({ models3d: false });
await window.__dfSettle(400);
// (b) TRACKED, regime ACTIVE but no model yet. Turning 3D on while
// tracking makes `_trackedModelRegimeActive()` true immediately; the
// GLB load takes frames, and the tracked billboard is the visual until
// it finishes. Sample within that window.
if (!fl.trackById('aaa097')) return { ...out, error: 'trackById(aaa097) failed' };
await window.__dfSettle(500);
const entBefore = v.trackedEntity?.position?.getValue(Cesium.JulianDate.now());
const cBefore = entBefore ? window.__dfCarto(entBefore) : null;
gf._clearMeshFloorCellsForTest();
fl._clearDisplayFloorStateForTest();
const seededTracked = (cBefore ? cBefore.h : 0) + 45;
if (cBefore) floorAround(cBefore, seededTracked);
// Release the tracked model so the next regime activation must load
// from scratch, then flip the regime on and sample IMMEDIATELY.
fl.setParams({ models3d: false });
await window.__dfSettle(400);
fl.stopTracking();
await window.__dfSettle(300);
fl.trackById('aaa097');
fl.setParams({ models3d: true });
v.scene.requestRender();
await new Promise((r) => setTimeout(r, 120)); // inside the load window
// Count only the contact under test. A headful run can legitimately
// render unrelated live fleet or military models at the same time;
// those say nothing about whether aaa097's loading handoff is still
// billboard-owned. The shared helper keys models by their pick id and
// uses the production ownership pair (`show && ready`).
out.renderingModelsDuringLoad = window.__dfCountModels('aaa097').rendering;
const entLoad = v.trackedEntity?.position?.getValue(Cesium.JulianDate.now());
out.trackedSeeded = seededTracked;
out.trackedLoadH = entLoad ? window.__dfCarto(entLoad).h : null;
fl.setParams({ models3d: false });
fl.stopTracking();
await window.__dfSettle(300);
return out;
});
if (dfLoading.skipped) {
skip('display-floor/loading: fleet model loading window', dfLoading.skipped);
} else {
record('display-floor/loading: a fleet model that is shown-but-not-ready does not own the visual',
!dfLoading.error && dfLoading.fleetModelShow === true && dfLoading.fleetModelReady === false
&& dfLoading.fleetBillboardVisible === true
&& Number.isFinite(dfLoading.fleetH)
&& dfLoading.fleetH >= dfLoading.fleetSeeded + DISPLAY_FLOOR_LIFT_M - 0.5,
dfLoading.error
|| `model show=${dfLoading.fleetModelShow} ready=${dfLoading.fleetModelReady}, billboard visible=${dfLoading.fleetBillboardVisible} at ${Number(dfLoading.fleetH).toFixed(1)} m on a ${Number(dfLoading.fleetSeeded).toFixed(1)} m floor`);
}
record('display-floor/loading: tracked regime active with no rendering model stays floored',
!dfLoading.error && dfLoading.renderingModelsDuringLoad === 0
&& Number.isFinite(dfLoading.trackedLoadH)
&& dfLoading.trackedLoadH >= dfLoading.trackedSeeded + DISPLAY_FLOOR_LIFT_M - 0.5,
dfLoading.error
|| `rendering models during load=${dfLoading.renderingModelsDuringLoad}, entity at ${Number(dfLoading.trackedLoadH).toFixed(1)} m on a ${Number(dfLoading.trackedSeeded).toFixed(1)} m floor`);
// ---- F5: a taxi-invalidated snap HOLDS, bounded by drift -------------
// The gate above ("no evidence ⇒ no model") is right for a contact that
// has NEVER resolved. Applied to one that HAS, it produces a new defect:
// taxiing past groundSnap's 50 m resample threshold drops the cache, and
// if the resample misses — tiles streaming, OSM fallback — the backoff is
// 230 s, so the aircraft pops from 3D back to 2D and back again while it
// rolls. The last MEASUREMENT is held through that instead, bounded by how
// far the contact can have moved from where it was taken. Same answer the
// billboard chain gives (`_heldDisplayFloorM`), a quarter of the distance,
// because a held floor only ever RAISES a sprite while a held snap IS the
// model's placement.
//
// Driven through the app's OWN handoff and its OWN groundSnap instance —
// real Cesium primitive, real cache, real backoff. Only the position is
// supplied by the harness rather than by the poll, which is exactly what a
// taxi is; waiting out the 30 s render delay for the feed to move the
// display would measure the same thing half a minute later.
const dfHold = await evalPage(async () => {
const Cesium = await import('/node_modules/cesium/Build/Cesium/index.js');
const v = window.__godsEyeView.viewer;
const fl = window.__godsEyeView.dataManager.layers.get('flights').module;
// `.module` is the layer OBJECT (the default export), not the module
// namespace, so the handoff seam is not on it. Reach the namespace the
// same way this group reaches groundFloor's: offer the URL the app
// itself loaded (Vite serves an edited file as `…?t=<hmr stamp>`, and
// the plain path would hand back a second, unrelated instance whose
// module state the app never touches), then prove identity by requiring
// its default export to BE the live layer object.
let ns = null;
const urls = [...new Set([
...performance.getEntriesByType('resource').map((e) => e.name)
.filter((n) => /\/src\/data\/flights\.js(\?|$)/.test(n)).reverse(),
'/src/data/flights.js',
])];
for (const url of urls) {
let mod; try { mod = await import(/* @vite-ignore */ url); } catch { continue; }
if (mod?.default === fl && typeof mod._driveFleetModelHandoffForTest === 'function') {
ns = mod;
break;
}
}
if (!ns) return { skipped: `the app's own flights module was not reachable (tried ${urls.length})` };
// Use a scenario-owned contact so its groundSnap entry is provably cold;
// earlier display-floor cases intentionally exercise aaa097's cache.
const holdIcao = 'aaa098';
const sourceBb = window.__dfFindBB('aaa097');
if (!sourceBb) return { error: 'aaa097 source billboard missing' };
const source = window.__dfCarto(sourceBb.position);
window.__SYNTH.flights = window.__SYNTH.flights.filter((f) => f.icao !== holdIcao);
window.__SYNTH.flights.push({
icao: holdIcao,
callsign: 'HOLD98',
lon: source.lon,
lat: source.lat,
alt: 0,
vel: 0,
track: 90,
onGround: true,
});
fl.setParams({ models3d: false });
await fl.update(v);
await window.__dfSettle(600);
const bb = window.__dfFindBB(holdIcao);
if (!bb) return { error: `${holdIcao} billboard missing` };
const base = window.__dfCarto(bb.position);
const basePos = Cesium.Cartesian3.fromDegrees(base.lon, base.lat, base.h);
// Offered skin: unmistakably not the feed altitude, for the case where
// this contact's cache is cold and a real sample has to fire.
const skin = base.h + 60;
// 1. Open a deterministic skin and let the REAL fleet tick admit, place
// and show the model — the arrival path this scenario then interrupts.
const baseSampleCount = () => window.__dfSkinSamples.filter((sample) => {
const dLat = sample.lat - base.lat;
const dLon = (sample.lon - base.lon) * Math.cos(base.lat * Math.PI / 180);
return Math.hypot(dLat, dLon) <= 0.0002;
}).length;
const baseSamplesBefore = baseSampleCount();
window.__dfSkinM = skin;
fl.setParams({ models3d: true });
const up = await window.__dfAwaitTrackedModel(holdIcao, 20000);
if (!up.rendering) {
window.__dfSkinM = null;
fl.setParams({ models3d: false });
return { skipped: `no fleet model rendered for ${holdIcao} in this browser` };
}
const freshOwns = ns._driveFleetModelHandoffForTest({
icao24: holdIcao, position: basePos, course: 90,
});
const baseSampleHits = baseSampleCount() - baseSamplesBefore;
const freshH = window.__dfModelHeight(holdIcao);
// 2. The tiles go away and the contact taxis ~96 m — past the 50 m
// resample threshold, inside the hold bound. Every resample from here
// misses, so this is the whole backoff window in one call.
window.__dfSkinM = null;
const taxiPos = Cesium.Cartesian3.fromDegrees(base.lon + 0.001, base.lat, base.h);
// What independent evidence says about each spot. A held snap now loses
// to a MEASURED floor at the contact's current cell that disagrees with
// it (groundSnap.HELD_SNAP_CONTRADICTION_M), so if this group has
// planted a floor at the taxi cell, that is what decides the outcome —
// and the numbers have to be visible or the failure is unreadable.
const gfns = window.__dfGf;
const baseCarto = window.__dfCarto(basePos);
const taxiCarto = window.__dfCarto(taxiPos);
const baseMeshM = gfns?.cachedMeshFloor?.(baseCarto.lat, baseCarto.lon) ?? null;
const taxiMeshM = gfns?.cachedMeshFloor?.(taxiCarto.lat, taxiCarto.lon) ?? null;
const heldOwns = ns._driveFleetModelHandoffForTest({ icao24: holdIcao, position: taxiPos, course: 90 });
const heldH = window.__dfModelHeight(holdIcao);
const heldBb = !!window.__dfFindBB(holdIcao)?.show;
// 3. ~385 m out the memory stops describing anywhere this contact has
// been. It is released rather than stretched, and the gate takes over.
const farPos = Cesium.Cartesian3.fromDegrees(base.lon + 0.004, base.lat, base.h);
const releasedOwns = ns._driveFleetModelHandoffForTest({ icao24: holdIcao, position: farPos, course: 90 });
const releasedBb = !!window.__dfFindBB(holdIcao)?.show;
fl.setParams({ models3d: false });
await window.__dfSettle(300);
return {
freshOwns,
freshH,
baseSampleHits,
heldOwns,
heldH,
heldBb,
baseMeshM,
taxiMeshM,
releasedOwns,
releasedBb,
taxiM: Cesium.Cartesian3.distance(
Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(basePos, new Cesium.Cartesian3()),
Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(taxiPos, new Cesium.Cartesian3()),
),
farM: Cesium.Cartesian3.distance(
Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(basePos, new Cesium.Cartesian3()),
Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(farPos, new Cesium.Cartesian3()),
),
};
});
if (dfHold.skipped) {
skip('display-floor/hold: a taxi-invalidated ground snap holds the model through the resample backoff',
dfHold.skipped);
} else {
// The taxi has to actually cross the threshold, or the rest proves
// nothing: > 50 m invalidates, < 250 m is still inside the bound.
record('display-floor/hold: the taxi really does invalidate, and the far step really does exceed the bound',
!dfHold.error && dfHold.taxiM > 50 && dfHold.taxiM < 250 && dfHold.farM > 250,
dfHold.error || `taxi ${Number(dfHold.taxiM).toFixed(1)} m (> 50 m invalidate, < 250 m bound), far step ${Number(dfHold.farM).toFixed(1)} m (> 250 m bound)`);
record('display-floor/hold: a taxi-invalidated ground snap holds the model through the resample backoff',
!dfHold.error && dfHold.baseSampleHits > 0
&& dfHold.freshOwns === true && dfHold.heldOwns === true
&& dfHold.heldBb === false
&& Number.isFinite(dfHold.heldH) && Number.isFinite(dfHold.freshH)
&& Math.abs(dfHold.heldH - dfHold.freshH) < 0.5,
dfHold.error || `fresh owns=${dfHold.freshOwns} after ${dfHold.baseSampleHits} positive base sample(s), on a MEASURED floor at ${Number(dfHold.freshH).toFixed(1)} m; tiles gone + ${Number(dfHold.taxiM).toFixed(1)} m taxi → owns=${dfHold.heldOwns} at ${Number(dfHold.heldH).toFixed(1)} m, billboard shown=${dfHold.heldBb} (want owns=true, bb=false: no 3D→2D pop). Independent mesh floor: base=${dfHold.baseMeshM == null ? 'cold' : Number(dfHold.baseMeshM).toFixed(1)} m, taxi=${dfHold.taxiMeshM == null ? 'cold' : Number(dfHold.taxiMeshM).toFixed(1)} m`);
record('display-floor/hold: past the drift bound the hold is released and the model is withheld',
!dfHold.error && dfHold.releasedOwns === false && dfHold.releasedBb === true,
dfHold.error || `${Number(dfHold.farM).toFixed(1)} m from the sample: model owns=${dfHold.releasedOwns}, billboard back at shown=${dfHold.releasedBb}`);
}
}
// Cleanup: drop the synthetics and the seeded cells so nothing leaks into
// the run-wide console/HTTP checks below.
await evalPage(async () => {
const gev = window.__godsEyeView;
const v = gev.viewer;
const fl = gev.dataManager.layers.get('flights').module;
window.__SYNTH.flights = window.__SYNTH.flights.filter((f) => !/^aaa09/.test(f.icao));
fl.stopTracking();
window.__dfGf?._clearMeshFloorCellsForTest();
delete v.scene.sampleHeight;
if (gev.tileset) {
const prior = window.__dfPriorTilesLoadedDescriptor;
if (prior) Object.defineProperty(gev.tileset, 'tilesLoaded', prior);
else delete gev.tileset.tilesLoaded;
}
delete window.__dfPriorTilesLoadedDescriptor;
delete window.__dfSkinSamples;
delete window.__dfSkinM;
await fl.update(v);
});
// Harness hardening (2026-07-06): the two earlier console-error checks run
// BEFORE the ground/ground-3d/arrival groups — an exception thrown in
// those later scenarios (e.g. inside a fleet tick) was invisible and
// surfaced only as inexplicable downstream assertion failures. Catch-all.
record('no console errors across the FULL run (late groups included)', consoleErrors.length === 0,
consoleErrors.length
? `${consoleErrors.length}: ${consoleErrors.slice(-3).join(' | ')}`
: 'clean');
record('no HTTP 5xx responses across the FULL run', failedResponses.length === 0,
failedResponses.length
? `${failedResponses.length}: ${failedResponses.slice(-3).join(' | ')}`
: 'clean');
finishAndExit();
} finally {
if (!KEEP_OPEN) {
await browser.close();
} else {
console.log('\n--keep-open set; leaving browser running. Ctrl-C to exit.');
}
}
function finishAndExit() {
const failed = results.filter((r) => r.ok === false);
const passed = results.filter((r) => r.ok === true);
const skipped = results.filter((r) => r.ok === null);
console.log(`\n${'─'.repeat(60)}`);
console.log(` RESULT: ${passed.length} passed, ${failed.length} failed, ${skipped.length} skipped`);
console.log(`${'─'.repeat(60)}\n`);
process.exitCode = failed.length > 0 ? 1 : 0;
}
}
// ---------------------------------------------------------------------------
// Frame sampler: run `sampleFn` once per render frame for `count` frames,
// in the page, collecting its numeric return (or null).
// ---------------------------------------------------------------------------
async function sampleFrames(page, count, sampleFn, ...args) {
const { values, timedOut } = await page.evaluate(async (fnStr, n, extra) => {
const fn = new Function('return (' + fnStr + ')')();
const v = window.__godsEyeView.viewer;
const out = [];
let timedOut = false;
await new Promise((resolve) => {
let i = 0;
let settled = false;
const finish = () => {
if (settled) return;
settled = true;
clearTimeout(timer);
remove();
resolve();
};
const remove = v.scene.postRender.addEventListener(() => {
try { out.push(fn(...extra)); } catch (e) { out.push(null); }
if (++i >= n) {
finish();
return;
}
// Cesium runs with requestRenderMode enabled, so one request produces
// one postRender callback. Drive every sample explicitly instead of
// waiting forever after the first frame.
v.scene.requestRender();
});
const timer = setTimeout(() => {
timedOut = true;
finish();
}, Math.max(15000, n * 1500));
v.scene.requestRender();
});
return { values: out, timedOut };
}, sampleFn.toString(), count, args);
return { values, timedOut };
}
function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }
/** Great-circle surface distance (m) between two lat/lon points (small-angle safe). */
function haversineMeters(lat1, lon1, lat2, lon2) {
const R = 6371000;
const toRad = (d) => (d * Math.PI) / 180;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a = Math.sin(dLat / 2) ** 2
+ Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;
return 2 * R * Math.asin(Math.sqrt(a));
}
// Poll a node-side predicate.
function waitFor(pred, timeoutMs) {
return new Promise((resolve, reject) => {
const start = Date.now();
const tick = () => {
if (pred()) return resolve();
if (Date.now() - start > timeoutMs) return reject(new Error('waitFor timeout'));
setTimeout(tick, 100);
};
tick();
});
}
main().catch((err) => {
console.error('\n\x1b[31mHarness error:\x1b[0m', err && err.stack ? err.stack : err);
process.exit(2);
});