Commit Graph
3552 Commits
Author SHA1 Message Date
Sameh Khamis 9e3786716d test(camera): pin that application controls install the zoom-out guard
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.
2026-11-03 09:11:51 -08:00
German Khokhlov 074f4af10e Release a running camera verb when a Navara scene is parked or torn down, as the Cesium scene does 2026-11-03 21:11:30 +04:00
German Khokhlov dcb8de9d2c Run the camera verbs on the globe contract so orbit, pan, tilt, rotate, globe rotation and the route dolly move a Navara camera as they move Cesium's
A motion drives one camera through a rig: a Cesium viewer's own camera, or any globe engine through camera.pose/setView/lookAt/release/transform/flightActive/following and frames.preRender. An engine rig binds its frame, canvas-input and follow listeners only while its motion runs. A finished once orbit now releases its lookAt lock, and an orbit armed through a flight keeps its nudge budget until it starts.
2026-11-03 21:11:30 +04:00
Sameh Khamis b817d5802b fix(camera): let a two-finger tilt win over finger-spacing drift
Above 300 km the guard treated any shrinking pinch distance as an outward
zoom, so a two-finger tilt whose fingers drifted slightly closer had its
pitch overwritten. A two-finger gesture now counts as a zoom only when the
spacing changes more than the fingers' midpoint moves.
2026-11-03 09:10:58 -08:00
Sameh Khamis e4b3933166 fix(camera): read zoom input at the ceiling when the scene is idle
The guard reads its input in preRender, which Cesium only fires on frames
that draw. In request-render mode, wheel input at the ceiling doesn't move
the camera, so nothing drew and the input was applied later by an
unrelated frame. The guard now requests a frame through the render
governor whenever it has unread input.
2026-11-03 09:10:30 -08:00
Sameh Khamis 08ff7f3e9d fix(camera): let a camera above the zoom ceiling zoom in without a jump
Cesium clamps any zoom that starts above maximumZoomDistance to that
limit, in either direction, so a share link or flight that left the
camera above 40,000 km jumped to the ceiling on the first wheel tick.
While the camera is above the ceiling, the guard now uses its current
height as the limit and lowers it as the camera descends.
2026-11-03 09:09:55 -08:00
Sameh Khamis 540629a0fc fix(osm): keep a capped place list incomplete in analyst follow-ups
osm_query said "At least N" when the server capped its list, but handed
the places to the analyst engine with truncated:false, so "which of those
have emergency?" answered as if the list were whole. The handoff now
carries the cap and its caveat, and follow-ups (and their follow-ups)
stay incomplete with an unknown total.
2026-11-03 09:09:28 -08:00
German Khokhlov 9a1bc34042 Keep weak Active Fires as markers through the hand-off
The 750–3,000 km markers band now draws up to 20,000 detections instead
of 2,500. At the 2,400 km end of the cross-fade the padded view over
Africa holds ~21,000 fires, and the old cap kept only those above
~17 MW, so most heat spots faded into empty ground as the heatmap went
out. A rebuild of that many costs ~60 ms, and only in the densest views.
2026-11-03 21:09:09 +04:00
Sameh Khamis 4efba8ccca fix(osm): end the server's place search before the voice answer gives up
The voice answer waited 25 s for /api/osm/features, while the server let
Overpass run for 25 s and itself waited up to 40 s per endpoint and 45 s
in all. When the browser gave up first it closed the request, the route
cancelled the upstream query, and nothing was cached, so the OSM_TIMEOUT
retry started the same query from scratch and timed out again.

The server now tells Overpass 20 s, waits 22 s per endpoint and 22 s in
all, which ends inside the client's 25 s. A test pins that ordering.
2026-11-03 09:08:16 -08:00
Sameh Khamis 51637a5e96 Merge branch 'main' into feat/voice-geometry
# Conflicts:
#	SECURITY.md
#	scripts/format-scope.json
#	src/app/constructCatalog.test.mjs
#	src/app/sourceComposition.test.mjs
#	src/firstRunExperience.test.mjs
#	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
#	src/voice/actionSchemas.test.mjs
2026-11-03 09:07:16 -08:00
Sameh Khamis d5a568e55f Merge branch 'main' into fix/zoom-out-runaway 2026-11-03 09:04:51 -08:00
Sameh Khamis 93804d5dbd Merge pull request #1527 from bilawalsidhu/sameh/restore-format-scope
fix(tooling): restore 97 format-scope entries dropped by a merge
2026-11-03 09:04:26 -08:00
manjunath22466 0a8d824124 fix(voice): keep a stopped round's actions and follow-up memory
A reply stopped partway through a round now keeps the actions that ran,
answering the calls it never reached as skipped, so the history stays
paired for both providers. A failed typed turn no longer resets the
pointer, referents and follow-up memory, since its conversation continues.

