Commit Graph
3532 Commits
Author SHA1 Message Date
German Khokhlov 47d63128ff Bin Navara ground corridors set-wide and give corridors glow, pulse and dash
Navara's ground pass cut each corridor into chunks and tested them per
screen cell, so dense corridor sets were slow (10,000 cost about 150 ms a
frame). A corridor set is now cut into pieces along its great circles,
sorted into lon/lat tiles, each with a pyramid of bins listing the
segment runs within its margin; a pixel takes its tile and the finest
bin that covers its reach and tests only those runs. At 10,000 corridors
a frame now takes 11.8 ms still (Cesium 23 ms), at 15,000 17.9 ms. A
pixel corridor's width is measured across the line, so diagonal lines no
longer draw up to 1.4 times wider.

Pixel corridors take three looks, evaluated on the GPU from a time
uniform: Cesium's PolylineGlow falloff (glow), an alpha pulse and the
annotation route's flowing dash. While a shown set pulses or flows the
engine draws continuously, as Cesium did. Traffic's jam lines take the
glow and pulse again and the Directions route its flowing dash and render
hold, so on Cesium both match the drawing before they moved to the
contract pixel for pixel. The contract suite passes on both engines
(Cesium 69/69, Navara 72/72).
2026-11-07 09:50:49 +04:00
German Khokhlov 48885d9e61 Build the catalog from one layer manifest and attach one tools tree
src/app/layers/renderers.js now holds LAYER_MANIFEST, one entry per
layer in directory order: a display (the same render/display.js on every
engine, with the contract primitives it needs and, for CCTV and Global
Context, a Navara backend loaded by import()), a layer that draws itself
through the contract, or per-engine renderers for the layers not on a
display yet (weather, wind, Bhote Koshi, sea marks, ski pistes). A layer
is available where the engine has the primitives it needs. The Cesium
renderer table, CESIUM_BUILTIN, the registry and the Navara mode's map of
about 35 loaders go; the application loads a kind's renderers before it
builds the catalog.

The tools attach through one tree over the engine, in Cesium's order.
Each engine kind adds its own tools from one backend that reads its
extension once: the Cesium backend holds the viewer-only tools, the
Navara backend the annotation renderer, draw surface and file import
drawing.

Coupling: engine.extensions reads fall from 12 to 8, engine-name literal
lines from 73 to 66.
2026-11-07 09:41:02 +04:00
German Khokhlov f1ec9d4a22 Hand features the engine instead of guessing it from a viewer
No code outside src/globe calls isGlobeEngine or engineFromViewer any
more (14 calls left before this). The features that still sniffed take
the engine from their caller:

- Projection and surface helpers (focus de-emphasis, icon orientation,
  ground snap, the mesh floor sampler, ground picks) take the engine; the
  engine view's scene carries its projector instead of registering itself
  as a viewer.
- Credits go only through engine.credits, so annotations and layers
  share one OSM credit state on Cesium too (it could show twice).
- The annotation board and the resolver work on the engine: camera
  assists, visibility and picks go through engine.camera,
  engine.projector and src/geo, without Cesium.
- The Recent Imagery box tool has one implementation for both engines,
  on capture-phase canvas pointer events with the layer's engine.ground
  preview; the Navara copy goes. On Cesium the preview outline is solid
  now, as on Navara.
- Scene interactions take the engine, and the render governor has an
  engine variant beside the Cesium one.

Remaining engine-specific features stay behind explicit seams until the
contract covers them: the draw tool's Cesium surface (stock click actions
cannot be suspended), the annotation drapes (animated materials), share
follow, Cesium post effects and cyber sonar, and data packs (meshes).

Coupling: Cesium-importing files fall from 31 to 27, `viewer` lines
from 1367 to 1234, engine sniffing calls from 14 to 0.
2026-11-07 08:46:30 +04:00
German Khokhlov 406dd9122e Add raster imagery to the globe contract and draw FIRMS heat and Recent Imagery through it
engine.imagery draws raster layers over the globe: Web Mercator tile
templates and single images or canvases stretched over a rectangle, with
alpha, show, a left/right split against the engine's split position and
an order. A layer's source can be replaced in place.

