Commit Graph
1444 Commits
Author SHA1 Message Date
German Khokhlov 53b07ba91f Move QA scripts to the shared harness, batch 3 of 4
Each script launches and closes Chrome through scripts/qa/browser.mjs,
waits on the application through scripts/qa/ready.mjs instead of the
loading screen and fixed pauses, and reads the contract instead of
Cesium where the check is not about Cesium itself.
2026-11-10 16:43:58 +04:00
German Khokhlov 373edf2989 Move QA scripts to the shared harness, batch 2 of 4
Each script launches and closes Chrome through scripts/qa/browser.mjs,
waits on the application through scripts/qa/ready.mjs instead of the
loading screen and fixed pauses, and reads the contract instead of
Cesium where the check is not about Cesium itself.
2026-11-10 16:43:58 +04:00
German Khokhlov ee697422c9 Move QA scripts to the shared harness, batch 1 of 4
Each script launches and closes Chrome through scripts/qa/browser.mjs,
waits on the application through scripts/qa/ready.mjs instead of the
loading screen and fixed pauses, and reads the contract instead of
Cesium where the check is not about Cesium itself.
2026-11-10 16:43:58 +04:00
German Khokhlov 731eadc34a Give QA scripts one launch, readiness and geometry helper
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.
2026-11-10 16:43:58 +04:00
German Khokhlov 08d5c86e80 Merge branch 'german/refactor-e7-height-datum' into german/navara-refactor 2026-11-10 16:42:50 +04:00
German Khokhlov dd56cba2f3 Measure the heights the surface-bound layers place their points at
qa-surface-heights loads deterministic fixtures for import pins,
infrastructure bases, ALPR markers, directions A/B, bikeshare stations
and Bhote Koshi story points, waits for the app to settle on each engine
and records every placed point through the mover contract. --compare
fails when a point moved by more than 0.1 m on terrain; --tiles checks
the points land on the synthetic tileset's 50 m block.
2026-11-10 16:42:50 +04:00
German Khokhlov 59ff0b38a2 Merge branch 'german/refactor-e8-switch-protocol' into german/navara-refactor
# Conflicts:
#	scripts/engine-coupling-baseline.json
#	src/layers/wind/index.test.mjs
2026-11-10 16:35:39 +04:00
German Khokhlov a2905eb700 Move the engine switch protocol from the layers into the scene binding
attachRenderer takes one context { engine, signal, viewRestored, ... } and
bindCatalog no longer takes a viewer; no layer module receives Cesium's
viewer any more, and a rehearsal check fails if one reads it.

The handoff between engines is one typed object (layers, camera owners,
selection, director) created when the old scene leaves, replacing the
session's handoffLayers, restoringView and selectionContext. viewRestored
resolves where the camera is restored, and the nine layers that kept
their own restoring-view flag wait on it instead. After attach the
binding applies a disabled layer's visibility, registers the picks each
module declares, and resumes the camera owners, so engineSwitch.js no
longer names directions or satellites.
2026-11-10 16:33:29 +04:00
German Khokhlov d51e4140b7 Merge branch 'german/refactor-e10-layers-without-viewer' into german/navara-refactor
# Conflicts:
#	scripts/package-boundaries.json
2026-11-10 16:16:32 +04:00
German Khokhlov bcff542b16 Merge branch 'german/refactor-e7-surface-placement' into german/navara-refactor
# Conflicts:
#	scripts/package-boundaries.json
2026-11-10 16:15:09 +04:00
German Khokhlov aac65c21c4 Open the orbital cockpit on Navara
The orbital view, sensor zoom, ground focus and satellite switching run on
the contract: camera.setFovy sets the vertical lens on both engines and the
fake, including sub-degree angles on Navara through the guarded core
bridge, with a contract check and mutants. Cesium's imagery look-ahead
stays inside its adapter. KNOWN-ISSUES keeps the two parts Navara still
lacks: imagery prefetch for the orbital view and finest-detail meshes for
the ship bridge waterline.
2026-11-10 16:14:14 +04:00
German Khokhlov e0d3e93a28 Move the wind's Cesium rendering into the Cesium adapter
The particle canvas, its GPU path and the relief shading move unchanged
from src/layers/wind/ to src/globe/cesium/; the adapter reads the Cesium
viewer itself, so the layer no longer hands one in.
2026-11-10 16:14:14 +04:00
German Khokhlov 82ed68f443 Place every surface-bound layer through the shared placement
Import pins, infrastructure, ALPR, directions markers, bikeshare and the
Bhote Koshi story use createSurfacePoints instead of their own sampling,
budgets and partial triggers; ground snap, the mesh floor sampler,
traffic, transit, Street Level, the camera ground guard, wildlife and the
cockpit host read heights through readSurface or surfaceTriggers.
Per-layer offsets and floor policies stay as options. The import no
longer re-places pins on every camera move from the UI.

