Merge commit '2746ec753ce4d6ebafee881a212c3f327907c673' into codex/train-cctv-489

# Conflicts:
#	README.md
#	scripts/format-scope.json
This commit is contained in:
Bilawal Sidhu committed 2026-09-15 10:53:03 -05:00
commit 3571284782
252 files changed
+48512 -4509

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
{
"roots": ["src", "server"]
}
+50 -3
View File
@@ -676,10 +676,57 @@
"src/sources/httpBody.js",
"src/sources/overpass.js",
"src/sources/nominatim.js",
"server/providers/cctv/stream.js",
"server/providers/transit.js",
"server/providers/transitHistory.js",
"server/providers/transitHistory.test.mjs",
"src/data/transitFeeds.js",
"src/data/transitFeeds.test.mjs",
"src/data/transitProxy.js",
"src/data/transitProxy.test.mjs",
"src/data/gtfsRealtime.js",
"src/data/gtfsRealtime.test.mjs",
"src/data/transit.js",
"src/data/transit.test.mjs",
"src/layers/transit/controls.js",
"src/layers/transit/height.js",
"src/layers/transit/index.js",
"src/layers/transit/ingestion.js",
"src/layers/transit/lifecycle.js",
"src/layers/transit/policy.js",
"src/layers/transit/queries.js",
"src/layers/transit/rendering.js",
"src/layers/transit/selection.js",
"src/layers/transit/state.js",
"src/layers/transit/testing.js",
"src/layers/transit/viewport.js",
"src/layers/transit/lifecycle.test.mjs",
"scripts/qa-transit.mjs",
"src/tooling/transitProvider.test.mjs",
"src/app/layers/transit.js",
"src/data/transitIcons.js",
"src/data/cameraSensitivity.js",
"src/data/contactPlayback.js",
"src/data/contactTrailRenderer.js",
"src/data/contactTrailRenderer.test.mjs",
"src/layers/transit/trails.js",
"src/data/contactPlayback.test.mjs",
"src/layers/transit/movement.js",
"src/layers/transit/movement.test.mjs",
"src/data/transitPresetStyle.js",
"src/data/transitPresetStyle.test.mjs",
"src/data/transitIcons.test.mjs",
"src/overlays/worldOverlayTokens.test.mjs",
"src/app/layers/transit.test.mjs",
"src/layers/transit/qaMetrics.js",
"src/layers/transit/qaMetrics.test.mjs",
"scripts/qa-transit-scenes.mjs",
"scripts/qa-transit-controls.mjs",
"src/tooling/transitQa.test.mjs",
"scripts/qa-transit-browser.mjs",
"scripts/format-runtime.json",
"src/tooling/transitService.test.mjs",
"src/sources/overpassFeatures.test.mjs",
"src/data/cctvHlsStream.test.mjs",
"src/layers/cctv/videoPlayback.js",
"src/layers/cctv/videoPlayback.test.mjs",
"src/ui/cctvVideo.js",
"src/ui/cctvVideo.test.mjs"
]
+56 -3
View File
@@ -1,9 +1,58 @@
import { execFileSync } from 'node:child_process';
import { existsSync } from 'node:fs';
import { readFile, writeFile, realpath, stat } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import * as prettier from 'prettier';
/** Check or format the explicitly adopted files, without scanning other source. */
/** Discover owned runtime code; tests and other files retain explicit adoption. */
export async function discoverRuntimeFormatFiles(root) {
const configFile = path.join(root, 'scripts/format-runtime.json');
if (!existsSync(configFile)) return [];
const { roots } = JSON.parse(await readFile(configFile, 'utf8'));
if (
!Array.isArray(roots) ||
!roots.length ||
new Set(roots).size !== roots.length ||
roots.some(
(name) =>
typeof name !== 'string' ||
!/^[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/.test(name),
)
)
throw new Error(
'Runtime formatting roots must be unique repository directory paths',
);
const candidates = execFileSync(
'git',
[
'ls-files',
'-z',
'--cached',
'--others',
'--exclude-standard',
'--',
...roots,
],
{ cwd: root, encoding: 'utf8' },
).split('\0');
const files = [];
for (const name of new Set(candidates)) {
if (
!/\.[cm]?js$/.test(name) ||
/\.test\.[cm]?js$/.test(name) ||
!existsSync(path.join(root, name))
)
continue;
const info = await prettier.getFileInfo(path.join(root, name), {
ignorePath: path.join(root, '.prettierignore'),
});
if (!info.ignored) files.push(name);
}
return files.sort();
}
/** Check or format explicit adoption plus automatically discovered runtime code. */
export async function formatAdoptedFiles(root, mode) {
if (!['--check', '--write'].includes(mode)) {
throw new Error('Usage: node scripts/format.mjs --check|--write');
@@ -22,9 +71,13 @@ export async function formatAdoptedFiles(root, mode) {
);
}
const names = [
...new Set([...scope, ...(await discoverRuntimeFormatFiles(root))]),
];
// Validate the whole scope before any write, including resolved symlink paths.
const files = [];
for (const name of scope) {
for (const name of names) {
if (
typeof name !== 'string' ||
!name ||
@@ -91,7 +144,7 @@ if (import.meta.url === invoked) {
process.exitCode = 1;
} else {
console.log(
`${mode === '--write' ? 'Formatted' : 'Checked'} ${result.count} adopted files.`,
`${mode === '--write' ? 'Formatted' : 'Checked'} ${result.count} source files.`,
);
}
} catch (error) {
+268 -12
View File
@@ -68,7 +68,8 @@
"scripts/google-server-key.mjs",
"src/data/placeProviderPayloads.js",
"src/data/routeSteps.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/sources/rateLimit.js"
],
"external": []
},
@@ -205,7 +206,8 @@
"src/data/placeProviderPayloads.js",
"src/data/routeSteps.js",
"src/sources/httpBody.js",
"src/sources/overpass.js"
"src/sources/overpass.js",
"src/sources/rateLimit.js"
],
"external": []
},
@@ -223,7 +225,8 @@
"server/providers/overpass/constants.js",
"server/providers/overpass/geometry.js",
"server/providers/overpass/transport.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/sources/rateLimit.js"
],
"external": []
},
@@ -244,7 +247,8 @@
"server/providers/regional/weather.js",
"src/data/regionalModel.js",
"src/nominatimGeocode.js",
"src/sources/httpBody.js"
"src/sources/httpBody.js",
"src/sources/rateLimit.js"
],
"external": []
},
@@ -266,7 +270,8 @@
"src/hudSummaryResponse.js",
"src/voice/voiceCost.js",
"src/voice/actionSchemas.js",
"server/providers/openai/toolDescriptions.js"
"server/providers/openai/toolDescriptions.js",
"src/sources/rateLimit.js"
],
"external": []
},
@@ -588,6 +593,7 @@
"src/ui/styles/radio.css",
"src/ui/styles/cctv.css",
"src/ui/styles/scenes.css",
"src/ui/styles/bhote-koshi.css",
"src/ui/styles/recording.css",
"src/ui/styles/responsive.css",
"src/ui/styles/command-dock.css",
@@ -603,6 +609,11 @@
"scenes": {
"exports": ["./scenes"],
"modules": [
"src/scenes/nepalEvidencePack.js",
"src/data/bhoteKoshiIncidentPlaces.js",
"src/data/bhoteKoshiShotPaths.js",
"src/data/bhoteKoshiFloodPath.js",
"src/maps/catalog.js",
"src/scenes/director.js",
"src/scenes/recipes.js",
"src/scenes/scenePolicy.js",
@@ -878,6 +889,7 @@
"traffic-layer": {
"exports": ["./layers/traffic"],
"modules": [
"src/data/cameraSensitivity.js",
"src/data/flowMatch.js",
"src/data/tomtomTiles.js",
"src/data/trafficBounds.js",
@@ -899,7 +911,8 @@
"src/layers/traffic/state.js",
"src/layers/traffic/style.js",
"src/layers/traffic/timing.js",
"src/layers/traffic/viewport.js"
"src/layers/traffic/viewport.js",
"src/sources/overpassRoads.js"
],
"external": ["cesium", "pbf", "@mapbox/vector-tile"]
},
@@ -920,7 +933,8 @@
"src/layers/bikeshare/state.js",
"src/layers/bikeshare/testing.js",
"src/layers/bikeshare/viewport.js",
"src/data/inputOwnership.js"
"src/data/inputOwnership.js",
"src/data/cameraSensitivity.js"
],
"external": ["cesium"]
},
@@ -1115,6 +1129,13 @@
"./standalone/catalog"
],
"modules": [
"src/scenes/nepalEvidencePack.js",
"src/data/bhoteKoshiEvent.js",
"src/data/bhoteKoshiEmbeddedMedia.js",
"src/data/bhoteKoshiLocator.js",
"src/data/bhoteKoshiIncidentPlaces.js",
"src/data/bhoteKoshiFloodPath.js",
"src/data/bhoteKoshiShotPaths.js",
"src/annotations/annotationEngine.js",
"src/annotations/annotationResolver.js",
"src/annotations/hybridAnnotationRenderer.js",
@@ -1638,7 +1659,39 @@
"src/search/nominatim.js",
"src/nominatimGeocode.js",
"src/sources/httpBody.js",
"src/sources/nominatim.js"
"src/sources/nominatim.js",
"src/app/layers/transit.js",
"src/data/transit.js",
"src/data/transitFeeds.js",
"src/data/transitIcons.js",
"src/data/transitPresetStyle.js",
"src/layers/transit/controls.js",
"src/layers/transit/height.js",
"src/layers/transit/index.js",
"src/layers/transit/ingestion.js",
"src/layers/transit/lifecycle.js",
"src/layers/transit/policy.js",
"src/layers/transit/queries.js",
"src/layers/transit/rendering.js",
"src/layers/transit/selection.js",
"src/layers/transit/state.js",
"src/layers/transit/testing.js",
"src/layers/transit/viewport.js",
"src/data/cameraSensitivity.js",
"src/data/contactPlayback.js",
"src/data/contactTrailRenderer.js",
"src/data/transitProxy.js",
"src/data/gtfsRealtime.js",
"src/layers/transit/trails.js",
"src/layers/transit/movement.js",
"src/layers/transit/qaMetrics.js",
"src/layers/transit/source.js",
"src/sources/transitHistory.js",
"src/sources/featureGeometry.js",
"src/sources/overpassFeaturesRecords.js",
"src/sources/overpassFeatures.js",
"src/sources/featureSource.js",
"src/sources/overpassRoads.js"
],
"external": [
"@mapbox/vector-tile",
@@ -1657,6 +1710,12 @@
"application-layer-construction": {
"exports": ["./application/layers"],
"modules": [
"src/data/bhoteKoshiEvent.js",
"src/data/bhoteKoshiEmbeddedMedia.js",
"src/data/bhoteKoshiLocator.js",
"src/data/bhoteKoshiIncidentPlaces.js",
"src/data/bhoteKoshiFloodPath.js",
"src/data/bhoteKoshiShotPaths.js",
"src/annotations/annotationResolver.js",
"src/annotations/resolver.js",
"src/app/catalog.js",
@@ -1995,7 +2054,38 @@
"src/nominatimGeocode.js",
"src/data/regionalModel.js",
"src/sources/httpBody.js",
"src/sources/nominatim.js"
"src/sources/nominatim.js",
"src/app/layers/transit.js",
"src/data/transitFeeds.js",
"src/data/transitIcons.js",
"src/data/transitPresetStyle.js",
"src/layers/transit/controls.js",
"src/layers/transit/height.js",
"src/layers/transit/index.js",
"src/layers/transit/ingestion.js",
"src/layers/transit/lifecycle.js",
"src/layers/transit/policy.js",
"src/layers/transit/queries.js",
"src/layers/transit/rendering.js",
"src/layers/transit/selection.js",
"src/layers/transit/state.js",
"src/layers/transit/testing.js",
"src/layers/transit/viewport.js",
"src/data/cameraSensitivity.js",
"src/data/contactPlayback.js",
"src/data/contactTrailRenderer.js",
"src/data/transitProxy.js",
"src/data/gtfsRealtime.js",
"src/layers/transit/trails.js",
"src/layers/transit/movement.js",
"src/layers/transit/qaMetrics.js",
"src/layers/transit/source.js",
"src/sources/transitHistory.js",
"src/sources/featureGeometry.js",
"src/sources/overpassFeaturesRecords.js",
"src/sources/overpassFeatures.js",
"src/sources/featureSource.js",
"src/sources/overpassRoads.js"
],
"external": [
"cesium",
@@ -2044,7 +2134,11 @@
"src/nominatimGeocode.js",
"src/data/regionalModel.js",
"src/sources/httpBody.js",
"src/sources/nominatim.js"
"src/sources/nominatim.js",
"src/sources/featureGeometry.js",
"src/sources/overpassFeaturesRecords.js",
"src/sources/overpassFeatures.js",
"src/sources/featureSource.js"
],
"external": [
"cesium",
@@ -2245,7 +2339,10 @@
},
"installations-source": {
"exports": ["./layers/installations/source"],
"modules": ["src/layers/installations/source.js"],
"modules": [
"src/layers/installations/source.js",
"src/data/militaryInstallationData.js"
],
"external": []
},
"launches-source": {
@@ -2269,7 +2366,8 @@
"src/data/tomtomTiles.js",
"src/layers/traffic/flowDecode.js",
"src/layers/traffic/flowSource.js",
"src/layers/traffic/source.js"
"src/layers/traffic/source.js",
"src/sources/overpassRoads.js"
],
"external": ["@mapbox/vector-tile", "pbf"]
},
@@ -2316,5 +2414,163 @@
"src/sources/httpBody.js"
],
"external": []
},
"transit-provider": {
"runtime": "node",
"exports": ["./server/providers/transit"],
"modules": [
"server/providers/common/http.js",
"server/providers/common/rate-limit.js",
"server/providers/transit.js",
"server/providers/transitHistory.js",
"src/data/gtfsRealtime.js",
"src/data/transitFeeds.js",
"src/data/transitProxy.js",
"src/sources/httpBody.js",
"src/sources/transitHistory.js",
"src/sources/transitService.js",
"src/sources/transitHistoryStore.js",
"src/sources/rateLimit.js"
],
"external": ["pbf"]
},
"transit-source": {
"exports": ["./sources/transit"],
"modules": [
"src/data/gtfsRealtime.js",
"src/data/transitFeeds.js",
"src/data/transitProxy.js",
"src/sources/transitHistory.js"
],
"external": ["pbf"]
},
"transit-standalone": {
"exports": ["./layers/transit/standalone"],
"modules": [
"src/app/sourceSlot.js",
"src/celestialRing.js",
"src/data/cameraSensitivity.js",
"src/data/contactPlayback.js",
"src/data/contactTrailRenderer.js",
"src/data/dataCredits.js",
"src/data/detectionCohort.js",
"src/data/detectionPolicy.js",
"src/data/geoid.js",
"src/data/groundFloor.js",
"src/data/gtfsRealtime.js",
"src/data/iconOrientation.js",
"src/data/inputOwnership.js",
"src/data/labelArbiter.js",
"src/data/meshFloorSampler.js",
"src/data/pickRegistry.js",
"src/data/spriteOrder.js",
"src/data/terrainHeights.js",
"src/data/transit.js",
"src/data/transitFeeds.js",
"src/data/transitIcons.js",
"src/data/transitPresetStyle.js",
"src/data/transitProxy.js",
"src/layers/transit/controls.js",
"src/layers/transit/height.js",
"src/layers/transit/index.js",
"src/layers/transit/ingestion.js",
"src/layers/transit/lifecycle.js",
"src/layers/transit/movement.js",
"src/layers/transit/policy.js",
"src/layers/transit/qaMetrics.js",
"src/layers/transit/queries.js",
"src/layers/transit/rendering.js",
"src/layers/transit/selection.js",
"src/layers/transit/state.js",
"src/layers/transit/testing.js",
"src/layers/transit/trails.js",
"src/layers/transit/viewport.js",
"src/overlays/worldOverlay.js",
"src/overlays/worldOverlayDraw.js",
"src/overlays/worldOverlayTokens.js",
"src/renderGovernor.js",
"src/services/application.js",
"src/services/groundFloor.js",
"src/services/meshFloorSampler.js",
"src/services/requests.js",
"src/services/terrainHeights.js",
"src/sources/sourceSlot.js",
"src/layers/transit/source.js",
"src/sources/transitHistory.js",
"src/sources/featureGeometry.js",
"src/sources/overpassFeaturesRecords.js",
"src/sources/overpassFeatures.js",
"src/sources/featureSource.js"
],
"external": ["cesium", "egm96-universal", "pbf"]
},
"transit-layer": {
"exports": ["./layers/transit"],
"modules": [
"src/data/iconOrientation.js",
"src/data/inputOwnership.js",
"src/data/transitFeeds.js",
"src/data/transitIcons.js",
"src/data/transitPresetStyle.js",
"src/layers/transit/controls.js",
"src/layers/transit/height.js",
"src/layers/transit/index.js",
"src/layers/transit/ingestion.js",
"src/layers/transit/lifecycle.js",
"src/layers/transit/policy.js",
"src/layers/transit/queries.js",
"src/layers/transit/rendering.js",
"src/layers/transit/selection.js",
"src/layers/transit/state.js",
"src/layers/transit/testing.js",
"src/layers/transit/viewport.js",
"src/data/cameraSensitivity.js",
"src/data/contactPlayback.js",
"src/data/contactTrailRenderer.js",
"src/data/transitProxy.js",
"src/data/gtfsRealtime.js",
"src/layers/transit/trails.js",
"src/layers/transit/movement.js",
"src/layers/transit/qaMetrics.js",
"src/layers/transit/qaMetrics.test.mjs",
"scripts/qa-transit-scenes.mjs",
"scripts/qa-transit-controls.mjs",
"scripts/qa-transit-browser.mjs",
"src/layers/transit/source.js",
"src/sources/transitHistory.js"
],
"external": ["cesium", "pbf"]
},
"transit-source-factory": {
"exports": ["./layers/transit/source"],
"modules": [
"src/layers/transit/source.js",
"src/sources/transitHistory.js"
],
"external": []
},
"transit-service": {
"exports": ["./sources/transit-service"],
"modules": [
"src/data/transitFeeds.js",
"src/data/transitProxy.js",
"src/data/gtfsRealtime.js",
"src/sources/httpBody.js",
"src/sources/transitHistory.js",
"src/sources/transitService.js",
"src/sources/transitHistoryStore.js",
"src/sources/rateLimit.js"
],
"external": ["pbf"]
},
"map-feature-source": {
"exports": ["./sources/map-features"],
"modules": [
"src/sources/featureGeometry.js",
"src/sources/overpassFeaturesRecords.js",
"src/sources/overpassFeatures.js",
"src/sources/featureSource.js"
],
"external": []
}
}
+4 -1
View File
@@ -85,6 +85,7 @@ async function settleTraffic(page, view, { minCount = 1, timeoutS = 30 } = {}) {
const dm = gev.dataManager;
await dm.setEnabled('traffic', true);
const mod = dm.layers.get('traffic').module;
const beforeUpdate = mod.getStats().lastUpdate;
const ell = gev.viewer.scene.globe.ellipsoid;
const d2r = Math.PI / 180;
// The app's intro flyTo animation clobbers a setView issued mid-flight —
@@ -98,7 +99,9 @@ async function settleTraffic(page, view, { minCount = 1, timeoutS = 30 } = {}) {
for (let i = 0; i < tS; i++) {
await new Promise((r) => setTimeout(r, 1000));
s = mod.getStats();
if (s.count >= minC && !s.loading) break;
// Retained roads from the previous city can satisfy count/loading before
// the move debounce starts its request. Require the destination render.
if (s.lastUpdate !== beforeUpdate && s.count >= minC && !s.loading) break;
}
return s;
}, view, minCount, timeoutS);
+595
View File
@@ -0,0 +1,595 @@
/** Bound page promises as well as CDP itself; labels identify a stalled section. */
export function boundPageEvaluations(page, defaultTimeoutMs = 30000) {
const evaluate = page.evaluate.bind(page);
page.evaluate = (fn, ...args) => {
// The two long trace collectors pass their duration explicitly.
const duration =
args.find((v) => typeof v === 'number' && v >= 6000 && v <= 120000) || 0;
const timeoutMs = Math.max(
defaultTimeoutMs,
duration ? duration + 5000 : 0,
);
const label = String(fn).slice(0, 120).replace(/\s+/g, ' ');
return evaluate(
async (source, values, timeoutMs, label) => {
let timer;
try {
return await Promise.race([
// Puppeteer callbacks are standalone functions, just as in evaluate.
Promise.resolve().then(() => (0, eval)(`(${source})`)(...values)),
new Promise((_, reject) => {
timer = setTimeout(
() =>
reject(
new Error(
`Transit QA page wait timed out after ${timeoutMs} ms: ${label}`,
),
),
timeoutMs,
);
}),
]);
} finally {
clearTimeout(timer);
}
},
String(fn),
args,
timeoutMs,
label,
);
};
}
export async function reportTransitVisibility(page, label) {
const result = await page.evaluate(() => {
const app = window.__godsEyeView;
const layer = app.dataManager.layers.get('transit').module;
const state = layer._transitStateForTest();
return {
total: state._vehicles.size,
visible: state._visible.size,
moving: state._moving.size,
held: state._renderHeld,
requestRenderMode: app.viewer.scene.requestRenderMode,
renderLoop: app.viewer.useDefaultRenderLoop,
renderErrors: window.__transitRenderErrors || [],
bounds: state._viewBounds,
hidden: layer._transitVisibilityForTest().filter((e) => !e.shown),
};
});
console.log(` ${label}: ${JSON.stringify(result)}`);
if (result.renderLoop === false || result.renderErrors.length)
throw new Error(
`${label}: Cesium render loop stopped or raised an error: ${JSON.stringify(result.renderErrors)}`,
);
return result;
}
/** Intersect primed histories with the new snapshot; disappearance is availability. */
export async function restoreRetainedTransit(retained) {
if (!retained.length)
return {
error: 'No multi-fix history observed during the probe',
unexercised: true,
};
const app = window.__godsEyeView;
await app.dataManager.setEnabled('transit', true, { source: 'qa' });
const layer = app.dataManager.layers.get('transit').module;
const state = layer._transitStateForTest();
// enable() schedules proximity discovery; an empty pre-discovery map is not
// evidence that every primed vehicle departed. Wait for this feed's poll.
const deadline = Date.now() + 12000;
while (state._activeFeeds && !state._vehicles.size && Date.now() < deadline)
await new Promise((r) => setTimeout(r, 100));
await layer.update();
if (
retained[0]?.primedAt &&
Math.floor(Date.now() / 60000) !== Math.floor(retained[0].primedAt / 60000)
)
return {
error: 'Reload crossed the priming minute; same-minute proof unavailable',
unexercised: true,
};
const history = retained.find((h) =>
state._vehicles.has(`${h.feedId || 'mbta'}:${h.vehicleId}`),
);
if (!history)
return {
error: `All ${retained.length} primed vehicles left the current snapshot`,
unexercised: true,
};
const entry = state._vehicles.get(
`${history.feedId || 'mbta'}:${history.vehicleId}`,
);
const camera = app.viewer.camera,
C = camera.positionCartographic.constructor;
camera.setView({
destination: C.toCartesian(
C.fromDegrees(entry.record.lon, entry.record.lat, 600),
),
orientation: { heading: 0, pitch: -Math.PI / 2, roll: 0 },
});
layer._transitPartsForTest().selection.selectVehicle(entry.key);
return { key: entry.key, oldest: history.oldestT };
}
export async function sampleTransitPixels(page, palette) {
return page.evaluate(async (palette) => {
const app = window.__godsEyeView;
const state = app.dataManager.layers
.get('transit')
.module._transitStateForTest();
// Decode the actual billboard rasters before the paint being judged.
const overlay = window.location
? await import('/src/overlays/worldOverlay.js')
: null;
const rasters = new Map();
await Promise.all(
[
...new Set(
[...state._vehicles.values()]
.map((e) => e.marker?.image)
.filter(Boolean),
),
].map(async (url) => {
const img = new Image();
img.src = url;
await img.decode();
const c = document.createElement('canvas');
c.width = img.width;
c.height = img.height;
const ctx = c.getContext('2d');
ctx.drawImage(img, 0, 0);
rasters.set(url, {
width: c.width,
height: c.height,
data: ctx.getImageData(0, 0, c.width, c.height).data,
});
}),
);
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
remove();
reject(
new Error('Transit pixel readback: no postRender within 5000 ms'),
);
}, 5000);
const remove =
window.__godsEyeView.viewer.scene.postRender.addEventListener(() => {
const app = window.__godsEyeView;
const layer = app.dataManager.layers.get('transit').module;
const state = layer._transitStateForTest();
const scene = app.viewer.scene;
const canvas = scene.canvas;
const view = scene.camera.viewMatrix;
const proj = scene.camera.frustum.projectionMatrix;
const mul = (m, v) => [
m[0] * v[0] + m[4] * v[1] + m[8] * v[2] + m[12] * v[3],
m[1] * v[0] + m[5] * v[1] + m[9] * v[2] + m[13] * v[3],
m[2] * v[0] + m[6] * v[1] + m[10] * v[2] + m[14] * v[3],
m[3] * v[0] + m[7] * v[1] + m[11] * v[2] + m[15] * v[3],
];
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const sprites = [];
const footprints = [];
const intersects = (a, b) =>
a.x < b.x + b.w &&
a.x + a.w > b.x &&
a.y < b.y + b.h &&
a.y + a.h > b.y;
const plates =
app.styleManager
?.getDetectionDiagnostics?.()
?.calloutRects?.filter((r) => r.alpha > 0.01) || [];
if (state._selectedKey) {
const card = overlay?.getOverlayPaintRect(
'transit-selected',
state._selectedKey,
);
if (card) plates.push(card);
}
const panels = (overlay?.WORLD_OVERLAY_OCCLUDER_SELECTORS || [])
.flatMap((selector) => [...document.querySelectorAll(selector)])
.filter(
(el) =>
!el.hidden &&
el.checkVisibility({
checkOpacity: true,
checkVisibilityCSS: true,
}),
)
.map((el) => {
const r = el.getBoundingClientRect();
return { x: r.left, y: r.top, w: r.width, h: r.height };
});
const skipped = [];
const style = state._stylePreset;
const uniforms = app.styleManager?.stages?.[style]?.uniforms || {};
const intensity = uniforms.intensity ?? 1;
const pixelation =
uniforms.pixelation ?? (style === 'surveillance' ? 2.5 : 1.5);
const sensor = style === 'surveillance' || style === 'thermal';
// Invert NVG's barrel transform; thermal only quantizes the source.
const screenPoint = (sx, sy) => {
let x = sx,
y = sy;
if (style === 'surveillance') {
const tx = (sx / width) * 2 - 1,
ty = (sy / height) * 2 - 1;
let cx = tx,
cy = ty;
for (let i = 0; i < 16; i++) {
const r2 = cx * cx + cy * cy;
const d =
1 + r2 * intensity * 0.25 + r2 * r2 * intensity * 0.075;
cx = tx / d;
cy = ty / d;
}
x = ((cx + 1) * width) / 2;
y = ((cy + 1) * height) / 2;
}
const offset = sensor
? ((1 + (pixelation - 1) * intensity) * intensity) /
2 /
(canvas.width / width)
: 0;
return { x: x + offset, y: y - offset };
};
const uiBlocked = (x, y) => {
const el = document.elementFromPoint?.(x, y);
return (
el &&
el !== canvas &&
!el.closest?.(
'#world-overlay-root, #world-overlay-detection-surface',
) &&
el.tagName !== 'BODY' &&
el.tagName !== 'HTML'
);
};
for (const entry of state._vehicles.values()) {
if (!entry.marker || entry.marker.show === false) continue;
const p = entry.marker.position;
const clip = mul(proj, mul(view, [p.x, p.y, p.z, 1]));
if (!(clip[3] > 0)) continue;
const screen = entry.marker.computeScreenSpacePosition?.(scene) || {
x: ((clip[0] / clip[3]) * 0.5 + 0.5) * width,
y: (1 - ((clip[1] / clip[3]) * 0.5 + 0.5)) * height,
};
const rect = entry.marker.constructor.getScreenSpaceBoundingBox?.(
entry.marker,
screen,
) || { x: screen.x - 16, y: screen.y - 16, width: 32, height: 32 };
const { x, y } = screenPoint(screen.x, screen.y);
const c = Math.abs(Math.cos(entry.marker.rotation || 0)),
sn = Math.abs(Math.sin(entry.marker.rotation || 0));
const w = rect.width * c + rect.height * sn,
h = rect.height * c + rect.width * sn;
const footprint = { x: x - w / 2, y: y - h / 2, w, h };
footprints.push({ key: entry.key, ...footprint });
let reason = null;
if (
rect.x < 0 ||
rect.y < 0 ||
rect.x + rect.width > width ||
rect.y + rect.height > height
)
reason = 'billboard rectangle outside frame';
if (
entry.marker.color?.alpha < 0.95 ||
entry.markerCollection?.show === false
)
reason = 'billboard not opaque/collection hidden';
const raster = rasters.get(entry.marker.image);
if (!raster) reason = 'billboard alpha unavailable';
else if (
raster.data[
(Math.floor(raster.height / 2) * raster.width +
Math.floor(raster.width / 2)) *
4 +
3
] < 242
)
reason = 'billboard centre is transparent';
if (
sensor &&
Math.hypot(
(((x / width) * 2 - 1) * width) / height,
(y / height) * 2 - 1,
) > 0.6
)
reason = 'outside unmasked sensor lens';
if (style === 'noir') {
// Noir deliberately darkens the frame edges. Judge the core in
// its unmasked field, independently of the measured brightness.
const u = x / width,
v = y / height;
const transmission = Math.pow(
16 * u * (1 - u) * v * (1 - v),
0.3 + 0.4 * (uniforms.vignetteAmt ?? 0.5) * intensity,
);
if (1 - intensity + transmission * intensity < 0.9)
reason = 'outside unmasked noir field';
}
if (
[
[x, y],
[rect.x, rect.y],
[rect.x + rect.width, rect.y + rect.height],
[rect.x + rect.width, rect.y],
[rect.x, rect.y + rect.height],
].some(([px, py]) => uiBlocked(px, py))
)
reason = 'UI panel overlaps billboard';
if (panels.some((r) => intersects(footprint, r)))
reason = 'UI panel rectangle overlaps billboard';
if (plates.some((r) => intersects(footprint, r)))
reason = 'DETECT label/card rectangle overlaps billboard';
if (reason) {
skipped.push({ key: entry.key, reason });
continue;
}
if (x < 40 || y < 40 || x > width - 40 || y > height - 40) continue;
sprites.push({
key: entry.key,
mode: entry.mode,
x,
y,
selected: state._selectedKey === entry.key,
screenX: screen.x,
screenY: screen.y,
rect,
footprint,
bracketX: entry.detectContact?._candidateScreenX ?? screen.x,
bracketY: entry.detectContact?._candidateScreenY ?? screen.y,
raster,
rotation: entry.marker.rotation || 0,
halfW: Number.isFinite(entry.marker.width)
? Math.ceil(entry.marker.width / 2) + 2
: 11,
halfH: Number.isFinite(entry.marker.height)
? Math.ceil(entry.marker.height / 2) + 2
: 7,
});
}
const isolated = sprites.filter(
(a) =>
!a.selected &&
footprints.every(
(b) => b.key === a.key || !intersects(a.footprint, b),
),
);
const gl = canvas.getContext('webgl2') || canvas.getContext('webgl');
const scale = canvas.width / canvas.clientWidth;
const luma = (r, g, b) => (0.299 * r + 0.587 * g + 0.114 * b) / 255;
const readLuma = (cx, cy) => {
const px = Math.floor(cx * scale);
const py = Math.floor(canvas.height - 1 - cy * scale);
const buf = new Uint8Array(4);
gl.readPixels(px, py, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
return luma(buf[0], buf[1], buf[2]);
};
const surface = document.getElementById('world-overlay-canvas');
const ctx = surface?.getContext('2d');
// A hidden surface has no client size; nothing to read there.
const sscale =
surface && surface.clientWidth > 0
? surface.width / surface.clientWidth
: 0;
const out = [];
for (const s of isolated) {
if (out.length >= 12) break;
// The normal canvas includes DETECT plates and selected cards.
// A plate over the body invalidates this contact, even if WebGL below is hot.
if (ctx && sscale > 0) {
const body = ctx.getImageData(
Math.floor((s.x - 3) * sscale),
Math.floor((s.y - 3) * sscale),
Math.max(1, Math.ceil(6 * sscale)),
Math.max(1, Math.ceil(6 * sscale)),
).data;
if (body.some((v, i) => i % 4 === 3 && v > 0)) {
skipped.push({
key: s.key,
reason: 'DETECT label/card overlaps core',
});
continue;
}
}
// Picking is independent of rendered brightness: an overlapping
// label or sprite must not masquerade as a dim sensor signature.
// Check the whole sampled core, not just its centre pick.
let coreOwned = true;
if (scene.pick) {
const framebuffer = gl.getParameter?.(gl.FRAMEBUFFER_BINDING);
for (let dx = -1; dx <= 1; dx++)
for (let dy = -1; dy <= 1; dy++) {
let u = (s.x + dx) / width,
v = 1 - (s.y + dy) / height;
if (style === 'surveillance') {
const x = u * 2 - 1,
y = v * 2 - 1,
r2 = x * x + y * y;
const d =
1 + r2 * intensity * 0.25 + r2 * r2 * intensity * 0.075;
u = (x * d + 1) / 2;
v = (y * d + 1) / 2;
}
if (sensor) {
const grid = 1 + (pixelation - 1) * intensity;
u +=
((Math.floor((u * canvas.width) / grid) * grid) /
canvas.width -
u) *
intensity;
v +=
((Math.floor((v * canvas.height) / grid) * grid) /
canvas.height -
v) *
intensity;
}
const picked = scene.pick(
{ x: u * width, y: (1 - v) * height },
1,
1,
);
if (picked?.id !== s.key && picked?.primitive?.id !== s.key)
coreOwned = false;
}
if (gl.bindFramebuffer)
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
}
if (!coreOwned) {
skipped.push({
key: s.key,
reason:
'sampled core is partially obscured or outside the sprite',
});
continue;
}
let centre = 0;
for (let dx = -1; dx <= 1; dx += 1)
for (let dy = -1; dy <= 1; dy += 1)
centre += readLuma(s.x + dx, s.y + dy) / 9;
let ringMin = 1;
let ringMax = 0;
// Sample the actual rotated raster halo, not a fixed-radius circle
// that can hit the hot body or terrain after a display-size change.
const raster = s.raster;
const cos = Math.cos(s.rotation),
sin = Math.sin(s.rotation);
for (let ry = 1; ry < raster.height - 1; ry++)
for (let rx = 1; rx < raster.width - 1; rx++) {
const i = (ry * raster.width + rx) * 4;
if (
raster.data[i + 3] < 200 ||
raster.data[i] > 30 ||
raster.data[i + 1] > 30 ||
raster.data[i + 2] > 30
)
continue;
const dx = ((rx + 0.5) / raster.width - 0.5) * s.rect.width;
const dy = ((ry + 0.5) / raster.height - 0.5) * s.rect.height;
const q = screenPoint(
s.screenX + dx * cos + dy * sin,
s.screenY - dx * sin + dy * cos,
);
const v = readLuma(q.x, q.y);
ringMin = Math.min(ringMin, v);
ringMax = Math.max(ringMax, v);
}
let bracket = null;
if (ctx && sscale > 0) {
// Transit brackets follow the padded sprite extent and snapped
// stroke centres. Sample the middle of each straight segment,
// never a colour histogram containing antialiased edges/callouts.
const cx = Math.floor(s.bracketX) + 0.5,
cy = Math.floor(s.bracketY) + 0.5;
const hw = s.halfW,
hh = s.halfH,
mid = Math.max(4, Math.floor(Math.min(hw, hh) * 0.55)) / 2;
const points = [
[cx - hw + mid, cy - hh],
[cx + hw - mid, cy - hh],
[cx - hw + mid, cy + hh],
[cx + hw - mid, cy + hh],
[cx - hw, cy - hh + mid],
[cx + hw, cy - hh + mid],
[cx - hw, cy + hh - mid],
[cx + hw, cy + hh - mid],
];
let bestAlpha = 0;
for (const [index, [x, y]] of points.entries()) {
if (
uiBlocked(x, y) ||
plates.some((r) =>
intersects({ x: x - 1, y: y - 1, w: 2, h: 2 }, r),
)
)
continue;
// A label plate fills both sides of a stroke. Require empty
// pixels beyond its dark backing on the perpendicular axis.
const normal = index < 4 ? [0, 3] : [3, 0];
if (
[-1, 1].some(
(sign) =>
ctx.getImageData(
Math.floor((x + sign * normal[0]) * sscale),
Math.floor((y + sign * normal[1]) * sscale),
1,
1,
).data[3] > 0,
)
)
continue;
const data = ctx.getImageData(
Math.floor(x * sscale),
Math.floor(y * sscale),
1,
1,
).data;
if (data[3] > bestAlpha) {
bestAlpha = data[3];
bracket = [data[0], data[1], data[2]];
}
}
}
out.push({
key: s.key,
mode: s.mode,
verified: true,
rectangle: s.rect,
centre,
background:
[
readLuma(s.x + 25, s.y),
readLuma(s.x - 25, s.y),
readLuma(s.x, s.y + 25),
readLuma(s.x, s.y - 25),
].reduce((a, b) => a + b, 0) / 4,
ringMin,
ringMax,
bracket,
bracketTier: `transit_${s.mode}`,
bracketExpected: palette[s.mode]
? [1, 3, 5].map((i) =>
parseInt(palette[s.mode].slice(i, i + 2), 16),
)
: null,
x: s.x,
y: s.y,
});
}
clearTimeout(timer);
remove();
console.log(
`TRANSIT_SAMPLER ${style}: ${out.length} verified; skipped=${JSON.stringify(skipped)}`,
);
resolve(out);
});
window.__godsEyeView.viewer.scene.requestRender();
});
}, palette);
}
/** A fleet-to-fleet comparison must not inherit the city's selected marker. */
export function readTransitFleetStyle({ key, resetSelection = false } = {}) {
const layer = window.__godsEyeView.dataManager.layers.get('transit').module;
const state = layer._transitStateForTest();
if (resetSelection) layer._transitPartsForTest().selection.clearSelection();
const entry = key
? state._vehicles.get(key)
: [...state._vehicles.values()].find((e) => e.marker?.show);
return entry
? {
key: entry.key,
selected: state._selectedKey === entry.key,
color: entry.marker.color.toCssColorString(),
width: entry.marker.width,
image: entry.marker.image,
}
: null;
}
+204
View File
@@ -0,0 +1,204 @@
const pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export const BOSTON = {
id: 'boston',
label: 'Boston (MBTA)',
lat: 42.3554,
lon: -71.0605,
heading: 25,
zone: 'America/New_York',
};
const LIVE_CITIES = [
BOSTON,
{
id: 'austin',
label: 'Austin (CapMetro)',
lat: 30.2672,
lon: -97.7431,
heading: 340,
zone: 'America/Chicago',
},
{
id: 'minneapolis',
label: 'Minneapolis (Metro Transit)',
lat: 44.9778,
lon: -93.265,
heading: 0,
zone: 'America/Chicago',
},
{
id: 'helsinki',
label: 'Helsinki (HSL)',
lat: 60.1699,
lon: 24.9384,
heading: 0,
zone: 'Europe/Helsinki',
},
{
id: 'oslo',
label: 'Oslo (Entur)',
lat: 59.9139,
lon: 10.7522,
heading: 0,
zone: 'Europe/Oslo',
},
];
export function chooseLiveCities(now = new Date()) {
return LIVE_CITIES.filter((city) => {
const hour = Number(
new Intl.DateTimeFormat('en-US', {
timeZone: city.zone,
hour: 'numeric',
hourCycle: 'h23',
}).format(now),
);
return hour >= 6 && hour < 22;
}).slice(0, 2);
}
/**
* Switch the post-FX style the way a user does — the preset button — and
* fall back to the style manager only when the tray is not clickable, saying
* so. Then set any style parameters through their sliders.
* @param {import('puppeteer').Page} page
* @param {string} name
* @param {Record<string, number>} [params] aria-label → slider value
* @returns {Promise<string>} how the style was set
*/
export async function selectStyle(page, name, params = {}, wait = pause) {
let how = 'button';
// The presets live in the bottom control panel, which auto-dismisses when
// the pointer leaves it: pin it open the way a user does, once.
await page.evaluate(() => {
const panel = document.getElementById('control-panel');
if (panel && !panel.classList.contains('dock-pinned')) {
document
.querySelector('.dock-pin-btn[data-pin-target="control-panel"]')
?.click();
}
window.__godsEyeView.styleManager.setPanelCollapsed?.(
'control-panel',
false,
{ explicit: true },
);
});
await wait(400);
try {
await page.$eval(`.style-btn[data-style="${name}"]`, (el) =>
el.scrollIntoView({ block: 'center' }),
);
await page.click(`.style-btn[data-style="${name}"]`);
} catch {
how = 'styleManager.setStyle (button not clickable)';
await page.evaluate(
(n) => window.__godsEyeView.styleManager.setStyle(n),
name,
);
}
// A click can be swallowed by a loading cover or a collapsed tray without
// Puppeteer throwing. Verify the active style before querying generated rows.
if (
!(await page.evaluate(
(n) => document.documentElement.dataset.gevStyle === n,
name,
))
) {
how = 'styleManager.setStyle (button did not activate style)';
await page.evaluate(
(n) => window.__godsEyeView.styleManager.setStyle(n),
name,
);
}
await page.waitForFunction(
(n) => document.documentElement.dataset.gevStyle === n,
{ timeout: 10000 },
name,
);
await wait(1_800);
for (const [label, value] of Object.entries(params)) {
const selector = `#param-sliders input.param-slider[aria-label="${label}"]`;
await page.waitForSelector(selector, { timeout: 10000 });
await page.$eval(
selector,
(el, v) => {
el.value = String(v);
el.dispatchEvent(new Event('input', { bubbles: true }));
},
value,
);
await wait(700);
}
return how;
}
/**
* Turn DETECT on through its own button, cycling until the dense profile is
* reported on the detection surface.
* @param {import('puppeteer').Page} page
* @returns {Promise<string>} the profile reached
*/
export async function detectOn(page, wait = pause) {
// The real button toggles OFF/restore. Density determines its on-profile.
const mode = () =>
page.evaluate(() => {
const button = document.getElementById('detection-toggle');
const label = button?.getAttribute('aria-label') || '';
return {
on: button?.getAttribute('aria-pressed') === 'true',
mode: (label.split(':')[1] || 'off').trim().toUpperCase(),
};
});
// The loading screen swallows the first click of a fresh page.
await page
.waitForFunction(() => !document.getElementById('loading-screen'), {
timeout: 30_000,
})
.catch(() => {});
// The DISPLAY rail starts collapsed on a first run: open it the way a user
// does, then press DETECT until it reports on.
await page.evaluate(() => {
const rail = document.getElementById('pp-toggles');
if (rail?.classList.contains('collapsed'))
document
.querySelector('.panel-collapse-btn[data-collapse-target="pp-toggles"]')
?.click();
});
await page.waitForFunction(
() =>
document.getElementById('detection-toggle')?.getBoundingClientRect()
.width > 0,
{ timeout: 10_000 },
);
if (!(await mode()).on) {
await page.click('#detection-toggle');
await wait(300);
}
await page.$eval('#detection-density-slider', (el) => {
el.value = '100';
el.dispatchEvent(new Event('input', { bubbles: true }));
});
await page.waitForFunction(
() =>
document
.getElementById('detection-toggle')
?.getAttribute('aria-label') === 'Detection overlay: dense',
{ timeout: 10000 },
);
// Prove the button's actual OFF/restore cycle preserves DENSE.
await page.click('#detection-toggle');
await page.waitForFunction(
() =>
document
.getElementById('detection-toggle')
?.getAttribute('aria-pressed') === 'false',
{ timeout: 10000 },
);
await page.click('#detection-toggle');
await page.waitForFunction(
() =>
document
.getElementById('detection-toggle')
?.getAttribute('aria-label') === 'Detection overlay: dense',
{ timeout: 10000 },
);
return (await mode()).mode;
}
+583
View File
@@ -0,0 +1,583 @@
import { reportTransitVisibility } from './qa-transit-browser.mjs';
import { writeFile } from 'node:fs/promises';
import {
reduceFleet,
reduceMotion,
reduceBackground,
reduceSensorContrast,
} from '../src/layers/transit/qaMetrics.js';
/** CDP includes objects collected during the sample, not just surviving objects. */
export function allocationTotals(profile) {
let frameBytes = 0,
layerFrameBytes = 0,
sharedOverlayBytes = 0,
qaBytes = 0;
const allocators = new Map();
function visit(node, inFrame = false, inQa = false, inOverlay = false) {
const frame = node.callFrame || {},
name = frame.functionName || '',
url = frame.url || '';
const nested =
inFrame ||
name === 'onPreRender' ||
/^render\d*$/.test(name) ||
/^Scene\d*\.render$/.test(name);
// QA wraps the real frame callback: re-enter production attribution at its
// onPreRender boundary, but exclude QA's own Math/Cesium helper descendants.
const qa =
name === 'onPreRender'
? false
: inQa || /\/transit\/testing\.js(?:\?|$)/.test(url);
const overlay = inOverlay || name === '_drawOverlay';
const bytes = node.selfSize || 0;
if (nested) {
if (qa) qaBytes += bytes;
else {
frameBytes += bytes;
const allocator = `${name || '(anonymous)'} ${url.split('?')[0]}:${(frame.lineNumber ?? -1) + 1}`;
allocators.set(allocator, (allocators.get(allocator) || 0) + bytes);
if (overlay) sharedOverlayBytes += bytes;
if (
/\/layers\/transit\/|\/data\/(?:contactPlayback|contactTrailRenderer|transit[^/]*)\.js/.test(
url,
)
)
layerFrameBytes += bytes;
}
}
for (const child of node.children || []) visit(child, nested, qa, overlay);
}
visit(profile.head);
return {
frameBytes,
layerFrameBytes,
sharedOverlayBytes,
qaBytes,
topAllocators: [...allocators]
.sort((a, b) => b[1] - a[1])
.slice(0, 3)
.map(([allocator, bytes]) => ({ allocator, bytes })),
};
}
export async function runFleetBudgets({
page,
check,
wait,
shots,
tag,
detectOn,
selectStyle,
}) {
console.log(
'\n== moving fleet budgets: 1920×1080 CSS, warmed view, DETECT dense ==',
);
await selectStyle(page, 'normal');
await detectOn(page);
const cdp = await page.createCDPSession();
await cdp.send('HeapProfiler.enable');
for (const count of [800, 3000]) {
await page.evaluate(async (count) => {
const app = window.__godsEyeView;
await app.dataManager.setEnabled('transit', true, { source: 'qa' });
const camera = app.viewer.camera,
C = camera.positionCartographic.constructor;
camera.setView({
destination: C.toCartesian(
C.fromDegrees(-71.0605, 42.3554, count === 800 ? 600 : 30000),
),
orientation: { heading: 0, pitch: -Math.PI / 2, roll: 0 },
});
const layer = app.dataManager.layers.get('transit').module;
layer._transitPartsForTest().ingestion.abortAllInFlight();
layer._transitStateForTest()._activeFeeds.clear();
for (const key of layer._transitStateForTest()._vehicles.keys())
layer._transitPartsForTest().ingestion.removeVehicle(key);
}, count);
await wait(8000);
// Camera proximity can finish a live poll during tile warm-up. Remove it
// before the heap baseline, or its memory would discount the fixture fleet.
await page.evaluate(() => {
const layer =
window.__godsEyeView.dataManager.layers.get('transit').module;
const state = layer._transitStateForTest(),
parts = layer._transitPartsForTest();
parts.ingestion.abortAllInFlight();
state._activeFeeds.clear();
clearTimeout(state._cameraDebounceTimer);
state._cameraDebounceTimer = null;
for (const key of state._vehicles.keys())
parts.ingestion.removeVehicle(key);
parts.rendering.syncRenderHold();
window.__godsEyeView.viewer.scene.requestRender();
});
await wait(500);
await cdp.send('HeapProfiler.collectGarbage');
const before = await cdp.send('Runtime.getHeapUsage');
const loaded = await page.evaluate(
(count) =>
window.__godsEyeView.dataManager.layers
.get('transit')
.module._loadTransitFleetForTest(
count,
{ lat: 42.3554, lon: -71.0605 },
count === 800 ? 5 : 120,
),
count,
);
await reportTransitVisibility(
page,
`${count} budget visibility after load`,
);
await wait(2000);
await cdp.send('HeapProfiler.collectGarbage');
// The retained delta is conservative: it includes concurrent page growth.
const retained = await cdp.send('Runtime.getHeapUsage');
// Timing/upload acceptance runs without the allocation profiler attached.
const trace = await page.evaluate(() =>
window.__godsEyeView.dataManager.layers
.get('transit')
.module._measureTransitFramesForTest(8000),
);
await page.evaluate(() =>
window.__godsEyeView.dataManager.layers
.get('transit')
.module._resetTransitFixtureClockForTest(),
);
await wait(1500);
await cdp.send('HeapProfiler.startSampling', {
samplingInterval: 128,
includeObjectsCollectedByMajorGC: true,
includeObjectsCollectedByMinorGC: true,
});
await reportTransitVisibility(
page,
`${count} budget visibility before allocation trace`,
);
const allocationTrace = await page.evaluate(() =>
window.__godsEyeView.dataManager.layers
.get('transit')
.module._measureTransitFramesForTest(6000),
);
const { profile } = await cdp.send('HeapProfiler.stopSampling');
const allocations = allocationTotals(profile);
const retainedBytes = retained.usedSize - before.usedSize;
const evidence = reduceFleet(
trace.rows,
count,
allocations.layerFrameBytes / allocationTrace.rows.length,
retainedBytes,
loaded.fixBytes,
);
const details = {
...evidence,
...allocations,
wholeFrameBytesPerFrame:
allocations.frameBytes / allocationTrace.rows.length,
topAllocatorsPerFrame: allocations.topAllocators.map((a) => ({
...a,
bytesPerFrame: a.bytes / allocationTrace.rows.length,
})),
allocationFrames: allocationTrace.rows.length,
loaded,
dpr: trace.dpr,
viewport: [trace.width, trace.height],
heapMethod:
'GC-bracketed whole-page growth after fleet load (conservative)',
allocationMethod:
'CDP 128-byte sampling including collected objects; transit source self allocation gates, whole render stacks reported, QA scaffolding excluded',
};
await writeFile(
`${shots}/${tag}-fleet-${count}.json`,
JSON.stringify(details, null, 2),
);
await writeFile(
`${shots}/${tag}-fleet-${count}-allocations.json`,
JSON.stringify(profile),
);
check(
`${count} moving vehicles meet CPU, frame interval, billboard upload, heap and allocation budgets`,
evidence.pass && trace.width === 1920 && trace.height === 1080,
JSON.stringify(details),
);
check(
`${count}: transit-authored frame allocation <= 8 KiB`,
allocationTrace.rows.length >= 100 &&
reduceMotion(allocationTrace.rows).pass &&
allocationTrace.rows.every((r) => r.moving === count) &&
allocations.layerFrameBytes / allocationTrace.rows.length <= 8192,
`${allocations.layerFrameBytes / allocationTrace.rows.length} transit-authored bytes/frame; whole frame ${allocations.frameBytes / allocationTrace.rows.length}; top three ${JSON.stringify(details.topAllocatorsPerFrame)}; collected objects included. Full profile saved.`,
);
await page.screenshot({
path: `${shots}/${tag}-fleet-${count}.jpg`,
type: 'jpeg',
quality: 85,
});
const settled = await page.evaluate(async () => {
const layer =
window.__godsEyeView.dataManager.layers.get('transit').module;
const state = layer._transitStateForTest();
const { seek } = await import('/src/data/contactPlayback.js');
const { updatePlayback } =
await import('/src/layers/transit/movement.js');
for (const entry of state._vehicles.values()) {
entry.clocks.wallNowMs = Date.now();
entry.clocks.monoNowMs = performance.now();
seek(entry.track, entry.fixes.at(-1).t, entry.clocks);
updatePlayback(entry, Date.now(), performance.now());
layer._transitPartsForTest().rendering.schedulePlayback(entry);
}
layer._transitPartsForTest().rendering.syncRenderHold();
return { moving: state._moving.size, held: state._renderHeld };
});
check(
`${count}: settling releases the transit hold`,
settled.moving === 0 && !settled.held,
JSON.stringify(settled),
);
}
await cdp.detach();
}
export async function runBostonMatrix({
page,
check,
wait,
shots,
tag,
selectStyle,
sampleRendered,
detectOn,
}) {
console.log(
'\n== Boston matrix: scripted Red, 741, 742, Green-E; actual map backgrounds ==',
);
await detectOn(page);
const routes = ['Red', '741', '742', 'Green-E'];
const looks = [
{ name: 'normal', style: 'normal', params: {} },
{ name: 'nvg', style: 'surveillance', params: {} },
{ name: 'noir', style: 'noir', params: {} },
{
name: 'white-hot',
style: 'thermal',
params: { 'WHOT/BHOT': 0, Ironbow: 0 },
},
{
name: 'black-hot',
style: 'thermal',
params: { 'WHOT/BHOT': 1, Ironbow: 0 },
},
{
name: 'ironbow',
style: 'thermal',
params: { 'WHOT/BHOT': 0, Ironbow: 1 },
},
];
// Actual Boston views. Acceptance checks the measured background; a tile/key
// failure or an unsuitable view is explicitly unexercised, never assumed bright/dark.
const backgrounds = [
{
name: 'bright',
candidates: [
{ lat: 42.3458, lon: -71.0464 },
{ lat: 42.3659, lon: -71.018 },
{ lat: 42.3526, lon: -71.0461 },
{ lat: 42.3486, lon: -71.0825 },
],
},
{
name: 'dark',
candidates: [
{ lat: 42.3574, lon: -71.0375 },
{ lat: 42.3554, lon: -71.0655 },
{ lat: 42.3588, lon: -71.0738 },
{ lat: 42.348, lon: -71.032 },
],
},
];
const evidence = [];
for (const group of backgrounds) {
let background, backgroundResult;
const attempts = [];
await selectStyle(page, 'normal');
for (const candidate of group.candidates) {
background = { ...candidate, name: group.name };
await page.evaluate((b) => {
const camera = window.__godsEyeView.viewer.camera,
C = camera.positionCartographic.constructor;
camera.setView({
destination: C.toCartesian(C.fromDegrees(b.lon, b.lat, 600)),
orientation: { heading: 0, pitch: -Math.PI / 2, roll: 0 },
});
}, background);
await wait(8000);
await page.evaluate(
({ background, routes }) => {
const layer =
window.__godsEyeView.dataManager.layers.get('transit').module;
layer._loadTransitFleetForTest(8, background, 45, routes);
for (const entry of layer._transitStateForTest()._vehicles.values()) {
entry.track.rate = 0;
layer._transitPartsForTest().rendering.schedulePlayback(entry);
}
},
{ background, routes },
);
await wait(1000);
backgroundResult = reduceBackground(
group.name,
await sampleRendered(page),
);
attempts.push({ background, ...backgroundResult });
if (backgroundResult.pass) break;
}
check(
`Boston ${background.name}: all four routes over measured ${background.name} background`,
backgroundResult.pass,
JSON.stringify({ attempts, chosen: background }),
{ unexercised: !backgroundResult.pass },
);
for (const look of looks) {
await selectStyle(page, look.style, look.params);
await wait(1200);
await reportTransitVisibility(
page,
`Boston ${background.name}/${look.name} visibility`,
);
const pixels = await sampleRendered(page);
const modes = await page.evaluate(() => {
const layer =
window.__godsEyeView.dataManager.layers.get('transit').module;
return [...layer._transitStateForTest()._vehicles.values()].map(
(e) => ({
key: e.key,
route: e.record.routeId,
image: e.marker.image,
width: e.marker.width,
color: e.marker.color.toCssHexString(),
}),
);
});
const contrast =
look.name === 'normal'
? null
: reduceSensorContrast(
pixels,
look.name === 'black-hot' ? 'black' : 'white',
look.style,
);
check(
`Boston ${background.name}/${look.name}: all four silhouettes and mode brackets readable`,
pixels.length >= 6 &&
pixels.every(
(p) =>
p.bracket &&
p.bracketExpected &&
Math.hypot(...p.bracket.map((v, i) => v - p.bracketExpected[i])) <
48,
) &&
(!contrast || contrast.pass),
JSON.stringify({ pixels, contrast }),
{ unexercised: pixels.length < 6 },
);
await page.screenshot({
path: `${shots}/${tag}-matrix-${background.name}-${look.name}-fleet.jpg`,
type: 'jpeg',
quality: 90,
});
for (const target of modes) {
await page.evaluate(
(key) =>
window.__godsEyeView.dataManager.layers
.get('transit')
.module._transitPartsForTest()
.selection.selectVehicle(key),
target.key,
);
await wait(500);
await page.screenshot({
path: `${shots}/${tag}-matrix-${background.name}-${look.name}-${target.route}-selected.jpg`,
type: 'jpeg',
quality: 90,
});
const restored = await page.evaluate((key) => {
const layer =
window.__godsEyeView.dataManager.layers.get('transit').module;
layer._transitPartsForTest().selection.clearSelection();
const e = layer._transitStateForTest()._vehicles.get(key);
return {
image: e.marker.image,
width: e.marker.width,
color: e.marker.color.toCssHexString(),
};
}, target.key);
check(
`Boston ${background.name}/${look.name}/${target.route}: deselect restores fleet styling`,
restored.image === target.image &&
restored.width === target.width &&
restored.color === target.color,
);
}
await wait(300);
await page.screenshot({
path: `${shots}/${tag}-matrix-${background.name}-${look.name}-restored.jpg`,
type: 'jpeg',
quality: 90,
});
evidence.push({
background,
look,
pixels,
routes: modes.map((m) => m.route),
});
}
}
await selectStyle(page, 'normal');
await writeFile(
`${shots}/${tag}-boston-matrix.json`,
JSON.stringify(evidence, null, 2),
);
}
/** Real MBTA observations at oblique street views, separate from matrix fixtures. */
export async function runBostonLive({
page,
check,
wait,
shots,
tag,
detectOn,
selectStyle,
sampleRendered,
}) {
console.log('\n== Boston live oblique streets ==');
await page.evaluate(async () => {
const app = window.__godsEyeView;
await app.dataManager.setEnabled('transit', false, { source: 'qa' });
const camera = app.viewer.camera,
C = camera.positionCartographic.constructor;
camera.setView({
destination: C.toCartesian(C.fromDegrees(-71.0605, 42.3554, 600)),
orientation: { heading: 0, pitch: -Math.PI / 4, roll: 0 },
});
await app.dataManager.setEnabled('transit', true, { source: 'qa' });
const layer = app.dataManager.layers.get('transit').module;
layer._setTransitFixtureFloorsForTest([], 0);
await layer.update();
});
await wait(20000);
await detectOn(page);
const evidence = [];
for (const view of [
{
name: 'white-hot',
style: 'thermal',
altitude: 120,
heading: 0,
pitch: -20,
params: { 'WHOT/BHOT': 0, Ironbow: 0 },
},
{
name: 'nvg',
style: 'surveillance',
altitude: 600,
heading: 30,
pitch: -45,
params: {},
},
{
name: 'noir',
style: 'noir',
altitude: 400,
heading: 60,
pitch: -35,
params: {},
},
]) {
await page.evaluate((view) => {
const app = window.__godsEyeView,
camera = app.viewer.camera,
C = camera.positionCartographic.constructor;
app.dataManager.layers
.get('transit')
.module._transitPartsForTest()
.selection.clearSelection();
camera.setView({
destination: C.toCartesian(
C.fromDegrees(-71.0605, 42.3554, view.altitude),
),
orientation: {
heading: (view.heading * Math.PI) / 180,
pitch: (view.pitch * Math.PI) / 180,
roll: 0,
},
});
}, view);
await selectStyle(page, view.style, view.params);
await wait(8000);
const fleet = await page.evaluate(() => {
const state = window.__godsEyeView.dataManager.layers
.get('transit')
.module._transitStateForTest();
const entries = [...state._vehicles.values()];
return {
total: entries.length,
visible: entries.filter((e) => e.marker?.show).length,
fixtures: entries.filter((e) => e.qaFixture).length,
routes: [
...new Set(
entries.filter((e) => e.marker?.show).map((e) => e.record.routeId),
),
],
};
});
check(
`Boston live/${view.name}: observed vehicles in the oblique street view`,
fleet.total > 0 && fleet.visible > 0 && fleet.fixtures === 0,
JSON.stringify({ view, fleet }),
{ unexercised: fleet.visible === 0 },
);
const pixels = await sampleRendered(page);
const contrast = reduceSensorContrast(pixels, 'white', view.style);
check(
`Boston live/${view.name}: unobscured sensor contrast`,
contrast.pass,
JSON.stringify(contrast),
{ unexercised: contrast.unexercised },
);
const target = pixels[0];
let selection = null;
if (target) {
await page.mouse.click(target.x, target.y);
await wait(250);
selection = await page.evaluate((key) => {
const state = window.__godsEyeView.dataManager.layers
.get('transit')
.module._transitStateForTest();
return {
expected: key,
actual: state._selectedKey,
pick: state._lastPickForTest ?? null,
};
}, target.key);
}
check(
`Boston live/${view.name}: real mouse selects an observed vehicle`,
selection?.actual === target?.key && !!target,
JSON.stringify(selection),
{ unexercised: !target },
);
await page.screenshot({
path: `${shots}/${tag}-boston-live-${view.name}.jpg`,
type: 'jpeg',
quality: 90,
});
evidence.push({ view, fleet, pixels, contrast, selection });
}
await writeFile(
`${shots}/${tag}-boston-live.json`,
JSON.stringify(evidence, null, 2),
);
}
File diff suppressed because it is too large. Load diff
+139 -32
View File
@@ -2860,6 +2860,55 @@ async function main() {
tick();
setTimeout(() => { done = true; res(); }, ms);
});
// A timer can expire while the camera is new but the model/cache still
// belongs to the old frame. Observe the first completed exit frame,
// including a wrong result; never wait for visibility or height to pass.
window.__dfObserveTrackedExit = async ({ scene, trackedEntity, trackedModel,
getTrackedModel, getTrackedEntity, getTrackedId, getCameraHeight,
exitHeight, read, now = Date.now, setTimer = setTimeout, clearTimer = clearTimeout }) => {
const deadline = now() + 5000;
let removePre, removePost, removeError, timer;
let preFrame = null;
try {
return await new Promise((resolve) => {
let finished = false;
const finish = (result) => { if (!finished) { finished = true; resolve(result); } };
const valid = () => {
try {
if (now() > deadline) return 'tracked exit observation exceeded its 5000 ms deadline';
if (getTrackedEntity() !== trackedEntity || getTrackedId() !== 'aaa097') return 'tracked exit fixture identity changed';
if (!trackedModel || getTrackedModel() !== trackedModel) return 'tracked exit model identity changed';
if (!(getCameraHeight() > exitHeight)) return 'tracked exit camera left the exit regime';
return null;
} catch { return 'tracked exit fixture validation failed'; }
};
removePre = scene.preUpdate.addEventListener(() => {
if (finished) return;
const error = valid();
if (error) { finish({ error }); return; }
if (preFrame == null) preFrame = scene.frameState.frameNumber;
});
removePost = scene.postRender.addEventListener(() => {
if (finished || preFrame == null) return;
const error = valid();
if (error) { finish({ error }); return; }
if (scene.frameState.frameNumber === preFrame) {
finish({ error: 'tracked exit observation has no new rendered frame' }); return;
}
try {
const snapshot = read();
finish(snapshot ? { ...snapshot, observationFrame: scene.frameState.frameNumber }
: { error: 'tracked exit snapshot missing' });
} catch { finish({ error: 'tracked exit snapshot failed' }); }
});
removeError = scene.renderError.addEventListener(() => finish({ error: 'tracked exit render failed' }));
timer = setTimer(() => finish({ error: 'tracked exit update did not complete within 5000 ms' }), 5000);
scene.requestRender();
});
} finally {
clearTimer(timer); removePre?.(); removePost?.(); removeError?.();
}
};
// Cesium Models in the scene, split by visibility (duck-typed the same
// way the harness excludes them from height probes).
//
@@ -3378,10 +3427,30 @@ async function main() {
// 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 findOwnModel = () => {
let found = null;
const walk = (collection) => {
for (let i = 0; i < collection.length; i++) {
const item = collection.get(i);
if (typeof item?.get === 'function' && typeof item.length === 'number') walk(item);
else if (item?.id === 'aaa097' && item.activeAnimations !== undefined
&& item.minimumPixelSize !== undefined) found = item;
}
};
walk(v.scene.primitives);
return found;
};
const trackedEntity = v.trackedEntity;
const trackedModel = findOwnModel();
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 zoomedOut = await window.__dfObserveTrackedExit({
scene: v.scene, trackedEntity, trackedModel, getTrackedModel: findOwnModel,
getTrackedEntity: () => v.trackedEntity,
getTrackedId: () => fl.getTrackedInfo()?.icao24,
getCameraHeight: window.__dfCamH, exitHeight: window.__dfRegime.exit,
read: readTracked,
});
if (zoomedOut.error) return { error: zoomedOut.error };
const out = {
rawH: d0.h,
@@ -3643,11 +3712,10 @@ async function main() {
}
// ---- 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.
// Stress the fleet ownership predicate with synthetic show=true/ready=false
// flags. Production admission keeps the model hidden; these shadows do
// not simulate Cesium's internal loading/draw state. The tracked check
// below separately samples the no-rendering-model window.
const dfLoading = await evalPage(async () => {
const v = window.__godsEyeView.viewer;
const Cesium = await import('/node_modules/cesium/Build/Cesium/index.js');
@@ -3663,13 +3731,8 @@ async function main() {
};
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`).
// (a) FLEET: retain the adversarial flags until this contact has passed
// through its installed fleet update and that frame has completed.
const findFleetModel = (id) => {
let found = null;
const walk = (coll) => {
@@ -3698,8 +3761,26 @@ async function main() {
// 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.
const priorReady = Object.getOwnPropertyDescriptor(fleetModel, 'ready');
const priorShow = Object.getOwnPropertyDescriptor(fleetModel, 'show');
let armed = false;
let processedFrame = null;
let sample = null;
let removePostRender = null;
try {
Object.defineProperty(fleetModel, 'ready', { get: () => false, set: () => {}, configurable: true });
Object.defineProperty(fleetModel, 'show', { get: () => true, set: () => {}, configurable: true });
Object.defineProperty(fleetModel, 'show', {
get: () => true,
set: (value) => {
// Both the not-ready handoff and horizon cull clear show AFTER
// computing this contact's display floor. Neither a timer nor an
// unrelated rendered frame proves that this aircraft was processed.
if (armed && value === false && processedFrame == null) {
processedFrame = v.scene.frameState.frameNumber;
}
},
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
@@ -3713,21 +3794,45 @@ async function main() {
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 });
const tickDeadline = Date.now() + 5000;
removePostRender = v.scene.postRender.addEventListener(() => {
if (sample || processedFrame == null || v.scene.frameState.frameNumber < processedFrame) return;
if (Date.now() > tickDeadline) {
sample = { error: 'fleet loading fixture completed after its 5000 ms deadline' };
return;
}
const currentBb = window.__dfFindBB('aaa097');
const currentModel = findFleetModel('aaa097');
sample = {
fleetTickCompleted: true,
fleetFrame: v.scene.frameState.frameNumber,
fleetModelReady: fleetModel.ready,
fleetModelShow: fleetModel.show,
fleetBillboardVisible: !!currentBb?.show,
fleetSeeded: seededFleet,
fleetH: currentBb ? window.__dfCarto(currentBb.position).h : null,
};
if (currentBb !== bb || currentModel !== fleetModel || fleetModel.isDestroyed()
|| fl.getTrackedInfo()) sample.error = 'fleet loading fixture changed before its completed frame';
});
armed = true;
// This is a setup-completion deadline, not a visual latency budget.
// Take the FIRST completed fleet result, even when its height is wrong;
// never poll the height until the assertion happens to pass.
do {
await window.__dfSettle(50);
} while (!sample && Date.now() < tickDeadline);
if (!sample) return { error: 'fleet loading fixture did not complete an aircraft update within 5000 ms' };
Object.assign(out, sample);
} finally {
armed = false;
removePostRender?.();
if (priorReady) Object.defineProperty(fleetModel, 'ready', priorReady);
else delete fleetModel.ready;
if (priorShow) Object.defineProperty(fleetModel, 'show', priorShow);
else delete fleetModel.show;
fl.setParams({ models3d: false });
}
await window.__dfSettle(400);
// (b) TRACKED, regime ACTIVE but no model yet. Turning 3D on while
@@ -3771,7 +3876,8 @@ async function main() {
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.error && dfLoading.fleetTickCompleted === true
&& dfLoading.fleetModelShow === true && dfLoading.fleetModelReady === false
&& dfLoading.fleetBillboardVisible === true
&& Number.isFinite(dfLoading.fleetH)
&& dfLoading.fleetH >= dfLoading.fleetSeeded + DISPLAY_FLOOR_LIFT_M - 0.5,
@@ -3955,6 +4061,7 @@ async function main() {
delete window.__dfPriorTilesLoadedDescriptor;
delete window.__dfSkinSamples;
delete window.__dfSkinM;
delete window.__dfObserveTrackedExit;
await fl.update(v);
});