Merge pull request #313: finish browser QA renderer portability

Complete Tom-Neverwinter's deferred browser QA portability fixes, with renderer evidence, attribution keyboard and 2D floor-hold setup corrections.
This commit is contained in:
Sameh Khamis authored and GitHub committed 2026-09-11 15:04:57 -07:00
commit e9b6214ec4
6 files changed
+70 -17

No files matched your search

+11
View File
@@ -13,6 +13,17 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
## [Unreleased]
### Fixed
- Complete the first-run, view-target prewarm, cockpit-plates and floor-hold
browser harness renderer portability fixes contributed by Tom-Neverwinter.
macOS retains Metal; other platforms default to SwiftShader. Cockpit renderer
assertions and evidence labels follow the actual selected mode. Floor-hold
explicitly selects its measured 2D billboard mode and keeps its mesh and terrain assertions; software runs are not real-GPU evidence.
First-run QA now checks the existing attribution Escape-close/focus-return
behavior while preserving the launcher-underneath regression checks.
- Datacenter and dam factories are available through scoped package exports with
explicit context, overlay and render callbacks. The standalone app uses the
same implementation and bundled datasets.
+13
View File
@@ -218,3 +218,16 @@ While recording, call out anything in these areas — this is the feedback I mos
- **No planes:** OpenSky data may be momentarily sparse; scroll out or wait a poll cycle.
- **No GEV MIC button / voice errors:** `OPENAI_API_KEY` didn't load — use the console API for
the annotation tests and skip the voice-only ones (§2).
## Browser harness renderers
The first-run, view-target prewarm, cockpit-plates and floor-hold harnesses
select Metal on macOS and SwiftShader on other platforms. Cockpit-plates also
accepts `--swiftshader` on macOS; floor-hold retains `--angle=<backend>`.
Floor-hold explicitly selects 2D aircraft mode because it measures billboard
positions; the tracking suite covers the 3D handoff.
Software runs validate their assertions but do not establish real-GPU visual
correctness. Floor-hold retains both mesh and DEM checks: an unavailable mesh
oracle fails the run even when the DEM check passes. Record the backend with
any screenshots and run GPU visual checks separately when needed.
+5 -3
View File
@@ -46,7 +46,7 @@
* node scripts/qa-cockpit-plates.mjs --url http://localhost:4268 --tag before
* node scripts/qa-cockpit-plates.mjs --url http://localhost:4268 --teeth
*
* Defaults to the real GPU (ANGLE/Metal). `--swiftshader` selects software GL,
* Defaults to ANGLE/Metal on macOS and software GL elsewhere. `--swiftshader` selects software GL,
* which is deterministic but is NOT real-GPU evidence; the banner says which
* backend actually ran and the run records it alongside the results.
*/
@@ -64,7 +64,7 @@ const APP_ORIGIN = new URL(APP_URL).origin;
const TAG = getOpt('--tag', 'after');
const HEADFUL = argv.includes('--headful');
const TEETH = argv.includes('--teeth');
const SWIFTSHADER = argv.includes('--swiftshader');
const SWIFTSHADER = argv.includes('--swiftshader') || process.platform !== 'darwin';
const SHOT_DIR = path.resolve('qa-shots/cockpitplates');
/** Mirrors `SKY_PLATE_SCALE` in src/overlays/worldOverlayTokens.js. */
@@ -222,6 +222,8 @@ async function main() {
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
// Metal is a macOS-only ANGLE backend; off-Mac the GPU branch has to fall
// back to the software rasterizer or WebGL init fails outright.
...(SWIFTSHADER
? ['--use-gl=angle', '--use-angle=swiftshader']
: ['--use-angle=metal', '--enable-gpu', '--ignore-gpu-blocklist']),
@@ -292,7 +294,7 @@ async function main() {
console.log(` GL : ${renderer}\n`);
record(
SWIFTSHADER
? 'running on software GL as requested (structural checks, not GPU evidence)'
? 'running on software GL (structural checks, not GPU evidence)'
: 'running on the real GPU, so the screenshots are real-GPU evidence',
SWIFTSHADER ? softwareRenderer : !softwareRenderer,
renderer,
+12 -6
View File
@@ -332,14 +332,17 @@ async function runArbitrationSection(page, { shots, consoleErrors }) {
`session=${escUnderLightbox.session}`,
);
record(
'the lightbox keeps its OWN ESC semantics (Cesium binds none, so it stays)',
lightboxAfterEsc.shown,
'ESC closes attribution without dismissing the launcher underneath',
!lightboxAfterEsc.shown,
`overlay shown=${lightboxAfterEsc.shown}`,
);
// The guard disarms the launcher; it must never break it. Close the overlay
// the way a visitor does and the key comes straight back.
await page.evaluate(() => document.querySelector('.cesium-credit-lightbox-close')?.click());
// The attribution keyboard handler closes the overlay and restores focus.
// A second Escape belongs to the now-uncovered launcher.
const attributionFocusRestored = await page.evaluate(() => (
document.activeElement === document.querySelector('#cesium-credits .cesium-credit-expand-link')
));
record('closing attribution restores its disclosure focus', attributionFocusRestored);
await sleep(300);
const uncovered = await launcherState();
record('closing the lightbox hands the card back the key',
@@ -491,7 +494,10 @@ async function main() {
...(executablePath ? { executablePath } : {}),
args: [
'--no-sandbox', '--disable-setuid-sandbox',
'--use-angle=metal', '--enable-gpu', '--ignore-gpu-blocklist',
// Metal is a macOS-only ANGLE backend; anywhere else it fails WebGL init.
...(process.platform === 'darwin'
? ['--use-angle=metal', '--enable-gpu', '--ignore-gpu-blocklist']
: ['--use-gl=angle', '--use-angle=swiftshader']),
'--disable-dev-shm-usage', '--disable-background-timer-throttling',
'--disable-renderer-backgrounding', '--window-size=1440,900',
],
+22 -7
View File
@@ -15,7 +15,7 @@
* The contact must stay ON the mesh through phase B. Without the hold it falls
* to the geoid, which at an inland field is ~150 m of burial.
*
* node scripts/qa-floor-hold.mjs # real GPU (ANGLE/Metal)
* node scripts/qa-floor-hold.mjs # Metal on macOS, SwiftShader elsewhere
* node scripts/qa-floor-hold.mjs --headful # watch it
* QA_BASE_URL=http://localhost:4257 node scripts/qa-floor-hold.mjs
*
@@ -25,10 +25,11 @@
* under Metal — a backend comparison at one point, not to be confused with the
* same-backend run-to-run spread (122.1 m vs 20.6 m on a cell centre) that
* retired the hold chain's unvalidated tier. The
* default is the real GPU. Under `--angle=swiftshader` the rendered-mesh oracle
* is reported as unavailable rather than trusted, and the run falls back to the
* bare-earth DEM (fetched server-side, so the simulated outage cannot reach
* it) — a weaker but still decisive check, since the geoid sits ~150 m below it.
* default is Metal on macOS and SwiftShader elsewhere; `--angle` overrides it.
* Mesh samples describe the selected backend, not another GPU's rendered LOD.
* An unavailable rendered-mesh oracle remains a failed check, even if the
* separate bare-earth DEM check passes. Software evidence does not establish
* real-GPU visual correctness.
*/
import puppeteer from 'puppeteer';
import fs from 'node:fs';
@@ -37,7 +38,8 @@ import path from 'node:path';
const APP_URL = process.env.QA_BASE_URL || 'http://localhost:4173';
const argv = Object.fromEntries(process.argv.slice(2)
.map((a) => a.replace(/^--/, '').split('=')).map(([k, v]) => [k, v ?? true]));
const ANGLE = String(argv.angle || 'metal');
// Metal is a macOS-only ANGLE backend; defaulting to it off-Mac fails WebGL init.
const ANGLE = String(argv.angle || (process.platform === 'darwin' ? 'metal' : 'swiftshader'));
const HEADFUL = !!argv.headful;
// Austin airport apron by default — the site qa-floor-verify pins, where the
// mesh sits ~150 m above the geoid and burial is unmistakable.
@@ -108,6 +110,10 @@ await page.goto(APP_URL, { waitUntil: 'domcontentloaded', timeout: 120000 });
await page.waitForFunction(() => window.__godsEyeView?.viewer && window.__godsEyeView?.dataManager,
{ timeout: 150000 });
await sleep(12000); // let the boot fly-to settle before pinning
await page.evaluate(() => {
document.querySelector('#first-run-launcher:not([hidden]) [data-first-run-choice="explore"]')?.click();
});
await sleep(600); // let the launcher dismissal finish before taking evidence
await page.evaluate((site) => { window.__SITE = site; }, SITE);
const pin = () => page.evaluate(() => {
@@ -123,7 +129,16 @@ const pin = () => page.evaluate(() => {
v.camera.moveEnd.raiseEvent();
});
await pin();
await page.evaluate(async () => { await window.__godsEyeView.dataManager.toggle('flights'); });
const billboardMode = await page.evaluate(async () => {
const manager = window.__godsEyeView.dataManager;
const flights = manager.layers.get('flights').module;
// This harness measures billboard positions. A ready 3D model deliberately
// hides its billboard; that handoff is covered by track-regression instead.
flights.setParams({ models3d: false });
await manager.toggle('flights');
return flights.getParams().models3d === false;
});
record('the billboard floor test is explicitly in 2D aircraft mode', billboardMode);
/** Reads the contact's rendered height and the rendered mesh beneath it. */
const measure = () => page.evaluate(async (icao) => {
+7 -1
View File
@@ -39,7 +39,13 @@ const executablePath = chromeCandidates.find((candidate) => fs.existsSync(candid
const browser = await puppeteer.launch({
headless: headful ? false : 'new',
...(executablePath ? { executablePath } : {}),
args: ['--use-angle=metal', '--enable-gpu', '--no-sandbox'],
// Metal is a macOS-only ANGLE backend; anywhere else it fails WebGL init.
args: [
...(process.platform === 'darwin'
? ['--use-angle=metal', '--enable-gpu']
: ['--use-gl=angle', '--use-angle=swiftshader']),
'--no-sandbox',
],
});
const page = await browser.newPage();
const failures = [];