Calls to engine.surface outside src/globe go from 41 sampling calls to
10, each a raycast, a one-shot fly-to height or an asynchronous detailed
sample.
2026-11-10 16:13:06 +04:00
German Khokhlov ef104aaac3 Move surface placement into the globe and give it the fourth trigger
src/globe/surfacePlacement.js takes over the shared surface placer and
adds readSurface (tiles through sampleHeight, otherwise terrain, with a
plausibility range), surfaceTriggers (one subscription to camera moves,
tile loads, the photoreal switch and terrain revisions) and a forced full
pass. Points now re-place when the terrain provider changes, which they
did not before. GhostMaps, cables, OSM Places and Street Level move to the
new module unchanged.
2026-11-10 16:13:06 +04:00
German Khokhlov 50e486ceec Merge branch 'german/refactor-e11-boundary-catalogs' into german/navara-refactor
# Conflicts:
#	scripts/package-boundaries.json
2026-11-10 16:08:08 +04:00
German Khokhlov 75cf0aeaf9 Merge branch 'german/refactor-e4-model-retry' into german/navara-refactor 2026-11-10 16:04:06 +04:00
German Khokhlov a07d9f5d85 Retry a failed 3D model inside the engine instead of in the layers
A mover set whose glTF or atlas fails to load retries by itself after
retryAfterMs (1,500 ms by default), at most three attempts, on Cesium,
Navara and the fake engine alike: failed() is true while the latest
attempt failed and stays true after the last, ready() turns true when a
retry loads, and an instance given another pickId loads again. Healthy
models of the same class no longer load again when one fails.

The layers drop what they did instead: moverBank's rebuilds, the loops
that dropped failed handles in flights, military and local ADS-B, and the
tracked-model backoff in the aircraft display. The contract suite checks
the one behaviour on both engines, with a mutant that never retries.
2026-11-10 16:04:01 +04:00
German Khokhlov 27939a2d84 Own shared foundations by directory and check the manifest both ways
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.
2026-11-10 15:59:43 +04:00
German Khokhlov 1ac9f28c4a Merge branch 'german/refactor-e6-tiles-fixture' into german/navara-refactor
# Conflicts:
#	scripts/qa-harness-baseline.json
2026-11-10 15:54:13 +04:00
German Khokhlov e9ba5e9859 Check the photoreal paths in the browser on a synthetic 3D Tiles set
A generated tileset (a plate at ellipsoid level, 50 m and 200 m blocks and
a pitched roof, 27 KB) replaces Google's tiles when a QA page passes
?qaTileset=/path; only a root-relative path on the page origin is
accepted, and the Google credit is not shown for it. The strict harness
serves the set from disk, so nothing reaches Google.