- Cesium puts one ImageryLayer per layer on the globe's imagery stack,
  or on the shown 3D tileset's when the globe is hidden, and moves it
  when the surface changes; the Recent Imagery request gate moved here.
- Navara draws them in one screen pass after tone mapping that samples up
  to eight layers by geodetic position from mipmapped textures and a tile
  atlas, under the other drapes and engine.ground.
- The fake engine keeps each layer's state.

The FIRMS far-zoom heat raster and Recent Imagery now draw through it, so
FIRMS' heat seam and both its backends, and Recent Imagery's Cesium and
Navara renderers and tile plan, go. Against HEAD, Cesium's pixels are
identical in all four compared scenes; Navara's orbital heat changes by a
mean of 3.8 from new mipmapping, slightly towards Cesium. The contract
suite passes on both engines (Cesium 68/68, Navara 71/71).

engine.maps.addOverlay stays a Navara-only extension for Sea Marks and
Ski Pistes until imagery has a finer tile path for oblique global views.
2026-11-07 08:07:57 +04:00
German Khokhlov 1559bd57f4 Draw Street Level, traffic and directions through one display each
- Street Level: coverage sequences are ground corridor sets of up to
  120, draped on terrain and tiles as Cesium's ground polylines were;
  the marker and view cones are sprite movers turned to their compass
  bearing on screen and culled 1 km under WGS84. The layer no longer
  loads the Cesium SDK on Navara.
- Traffic: vehicles are two point mover sets (an outline disc under each
  fill) scaled and faded with Cesium's NearFarScalar maths; congestion
  heat lines are ground corridor sets draped on tiles. Heights, depth,
  readiness and the surface key go through the engine, and Navara no
  longer loads the Cesium SDK for traffic.
- Directions: the route is one ground corridor set in the annotation
  route's dash pattern, maneuvers are point movers and the A/B markers a
  disc and a letter sprite; the in-layer Navara branch and the Cesium
  point collection go.

Known gaps against Cesium, to close in the contract: the traffic heat
lines lose their glow and pulse and the route its flowing dashes
(no animated ground fills yet), and dense Street Level coverage on
Navara is costly as ground corridors (about 80 to 190 ms a frame at
6,000 to 14,400 sequences) until corridors are binned set-wide.

Coupling: Navara renderer lines fall from 3349 to 2767, Cesium-importing
files from 51 to 32, `viewer` lines from 1591 to 1373, Cesium SDK loads
on Navara from 6 to 4.
2026-11-07 08:03:25 +04:00
German Khokhlov 2fbdca62be Name the installations, Global Context and infrastructure displays in the current state 2026-11-07 07:14:06 +04:00
German Khokhlov 30c86a6001 Draw Mapped Installations, Global Context and the infrastructure layers through one display each
- Mapped Installations: one display holds the single copy of the logic
  the Cesium and Navara renderers each had (renderable records, painting,
  the selection fill, floors, named markers, selection). Discs are point
  movers, outlines ground corridors and the selection fill a ground
  polygon. Cesium's behaviour wins where they drifted: named areas draw
  their outlines (Navara dropped them), discs sit under the moving
  contacts, and outlines and the fill pick their site.
- Global Context: the range ring is a halo and a core line on
  engine.lines and the awareness logic no longer imports Cesium. The
  animated pulse disc, which no primitive draws yet, sits behind one
  seam, render/pulseDisc.js, with a Cesium and a Navara backend.
- Datacenters and dams: one display on movers, lines and ground sets
  with Cesium's LOD, motion probe, floor sampling and card cohort;
  localGeojsonCore.js keeps only the engine-free card and record code
  (1381 to 329 lines).

