The voice runner subscribes to camera handoffs as it is created. The Cyber sonar test builds its runner on a StyleManager made from the prototype, which has no navigation owner, so the facade's delegation threw and both Node jobs failed. The facade now returns nothing there, like its other optional owners; the real shell builds its navigation owner before voice creates a runner.
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.
The changelog fragment named share-link token 6 (sea marks); the layer
reserves 8. CURRENT-STATE said voice could toggle and query the layer and
listed it among the analyst record sources, but it is in VOICE_OFF_LAYERS.
Say voice is off for now, and that the layer covers FAA prohibited and
restricted special-use airspace only, not the UAS Facility Map / LAANC grids
or TFRs. A test pins these claims to the token ledger and the voice manifest.
Re-pin the Realtime tool payload hash for the merged tree (voice geometry plus pitchDeg). To fit main's 55,500 prompt ceiling with Overpass on, the pitchDeg schema drops its -90..90 range (the runner already clamps to -89..-5, now pinned by a test) and its description is shorter. The Overpass prompt measures 55,492.
Picks up #1527, which restores the 97 format-scope entries an earlier merge
dropped; this branch had kept the same 97. The resolved list is main's plus
this PR's 12 test and helper files, 1,222 paths, all present.
The guard's own tests pass even if createApplicationControls stops
installing it. This checks the ceiling and frame listeners are in place
after construction and gone after teardown.
Merge commit 34906c9a resolved the end-of-list conflict in scripts/format-scope.json with the branch's side, which dropped the 97 entries main had appended since Oct 26. Those files all still exist; 64 of them are tests that runtime discovery does not cover, so format:check had stopped checking them.
Each entry goes back at its position on main before the merge. All 1680 files pass npm run format:check.
Picks up #1308 (Overpass admission), #114 (Sea Marks and Ski Pistes),
#1206 (radio country coverage) and #1435. Resolutions:
- SECURITY.md: main's rewritten cross-site paragraph, with voice place
search listed beside /api/overpass among the keyless map routes.
- scripts/format-scope.json: both sides. A merge on main dropped 97 entries
(being restored there); keeping them, this PR's 12 and main's 2 new ones
keeps every file in format:check. All 1,222 paths exist.
- Translation catalogs: main's two new keys and this PR's 47, no overlap.
- Layer count 36 (33 + OSM Places + Sea Marks + Ski Pistes); both schema
pins re-derived, the first-run length is exactly 30,919 + 292 + 107.
Typed chat sessions no longer end on the voice inactivity timeout, and a
failed or stopped reply keeps the conversation: Stop cancels only the
reply in progress, and map actions that already ran stay in the model's
context. Each upstream request and map action gets its own deadline, old
tool results shrink instead of the history overflowing, and step limits,
a missing or rejected key, the OAuth lock and throttling each get their
own message.
- Server: OpenAI chat is off under GEV_PREFER_CODEX_OAUTH; chat throttles
default to the provider's throttle; replies carry API_KEY_MISSING,
API_KEY_REJECTED, CODEX_OAUTH_REQUIRED and RATE_LIMITED codes; upstream
Retry-After passes through, and a rejected key (Gemini's invalid-key 400
included) cools down for a minute
- Pinokio forwards the chat throttle settings
- UI: the reply reveal publishes only the message list; the border orbit
runs only while busy; layers attach with a button or Enter; the log is
aria-busy while a reply types out; auto-scroll respects a reader who
scrolled up; Escape closes the attach menu; the chat gear says Settings;
a note says chat bills the OpenAI key when voice uses ChatGPT sign-in
- Layout does less work while panel height animates; unused blurs removed
- Gemini voice start ends chat; the voice preview clears on every new
session
- Tests for the route gates, client limits, attachments and the fixes
Keeps main's locale catalogs and re-adds this PR's eight Street Level strings; re-pins the Realtime payload digests for main's two new overlay layers, where the unchanged tools match main's pin, so show_street_level is still the whole difference.
The slim Street Level core (#974) removed nearestImage from the Mapillary
provider. show_street_level and sl=mapillary links need it to open the
photo closest to a point, so this restores it on the slim core: Graph API
/images within 50 m, sorted by distance, first one that passes the imagery
filter. Kept as its own commit so it can be dropped if #974's removal
should stand.
show_street_level (voice and typed) flies to a place and opens its nearest
street-level photo from Google Street View, Mapillary, KartaView or
Panoramax; Street View switches to Google 3D first. The view model gains a
street_level field, share links carry sl=<source>,<lat>,<lon>, and
show_in_gods_eye_view can open a photo. A plain sl=google link only arms the
point and waits for OPEN, so it never bills a key without a click.
Embed pages show an open photo in an overlay that Esc closes. On-screen
strings are translated into es, ru, zh-CN and zh-Hant. Covered by unit tests
and three new steps in the Street Level browser suite.
From review:
- The browser client for /api/osm/features gets its own tests (request
shape, abort, network failure, coded refusals), and a 200 whose body is
not JSON is now a failure instead of zero places.
- An end-to-end test runs resolve_area, osm_query and an analyst follow-up
through the real runner and checks the follow-up keeps the area; it fails
with the wiring reverted.
- The Realtime token test pins Overpass off and compares the full tool
schemas again instead of names taken from the environment.
Cesium zooms a shallow view out by backing along the cursor ray with
heading and pitch held fixed, and GEV set no zoom ceiling. Past ~700 km
the limb drops below the fixed pitch, the steps grow with height, and
the camera flies off into space.
Cap user zoom at 40,000 km (whole-Earth view; flights are not limited)
and, above 300 km during a user wheel, pinch or right-drag zoom-out,
ease the pitch down to at least 8 degrees below the Earth's limb. The
clamp yields to disabled inputs, tracked transforms and camera flights.
The Cockpit Contact counts named fixed providers (OpenSky, adsb.lol,
AISStream) while the Layers panel and Contacts named the provider the last
snapshot reported, and the vessels layer kept that name out of getStats(),
so Contacts always said AISStream. Each cohort now carries the provider and
whether it answered as a fallback or from a stale snapshot, and both views
show it the way the Layers row does ("adsb.lol · FALLBACK").
Fixes HAL-721.