qa-tiles-fixture checks on both engines that sampleHeight reads the block
at 50 m, clampToHeight lands on the roof, tiles and terrain drapes draw
where they should, tilesLoaded turns true, surface points land on the
roof within their budget, and pick renders per pass stay within it.
2026-11-10 15:49:52 +04:00
German Khokhlov 37263a3e2b Give the draw ledger test a drawn mover instance
A mover set lists as shown only once one of its drawn instances is.
2026-11-10 15:48:49 +04:00
German Khokhlov 18da76e8d8 Merge branch 'german/refactor-e1-qa-readiness' into german/navara-refactor
# Conflicts:
#	scripts/qa-harness-baseline.json
#	scripts/qa-strict-harness.mjs
2026-11-10 15:47:21 +04:00
German Khokhlov 60f9de8511 Wait for the application, not the clock, in the strict QA set
The probe exposes settled() and the first-frame outcome; scripts/qa/ready.mjs
waits for drawn frames with the camera at rest and for a pick at the click
position, with a deadline and its reason in the error. The strict scenarios
use these instead of fixed pauses and loading-screen polling, and the
hidden-switch scenario checks how the loading screen was lifted instead of
how long it took.

Each switch scenario now records a draw ledger per engine and runs a
contract monitor; both write to the scenario's evidence file only, with an
empty allowlist until browser runs show what differs on purpose.
2026-11-10 15:46:26 +04:00
German Khokhlov 28f3030c31 Draw Navara world meshes in the overlay pass after tone mapping
Meshes now go through the same overlay as sprites and lines, so their
colours are the ones asked for without undoing the view's exposure. The
contract suite no longer carries the mesh colour check as a known
failure on Navara.
2026-11-10 15:45:26 +04:00
German Khokhlov 353eebf224 refactor(tools): normalize ALPR text once, in the records
Every camera find_alpr_cameras returns comes from the tile source, which builds
it through normalizeAlprNode, so the tags are already one line and capped.
Drop the second pass in the tool, its duplicate test and the boundary entry,
and the function check normalizeDisplayText never sees.
2026-11-10 15:37:16 +04:00
German Khokhlov a90407d547 Count the Navara canary script in the QA harness baseline
It drives a bare Navara view outside the app to test the package itself, so it launches Chrome and paces its fixture on its own.
2026-11-10 15:30:09 +04:00
German Khokhlov 33ccef9662 Merge branch 'german/refactor-e3-contract-behaviour' into german/navara-refactor 2026-11-10 15:27:12 +04:00
German Khokhlov 49b180f1fd Merge branch 'german/refactor-e9-import-plan' into german/navara-refactor 2026-11-10 15:27:12 +04:00
German Khokhlov 0953287c3d Merge branch 'german/refactor-e13-navara-workarounds' into german/navara-refactor 2026-11-10 15:27:12 +04:00
German Khokhlov b03edaaf2b Check the globe contract by behaviour on every engine
The contract suite is split into one module per area and grows from 87
to 114 checks, each named after the member it exercises: a gesture during
a flight does not cut it, a render request inside a frame draws the next
one, a pure rotation raises changed, ground corridors are as wide in CSS
pixels at device scale 2, imagery replans on resize, drapes draw only on
their surface, sampleTerrainMostDetailed keeps order and passes on a
rejection, terrainRevision changes on a new terrain and on fallback,
follows raise followChanged on retarget, and a mesh, a ground fill and an
imagery pixel draw the colour asked for. In the browser Cesium passes all
113 it runs at device scale 1 and 2; Navara passes 110 of 111 and reports
its single-colour mesh, drawn before tone mapping, as a known failure.

scripts/contract-mutants.test.mjs breaks one promise of the fake engine
at a time, 30 mutants in all, and names the check that catches each; the
list of contract members the suite never calls is down to five.