Coupling: layer renderer lines fall from 1011/4832 to 351/3349
(Cesium/Navara), `viewer` lines from 1745 to 1591,
ScreenSpaceEventHandler files from 8 to 6, Navara ground passes from 5
to 4.
2026-11-07 07:13:56 +04:00
German Khokhlov e18f12d34c Keep street maps legible on Navara after dusk
Navara lights the map tiles with the real sun and sky, and only the
landscape maps took the night ambient fill, so an OSM street map turned
black at local night where Cesium keeps it lit. Every base map now takes
the night fill; the landscape maps keep their orbital fill as well.
Daylight is unchanged.

This is why the strict acceptance's Navara pixel and first-frame checks
over Austin failed in evening runs: navara-hd, parked-release,
hidden-switch, context-loss, geo-import and scope saw a black frame, and
the soak and failure matrix waited for a first frame that never came.
At night with the fix all nine pass.
2026-11-07 06:29:33 +04:00
German Khokhlov 54fe0aea40 Draw nine layers' fills through engine.ground, one display each
Earthquakes, air quality, GNSS Integrity, fire perimeters, Prohibited &
Restricted Airspace, Active Fires, S2 GhostMaps, cyclone advisories and
submarine cables each have one render/display.js on the globe contract;
their render/cesium* and render/navara* files go. Their discs, cells,
polygons and corridors are engine.ground sets, so on Navara they come from
the one ground screen pass with exact colours instead of nine hand-written
classification passes and lit SDK vector layers. Cesium's look stays the
reference:

- Earthquake and air-quality discs have no outline (Cesium drew none on
  clamped ellipses); earthquake discs can now be picked on Navara too.
- Perimeters, drone zones and GhostMaps polygons outline their outer
  ring only, as Cesium did.
- GNSS cells stay out of the pick pass; cyclone cones, tracks and centres
  are culled by a port of Cesium's horizon occluder.
- Submarine cables are one ground corridor set, as Cesium batched them;
  landing points, tips and stems are movers and lines.
- FIRMS glows are a sprite set and its cells a ground set. The far-zoom
  heat raster, which no primitive draws yet, sits behind one seam,
  render/heatField.js, with a Cesium and a Navara backend.

The shared Navara ground helpers that only these layers used go
(navaraGroundCells, the cell and ground geometry, the zone renderers), as
does the ground prototype script.

Coupling: layer renderer lines fall from 1636/6953 to 1011/4832
(Cesium/Navara), Navara ground passes from 7 to 5, Cesium-importing files
from 65 to 53, engine.extensions reads from 26 to 19.
2026-11-07 06:20:48 +04:00
German Khokhlov 974a0b6361 Add ground fills to the globe contract
engine.ground draws sets of polygons (with holes), discs, cells and
corridors draped on the surface, with fill and outline colours, order and
picks, written in bulk and committed. Every engine implements it:

- Cesium batches each set into one GroundPrimitive for fills and one
  GroundPolylinePrimitive for outlines and pixel corridors, classified
  against terrain and 3D tiles; sets that are not pickable stay out of the
  pick pass.
- Navara draws them in one screen pass after tone mapping that finds each
  pixel's ground from the scene depth and tests the items in its screen
  cell; long rings are split into edge bins. Measured at Dubai against
  SDK vector layers, the pass matched Cesium's frame time up to 10,000
  polygons with a few megabytes instead of 70 to 146, drew exact colours
  and outlines, and hid reliably across an engine switch, where vector
  layers hidden with update({ show: false }) never hid. Dense corridors
  remain its limit (10,000 cost 135 ms a frame).
- The fake engine keeps the same registry and CPU picks.

