From 504f9342aab147c0a3846f9f7bc5b2ad29a5461e Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Thu, 22 Oct 2026 18:53:56 -0700 Subject: [PATCH] chore: remove unreachable legacy entry modules Delete three modules that no entry point, package export, test or script imports: - src/ui.js, a StyleManager subclass that pre-selected the standalone catalog. Application controls are built through src/app/controls.js and src/standalone/controls.js. - src/standalone/ui.js, a bare re-export of StyleManager. - src/data/localLayers.js, a list of default infrastructure, cable and FIRMS layer instances. The catalog builds these layers itself. With src/ui.js gone, the import-direction check keeps a single compatibility exception (server/providers/local.js to server/standalone/key-setup.js), and its test now asserts that a src/ui.js importing standalone code is rejected. The boundary and format registries and the docs that named these files are updated. --- CONTRIBUTING.md | 2 +- docs/CODE-BOUNDARIES.md | 12 +++++------- docs/CURRENT-STATE.md | 8 ++++---- scripts/check-import-directions.mjs | 7 +++---- scripts/format-scope.json | 2 -- scripts/package-boundaries.json | 1 - src/data/localLayers.js | 18 ------------------ src/standalone/ui.js | 1 - src/tooling/importDirections.test.mjs | 9 +++++++-- src/ui.js | 16 ---------------- 10 files changed, 20 insertions(+), 56 deletions(-) delete mode 100644 src/data/localLayers.js delete mode 100644 src/standalone/ui.js delete mode 100644 src/ui.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 442b9c1bf..bb2c2de9e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -116,7 +116,7 @@ The highest-leverage places to jump in: ## Architecture in one minute - **No framework.** Vanilla JS + [CesiumJS](https://cesium.com/platform/cesiumjs/) + [Vite](https://vitejs.dev/). -- **Assembly lives in `src/app/`; standalone defaults live in `src/standalone/`.** UI controllers live in `src/ui/`, layer factories in `src/layers/`, portable sources in `src/sources/`, and application operations in `src/services/`. Existing `src/ui.js` and `src/data/.js` entries retain compatibility; new code belongs with its focused owner. +- **Assembly lives in `src/app/`; standalone defaults live in `src/standalone/`.** UI controllers live in `src/ui/`, layer factories in `src/layers/`, portable sources in `src/sources/`, and application operations in `src/services/`. Existing `src/data/.js` entries retain compatibility; new code belongs with its focused owner. - Sources acquire records; renderers own Cesium resources. Import `gods-eye-view/layers//source` when only a source factory is needed. Common voice controls consume the session interface; protocol adapters own connection details. - **Secrets stay server-side.** Anything needing a private key goes through a local proxy under `server/providers/`. The browser only ever sees the Google Maps key (which you restrict) and ephemeral tokens. - `docs/CURRENT-STATE.md` is the authoritative runtime reference β€” read it first. diff --git a/docs/CODE-BOUNDARIES.md b/docs/CODE-BOUNDARIES.md index a23ba3e0f..3362b98f0 100644 --- a/docs/CODE-BOUNDARIES.md +++ b/docs/CODE-BOUNDARIES.md @@ -79,7 +79,6 @@ moves it. Do not label all ingestion modules platform-independent by filename. | Retained entry | Owner and current reason | | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -| `src/ui.js` | UI facade; direct callers retain standalone StyleManager defaults. Normal assembly uses `src/ui/composition.js` | | `src/data/manager.js` | Lifecycle/panel compatibility and existing tests; normal assembly constructs lifecycle and presentation separately | | `src/data/.js` | Legacy default instances; new assembly calls layer factories with supplied sources | | `src/data/localGeojson.js` | Infrastructure compatibility factories; catalog imports services from `src/app/localGeojsonServices.js` directly | @@ -87,9 +86,8 @@ moves it. Do not label all ingestion modules platform-independent by filename. | `src/app/sources.js`, `src/services/application.js` | Existing default/override API; current application construction supplies its own instances | | `server/providers/local.js` | Existing Node composition barrel and provider helper re-exports | -The two exact standalone-import exceptions are `src/ui.js` to -`src/standalone/catalog.js` and `server/providers/local.js` to -`server/standalone/key-setup.js`. They do not authorize new compatibility +The one exact standalone-import exception is `server/providers/local.js` to +`server/standalone/key-setup.js`. It does not authorize new compatibility back-edges. Voice actions use plain `src/data/feedState.js`, not the manager facade. Settings filesystem hardening belongs in `server/standalone/key-setup-hardening.mjs`; its settings policy is unchanged. @@ -237,7 +235,7 @@ DOM elements and callbacks; importing it creates no browser state. `destroy()` removes owned listeners and cancels pending work without changing saved state or moving focus. Call it before removing or replacing the controls. -`src/ui.js` retains panel layout, persistence, share restoration and application +`src/ui/composition.js` retains panel layout, persistence, share restoration and application reactions to state changes. Map Source selection and Location draft cleanup are provided through callbacks. The component imports no globe, data, application or server modules. Package checks and scoped formatting cover this entry. @@ -470,8 +468,8 @@ release listeners; pending action feedback is limited to its current owner. ## UI assembly and styles `ui/shell` assembles controls from supplied existing layer, navigation, terrain, -rendering, HUD and share operations. `src/standalone/ui.js` provides the running -application's instances; `src/ui.js` remains the compatibility entry. The shell +rendering, HUD and share operations. `src/standalone/controls.js` provides the running +application's instances. The shell imports no standalone bootstrap or concrete live layer implementation. Panel layout, position/drag, notices, recording and deferred UI work have separate owners with synchronous cleanup. Existing scene, share and HUD engines retain diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 5ec660548..7184c5d96 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -3595,7 +3595,7 @@ Historical planning documents may not match runtime behavior. ## Runtime Stack - Vite + CesiumJS app with Google Photorealistic 3D Tiles -- Scene/HUD/style systems in `src/ui.js` and `src/hud.js` +- Scene/HUD/style systems in `src/ui/` and `src/hud.js` - Layer management in `src/data/manager.js` - Map stack switching in `src/mapStackController.js` - Voice control in `src/voice/` (OpenAI Realtime over WebRTC) @@ -3627,8 +3627,8 @@ its criteria cannot be silently ignored. | Transit 🚌 | Operator GTFS-Realtime VehiclePositions (7 keyless regions, `src/data/transitFeeds.js`) | `src/layers/transit/` via `src/app/layers/transit.js` | `/api/transit` | 15s (poll + delayed playback) | | Bikeshare 🚲 | GBFS (Lyft + BCycle + Social Bicycles + PBSC incl. Bike Share Toronto, Bike ItaΓΊ (Brazil), Bicing (Barcelona) and seven other Spanish cities + Urban Sharing, Entur, JCDecaux (LillestrΓΈm, Valencia, Seville) + nextbike (AMBici)) | `src/data/bikeshare.js` | `/api/gbfs` | 60s | | Directions 🧭 | OSRM on FOSSGIS servers (OpenStreetMap) | `src/data/directions.js` | `/api/route` (`steps=1`) | on placement / mode change | -| Datacenters β–£ | OSM extract (bundled) | `src/data/localLayers.js` | β€” | static | -| Dams β–° | OpenInfraMap/OSM extract (bundled) | `src/data/localLayers.js` | β€” | static | +| Datacenters β–£ | OSM extract (bundled) | `src/data/infrastructure.js` | β€” | static | +| Dams β–° | OpenInfraMap/OSM extract (bundled) | `src/data/infrastructure.js` | β€” | static | | Submarine Cables β—  | TeleGeography public map (bundled) | `src/data/telegeographySubmarineCables.js` | β€” | static | | FIRMS Active Fires β–² | NASA FIRMS live (VIIRS Γ—3 NRT + MODIS NRT, trailing 24h) | `src/data/firmsHeatmap.js` | `/api/firms` (`FIRMS_MAP_KEY`) | 10 min (proxy TTL 30 min) | | Street Level πŸ“· | Mapillary street-level imagery (vector tiles, Graph API, MapillaryJS) | `src/layers/streetLevel/` via `src/app/layers/streetLevel.js` | `/api/mapillary/status`, `/api/mapillary/tiles/coverage/{z}/{x}/{y}` (`MAPILLARY_CLIENT_TOKEN`) | camera-driven (320 ms debounce, ≀9 tiles, server memory cache 24 h) | @@ -5164,7 +5164,7 @@ pins and share links already supply complete boxes. - **Grounded 3D handoff is terrain-validity gated (2026-08-23).** A ready civilian or military glTF does not own the visual until `groundSnap` (`src/data/groundSnap.js`) can answer with a MEASURED photoreal-surface height. On success the layer writes `height + the model's measured belly offset` before revealing the model. Cache movement is measured on the WGS84 surface, not across altitude, so a stationary contact keeps its snap through poll-time vertical-datum changes. Model existence or GPU readiness alone never suppresses the billboard floor, and ordinary zoom/style/deselect transitions preserve a valid snap cache. **Two states, and the difference is the whole design.** COLD β€” nothing has ever resolved for this icao (tiles still streaming on first sight, sample failure, backoff after a first miss): there is no evidence of where the ground is, `heightFor` returns null, the model stays hidden and the depth-test-free 2D billboard remains opaque and floored. WARM β€” a snap resolved and then a >`MOVE_INVALIDATE_M` (50 m) taxi move stopped it answering directly: the measurement is DEMOTED to a bounded last-known rather than deleted, and it keeps answering while the resample is outstanding, so a taxiing aircraft does not pop 3Dβ†’2Dβ†’3D across a 2–30 s retry backoff. The bound is `HELD_SNAP_MAX_DRIFT_M` = 250 m from the spot the value was measured at, past which the hold is dropped rather than stretched and the contact is COLD again. It is spatial with no timer beside it (ground under a contact that has not moved does not change; what invalidates the value is the contact MOVING) and deliberately a quarter of the billboard chain's `HELD_FLOOR_MAX_DRIFT_KM` β€” that hold only ever RAISES a sprite, while a held snap IS the model's placement, so its error shows in both directions. A fresh sample releases the hold, and so does a ground flip (which already calls `forget`). **A loading model is HIDDEN, never zero-scaled:** admission sets `show = false` (Cesium's default is `true`, and an unplaced primitive would claim the visual at the identity matrix), and ownership is `ready && show` β€” Cesium 1.138's `Model.update` has no `show` guard, so hiding a primitive costs its load nothing. - Commercial and military aircraft use the same high-level FLEET model regime: 2D billboards when zoomed out, optional glTF models when closer, controlled by the DISPLAY rail `3D` toggle and `Proximity` / `All` modes. Since 2026-08-16 (Hangar fleet) models are PER-CLASS: real CC-BY GLBs for light/bizjet/turboprop/widebody/helicopter/uav (`CLASS_MODEL_REAL` in `src/data/aircraftClass.js` β€” meters-baked, scale 1, per-model belly/radius; provenance in `public/models/README.md`), the shared `airplane.glb` for the remaining civilian classes, and the military layer maps weight classes (real GLBs / 747 heavies / `jet.glb` fastjets, per-model heading offsets, flat amber or emergency red). Textured civilians carry a HEAVY tint, not a light one: `MODEL_COLOR_BLEND_AMOUNT` is `0.94` in BOTH layers under Cesium's `ColorBlendMode.MIX`, so the class colour supplies 94% of the surface and the asset's own texture ~6%. The visual direction is clean light silhouettes with only a weak diffuse contribution from the approved textures, so liveries deliberately do NOT read. IR boost raises the blend to a full `1.0`. Under NVG/FLIR (map preset or Cockpit vision) models render unlit flat-white at full alpha and scene fog is disabled (fog otherwise blacks out distant models with the globe hidden); state restores on exit. - The DISPLAY-rail `3D` toggle is the user-facing activation path for both aircraft layers. Their small approved GLBs build their render resources without Cesium's frame-spread job queue, preventing continuous Photorealistic 3D Tiles streaming from starving model readiness; model caps, tracking, camera, and fallback billboards are unchanged. -- **The `3D` toggle DEFAULTS ON in `proximity` on a first run.** Proximity is itself the budget β€” models appear only below `MODEL_ALT_CEIL_M` and only for the nearest `MODEL_MAX` in view β€” so the default costs nothing at globe scale, and `all` remains a deliberate opt-in. A fresh boot runs NO layer-state restoration (`LayerStateCoordinator.start()` returns early with neither a share payload nor stored state), so four independent initializers decide what a first-run operator sees and must agree: `booleanOption('models3d', 'e', true)` in `src/data/layerState.js`, `_models3dEnabled = true` in BOTH flight layers, `this._models3dEnabled = true` in `src/ui.js`, and the `active` / `visible` classes on `#models3d-toggle` / `#models3d-mode-row` in `index.html`. All four are pinned together in `src/data/layerState.test.mjs`. Explicit state still wins: because the codec omits default-valued options, `models3d: false` is now what travels in a link (`lo=…f.e.0`) and restores OFF at both aircraft layers. **Consequence for returning users:** a stored `gev:layer-state:v2` blob is a FULL options snapshot, so a session that wrote one before this change carries `models3d:false` and keeps 3D off until the operator flips it (or clears the key) β€” the durable snapshot is treated as the recipient's own state, by design. +- **The `3D` toggle DEFAULTS ON in `proximity` on a first run.** Proximity is itself the budget β€” models appear only below `MODEL_ALT_CEIL_M` and only for the nearest `MODEL_MAX` in view β€” so the default costs nothing at globe scale, and `all` remains a deliberate opt-in. A fresh boot runs NO layer-state restoration (`LayerStateCoordinator.start()` returns early with neither a share payload nor stored state), so four independent initializers decide what a first-run operator sees and must agree: `booleanOption('models3d', 'e', true)` in `src/data/layerState.js`, `_models3dEnabled = true` in BOTH flight layers, `this._models3dEnabled = true` in `src/ui/aircraftDisplay.js`, and the `active` / `visible` classes on `#models3d-toggle` / `#models3d-mode-row` in `index.html`. All four are pinned together in `src/data/layerState.test.mjs`. Explicit state still wins: because the codec omits default-valued options, `models3d: false` is now what travels in a link (`lo=…f.e.0`) and restores OFF at both aircraft layers. **Consequence for returning users:** a stored `gev:layer-state:v2` blob is a FULL options snapshot, so a session that wrote one before this change carries `models3d:false` and keeps 3D off until the operator flips it (or clears the key) β€” the durable snapshot is treated as the recipient's own state, by design. - **Consequence of the flip on the recorded tracked/fleet inversion:** the 150–800 km band where surrounding contacts draw as models while the SELECTED one is still a glyph is now what an operator sees WITHOUT arming anything. The inversion itself is unchanged and still deliberate (see `src/data/trackedModelRegime.js`); only its reachability changed. - Civilian and military 2D aircraft use the established distance scale: `3Γ—` near the camera and a `0.5Γ—` floor from 8,000 km outward. A standard 20 px ambient diff --git a/scripts/check-import-directions.mjs b/scripts/check-import-directions.mjs index ac1a3f732..3f4fec617 100644 --- a/scripts/check-import-directions.mjs +++ b/scripts/check-import-directions.mjs @@ -24,11 +24,10 @@ const renderer = (file) => /^src\/layers\/[^/]+\/(?:index|rendering|snapshotRenderer|overlay|presentation|cards|controls)\.js$/.test( file, ); -// Two compatibility composition entries intentionally select standalone defaults. +// One compatibility composition entry intentionally selects standalone defaults. const compatibilityEdge = (from, to) => - (from === 'server/providers/local.js' && - to === 'server/standalone/key-setup.js') || - (from === 'src/ui.js' && to === 'src/standalone/catalog.js'); + from === 'server/providers/local.js' && + to === 'server/standalone/key-setup.js'; const portableExport = (key) => key.startsWith('./sources/') || /\/source$/.test(key) || diff --git a/scripts/format-scope.json b/scripts/format-scope.json index 2c78c0774..e313ade42 100644 --- a/scripts/format-scope.json +++ b/scripts/format-scope.json @@ -285,8 +285,6 @@ "src/ui/sceneControls.test.mjs", "scripts/qa-scene-controls.mjs", "scripts/qa-action-buttons.mjs", - "src/ui.js", - "src/standalone/ui.js", "src/ui/applicationShell.js", "src/ui/panelLayoutController.js", "src/ui/panelPositionControls.js", diff --git a/scripts/package-boundaries.json b/scripts/package-boundaries.json index a7c35c286..f2efea33c 100644 --- a/scripts/package-boundaries.json +++ b/scripts/package-boundaries.json @@ -1852,7 +1852,6 @@ "src/data/localGeojson.js", "src/data/localGeojsonCore.js", "src/data/localGeojsonLod.js", - "src/data/localLayers.js", "src/data/local_data/natural_earth/marine.json", "src/data/local_data/natural_earth/regions.json", "src/data/local_data/neighborhoods/san-francisco.json", diff --git a/src/data/localLayers.js b/src/data/localLayers.js deleted file mode 100644 index 63c07b073..000000000 --- a/src/data/localLayers.js +++ /dev/null @@ -1,18 +0,0 @@ -import { localGeoJsonServices } from './localGeojson.js'; -import { createInfrastructureLayers } from './infrastructure.js'; -import { createFirmsHeatmapLayer } from './firmsHeatmap.js'; -import submarineCablesLayer from './telegeographySubmarineCables.js'; - -const [datacenters, dams] = createInfrastructureLayers(localGeoJsonServices); - -// Live NASA FIRMS fires (VIIRS Γ—3 NRT via the /api/firms proxy). The id keeps -// the historical `local-` prefix for persistence + voice-tool-enum compat, -// but the data is NOT bundled anymore β€” it needs FIRMS_MAP_KEY server-side. -const fires = createFirmsHeatmapLayer({ - id: 'local-firms', - name: 'FIRMS Active Fires', - icon: 'β–²', - source: 'NASA FIRMS Β· LIVE', -}); - -export default [datacenters, dams, submarineCablesLayer, fires]; diff --git a/src/standalone/ui.js b/src/standalone/ui.js deleted file mode 100644 index 780d515cf..000000000 --- a/src/standalone/ui.js +++ /dev/null @@ -1 +0,0 @@ -export { StyleManager } from '../ui/composition.js'; diff --git a/src/tooling/importDirections.test.mjs b/src/tooling/importDirections.test.mjs index b34fee3b9..4352bd582 100644 --- a/src/tooling/importDirections.test.mjs +++ b/src/tooling/importDirections.test.mjs @@ -156,13 +156,18 @@ test('self package imports cannot evade portable ownership', (t) => { assert.throws(() => checkImportDirections(root), /Source imports rendering/); }); -test('compatibility exceptions are limited to the two existing composition entries', (t) => { +test('the compatibility exception is limited to the existing composition entry', (t) => { const { root, write } = fixture(t); - write('src/ui.js', "import './standalone/catalog.js';"); write('src/standalone/catalog.js'); write('server/providers/local.js', "import '../standalone/key-setup.js';"); write('server/standalone/key-setup.js'); assert.doesNotThrow(() => checkImportDirections(root)); + write('src/ui.js', "import './standalone/catalog.js';"); + assert.throws( + () => checkImportDirections(root), + /Reusable module imports standalone/, + ); + write('src/ui.js'); write('src/ui/new.js', "import '../standalone/catalog.js';"); assert.throws( () => checkImportDirections(root), diff --git a/src/ui.js b/src/ui.js deleted file mode 100644 index 5142301a3..000000000 --- a/src/ui.js +++ /dev/null @@ -1,16 +0,0 @@ -import { StyleManager as ApplicationControls } from './ui/composition.js'; -import { catalogControlServices } from './app/catalog.js'; -import { getStandaloneCatalog } from './standalone/catalog.js'; -/** Compatibility entry for direct standalone control construction. */ -export class StyleManager extends ApplicationControls { - constructor(viewer, options = {}) { - super(viewer, { - ...options, - services: { - ...catalogControlServices(getStandaloneCatalog()), - ...getStandaloneCatalog().surface.controlServices, - ...options.services, - }, - }); - } -}