maps.errors reports tile and terrain errors where an engine has them
(the tileErrors capability: Cesium yes, Navara no), and the map
controller falls back to another map only where it does; movers.list()
rows tell whether a set is shown, as the other families do; FollowHandle
.name and PickResult.primitive are marked deprecated. qa-contract-suite
takes --dpr and the ANGLE backend from QA_ANGLE.
2026-11-10 15:26:55 +04:00
German Khokhlov 9ae7dea918 Plan KML and KMZ drawing in one pure function, checked against Cesium
src/data/geoImportPlan.js decides what an imported file draws and with
what: raised or clamped geometry, rings and holes, rotation near the
poles and across 360 degrees, absolute and relative altitudes, draw
order, canvas budgets and the vertex and ring limits, with no engine and
no DOM. drawImportedFile draws that plan through the globe contract and
keeps pin placement, yielding and cancellation. Every limit of the import
lives in src/data/geoImportLimits.js with what it protects.

scripts/fixtures/geo-import holds 13 files covering those cases, and
reference.json what Cesium's own KML and GeoJSON data sources make of
them; scripts/qa-geo-import-reference.mjs records it and compares the
plan with it. Property tests on seeded random polygons check area,
bounds, ring closure and winding. Writing the plan fixed three cases:
overlays below the ellipsoid kept a negative height, raised plain-colour
overlays now draw, and the vertex limit no longer depends on whether a
ring repeats its first point.
2026-11-10 15:26:10 +04:00
German Khokhlov ffbceb977c Register the Navara package workarounds and check them against the package
src/globe/navara/WORKAROUNDS.md lists every place the adapter works
around @navaramap/three 0.2.1: what the package does wrong or lacks, how
it is detected and what to delete once it is fixed.
scripts/qa-navara-canaries.mjs confirms three of the bugs on the real
package in the browser (batch ids never released, events of a deleted
vector layer kept queued, idle reported before a raster tile arrives) and
names the workaround to delete when one is gone.

The private members the adapter reads are probed when the engine starts,
with an error naming the member and the pinned version instead of a
silent fallback, and the test that only internals.js reaches private
members now scans the adapter's subfolders too.
2026-11-10 15:22:43 +04:00
German Khokhlov bd4f9eaee4 Keep the strict scenarios in step with main's photos and satellite groups
Main's flight photos ask Planespotters for every tracked aircraft, which
the strict network policy counted as a violation; the harness now answers
those lookups with no photos, as the other QA scripts already do. Main
also reads five more TLE groups (resource, weather, planet, SAR and
science): the satellite fixture serves them, and the space switch expects
all twelve groups and derives its catalog sizes from the fixture.
2026-11-10 15:01:39 +04:00
German Khokhlov 9c2a2d6951 Measure engine coupling, QA harness use and contract coverage
Counters that may only fall, each with a committed baseline and a test
that fails on growth:

- report-engine-coupling.mjs gains layer modules that take the viewer
  in attachRenderer (33), layer folders with their own "view being
  restored" flag (9), engine.surface calls outside src/globe (41) and
  layer ids named in the engine switch (3).
- report-qa-harness.mjs counts QA scripts that launch Chrome themselves
  (98), wait with fixed sleeps (117), take the hidden loading screen as
  readiness (9), read Cesium-only objects (75) or define their own
  waitFor helpers (19).
- withCallLog records every contract member the contract suite calls on
  the fake engine; contractCoverage.test.mjs fails when a member outside
  contract-uncalled-baseline.json goes uncalled, and when a listed one
  is called now, so the list of 12 only shrinks.
2026-11-10 14:23:29 +04:00
German Khokhlov ba04ceaa32 Describe the strict page clock as the nearest 18:30 UTC 2026-11-10 14:23:29 +04:00
German Khokhlov ed6ae54ef6 Stop the strict acceptance from waiting for itself
A scenario whose body ran past about 19 s idled until 45 s after its
start, and twice one never exited and hit the runner's 300 s timeout
after it had passed: something of Chrome outlived Browser.close and kept
its stdout and stderr open.

- scripts/qa/browser.mjs closes Chrome within 5 s, kills its process
  group and closes its pipes; the harness then finishes and exits with
  the scenario's code. QA_EXIT_DIAGNOSTICS=1 keeps the old ending and
  prints the open handles and Chrome's process tree 5 s after finish.