The contract suite checks it on both engines (Cesium 66/66, Navara 69/69).
Earthquakes and fire perimeters have unwired ground prototypes whose
drawing matches today's Cesium one (0.998 on Cesium, 0.976 on Navara).
docs/GLOBE-PRIMITIVES.md describes the primitives and when to use each.
2026-11-07 05:14:42 +04:00
German Khokhlov 6dc643182e Count OSM Places on the movers set on both engines in the open layers scenario
OSM Places draws through one display on every engine now, so on Cesium its
points are a movers set too, not a data source's entities.
2026-11-07 04:36:31 +04:00
German Khokhlov dc1144b947 Draw radio, transit and CCTV through one display each
- Radio: stations, clusters, the selection and its brackets are point
  and sprite sets; clusters come from the layer's engine-neutral screen
  clusterer with Cesium's EntityCluster rules, and clicks go through the
  selection dispatcher. One style module holds the sizes and colours.
- Transit: vehicles are two sprite sets from an up-front atlas, rotated
  with Cesium's projected-rotation maths. The selected vehicle's trail is
  engine.lines in two lanes and 29 age bands, so trails are no longer
  draped over terrain until the contract has ground corridors. The
  Cesium contact trail renderer and its re-export go.
- CCTV: markers, wedges, the plane outline and the calibration gizmo
  (rings, arrows, handles, drags through engine.input) draw on the
  contract. The textured monitor plane and the viewshed volume, which no
  primitive expresses yet, sit behind one seam, render/meshes.js, with a
  Cesium backend and a Navara backend the Navara mode passes in.

Known gaps against Cesium: transit trails are not draped, and the
surveillance-lens click correction runs only where the engine reports
its style stage (Navara).

Coupling: layer renderer lines fall from 2638/8735 to 1636/6953
(Cesium/Navara), ScreenSpaceEventHandler files from 15 to 10, `viewer`
lines from 2014 to 1901.
2026-11-07 04:29:50 +04:00
German Khokhlov fc75e245a6 Assert Wildlife Sightings on both engines in the strict acceptance
qa-wildlife-switch.mjs serves four Salish Sea sightings (three from
iNaturalist, one obscured, and an Acartia orca) through the app's own
iNaturalist and Acartia proxies over faked upstream feeds, then on Cesium,
Navara, Cesium and Navara again checks the badge set and its positions,
picks, the density glow, the privacy cell outline and a clicked card.
Two of the switches are made from the keyboard and must keep the
selection; the last is made with the pointer on the Globe Engine picker,
whose click closes the card like any click outside it.
2026-11-07 03:52:50 +04:00
German Khokhlov 145adc08e0 Keep the tracked aircraft through a failed engine switch on Cesium
Cesium follows a display's sprite through a proxy Entity that mirrors the
native's readout fields, and gevRestoring was not one of them. A follow
the flights layer resumed on attach therefore read as new navigation to
the shell's tracked-entity watcher, which made the share restore of the
same attach count itself superseded and clear the selection. That is why
the aircraft was lost after a failed switch's rollback onto Cesium, and
after the retry. The proxy now shows the restoring mark while its follow
starts.

The flights renderer test runs a detach, a failed attach to a candidate,
the rollback and a retry on headless Cesium engines, and checks that the
aircraft stays tracked and no navigation is stamped.
2026-11-07 03:44:38 +04:00
German Khokhlov f06b93fbc9 Draw vessels, satellites, Space Missions, ALPR, bikeshare and OSM Places through one display each
Each layer now has one render/display.js on the globe contract, the same
factory on both engines; its render/cesium* and render/navara* files go.
Cesium's behaviour is the reference, and the logic that was written twice
is written once:

- AIS vessels: atlas chevrons and engine.lines trails. The display
  registers the gev-trail pick claim itself and its trailing visibility
  pass now also runs on Navara.
- Satellites: point banks per look, orbit rings as lines turned by their
  model matrix, and selection and follow through engine.camera.follow.
  The emulated _viewer is gone, and the tracked readout republishes card
  text on Navara too.
- Space Missions: dots, reticle, trajectories and tactical orbits as
  movers and lines. The layer keeps its own records instead of Entities
  and DataSources, and camera work goes through engine.camera. Clicks go
  through the selection dispatcher, and hover keeps Cesium's throttle. The
  pad zone is its rim only: the contract has no surface fill yet.