The server now tells a rejected key (401, or Gemini's 400 with reason
API_KEY_INVALID, matched exactly), denied access (403) and an account out
of credit (OpenAI's 429 insufficient_quota) apart; each cools down for a
minute and gets its own message in the chat.
2026-11-03 22:34:21 +05:30
German Khokhlov 4c28cc0212 Draw the visual styles on Navara as one post pass behind an optional render.setStyle capability
CRT, NVG, FLIR, Anime and Noir run their Cesium shaders through a GLSL prelude with the exact sRGB transfer, crossfade in the stage order, fade the Navara stars with Anime, and report the visualStyles capability through engineCapabilities.
2026-11-03 21:02:50 +04:00
German Khokhlov 00dfed7959 Run the scenarios from the served clean checkout 2026-11-03 21:01:17 +04:00
German Khokhlov f7945d6844 Stop the runner's preview at the end and record only .env names and credential leaks in the served build 2026-11-03 21:00:58 +04:00
German Khokhlov 96b5b0bb1f Draw the session annotation board on Navara: draped areas and routes as clamped meshes, every other mark on the shared screen board over the engine's projector 2026-11-03 20:59:10 +04:00
Sameh Khamis ceb3fe1b2b fix(tooling): restore 97 format-scope entries dropped by a merge
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.
2026-11-03 08:55:02 -08:00
Manjunath fdecc8c581 Keep the tilt clearance through a zoom in
A zoom in during a pivoting tilt stops at the range that keeps the camera 150 m above the pivot at its current pitch. A zoom that moves the range by less than half a metre (at the clearance, the 80 m floor or the 5,000 km cap) now answers not zoomed instead of ok, and a tilt reports tiltRangeAdjusted rather than orbitRadiusAdjusted.
2026-11-03 22:23:38 +05:30
Manjunath 582bfce660 fix(osm): gate place search like /api/overpass after #1308
#1308 moved /api/overpass to the keyless cross-site gate: foreign origins
and cross-site fetches are still refused, but forwarding headers are not,
so the map works behind a reverse proxy. Voice place search spends the same
operator Overpass, so it now uses the same gate; with the stricter one,
place search failed behind a proxy while the map kept working. The prompt
lint note records the merged size, 55,370 with an operator Overpass.
2026-11-03 22:18:06 +05:30
Manjunath 1e12d5ba26 Merge branch 'main' into feat/voice-geometry
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.
2026-11-03 22:16:52 +05:30
German Khokhlov f01200b467 Cross-fade Active Fires markers and heatmap; fix the spot size
The far-zoom heatmap now uses the ½× grid (4096 × 2048, ≈10 km per
pixel, one-pixel blur), so a lone fire's spot matches its marker at the
3,000 km hand-off. The spot size slider and its share option are gone.

Markers and heatmap are both kept built at every zoom and cross-fade by
camera height between 2,400 and 3,600 km on every frame, so a fast zoom
never shows a beat with neither. The heatmap fades by imagery alpha:
hiding a Cesium imagery layer unmaps it from the globe tiles, and showing
it again re-mapped them late, which was the gap at the band edge. Under
the markers the heatmap is built 150 ms after the data or filter changes.
2026-11-03 20:41:50 +04:00
German Khokhlov 5b7171f485 Pin that push-to-talk starts from the Navara canvas inside its renderer host 2026-11-03 20:40:34 +04:00
German Khokhlov f5c14ec30d Move the session annotation board, Draw and Import out of the Cesium tools into sessionTools.js and give Navara its tools seam 2026-11-03 20:37:59 +04:00
German Khokhlov dea10cac4f Give Local ADS-B the selectById hook the other selectable layers expose
It takes the ICAO a position row carries, in any case, or the marker id, and selects through the same path as a click; selectAircraft now delegates to it.
2026-11-03 20:36:10 +04:00
German Khokhlov 60a230b2ff Keep a bikeshare city's last known stations, marked stale, when it comes back into range during a source outage 2026-11-03 20:33:13 +04:00
manjunath22466 9d4d7b3ee0 Merge branch 'main' into feat/typed-ai-chat 2026-11-03 22:02:28 +05:30
German Khokhlov 057dbe24af Reframe a mission after a late active-satellite answer only while nobody has left its orbit view
A flyover, a launch-site view, a cancelled flyover or another mission now clears the pending orbit framing, so a late TLE lookup followed by a data refresh never takes the camera back.
2026-11-03 20:31:49 +04:00
manjunath22466 da8b0dd8cd fix(voice): address review of typed AI chat
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
2026-11-03 22:01:08 +05:30
German Khokhlov f0d7def9c7 Report an empty wind field from get_wind as no surface reading instead of a NaN speed 2026-11-03 20:29:44 +04:00
Manjunath 9d8db97a33 Merge main into the voice tilt branch
Re-pin the Realtime tool payload hash for the merged tree (main's layer changes plus pitchDeg). The Realtime prompt measures 51,960 of 52,000.
2026-11-03 21:58:10 +05:30
Said Turksever 2c936ae131 docs: correct hidden-contact rotation interval 2026-11-03 16:26:45 +00:00
Said Turksever b68cd25e9e Merge commit '2ebde97fb3af19402eab83fca2bfbec9ddfd166a' into easy-wins-20261103-pr870 2026-11-03 16:17:34 +00:00
Said Turksever fa8db45d63 Merge commit '2ebde97fb3af19402eab83fca2bfbec9ddfd166a' into easy-wins-20261103-pr1518 2026-11-03 16:17:33 +00:00
Said Turksever 66a5c483c2 fix: resolve review findings and refresh PR #870 against main 2026-11-03 16:17:31 +00:00
Said Turksever a0924c00d7 fix: resolve review findings and refresh PR #1518 against main 2026-11-03 16:17:30 +00:00
German Khokhlov 1773494116 Run the layer acceptance under a default-deny network policy with per-layer assertion manifests and strict switch contracts
Every scenario runs through scripts/qa-strict-harness.mjs: each page, frame and worker gets an ordered block list before it runs (paid hosts and routes first, then only the preview, declared fixtures, keyless probes and cached free tile hosts), switches with real input on the picker, and records its assertions per layer and engine. The runner reads the catalog from the live page, fails any layer without an assertion on either engine, can build and serve a keyless checkout itself, and adds rapid, hidden-tab, context-loss, failure-injection, cold-chunk and soak scenarios. The main chunk gets a 1% size budget.
2026-11-03 20:15:50 +04:00
German Khokhlov 3144169057 Draw the Navara CCTV frame and viewshed in the depth-tested opaque scene so walls hide them
Navara's transparent pass runs after the post effects without the scene depth, so a camera frame clamped in front of a wall still painted through it. scripts/qa-edge-cctv-occlusion.mjs serves a one-box tileset as a local fixture with no network and checks on both engines that the frame ends at the wall and is not visible behind it.
2026-11-03 20:11:23 +04:00
Said Turksever 2ebde97fb3 Merge pull request #1206 from m3ayush/feat/radio-country-coverage
feat(radio): add configurable priority-country coverage
2026-11-03 16:07:29 +00:00
German Khokhlov 37ea4e1f93 Keep the six map-source tiles on one row and follow the engine picker in the map tray gate
Sentinel-2 made the desktop source row wrap to two rows; the row now lays out every tile in one row (three columns on a phone, as before). scripts/qa-map-source-tray.mjs read the controller's removed imagery internals and counted five tiles between OSM and the styles; it now reads the live base provider and counts the section's tiles and engine picker. The five failures left also fail on origin/main e5d15f24.
2026-11-03 20:00:55 +04:00
German Khokhlov 31b1f27a2e Wait for the traffic refinement task by task instead of for five milliseconds
The handoff test failed under a loaded test runner when the refined pass needed more yields than a fixed 5 ms timer allowed; it now yields until the refined paint lands (bounded by a task count, not wall time).
2026-11-03 19:55:33 +04:00
German Khokhlov f2117a98f2 Ask a parked Navara globe for no frames and guard parked engines in the switch gate
The Navara look stopped requesting frames once its globe is parked. scripts/qa-app-once.mjs now fails if anything moves a parked engine's camera or asks it to draw (its own resume aside).
2026-11-03 19:54:45 +04:00
German Khokhlov 40a81c58e6 Hold the shell's inputs between two engines instead of reaching released controllers
A visual choice made while no globe is attached (a style key, a Display control, a voice command) is queued and applied to the next engine's settings after it restored the address's view, so the person's choice wins; reads answer from the released settings. The globe reset and a location lookup started without a globe do nothing, and the map-source chips and camera buttons are unbound until the next globe binds them.
2026-11-03 19:54:45 +04:00
manjunath22466 11cd0142ac Merge remote-tracking branch 'upstream/main' into feat/typed-ai-chat 2026-11-03 21:22:43 +05:30
Manjunath 3c6c342b2b perf(awareness): skip echo work for the whole frame while pulses rest
The detection overlay asked the echo field for every visible flight,
military aircraft and vessel on every frame while a subject was
selected, projecting each to the ground before learning the pulses were
resting. It now checks awarenessEchoActive once per frame and builds no
echo paths at rest, and awarenessEchoAt checks the level before the
projection.

A detectionHost test with six echo-eligible flights checks that a
resting frame asks for the level fewer times than there are contacts
and paints no echo; it fails on the per-contact path.

The pulse and echo policy doc comments are attached to their constants
again, and one long comment line is re-wrapped.
2026-11-03 21:22:36 +05:30
German Khokhlov df73c5b21a Break Contacts distance ties by identity so navigation reaches the same ID in any feed order 2026-11-03 19:50:25 +04:00
German Khokhlov c96d4ecfb1 Check that a superseded or cancelled launch flyover never takes the Navara camera back 2026-11-03 19:50:24 +04:00
German Khokhlov d5218c4722 Check that a late route answer and the previous engine's camera never take over a Directions route 2026-11-03 19:48:15 +04:00
German Khokhlov 4f8a9f2615 Cover a scene switch at a stopped satellite epoch with an edge-case test 2026-11-03 19:48:05 +04:00
German Khokhlov 1c09c90e13 Test that a late Nepal boundary after cancel leaves the live locator scene alone on both engines 2026-11-03 19:47:29 +04:00