Merge branch 'main' into exp/cyclone-shared-context

This commit is contained in:
German Khokhlov authored and GitHub committed 2026-11-06 16:03:13 +04:00
commit aca5317a2a
182 files changed
+28226 -558

No files matched your search

+87 -1
View File
@@ -1127,6 +1127,8 @@
"scripts/qa-status-badges.mjs",
"src/dockerTrustedPeers.test.mjs",
"src/cameraGlobeRotation.test.mjs",
"src/cameraTilt.test.mjs",
"src/ui/shellFacade.test.mjs",
"src/voice/globeResetConfirmation.test.mjs",
"src/hudDms.test.mjs",
"src/hudSummaryGate.test.mjs",
@@ -1268,5 +1270,89 @@
"src/voice/geminiTextChat.js",
"src/voice/panelLayout.js",
"src/voice/textChat.js",
"src/voice/textProtocol.js"
"src/voice/textProtocol.js",
"src/app/sourceComposition.js",
"src/app/sourceComposition.test.mjs",
"src/data/dataCredits.js",
"src/data/layerState.js",
"src/data/layerState.test.mjs",
"src/data/spriteOrder.js",
"src/i18n/locales/ar.json",
"src/i18n/locales/de.json",
"src/i18n/locales/es.json",
"src/i18n/locales/fr.json",
"src/i18n/locales/it.json",
"src/i18n/locales/ja.json",
"src/i18n/locales/pt.json",
"src/i18n/locales/ru.json",
"src/i18n/locales/uk.json",
"src/i18n/locales/zh-CN.json",
"src/i18n/locales/zh-Hant.json",
"src/i18n/same-as-english.json",
"src/navigationPolicy.js",
"src/overlays/worldOverlayDraw.js",
"src/overlays/worldOverlayDraw.test.mjs",
"src/sources/rateLimit.js",
"src/ui/layerNames.js",
"src/ui/styles/cyber.css",
"src/voice/layerManifest.js",
"src/worldFocus.js",
"src/worldFocus.test.mjs",
"server/providers/acartia.js",
"server/providers/acartia.test.mjs",
"server/providers/common/userAgent.js",
"server/providers/inaturalist/client.js",
"server/providers/inaturalist/observations.js",
"server/providers/inaturalist/observations.test.mjs",
"src/app/layers/wildlifeSightings.js",
"src/layers/wildlifeSightings/cards.js",
"src/layers/wildlifeSightings/cards.test.mjs",
"src/layers/wildlifeSightings/controls.js",
"src/layers/wildlifeSightings/docs.test.mjs",
"src/layers/wildlifeSightings/index.js",
"src/layers/wildlifeSightings/lifecycle.js",
"src/layers/wildlifeSightings/model.js",
"src/layers/wildlifeSightings/model.test.mjs",
"src/layers/wildlifeSightings/ownership.test.mjs",
"src/layers/wildlifeSightings/photos.js",
"src/layers/wildlifeSightings/photos.test.mjs",
"src/layers/wildlifeSightings/policy.js",
"src/layers/wildlifeSightings/records.js",
"src/layers/wildlifeSightings/records.test.mjs",
"src/layers/wildlifeSightings/rendering.js",
"src/layers/wildlifeSightings/selection.js",
"src/layers/wildlifeSightings/source.js",
"src/layers/wildlifeSightings/source.test.mjs",
"src/layers/wildlifeSightings/viewport.js",
"src/layers/wildlifeSightings/viewport.test.mjs",
"src/sources/rateLimit.test.mjs",
"src/layers/wildlifeSightings/bounds.js",
"src/layers/wildlifeSightings/acartiaTaxa.js",
"src/layers/wildlifeSightings/acquisition.test.mjs",
"server/providers/inaturalist/client.test.mjs",
"src/layers/wildlifeSightings/acartiaTaxa.test.mjs",
"src/ui/wildlifeSightingCard.test.mjs",
"src/overlays/wildlifeSightingOverlay.test.mjs",
"scripts/run-perf-tests.mjs",
"src/perfTestRunner.test.mjs",
"src/testSupport/wildlifeBillboardModel.mjs",
"src/layers/wildlifeSightings/gridViewport.test.mjs",
"src/layers/wildlifeSightings/rendering.test.mjs",
"src/layers/wildlifeSightings/sprites.test.mjs",
"src/layers/wildlifeSightings/performance.test.mjs",
"src/layers/wildlifeSightings/model.perf.test.mjs",
"src/ui/wildlifeSightingPlacement.js",
"server/providers/inaturalist/queue.js",
"server/providers/inaturalist/queue.test.mjs",
"server/providers/inaturalist/grid.js",
"server/providers/inaturalist/grid.test.mjs",
"server/providers/inaturalist/grid.fixture.mjs",
"src/layers/wildlifeSightings/performance.js",
"src/layers/wildlifeSightings/renderPerformanceFixtures.mjs",
"server/providers/inaturalist/speed.test.mjs",
"src/layers/wildlifeSightings/render.perf.test.mjs",
"src/layers/wildlifeSightings/cache.integration.test.mjs",
"src/layers/wildlifeSightings/density.test.mjs",
"src/layers/wildlifeSightings/selection.test.mjs",
"server/providers/inaturalist/proxy.fixture.mjs"
]
+160 -7
View File
@@ -39,6 +39,9 @@
"src/ui/views/panels/CockpitBriefing.vue",
"src/ui/views/panels/CockpitContext.vue",
"src/ui/views/panels/CockpitRoute.vue",
"src/ui/cockpitPresentation.js",
"src/data/headingDegrees.js",
"src/data/distanceFormat.js",
"src/ui/views/panels/CockpitRollingValue.vue",
"src/ui/views/panels/CockpitSignalList.vue",
"src/ui/views/panels/CockpitUtilityControls.vue",
@@ -151,7 +154,8 @@
"src/ui/views/panels/GlobeCompass.vue",
"src/ui/stores/recording.js",
"src/ui/styleParameters.js",
"src/ui/i18n.js"
"src/ui/i18n.js",
"src/ui/surfaceKeyboard.js"
],
"external": ["vue", "pinia", "vue-i18n"]
},
@@ -160,6 +164,7 @@
"modules": [
"src/app/viewer.js",
"src/app/atmosphereCompat.js",
"src/globeInView.js",
"src/sky/starrySky.js",
"src/sky/stars.js",
"src/data/bundledJson.js",
@@ -199,7 +204,22 @@
"src/data/aisStreamAdapter.js",
"src/data/aisWatchdog.js",
"src/sources/httpBody.js",
"src/i18n/marker.js"
"src/i18n/marker.js",
"server/providers/acartia.js",
"server/providers/common/rate-limit.js",
"server/providers/common/same-site.js",
"server/providers/common/userAgent.js",
"server/providers/inaturalist/client.js",
"server/providers/inaturalist/observations.js",
"src/layers/wildlifeSightings/records.js",
"src/layers/wildlifeSightings/policy.js",
"src/localRequestGate.mjs",
"src/sources/rateLimit.js",
"src/layers/wildlifeSightings/bounds.js",
"src/layers/wildlifeSightings/acartiaTaxa.js",
"server/providers/inaturalist/grid.js",
"src/layers/wildlifeSightings/gridViewport.js",
"server/providers/inaturalist/queue.js"
],
"external": ["ws"]
},
@@ -869,6 +889,7 @@
"src/ui/cockpitDisplayPortal.js",
"src/ui/displayPanelScroll.js",
"src/ui/cockpitInput.js",
"src/data/inputOwnership.js",
"src/ui/cockpitInstruments.js",
"src/ui/cockpitLayout.js",
"src/ui/cockpitPresentation.js",
@@ -997,6 +1018,7 @@
"src/ui/cockpitDisplayPortal.js",
"src/ui/displayPanelScroll.js",
"src/ui/cockpitInput.js",
"src/data/inputOwnership.js",
"src/ui/cockpitInstruments.js",
"src/ui/cockpitLayout.js",
"src/ui/cockpitPresentation.js",
@@ -1149,7 +1171,14 @@
"src/ui/stores/globeActions.js",
"src/ui/stores/recording.js",
"src/ui/i18n.js",
"src/ui/kit/UiSegmented.vue"
"src/ui/kit/UiSegmented.vue",
"src/ui/wildlifeSightingCard.js",
"src/layers/wildlifeSightings/records.js",
"src/layers/wildlifeSightings/acartiaTaxa.js",
"src/ui/views/panels/WildlifeSightingCard.vue",
"src/ui/wildlifeSightingPlacement.js",
"src/overlays/worldOverlayChrome.js",
"src/layers/wildlifeSightings/photoText.js"
],
"external": ["cesium", "vue", "pinia", "vue-i18n"]
},
@@ -2336,6 +2365,7 @@
"src/camera.js",
"src/cameraGroundGuard.js",
"src/cameraVerbs.js",
"src/globeInView.js",
"src/cctvFocusPolicy.js",
"src/cctvFocusRequest.js",
"src/celestialRing.js",
@@ -3264,7 +3294,32 @@
"src/voice/osmActions.js",
"src/layers/osmPlaces/index.js",
"src/app/layers/osmPlaces.js",
"src/voice/areaActions.js"
"src/voice/areaActions.js",
"src/app/layers/wildlifeSightings.js",
"src/layers/wildlifeSightings/cards.js",
"src/layers/wildlifeSightings/controls.js",
"src/layers/wildlifeSightings/index.js",
"src/layers/wildlifeSightings/lifecycle.js",
"src/layers/wildlifeSightings/model.js",
"src/layers/wildlifeSightings/photos.js",
"src/layers/wildlifeSightings/policy.js",
"src/layers/wildlifeSightings/records.js",
"src/layers/wildlifeSightings/rendering.js",
"src/layers/wildlifeSightings/density.js",
"src/layers/wildlifeSightings/selection.js",
"src/layers/wildlifeSightings/source.js",
"src/layers/wildlifeSightings/viewport.js",
"src/layers/wildlifeSightings/bounds.js",
"src/layers/wildlifeSightings/acartiaTaxa.js",
"src/ui/wildlifeSightingCard.js",
"src/ui/views/panels/WildlifeSightingCard.vue",
"src/layers/wildlifeSightings/gridViewport.js",
"src/layers/wildlifeSightings/billboardModel.js",
"src/layers/wildlifeSightings/sprites.js",
"src/ui/wildlifeSightingPlacement.js",
"src/overlays/worldOverlayChrome.js",
"src/layers/wildlifeSightings/photoText.js",
"src/layers/wildlifeSightings/performance.js"
],
"external": [
"hls.js",
@@ -3668,6 +3723,9 @@
"src/annotations/worldAnnotationRenderer.js",
"src/cameraGroundGuard.js",
"src/cameraVerbs.js",
"src/globeInView.js",
"src/scopeMaskPolicy.js",
"src/scopeMask.js",
"src/services/groundFloor.js",
"src/data/routeSteps.js",
"src/layers/directions/index.js",
@@ -3888,7 +3946,30 @@
"src/data/local_data/wof_neighborhoods/files.js",
"src/layers/osmPlaces/model.js",
"src/layers/osmPlaces/index.js",
"src/app/layers/osmPlaces.js"
"src/app/layers/osmPlaces.js",
"src/app/layers/wildlifeSightings.js",
"src/layers/wildlifeSightings/cards.js",
"src/layers/wildlifeSightings/controls.js",
"src/layers/wildlifeSightings/index.js",
"src/layers/wildlifeSightings/lifecycle.js",
"src/layers/wildlifeSightings/model.js",
"src/layers/wildlifeSightings/photos.js",
"src/layers/wildlifeSightings/policy.js",
"src/layers/wildlifeSightings/records.js",
"src/layers/wildlifeSightings/rendering.js",
"src/layers/wildlifeSightings/density.js",
"src/layers/wildlifeSightings/selection.js",
"src/layers/wildlifeSightings/source.js",
"src/layers/wildlifeSightings/viewport.js",
"src/ui/rail/utcClock.js",
"src/layers/wildlifeSightings/bounds.js",
"src/layers/wildlifeSightings/acartiaTaxa.js",
"src/layers/wildlifeSightings/gridViewport.js",
"src/layers/wildlifeSightings/billboardModel.js",
"src/layers/wildlifeSightings/sprites.js",
"src/overlays/worldOverlayChrome.js",
"src/layers/wildlifeSightings/photoText.js",
"src/layers/wildlifeSightings/performance.js"
],
"external": [
"hls.js",
@@ -4424,7 +4505,15 @@
"src/layers/airQuality/model.js",
"src/layers/airQuality/source.js",
"src/layers/droneAirspace/source.js",
"src/layers/droneAirspace/records.js"
"src/layers/droneAirspace/records.js",
"src/layers/wildlifeSightings/policy.js",
"src/layers/wildlifeSightings/records.js",
"src/layers/wildlifeSightings/source.js",
"src/layers/wildlifeSightings/viewport.js",
"src/layers/wildlifeSightings/bounds.js",
"src/layers/wildlifeSightings/acartiaTaxa.js",
"src/layers/wildlifeSightings/gridViewport.js",
"src/layers/wildlifeSightings/performance.js"
],
"external": []
},
@@ -4575,7 +4664,8 @@
"src/i18n/locales/ru.json",
"src/i18n/locales/uk.json",
"src/i18n/locales/zh-CN.json",
"src/i18n/locales/zh-Hant.json"
"src/i18n/locales/zh-Hant.json",
"src/overlays/worldOverlayChrome.js"
],
"external": ["cesium", "egm96-universal", "pbf"]
},
@@ -5057,5 +5147,68 @@
"src/i18n/marker.js"
],
"external": ["cesium"]
},
"wildlife-sightings": {
"exports": ["./layers/wildlife-sightings"],
"modules": [
"src/data/dataCredits.js",
"src/data/iconOrientation.js",
"src/i18n/index.js",
"src/i18n/locale.js",
"src/i18n/locales/ar.json",
"src/i18n/locales/de.json",
"src/i18n/locales/es.json",
"src/i18n/locales/fr.json",
"src/i18n/locales/it.json",
"src/i18n/locales/ja.json",
"src/i18n/locales/pt.json",
"src/i18n/locales/ru.json",
"src/i18n/locales/uk.json",
"src/i18n/locales/zh-CN.json",
"src/i18n/locales/zh-Hant.json",
"src/i18n/marker.js",
"src/layers/wildlifeSightings/cards.js",
"src/layers/wildlifeSightings/controls.js",
"src/layers/wildlifeSightings/index.js",
"src/layers/wildlifeSightings/lifecycle.js",
"src/layers/wildlifeSightings/model.js",
"src/layers/wildlifeSightings/photos.js",
"src/layers/wildlifeSightings/policy.js",
"src/layers/wildlifeSightings/records.js",
"src/layers/wildlifeSightings/rendering.js",
"src/layers/wildlifeSightings/density.js",
"src/layers/wildlifeSightings/selection.js",
"src/layers/wildlifeSightings/source.js",
"src/layers/wildlifeSightings/viewport.js",
"src/overlays/worldOverlayDraw.js",
"src/overlays/worldOverlayTokens.js",
"src/sources/httpBody.js",
"src/layers/wildlifeSightings/bounds.js",
"src/layers/wildlifeSightings/acartiaTaxa.js",
"src/ui/statusText.js",
"src/ui/layerNames.js",
"src/layers/wildlifeSightings/gridViewport.js",
"src/layers/wildlifeSightings/billboardModel.js",
"src/layers/wildlifeSightings/sprites.js",
"src/layers/wildlifeSightings/photoText.js",
"src/layers/wildlifeSightings/performance.js"
],
"external": ["cesium"]
},
"wildlife-sightings-source": {
"exports": ["./layers/wildlife-sightings/source"],
"modules": [
"src/i18n/marker.js",
"src/layers/wildlifeSightings/policy.js",
"src/layers/wildlifeSightings/records.js",
"src/layers/wildlifeSightings/source.js",
"src/layers/wildlifeSightings/viewport.js",
"src/sources/httpBody.js",
"src/layers/wildlifeSightings/bounds.js",
"src/layers/wildlifeSightings/acartiaTaxa.js",
"src/layers/wildlifeSightings/gridViewport.js",
"src/layers/wildlifeSightings/performance.js"
],
"external": []
}
}
+19 -10
View File
@@ -2321,9 +2321,11 @@ async function runBehaviorLayer() {
`result=${JSON.stringify(r)?.slice(0, 120)} state=${JSON.stringify(contextExited)?.slice(0, 80)}`,
);
// (9f) With Contacts OFF the entry gate is shut. Entry must refuse with the
// reason rather than produce the half-entered state the operator saw: a
// plane anchored under the camera with no HUD and no exit control.
// (9f) Cockpit needs only the tracked aircraft's own layer, not Contacts.
// With Contacts OFF, status must explain a shut gate without blaming
// Contacts, and entry must either enter cleanly or refuse with the reason
// rather than produce the half-entered state the operator saw: a plane
// anchored under the camera with no HUD and no exit control.
r = await run('control_cockpit', { action: 'status' });
const gateReport = r?.state || {};
const cockpitBeforeGate = await page.evaluate(() =>
@@ -2331,10 +2333,13 @@ async function runBehaviorLayer() {
);
report(
gateReport.active === false &&
gateReport.entryAllowed === false &&
gateReport.entryBlockedReason === 'contacts-inactive' &&
(gateReport.entryAllowed === true
? gateReport.entryBlockedReason === null
: ['subject-layer-off', 'no-tracked-aircraft'].includes(
gateReport.entryBlockedReason,
)) &&
!cockpitBeforeGate,
'behavior: cockpit status names why entry is blocked with Contacts off',
'behavior: cockpit status explains its gate without requiring Contacts',
`state=${JSON.stringify(gateReport)?.slice(0, 150)}`,
);
@@ -2348,12 +2353,16 @@ async function runBehaviorLayer() {
Boolean(window.__godsEyeView?.styleManager?.cockpitView?.active),
);
report(
gated?.ok === false &&
/contacts/i.test(gated?.error || '') &&
!cockpitAfterGate,
'behavior: cockpit entry with Contacts off is refused, not half-entered',
gated?.ok === true
? cockpitAfterGate
: !cockpitAfterGate && !/contacts/i.test(gated?.error || ''),
'behavior: cockpit entry with Contacts off follows the own-layer gate, never half-entered',
`ok=${gated?.ok} error=${String(gated?.error || '').slice(0, 90)} active=${cockpitAfterGate}`,
);
if (cockpitAfterGate)
await page.evaluate(() =>
window.__godsEyeView?.styleManager?.controlCockpit?.('exit'),
);
await runBundledOutlineScenarios({
page,
+59
View File
@@ -0,0 +1,59 @@
import { spawnSync } from 'node:child_process';
import path from 'node:path';
import { pathToFileURL } from 'node:url';
import {
discoverUnitTestFiles,
UNIT_TEST_NODE_FLAGS,
} from './run-unit-tests.mjs';
/** Discover every layer/provider benchmark, including those added by other branches. */
export function discoverPerfTestFiles(root = process.cwd()) {
return discoverUnitTestFiles(root).filter((file) =>
file.endsWith('.perf.test.mjs'),
);
}
/** Shared by benchmarks so normal unit runs visibly skip timing assertions. */
export function perfBudgetTestOptions(env = process.env) {
return {
skip:
env.GEV_PERF_BUDGETS === '1'
? false
: 'Timing budgets are opt-in; run npm run test:perf (GEV_PERF_BUDGETS=1). Deterministic delta/write checks still run in the normal suite.',
};
}
/** Build a serial invocation so benchmarks do not compete for CPU time. */
export function perfTestArgs(files) {
// A single serial test process keeps benchmark files from competing with
// each other; the normal suite still discovers them and reports their skips.
return [
...UNIT_TEST_NODE_FLAGS,
'--test',
'--test-concurrency=1',
'--test-isolation=none',
...files,
];
}
/** Run discovered benchmarks with wall-clock budgets enabled. */
export function runPerfTests({
root = process.cwd(),
env = process.env,
run = spawnSync,
} = {}) {
const files = discoverPerfTestFiles(root);
if (!files.length) throw new Error('No *.perf.test.mjs benchmarks found');
const result = run(process.execPath, perfTestArgs(files), {
cwd: root,
stdio: 'inherit',
env: { ...env, GEV_PERF_BUDGETS: '1' },
});
if (result.error) throw result.error;
return result.status ?? 1;
}
const invoked = process.argv[1]
? pathToFileURL(path.resolve(process.argv[1])).href
: '';
if (import.meta.url === invoked) process.exitCode = runPerfTests();