- ALPR, bikeshare and OSM Places: one display and, for bikeshare, one
  style module each; clicks through engine.input, no
  ScreenSpaceEventHandler or EntityCluster. ALPR keeps Navara's horizon
  cull, and OSM Places points sample the surface where Cesium clamped them.

Coupling: layer renderer lines fall from 4546/11106 to 2638/8735
(Cesium/Navara), `viewer` lines from 2209 to 2014, ScreenSpaceEventHandler
files from 20 to 15.
2026-11-07 03:34:06 +04:00
German Khokhlov 3e261d1baf Give the contract suite a clear pointer path and real canvases in the app
In the app the world overlay draws on a canvas of its own above the
globe, so letting every canvas take the pointer sent the suite's clicks
there. Only the engine's canvas takes it now. Without makeCanvas the
pick check's sprite atlas was a plain object no real engine draws, so its
sprites could not be picked; the page now hands the suite real 2D
canvases. --only=prefix,... runs a subset of the checks. With both, Cesium
passes 63 of 63 checks and Navara 66 of 66.
2026-11-07 02:39:02 +04:00
German Khokhlov 35e70ec280 Draw the aircraft family, Wildlife Sightings and the Cockpit through the contract
The layers that still had one Cesium and one Navara implementation, or
drew on Cesium only, now draw through engine.movers, engine.lines and
engine.camera on both engines, and application code holds the engine
instead of guessing it from a viewer.

- Aircraft family: flights, military and local ADS-B share one display
  (src/layers/aircraft/render/display.js). The Cesium and Navara
  renderers are gone. Where they differed, the display follows Cesium:
  - attach and visibility tracking, live disableDepthTestDistance
    changes, the tracked glyph's distance scale, model ids that change,
    local ADS-B markers hidden until shown and its UAT ring as a point;
  - the trail head's hidden alpha is 0.45, the contract's
    depthFailAlpha scaled by the head's 0.9.
  The tracked glyph stays over the fleet, as on Navara. The movers
  contract reports readiness per model and reads model axes as the
  glTF's own on every engine. Cesium's follow takes any native target
  through a proxy entity in the ENU frame and mirrors its readout fields.
- Wildlife Sightings draws badges and the density glow as sprite sets
  and its privacy cells as line outlines (no fill yet). It takes clicks
  from engine.input and its card anchors to the engine's canvas and
  camera, so the layer is in both engines' catalogs again and a switch
  keeps the session's layer set.
- Cockpit: cockpitHost takes the engine only. The ridden aircraft is the
  engine follow's target, hidden through its sprite; only the Cesium
  Viewer's stock double-click is still routed around.
- About forty camera, navigation, share-link, HUD, voice, detection and
  layer-lifecycle callers take the engine. isGlobeEngine and
  engineFromViewer calls outside src/globe fall from 51 to 14.

The coupling baseline drops accordingly: layer renderer lines from
5239/12331 to 4546/11106 (Cesium/Navara), `viewer` lines from 2424 to
2209, Cesium-importing files from 69 to 66.
2026-11-07 02:34:34 +04:00
German Khokhlov 48988015f1 Give each engine its own extensions in place of the navaraViews map
What only one engine has now travels with the engine instead of a
WeakMap in navaraMode.js: engine.extensions.navara holds Navara's view,
its SDK classes and the daylight reset, engine.extensions.cesium the
Cesium viewer. The contract documents the field as outside the contract,
and the coupling report counts its reads outside src/globe in place of
the navaraViews reads (27, unchanged).
2026-11-07 01:28:51 +04:00
German Khokhlov 2213be6566 Draw movers and lines on Cesium and require them of every engine
Layers are to draw through the globe contract on both engines, so Cesium
gets back the movers and lines removed as unused:

