scripts/qa/browser.mjs launches headless Chrome with QA_ANGLE and the
shared Chrome lookup; scripts/qa/ready.mjs adds frame, tile and transition
readiness and bounded polling; scripts/qa/geometry.mjs hands page
evaluations the engine-neutral geometry without dev-only source URLs.
CODE-BOUNDARIES gains the rule for new QA scripts.
The Bhote Koshi event flies with engine.camera instead of the viewer's
camera, tools listens to camera.followChanged instead of the viewer's
tracked entity, and the celestial ring uses the engine's host, frames,
pose and render requests. The embedded story media no longer imports
Cesium, which removes one of the three import exceptions.
src/i18n/, src/geo/ and the engine-neutral part of src/globe/ are owned by
directory entries, and aggregate groups use a directory wherever their
list covered it, so a new shared module no longer needs a manifest edit.
Small groups keep explicit lists, now checked as a snapshot: the check
fails on a reached module that is not declared and on a declared one no
longer reached, and prints both per group. --write keeps directory
entries as they are.
The manifest goes from 4,737 entries to 3,494; src/i18n accounts for 87
of them instead of 666.
Main's work since the last merge runs on the globe contract where this
branch draws through it:
- Satellites take main's classes, sensors, ground-track bearings and
world time through contract points and rings; launches take the world
timeline. The satellite's cockpit subject dims, copies positions and
refocuses through the contract.
- Flights, military and vessels keep main's photos, retry cool-downs,
world-clock motion and the ship bridge. Trail seeding in the shared
aircraft tracking reads each layer's clock.
- Traffic's flow lines and single build draw as ground sets; transit
keeps dated credits and the new cities; CCTV opens the nearest camera,
and the Quebec overlay projects and tests the horizon through the
contract. Bikeshare's manager cleanup moved into its current lifecycle.
- Draw keeps main's mark actions across engine switches.
- The world clock in src/time is plain numbers again: Julian dates come
from src/geo, the frame loop is injected, and the binding to Cesium's
viewer clock lives in src/globe/cesium/worldTime.js. Navara's sky and
sun follow the world time; live feeds keep the real time.
- The cockpit's orbital view, with its sensor zoom, ground focus and
satellite switching, stays Cesium-only for now: Navara hides its entry.
Its Cesium calls live in src/globe/cesium/orbital.js. The ship bridge's
finest-detail waterline sampling is Cesium-only too; Navara samples
loaded geometry and detailed terrain. Both are in KNOWN-ISSUES.
- Main's tests that built a Cesium scene by hand run on the fake engine.
- The boundary manifest is regenerated, the coupling baseline records
the orbital and bridge code, and the main-chunk baseline is raised to
the merged size: main itself grew its main chunk by 93,959 bytes
(gzip -9) since the previous merge base.
`node scripts/check-package-boundaries.mjs --write` regenerates each
group's module list in scripts/package-boundaries.json from what the
group's build reaches: entries that own nothing reached are removed, newly
reached modules are appended in sorted order, and the order of kept
entries stays. The check without the flag is unchanged.
Tracking a civil flight asks Planespotters for that aircraft's photo, once
per aircraft, straight from the browser. The CONTEXT panel's CONTACTS view
shows it under the flight's name with the photographer's credit, as a plain
link to the photo's page. Only images on plnspttrs.net and pages on
www.planespotters.net are ever shown or linked. Military aircraft and a
converted TR-3B are never looked up.
Flight lookups (type, route, photo) whose source failed temporarily are
asked again after a 60-second cool-down; an answer, found or not, and a
permanent refusal stay final for the session. A route belongs to the
callsign it was looked up for, so a callsign change drops the old route.
Browser QA scripts that track a flight answer the photo lookup themselves,
so they never call the third party.
Navara now matches Cesium where the review found it diverging: a flight
holds the camera inputs, camera.changed counts turns as Cesium does,
render requests made during a frame survive it, follow pinches zoom,
ground widths follow the pixel ratio and Cyber sonar reaches glyph caches
and models. On Cesium, a staged imagery swap keeps loading tiles, setView
replaces a running flight, and a cleared weather detail goes away.
The contract gains MoverSet.failed, maps.terrainRevision,
render.maxTextureSize and surface.sampleTerrainMostDetailed on every
engine, so layers retry failed models, key road heights by terrain,
size weather textures to the GPU and place Bhote Koshi cards on detailed
terrain.
Engine switches keep the live view, follows, focus, layer options and
cards: a pick hands over the exact pose, applies no address options and
pans no carried-over card; a history visit still applies its entry.
Layers put GhostMaps pins, cable landings, OSM Places and directions on
the measured surface without per-frame sampling, draw the Cockpit contact
dot, hide disabled CCTV on attach, and keep ALPR running outside secure
contexts. KML imports draw raised polygon fills, rotated and coloured
ground overlays and north-referenced icon headings, and report files
with nothing to draw.
QA scripts read the contract instead of Cesium internals (test:track is
109/109 again), wait for the camera to rest before clicking, and give
cold switches and parked engines realistic time. Docs follow the code.
The satellites layer now sorts every object into Stations, Imaging,
Telecom, Starlink, Probes or Debris, each with a chip and a live count on
the layer row. Stations and Imaging show by default; the Starlink chip is
the former DENSE catalog switch. Hidden classes keep their points, so a
toggle needs no reload, and they leave the detection overlay and the voice
position lists.
A class comes, strongest evidence first, from CelesTrak SATCAT (object type
and status, served by a new /api/celestrak-satcat/<group> proxy route and
cached for a day), the bundled UCS Satellite Database pack (operator, owner
country and purpose), name patterns for later launches, and the CelesTrak
group. The core catalog also reads the resource, weather, planet, sar and
science groups. Payloads with no evidence of life launched 20 or more years
ago are filed as debris. The UCS pack, its build script and its data credit
are added.
Move engine request ordering and the single rollback decision into the scene
host. Run handoff, renderer release, candidate acquisition, attachment,
restoration and settling in one transaction. Pass that transaction to nested
parts so unrelated calls wait without putting nested work behind itself.
Keep the engine-switch entry point as a delegating adapter.
Route direct shell attachment and detachment through the same host and remove
the shell queue. Serialize late part registration with attachment and release.
Keep failed-attachment cleanup and renderer release inside the transaction,
including failed restoration. Replacement applications share the transition
owner with fresh parts, and retired applications release their part registry.
A shell used alone creates its own scene host.
Preserve Cesium's picker and history ordering, single recovery, retained layer
session, cockpit restoration, hidden-tab settling and parked-renderer policy.
Navara keeps the same behavior. No user-visible change is intended on either
engine. Keep the existing behavioral assertions and cover concurrent operations,
failed cleanup followed by recovery, retired transaction handles, replacement
startup failure and parked expiry during a switch.
All eleven coupling counts remain unchanged; none fell or grew. Renderer lines
remain 0 and 189, external Cesium import files 3, viewer lines 891, Navara kind
checks 1, engine-sniff calls 0, extension reads 3, ground passes 1, SDK loads 3,
screen-handler files 4 and engine-name lines 32.
Checked on the keyless production build: the engine, Director and layer
handoff switches, app-once, and the rapid, hidden-tab, context-loss,
parked-release, failure-matrix and soak scenarios pass.
Give each scene its own render governor, owner holds and recent idle requests.
Make the Cesium render backend own its request mode directly, so the governor
drives engine.render on both engines without a dependency back from Cesium.
Route layer requests through their attached engine and capture the attachment's
governor for camera motions, orbit, annotations and shell controls. Release
retained-layer holds before clearing the outgoing engine, and destroy the
governor after scene consumers have detached.
Preserve Cesium's owner-keyed holds, pre-install buffering, last-release settling
frame and one-shot requests during continuous rendering. Navara keeps the same
render policy. There is no intended visible change on either engine. Simultaneous
scenes no longer share holds, and an old captured service cannot release a
replacement attachment's hold. Cover both rules on fake and headless Cesium
engines, including an old orbit ending after reattachment.
Viewer-reference lines fall from 910 to 891, Navara-kind checks from 2 to 1,
and engine-name lines from 33 to 32. All other coupling counts stay unchanged.
Checked in the browser, keyless: qa-perf passes on both engines with the
same idle, active and release counts as before (24 checks on Cesium, 22 on
Navara).
Restrict runtime SDK imports to their engine directories, including package
subpaths, re-exports and dynamic imports. Keep three measured, reasoned
exceptions for the Bhote Koshi property-record models and reject stale
exceptions. Move the Cesium annotation renderers and both wind adapters to
their engine folders, preserving their implementations and lazy loading.
Load all 35 manifest display entries on a fake engine with an unknown kind
and no native extensions. Draw small fixtures and verify resource and
subscription cleanup before destroying the engine. Name the three entries
without display factories as skips. Update the architecture, infrastructure
lifecycle and engine integration documentation to describe the code today.
Cesium behavior is unchanged, and Navara keeps its existing behavior. The
weather comparison harness supplies the Navara flow-mesh factory and accepts
the previous backend location for comparison runs. No user-visible strings
change.
Cesium layer-renderer lines fall from 14 to 0, Navara layer-renderer lines
from 314 to 189, outside-engine Cesium import files from 5 to 3, viewer lines
from 933 to 910, extension reads from 4 to 3, and engine-name lines from 36
to 33. No coupling count grows. Targeted checks pass: 845 tests, three named
rehearsal skips. Import directions, package boundaries, formatting and syntax
checks pass.
Checked in the browser, keyless: the contract suite passes on Navara and on
Cesium apart from the camera-events check that also fails intermittently
before; Navara annotations pass across engine switches; the ground-look
comparison is pixel-identical. qa-draw-tool's hidden-line check and the wind
engine switch fail the same way before this change.
Move Cesium viewer, map, sky, projection, trail and sonar internals into
its engine. Drive styles, bloom, sharpening and contact sonar through
engine.render. Count camera-input suspensions across all three engines
and migrate the feature callers. Preserve Cesium's effects and input
behaviour; fix transit lens clicks on Cesium and make zero sharpening on
Navara disable sharpening, as it does on Cesium.
Parse imported files into plain records and draw them through movers,
lines, ground and imagery on both engines. Follow Cesium's KML style
precedence, preserve local KMZ images and frame the drawable records.
Open overlays use imagery when the engine has no native map-overlay API.
Run every imported-display case on fake and headless Cesium engines.
The shared import path retains these known differences from Cesium's old
DataSources: wall fills, extruded prisms and gx:LatLonQuad are undrawn;
raised polygon fills drape while outlines retain altitude; GroundOverlay
rotation, altitude and RGB tint are not applied; rhumb lines become great
circles. Ground heights use the loaded surface synchronously instead of
waiting for most-detailed sampling. Supported KMZ ground overlays now
draw on Navara too. Document the limits rather than claiming full parity.
Combine batches B and C because their disjoint path manifests cannot
place the shared boundary and format files in a later commit while
keeping B independently valid. This combined commit owns the shared
docs, package boundaries, format scope, locale catalogs and coupling
baseline. Remove five obsolete import strings from all eleven catalogs.
Make the load-time source scan include new files and skip deleted paths
so the same checks work before and after recording the moves.
Coupling: Navara renderer lines fall from 1695 to 1294, Cesium import
files from 25 to 9, viewer lines from 1177 to 1026, SDK loads from 4 to 3
and engine-name lines from 62 to 42. No count grows.
The full unit suite and the boundary, format and coupling checks pass.
Browser validation remains to be run.
Browser checks to run
GOOGLE_MAPS_API_KEY= CESIUM_ION_TOKEN= npm run dev -- --port 4291
node scripts/qa-contract-suite.mjs http://localhost:4291
node scripts/qa-navara-visual-styles.mjs http://localhost:4291
node scripts/qa-navara-bloom.mjs http://localhost:4291
node scripts/qa-navara-sonar.mjs http://localhost:4291
QA_BASE_URL=http://localhost:4291 node scripts/qa-visual-effects.mjs
QA_BASE_URL=http://localhost:4291 node scripts/qa-zoom-out-guard.mjs
node scripts/qa-sky-model-lighting.mjs --url http://localhost:4291
node scripts/qa-geo-import.mjs http://localhost:4291
node scripts/qa-geo-import-regressions.mjs http://localhost:4291
node scripts/qa-geo-import-large.mjs http://localhost:4291
node scripts/qa-navara-geo-import.mjs http://localhost:4291
Use the keyless server for every check. Photoreal-only cases remain
unverified; do not enable paid tiles to run them.
- src/geo drops the ported debug argument checks and the tests that
bitExact already covers; package boundaries accept a directory entry,
so src/geo/ is listed once per group.
- Cesium no longer carries movers and lines nobody draws with: they are
optional engine capabilities. The fake engine and the Cesium camera use
the shared cameraMath; unused contract tables, clock.ticked, the
'finest' surface detail and Navara click statistics are gone.
- ALPR keeps one overlay core and one presentation model for both
engines, bikeshare one station bookkeeping, the Navara ground effects
one definition helper; image atlases, view centres, mover banks and
colours are shared.
- The legacy switch route, the clock offset and rate controls and other
unused exports are removed.
- The acceptance runs the Navara draw, geo import and scope checks;
scenarios use the harness switch and page helpers; the main chunk
check keeps the size budget only and runs once in CI.
Preserve the camera, map source and layer selection across engine sessions. Restore the previous engine if startup fails and retain local history navigation.
The dock renders the chips from the map source controls' published view,
so renderMapStackChips, syncMapStackChips and MAP_STACK_CHIP_CLASS have no
callers. Their tests now pin the chip models; the dock test keeps the
rendered chips' button type and native enablement.
The Vue views apply the gev-action-button and gev-status-badge classes
themselves, so the DOM builders have no users left. The docs describe the
views instead.
presentCctvCalibration() joins the panel view: ADJUST, SAVE CAL, RESET CAL
and the seven pose chips render from the gev-cctv store. The inline editor
is store state: starting an edit publishes its field, starting value and
finish(), and the CctvCalValue chip renders the number input. The draft is
set once on mount so a refresh while typing keeps it; each edit gets its
own input. Commit and cancel rules, the captured base pose and the camera
guards stay with CctvControls.
formField.js had no other user and is removed.
The scene chrome, cockpit, Display controls, command dock, layer panels,
Context rail, welcome card and Provider Settings move verbatim into
src/ui/views and mount into their hosts before the page is translated and
wired. Each view renders the same elements, attributes and text as its
template; Vue keeps whitespace between elements as one space, and no view
markup sits under a white-space: pre rule.
Template asset URLs stay literal, view files are left out of Prettier so
the markup is not reflowed, and the Node component loader moves to build/
and is exported as build/register-vue for host test runners. Hosts that do
not initialize Core's locale pass localePicker: false instead of editing
the markup.
* feat(share): export the share-view codec for host servers
Add `@gods-eye-view/core/share/view-codec` (src/share/viewCodec.js) as a
package export with its own boundary group. The codec is pure (no DOM, no
Cesium, no external dependencies), so a host's server can decode a
/share/<code> link, for example to describe the view in link previews.
* feat(share): export the share-link address helpers
Add `@gods-eye-view/core/share/link-path` (src/share/shareLinkPath.js), so a
host's server reads /share/<code> addresses the way the app does.
* chore: remove four modules nothing in the app uses
src/app/sourceSlot.js re-exported src/sources/sourceSlot.js, which every
caller imports directly. src/data/flowTiles.js and src/data/issPass.js were
reached only by their own tests. src/data/localGeojson.js wrapped
localGeojsonCore.js with the app's services, which the catalog already
passes itself. The local GeoJSON layer tests now build layers the way the
catalog does, so they keep covering localGeojsonCore.js; only the test of
the wrapper's own default host goes. Boundary lists, format scope and docs
drop the removed paths.
* docs: changelog for #1403
The README source tree now lists src/ui/ instead of the removed
src/ui.js. docs/CODE-BOUNDARIES.md names src/ui/applicationShell.js as
the owner of panel layout, persistence and share restoration, and
docs/CURRENT-STATE.md places GLOBAL_POST_DEFAULTS in
src/ui/visualPresets.js. QA script comments and test assertion messages
that still named ui.js are updated the same way.
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.
- Google 3D: the OPEN button re-measures a ground whose tiles are still
loading (a few times, a second apart) and on a map change, not only
after the next camera move.
- Mapillary: two mounts on one host during the first download share one
build instead of leaking a second WebGL viewer.
- Retired floating-panel keys (v8 panelPos, panelFloatHintShown) are
dropped from localStorage; dead inline-position resets, the drag JSDoc
and the dead qa-ui-disposal observer branch are gone.
- Docs: z ladder, panel chrome, position storage and the fixture gate's
actual coverage; changelog fragment for #974 (old .gev-cache/mapillary
can be deleted).
- ru/es: the layer is named as everywhere else in the UI.
- Fixtures and test fakes: unused exports removed; a fake credit removal
of an absent credit no longer drops another one; the tile test reset
frees upstream slots.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The import-direction check now tells dynamic imports apart
(analyzeModule(source, { dynamic: true })) and rejects any static import
or re-export of src/globe/navara/** from outside that directory, so the
Navara engine can only be a lazily loaded chunk of the app.
Navara's prebuilt workers load their wasm by file name next to
themselves, which the bundler cannot see; a build-only Rollup plugin
copies the missing ones (draco decoder, font worker) into assets/ when
the bundle includes Navara, and adds nothing to a build without it.
Engine events get their own documented semantics (single registration,
branded instances); the fake follows Cesium's roll sign, angle ranges,
synchronous zero-duration flights, flyToSphere defaults and
computeViewRectangle. The contract adds viewProjection, horizonVisible,
flightActive, lookAtTransform/transform, zoomIn/zoomOut, input modifiers,
terrainHeight and clampToHeight, with geometric suite checks. Engine
import rules now follow each engine graph transitively.
src/globe/contract.js defines the engine-neutral GlobeEngine capabilities
(JSDoc), createEngineEvent with Cesium.Event semantics and
assertGlobeEngine. src/globe/testing adds a geo-based fake engine for shell
tests and an engine-agnostic contract suite that the fake passes in Node.
check-import-directions keeps the contract free of cesium, three and
@navaramap, and each engine directory free of the other engine.
An engine-neutral port of the CesiumJS 1.138 core maths gev uses: angle
maths, the WGS84 ellipsoid and geodetic coordinates, 2D/3D vectors, 3x3/4x4
matrices, quaternions and local east-north-up / heading-pitch-roll frames.
Formulas and operation order match Cesium, so outputs are bit-identical
(golden tests pin the centre, pole, -0 and quaternion branches).
- Values are plain-data instances of module-private constructors (own
enumerable fields only), so geo's hot functions keep their own V8 hidden
classes; matrices are plain column-major arrays Cesium accepts.
- Cesium's debug argument checks are ported with the same conditions, order
and DeveloperError messages, gated on DEBUG (src/geo/debug.js): on in Node
and the dev server, folded away by vite build, as Cesium's Build strips
them. A release-parity test compares DEBUG=false geo with Build/Cesium.
- The import-direction check forbids cesium and @cesium/* in src/geo;
CODE-BOUNDARIES.md and THIRD_PARTY_NOTICES.md document the port.
Traffic roads come from OpenFreeMap vector tiles, or TomTom flow tiles with a
key (Hybrid by default). Military areas use OpenFreeMap polygons with a bundled
worldwide name index; wide views show named points. ALPR reads an hourly
OpenStreetMap extract. Cockpit place context and country, state and US county
outlines use bundled Natural Earth and US Census data. Overpass is used only
when an operator configures their own endpoint.
Also: camera arrivals no longer land below ground, keyless terrain retries on
429, bounded relation geometry for configured Overpass, one shared
OpenStreetMap credit, and separate tile and API transports for embedders.
Co-authored-by: theGaryLarson <[email protected]>
Co-authored-by: Milan Khanal <[email protected]>
Wind (NOAA GFS and ECMWF IFS: animated particles, colour field, a reading at map centre), observed weather (NOAA MRMS radar, GOES and NESDIS infrared clouds, lightning density) on one shared history timeline, NHC and CPHC cyclone advisories with tracks and cones, and a WEATHER panel in the right rail. On 3D Tiles the observed products render as raised shells with a sharper window around the view.
Co-authored-by: Gustavo Beneduzi <[email protected]>
Co-authored-by: Daniel Slay <[email protected]>
Co-authored-by: Rehaan Delmotra <[email protected]>
Co-authored-by: Cursor Agent <[email protected]>