Name each Rio feed in its credit instead of repeating the licence, drop the
deprecation history from the bus note, list Rio among the feeds with a
route-name table, and shorten the route-table header and test comments.
The Transit prompt said "Fly below 3,000 km", but the closed gate opens at
2,850 km; it now names the enter threshold, as Bike Share does. When the
camera changes coverage, Transit and Bike Share ask the Layers panel to
repaint instead of leaving the old prompt up until the next 15 s / 60 s tick.
The callout now asks for the opacity its own card paints with this frame,
keyhole fade included, and fades out as the card fades in. A card faded out
at the keyhole rim leaves the callout readable, and a card fading out after
leaving its source still hides it. The vessel card id is cached on the
record, and the allocation gate covers the lookup.
- Navara 0.2.1 never frees pick batch ids, and the mover banks rebuilt
their instanced meshes on each attach, leaking about 260 KiB of
WebAssembly memory per switch. A per-view pool hands released ids back
out; the long soak now asserts native growth of at most 32 KiB per switch.
- Navara 0.2.1 sometimes drops the first show:false update on a new
vector layer, so a zone turned off right after a switch back stayed
drawn. Polygon displays hide by deleting their layers and rebuild them
when shown.
- Camera verbs drive both engines through the globe contract; the Cesium
viewer rig and the tests of states it can no longer reach are gone.
- Flights and military tracking share src/layers/aircraft/tracking.js.
- The geo import scenario reads movers only where the engine has them.
- Add the Navara section to docs/CURRENT-STATE.md and a changelog fragment.
foldPlaceName drops a leading "the", so "The Hague" over upstate New
York accepted Hague, NY as an exact nearby match. Split the script-aware
fold into foldPlaceText and use it for keyless toponyms; foldPlaceName
keeps its behaviour for the packs and street matchers.
Also: changelog fragment credits #1585, folding test pins the Latin
letters NFD does not decompose (ß, ø, ł), and CURRENT-STATE notes that
non-Latin names match only when spelled with their marks.
Both SMTR feeds now publish Position.speed in m/s. Compared with how far
vehicles moved between reports on 2026-11-05, the published values ran
3.1x (buses) and 3.6x (BRT) below the observed speed, so the km/h
conversion divided real speeds by 3.6. Drop speedUnit and the conversion.
- 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.
A Director hold longer than the settle check's five-minute bound used
to expire the deferred check, so a run that ended on a stars-only shot
after a long hold stayed there until the next move. While a flight or a
playing scene defers the check, its bound no longer counts down; the
flight or scene bounds the deferral itself.
Also correct the trackball note in CURRENT-STATE: Cesium's tilt tests
the screen centre, so any tilt (drag or touch) with the centre on the
stars between 1,000 and 7,500 km now tilts about the planet's edge or
does nothing, wherever it starts. Rotation drags that start on the
planet are unchanged.
Writing a fractional alpha onto the overlay record for every paint item
boxed a heap number per item per frame. The allocation gate caught it:
the generic 60-entry workload went from 2,838 to 12,614 B/frame. The
record now keeps only the frame stamp and a pointer to its paint item,
and isOverlayEntryQueued multiplies the alphas when it is asked. The
gate is back to main's numbers on Node 24.
A check skipped because a flight or a playing Director scene was in
progress used to be dropped, so a run that ended or held on a stars-only
shot stayed there until the next camera move. Keep watching instead:
the settle check retries once the flight or scene ends, within its
existing five-minute bound, and a moveEnd that arrives while it is
deferred keeps the check armed rather than stopping it.
Also test that the free-look limit never raises Cesium's trackball
height and that dispose keeps a value set after install, note in its
JSDoc the enableLook case it cannot tell apart, and document the
trackball change and the retry in CURRENT-STATE and the changelog.
With Vessels and Detection on, a vessel with an ambient card on the map
also got its detection callout next to the bracket. The callout lane
paints beneath the cards, so its text showed through the card's plate
and covered the speed and course.
The callout now gives way only to a card the shared overlay actually
paints in the same frame. The overlay paints part of the published
cards (shared budget, collisions, UI chrome), so a vessel whose card
was dropped keeps its callout.
The detection lane paints before the cards publish their paint rects,
so getOverlayPaintRect has nothing for the current frame there. The new
isOverlayEntryQueued answers from the paint queue that the overlay
solves before painting. Vessel detection objects name their card in
cardSourceId/cardEntryId.
Over a city with no feed or system (London, Tokyo) both rows read
"ON · — · never", the same as a feed that never answered. Transit already
computed a coverage note but put it only in `coverage`, which the row does
not show; Bike Share reported nothing at all.
Both layers now report a `zoom-in` guidance status with a `statusMessage`:
"Fly below 3,000 km to a covered region" / "No feed here yet · N regions
available" for Transit, and "Fly below 48 km to a covered city" / "No bike
share here yet · N systems available" for Bike Share. A loading or failed
Bike Share city keeps its own text. Leaving coverage clears the layer's
last-update time, so the row no longer dates data it no longer draws.
The coverage-note translations move from the voice card into
`translateStatusMessage` (ui/statusText.js), which the Layers row and the
voice card now share.
The launches layer swallowed every fetch error in its update, so the
manager treated a 429 or timeout on /api/launches as a successful start.
Context then committed the isolating mode with no missions: the other
layers stayed off, unrelated enables were refused, the camera stayed at
the full-globe view and the roster kept reading "loading".
Until the first index loads, the update now reports the failure. The
manager fails the enable closed and both entry routes roll back to the
pre-entry layers. The camera pose captured at entry is restored when the
mode is left before any index loaded, and the roster shows a failed
state instead of loading. A valid empty index still enters, and a
refresh failure after a loaded index keeps its records.
An installation card on Navara now names an unnamed feature and its
class in the UI language, and an ALPR camera keeps its context label as
English data that is translated when shown.
The panel reads legend entries as label and count; the layer sent text, so each entry showed 'undefined'.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Replace the four era chips with the start and end year pickers the
air-accidents layer uses (the same RowRange control, ported as is);
the era colours stay as a legend under the row.
- Rasterize the boat marker at 144 px so large markers stay sharp.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A new Events layer maps shipwrecks with a card per wreck:
- EMODnet Human Activities heritage shipwrecks (about 6,500 in European
waters, CC BY 4.0), skipping rows taken from wrecksite.eu.
- Wikidata shipwrecks with a Wikipedia article plus sinking events
(CC0); an event folds into its ship for the date and death toll.
- A same-origin /api/shipwrecks proxy refreshes once a day and serves
the last snapshot as stale for up to a week.
Markers are a boat icon coloured by era and sized by deaths; four era
chips filter the layer. The card follows the air-accidents layout
(deaths first). Text that names people is dropped; victims appear as
a count only.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Below Cesium's trackball height (7,500 km by default) a drag that starts
on the stars turns the camera in place, whatever enableLook says, which
was the drag path to a view with no planet in it. Lower that height to
the free-look height with the free-look limit, never raising it, and
restore it on dispose. Above 1,000 km such a drag now orbits the globe,
as it already did above 7,500 km, at a similar rate, and a tilt drag
from the stars there tilts about the planet's edge or does nothing
instead of turning the camera. Drags that start on the planet are
unchanged.
At the ~20 px the fleet renders at, the bus, tram, metro and unknown
glyphs were near-symmetric boxes: rotated along the course, nothing showed
which end was the front. Each now has a front built into its outline (an
arrow-like nose for the bus, a pointed cab for the tram, a chamfered cab
for the metro), so it survives the tint, the halo and the sensor profiles,
which keep only the outline.
A vehicle with no known course sits at rotation 0, where a pointed glyph
would claim it is heading north. Those vehicles, fleet and selected alike,
now get a symmetric outline (rail and ferry included) and switch to the
pointed one once a course arrives. The raster cache doubles to a fixed 72
variants.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review follow-ups for the globe-in-view recovery and voice limits.
- Leave a camera flight in progress and a playing Director scene, holds
included, to their own framing. The recovery is now installed with the
scene tools, which own the Director, and reads its running state.
- Reuse a voice turn's half-degree proof only from the position and
direction it was proven at, so a release that moves the camera checks
the turn again.
- Share one free-globe-camera check between the recovery, the voice
turn limit and the globe rotation.
- Keep an enableLook setting other code makes after the free-look limit
is installed, instead of writing back the install-time value.
- Name the nudging test for what it asserts, the 1% floor, and document
that a view losing its surface without a camera move waits for the
next one.
- A tilt's angle, limits and "unchanged" check use the camera's own
pitch. At regional range the pivot pitch is up to about 8 degrees
shallower, so "tilt to 5 degrees" from 900 km ended at -12.9 degrees.
The swing now solves for the pivot pitch that gives the camera angle.
- A zoom out during a pivoting tilt stops at the 1,000 km pivot limit
instead of the orbit's 5,000 km, and a zoom in that reaches the
clearance is applied before the pivot ends.
- An angle the camera already holds still takes navigation, so it stops
a running motion and releases the follow camera.
- A motion queued behind a fly-to moves to a newer fly-to as soon as it
begins, so a stalled lookup no longer holds it past a flight that
landed. Wait listeners are removed when a wait ends, and a lookup that
found nothing points straight at the flight that moved.
- A fly-to that stops a running motion names it (stoppedMotion).
- A tilt left or right is refused, and the pitchDeg description says
steps use direction.
Review follow-up for #1552:
- environmentProviders: assert exactly 3 upstream calls per refresh again,
so a returning fourth source would fail the test.
- firmsProxy: build the test's SOURCES from server/providers/firms.js, so
there is one list instead of a mirrored copy.
- firmsProxy: drop the unused fourth count entry.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The incident card rounded the WFIGS size to whole acres, so every fire
under half an acre read "0 ac". The live perimeter feed carries many of
these (0.01 to 0.37 acres). Sizes under one acre now keep the reported
hundredths.
SMTR's realtime feeds carry internal route keys, so a Rio card read
"Route O0731AAN0A" where riders know line SN731. Join both feeds to the
route_short_name in SMTR's static GTFS routes.txt (CC BY 4.0, same
publisher and terms). The keys cannot be parsed: O0014AAA0A is LECD135.
A 2026-11-04 snapshot found all 282 bus and 21 BRT routes in service in
the table; an unknown key still falls through raw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Cockpit entry no longer needs Contacts or both flight feeds: a civilian
aircraft needs Live Flights, a military one Military Flights. Contacts and
every other layer can be turned on or off before or during a session, and
turning off the ridden layer ends it. A Context mode change in flight still
blocks entry.
When the other air feed is off, Live Signals and the Contact card say
FLIGHTS FEED OFF or MILITARY FEED OFF · PARTIAL PICTURE instead of
presenting a partial picture as complete. Voice refuses entry with
subject-layer-off rather than contacts-inactive, and its tool description
says Contacts is not required.
Double-clicking the followed aircraft enters Cockpit through the same gate.
The Cockpit takes the scene's double-click before Cesium's stock handler,
which would otherwise untrack a followed aircraft whose model is a
primitive. The entry also shows under the Intel HUD readout, sharing the
Contacts button's face. A test keeps the classes the Cockpit adds to the
body from matching another element's rule.