- engine.movers draws sprite sets as a BillboardCollection (atlas cells
  cropped once per set), point sets as a PointPrimitiveCollection and
  model sets as one Model per instance. depthTest, disableWithinM, order,
  scaleByDistance, colorBlend, unlit and minimumPixelSize follow the
  contract; a model's matrix is written in place, so instances no longer
  share one scratch matrix.
- engine.lines draws each line as a polyline Primitive with width in CSS
  px, geodesic arcs, dashes, the tactical and arrow materials,
  depthFailAlpha and modelMatrix; a rebuild keeps its show, matrix,
  colour and place in order.
- The picker returns the pickId a layer wrote last, skips sets that are
  not pickable and instances behind the horizon, and falls through to
  what lies under them. Surface samples can exclude mover sets again.

movers and lines move from the optional capabilities into the required
contract shape, and the contract suite always runs their checks.
2026-11-07 01:24:59 +04:00
German Khokhlov 59a233db51 Skip the contract checks the running app drives itself
The app sets contact sonar on every frame (src/cyberSonarEngine.js), so a
value the contract suite sets never survives to its next frame inside the
app. qa-contract-suite.mjs reports such checks as skipped, naming their
owner, instead of failing them.
2026-11-07 01:24:50 +04:00
German Khokhlov 9daa4bd2db Measure engine coupling and run the contract suite on the real engines
scripts/report-engine-coupling.mjs counts the engine-specific code left
outside src/globe/cesium and src/globe/navara: layer renderer lines per
engine, Cesium imports, `viewer` mentions, engine-name checks, raw Navara
reads, Navara ground passes, Cesium SDK loads and ScreenSpaceEventHandler
users. engineCoupling.test.mjs fails npm test when a count grows past
scripts/engine-coupling-baseline.json, so each step towards drawing
through the globe contract can only lower them.

scripts/qa-contract-suite.mjs runs src/globe/testing/contractSuite.mjs in
headless Chrome on the Cesium and Navara of a keyless dev server, which
until now only ran on the fake engine. The page imports the suite from the
dev server, starts at a fixed view, waits for the camera to rest and lets
the pointer through the panels. Cesium passes 57 of 57 checks, Navara 64
of 67; docs/CURRENT-STATE.md names the three that fail.
2026-11-07 01:08:15 +04:00
German Khokhlov 92c8f8d9da Merge origin/main into german/navara
Main's camera, voice, Cockpit and layer work now runs on the globe
contract where this branch draws through it:

- The voice tilt to an angle, its pivot about the place under the
  crosshair and the frame limit from orbit run through the camera rig;
  src/globeInView.js measures a camera pose with src/geo instead of a
  Cesium camera. The free-look height limit and the globe-in-view
  recovery stay Cesium-only for now.
- Cockpit takes main's own-layer entry rule. Double-clicking the
  followed track goes through cockpitHost.routeDoubleClick, so it works
  on both engines.
- Space Missions' failed-entry rollback and GhostMaps' age filter run
  in the engine-neutral layer code. On Cesium an expired report is
  dropped in place; on Navara its product is redrawn.
- Wildlife Sightings joins the catalog Cesium-only: Navara leaves it
  out, and the shell builds its card only for the real layer, so a
  Navara page no longer fails to start on its stand-in.
- One instruction sentence is shorter, which keeps the Realtime prompt
  within its 55,500-character budget with the Sentinel-2 basemap.
2026-11-07 01:07:26 +04:00
Mazeyar Moeini Feizabadi c56d5f2f06 Merge pull request #1578 from bilawalsidhu/german/space-missions-failed-entry
Roll back a Space Missions entry whose mission index fails to load