- Every strict page starts with its clock at the 18:30 UTC nearest to
  the real time, so Navara's sun is up over the test cities whenever the
  acceptance runs; a scenario can ask for its own instant or the real
  clock (Wildlife does, for its freshness fixtures).
- The runner records a scenario that passed but did not exit as hung,
  kills the whole process group on a timeout, runs a failed scenario
  once more and reports one that passes then as flaky, and appends each
  run to --history=FILE; scripts/report-acceptance-flake.mjs reads it.
2026-11-10 14:10:46 +04:00
German Khokhlov 39246adaf7 Merge remote-tracking branch 'origin/main' into codex/fix-tool-display-text
Conflicts:
- docs/CURRENT-STATE.md: keep main's hidden-tab polling paragraph and the
  display-text normalization paragraph.
- scripts/package-boundaries.json: keep main's voice panel and text chat
  modules and add src/data/displayText.js.
- src/voice/gevActions.test.mjs: keep main's set_panel_open and partial
  analyst card tests and the display-text tests.
2026-11-10 13:58:41 +04:00
German Khokhlov 2a761aa5eb Merge origin/main into german/navara
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.
2026-11-10 13:52:52 +04:00
German Khokhlov f437c615a0 Add a --write mode to the package boundary check
`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.
2026-11-10 12:56:36 +04:00
manjunath22466 26b268a06c chore: merge main into viewport diagnostics pr (#835) 2026-11-10 12:36:12 +05:30
manjunath22466 1cd21d784a Merge main into viewport diagnostics PR (#835) 2026-11-10 10:45:23 +05:30
Sameh Khamis 9fe27c2d75 Merge branch 'main' into sameh/flight-photo 2026-11-09 21:13:16 -08:00
Sameh Khamis 1a8defbfc8 feat(flights): show the tracked aircraft's Planespotters photo in Contacts
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.
2026-11-09 20:36:03 -08:00
Sameh Khamis 4dc51927bc perf(traffic): build road lines one set at a time
With Lines on, every progressive paint of a loading city rebuilt all road
lines: up to three ground-line primitives for as many as 1,500 roads, built
asynchronously. Builds started faster than they finished, and each kept the
set it replaced in the scene until it was ready, so sets piled up.

One set now builds at a time. A rebuild asked for while lines are building
replaces the one waiting, and the newest starts when the build finishes.
Lines replaced by a finished build are removed before the next one starts.
Turning Lines off removes the lines at once and drops the waiting rebuild.
2026-11-09 20:31:28 -08:00
German Khokhlov 60fb8fee07 Fix the follow-up review findings in import, layers, startup and engines
- KML/KMZ import: a per-file canvas budget and cache for ground overlays,
  limits on rings and vertices of raised polygons, overlays across 360° and
  near the poles, degenerate holes, polar and single-latitude fills,
  absolute overlays at their altitude, overlay order by drawOrder as on
  Cesium, and pins on tiles keep their measured height.
- Points on the surface: OSM Places and Street Level cones share the
  surface sampler and sit on the terrain before they are measured, within
  a sampling budget per pass; Cockpit's contact-dot bank keeps the dot
  atlas, and a failed fleet model loads again after a pause.
- Startup: the loading screen lifts after the share-link view is restored,
  the retry screen names the failed engine and takes focus, and the
  fallback toast stays for 6 s.
- Engines: an engine switch lands a running camera flight at its
  destination (camera.completeFlight on both engines), the sighting card
  leaves focus on the engine picker after a switch, and a Cesium model
  error stays with the instance that failed.
- The MCP panel builds again: its wind-mesh alias resolves to the stub.
- QA: the wildlife switch waits for the camera to rest, GBFS --w2 says it
  needs the dev server, and test fixtures are shared instead of copied.
2026-11-10 01:57:11 +04:00
Meir Michanie f79ceb690f i18n(he): apply review (#1594)
Before merging: singular 'one' forms from the review table (44 entries),
counters keep their order across the slash (מתוך, as Arabic المن), the
lightning layer says ברקים (the legend now counts ברק strikes, the help
text keeps 110°E Latin), configured-elsewhere keys are promised
untouched, Punk is פאנק רוק, dock/panel side labels follow the mirrored
layout, and the HUD-summary English guard covers he (NON_LATIN_LOCALES,
tested) — documented in Adding a language along with format-scope.

Suggestions and nits: restricted is מוגבל, stage recovery is החבה not
שחזור, voice-inactivity names the behavior, lane directions use
attributes (השמאלי) and around is לאחור, Ironbow and KM/S stay Latin in
same-as-english, {age} no longer doubles לפני, typos and garbled words
fixed (תנאים, ידנית, ודאות, מקלט, זמניים, ערוץ 14, מעונן חלקית, אין אות
קריאה, Tab לתצוגה מקדימה, השאר ריק, היוועץ), counted units shortened
(שנ' דק' שע' ימ'), terminology unified (briefing תדריך, forecast תחזית,
course מהלך, אונייה, שריפה), rtl.css shares the mono redirect under
:is(:lang(ar), :lang(he)) and its comments match the rules,
worldOverlayTokens adds Noto Sans Hebrew to the canvas card fonts, he.md
gets the fraction-aware plural table, iw/iw-IL map to he (tested).
2026-11-09 14:41:36 -06:00
Meir Michanie 584732c3ec i18n(he): complete and ship Hebrew
- Add the full catalog (2940 entries keyed by the English text; 75 plural
  entries carry one/two/other per Intl.PluralRules('he')), reviewed for
  meaning, terms, separators and label length.
- Register he: he-IL and he map to it; it joins RTL_LOCALES so <html
  dir=rtl> mirrors the chrome through logical properties and rtl.css.
- rtl.css: Noto Sans Hebrew (loaded with the other Google fonts) leads the
  mono and sans stacks, tracking released like Arabic, HUDs keep JetBrains
  Mono for Latin telemetry.
- same-as-english: instrument codes and HUD readouts stay as printed
  (HDG/BRG/CRS/FOV/CRT/NVG/FLIR/CAL/SRC, MW units, Sentinel-2, km/h...).
- docs/translations/he.md: style, plurals and glossary.
- docs: TRANSLATORS.md and CURRENT-STATE.md updated; normalizeLocale test
  covers he-IL.
2026-11-09 14:41:36 -06:00
Kaj ObstandClaude Opus 5.5 cdccf88bbb i18n(sv): address review (export buttons, singular, consistent terms)
- EXP. {slot} and EXPORT so the Recent Imagery export buttons fit and A
  and B read apart; EXPORT listed as same-as-English.
- {count} HÖRT / hört for one aircraft; the plural rule in sv.md no
  longer lists HÖRDA.
- INTE FARA ÖVER throughout; VÄ/HÖ for left/right (V is west on the
  compass); STYRD KURS vs KURS Ö. GRUND; MIK in the first-run tip.
- Label-first counts for sightings and standby cameras; neuter audio
  states; OSÄKER on chip and status line; KN for knots; the ellipsis
  character; Ladda ned and VÄNTLÄGE throughout; Olagligt ingripande;
  FÖRHANDSVY for the preview flag and authoring heading.
- sv.json in the format scope; Swedish in language-code order in
  TRANSLATORS.md; glossary row reduced to incident → händelse; 29
  letterless entries dropped from same-as-english.json.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:25:24 +01:00
German Khokhlov 0ef29781e5 Fix the review findings across the engines, layers, data and QA
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.
2026-11-09 21:34:42 +04:00
German Khokhlov 015e3ff7fc Merge branch 'main' into fix/node26-allocation-gates 2026-11-09 20:19:29 +04:00