Thanks @gekh. Maintainer review fixes (separate commits): exit cancels the layer's own camera flights again, a failed index load shows a specific toast, tests and docs.
2026-11-06 20:26:55 +01:00
Mazeyar Moeini FeizabadiandClaude Opus 5.5 8da8c05eaf test(launches): keep the fixture's toast recorder for the failure-message test
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 20:10:34 +01:00
Mazeyar Moeini Feizabadi 5dd7f41436 Merge branch 'pr-1578-new' into review/pr-1578
# Conflicts:
#	changelog.d/1578-space-missions-failed-entry.md
#	docs/CURRENT-STATE.md
#	src/layers/launches/controls.js
2026-11-06 20:10:01 +01:00
Mazeyar Moeini FeizabadiandClaude Opus 5.5 efa4374644 fix(launches): hand the camera over before stopping, and only blame a fresh index error
- releaseCameraOwnership marks the camera released before stopping, so a
  flight navigation asked to preserve survives; exit also releases it, so an
  inactive layer never cancels another owner's flight.
- The failure toast names the mission index only when its error is from the
  current Context attempt (stats.errorAt), not an earlier one.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 19:28:56 +01:00
Mazeyar Moeini FeizabadiandClaude Opus 5.5 13219828e3 fix(launches): cancel mission flights on exit and name a failed index load
Review fixes on top of #1578:
- Exiting Space Missions cancels the layer's own camera flights again (entry,
  roster preview, mission focus); only a flight navigation started after
  releaseCameraOwnership() runs on.
- A failed first index load says so: "Space Missions unavailable: the
  mission index could not load. Try again later." on both the Context and
  Data Layers routes, instead of a generic transition toast. Translated.
- Regression tests for both; docs and changelog describe the real feedback.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 19:20:11 +01:00
German Khokhlov 096b891099 Simplify failed-entry camera handling and tests 2026-11-06 22:01:39 +04:00
Mazeyar Moeini Feizabadi 3cd7ed68aa Merge remote-tracking branch 'origin/main' into review/pr-1578 2026-11-06 18:55:07 +01:00
Mazeyar Moeini Feizabadi 4effadd3e9 Merge pull request #1601 from bilawalsidhu/fix/street-level-keyless-default
fix(street-level): without a Mapillary key, start on a keyless source

Thanks @asturksever. Maintainer review fixes (separate commits): filter-only updates keep an explicitly chosen source, keyless Street Level QA gate updated, tests and docs.
2026-11-06 18:45:17 +01:00
Mazeyar Moeini Feizabadi ddc14c8f51 Merge remote-tracking branch 'origin/main' into review/pr-1601 2026-11-06 18:32:31 +01:00
Mazeyar Moeini FeizabadiandClaude Opus 5.5 f7b9a2e5af test(street-level): keyless QA branch handles a keyed bundle behind a keyless server
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 18:20:47 +01:00
Mazeyar Moeini FeizabadiandClaude Opus 5.5 8a7402d80c fix(street-level): keep explicit provider choices on filter-only updates
Review fixes on top of #1601:
- Only redirect a provider the params switch on to a keyless source, so a
  filter-only setParams (360°, SINCE) no longer moves an explicitly chosen
  keyless Mapillary to KartaView.
- Keyless QA gate: assert the new KartaView default and that the Mapillary
  chip explains its key instead of switching (it used to expect KEY REQUIRED).
- Tests: Graph-proxy keyReady, filter-only updates; shared test helper.
- README and CURRENT-STATE describe the keyless default.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 18:14:16 +01:00
German Khokhlov 72e2eba70d Merge pull request #1581 from bilawalsidhu/german/i18n-new-strings-fixes
Fix the translations of the voice geometry, fire filter, airspace and sea mark strings
2026-11-06 21:03:09 +04:00
German Khokhlov 41cc57d630 Merge branch 'main' into german/i18n-new-strings-fixes 2026-11-06 20:55:36 +04:00
Mazeyar Moeini Feizabadi 61dfdc771e Merge remote-tracking branch 'origin/main' into review/pr-1601 2026-11-06 17:54:23 +01:00
Mazeyar Moeini Feizabadi b35c810284 Merge pull request #1528 from dylanmaniatakes/codex/s2-ghostmaps-age-filter
feat: add adjustable age filtering across S2 GhostMaps

Thanks @dylanmaniatakes. Maintainer review fixes (separate commits): age-window narrowing/restore consistency, card kept across same-report reloads, date-only events cover their whole UTC day, and the age choice as a labelled Event age switch.
2026-11-06 17:52:28 +01:00
Mazeyar Moeini Feizabadi d5d824f705 Merge remote-tracking branch 'origin/main' into review/pr-1528 2026-11-06 17:40:33 +01:00
Mazeyar Moeini FeizabadiandClaude Opus 5.5 91ab9b5811 fix(ghostmaps): follow-up review fixes for the age switch
- Keep the open card across a widened reload only when its index still
  holds the same report; the server may answer a pinned version with newer
  bytes.
- Narrowing to a window the loaded data already covers clears a failed
  wider reload, so the row no longer stays in error.
- Label the every-age option "All" (contextual) so the six-option switch
  fits the row in every locale; tooltip and info line keep "All markers".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 17:37:29 +01:00
German Khokhlov d544613aae Merge pull request #847 from kvnloo/exp/cyclone-shared-context
feat(cyclones): publish explicit storm selection to shared context
2026-11-06 20:35:22 +04:00
Mazeyar Moeini FeizabadiandClaude Opus 5.5 c4298c4450 fix(ghostmaps): keep age-window changes consistent and make the age choice a switch
Review fixes on top of #1528:
- Narrowing the age window only removes markers; a product loaded with a
  narrower window is reloaded when the window widens again. Fixes markers
  missing after 7d -> 1d -> 7d and avoids reparsing every KMZ on narrowing.
- A wider window over the same edition keeps the open report card.
- Date-only event dates cover their whole UTC day, so 1d still shows
  yesterday's reports.
- The age options are one labelled "Event age" radio switch (row
  `segmented` control, as FIRMS confidence) instead of toggle chips mixed
  with the product chips.
- Un-nest the per-product age test; QA compares data-source counts with the
  live defaults instead of a hard-coded 2.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 17:25:01 +01:00
German Khokhlov 8917eebe12 Tighten failed-entry comments and docs 2026-11-06 20:20:11 +04:00
German Khokhlov 5bab5ec26d refactor(cyclones): drop defensive shared-context state and checks 2026-11-06 20:15:27 +04:00
German Khokhlov 5e64e599e1 docs(cyclones): tighten shared-context comments, changelog and notes 2026-11-06 20:07:56 +04:00
Mazeyar Moeini Feizabadi 7673351ce0 Merge remote-tracking branch 'origin/main' into review/pr-1528
# Conflicts:
#	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
2026-11-06 17:02:29 +01:00
German Khokhlov e1ea524b68 Merge main into german/space-missions-failed-entry 2026-11-06 20:00:21 +04:00
German Khokhlov ea22d16c1a Merge branch 'main' into exp/cyclone-shared-context 2026-11-06 19:44:54 +04:00
German Khokhlov 4e518821b5 fix(cyclones): name the classification and mark a stale cache in shared context
- Publish classificationName next to the raw NHC code; unknown codes stay
  unexpanded.
- Publish staleCacheFetchedAt only while the proxy serves its cache.
- Touch the shared store on clear only after this layer published, so a
  feed failure no longer evicts another layer's dangling selection.
- Drop the unreachable no-storm branch and the unused return value.
- Tests: split the heading fixture into due north and stationary, cover
  the unavailable and failure paths with the real store, and check that
  clear/disable leave another layer's selection alone; fold the fake-store
  test into the real-store one.
2026-11-06 19:43:04 +04:00
Said Turksever 3d6423c6f8 Merge pull request #870 from waar19/perf/fleet-tick-skip-hidden
perf(flights): skip dead-reckoning contacts that stay behind the horizon
2026-11-06 15:03:33 +00:00
Said Turksever 15fdf65a73 Merge branch 'main' into perf/fleet-tick-skip-hidden 2026-11-06 14:52:56 +00:00