mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
chore: merge main and preserve changelog entries
This commit is contained in:
commit
d23abd3116
118 files changed
+18241
-1283
No files matched your search
+112
-14
@@ -14,6 +14,19 @@ new views from the page that frames it; framing is off unless
|
||||
`GEV_EMBED_FRAME_ANCESTORS` allows the framing page. MCP leads with the tools that find
|
||||
what to show. See [tools and the MCP server](TOOLS.md).
|
||||
|
||||
Stdio processes from one install share the panel key in
|
||||
`.gev-cache/mcp-panel-key`, resolved from the checkout rather than the client's
|
||||
working directory. First creation is atomic; malformed-file repairs select one
|
||||
winner and concurrent processes re-read it. A busy repair waits at most two
|
||||
seconds before falling back. If the cache cannot be read/written or repair remains
|
||||
busy, stderr reports the fallback to a per-process key; cross-process panels can
|
||||
still fail in that mode. An abandoned `.repair-lock` is left intact: after
|
||||
confirming no repair process is running, remove it to allow repair on restart.
|
||||
HTTP MCP servers retain per-server keys. This key is a panel routing guard, not
|
||||
authentication. Large-response continuations remain process-local and require
|
||||
consistent tool-call routing. Two-process reproduction is covered locally;
|
||||
Windows/Claude Desktop Cowork confirmation remains outstanding (#927).
|
||||
|
||||
## Tools and local MCP server — October 1, 2026
|
||||
|
||||
`gods-eye-view/tools` defines queries that answer questions from the app's data,
|
||||
@@ -278,7 +291,7 @@ Consult the linked official advisory for safety decisions.
|
||||
|
||||
Voice and HUD snapshots reuse the existing feedState classifier. Analyst follow-ups retain their original data provenance; current-view results append provenance without replacing legacy fields. HUD context and deterministic telemetry include non-nominal feed state.
|
||||
|
||||
Satellite and local infrastructure layers expose on-demand analyst records through their current factory owners. Analyst counts and ranks explicitly cover only bounded examined loaded records (default 2,000 per new layer, core satellite rows before dense extras); omitted records can change nearest/count and satellite distance is ground distance. Existing tools and result fields remain available.
|
||||
Analyst records come on demand from each layer's `getAnalystRecords`: flights, military, local ADS-B, vessels, satellites, launches, earthquakes, FIRMS (VIIRS and MODIS, with a `sensor` field), fire perimeters, cyclones, transit, bikeshare, ALPR cameras, mapped installations, datacenters and dams. `analyst_query` counts the whole loaded set (up to 250,000 records per layer; past that `coverage.records` reports `returned`, `total` and `truncated: true` and the result carries `complete: false`). Ranking keeps a top-k and scans in 20,000-row slices that yield to the page and stop when superseded. It refuses unknown fields, operators, units that do not convert (`altitudeM(ft)` converts), wrong-typed values, invalid centres, unknown scope kinds and sort fields with `code` and `allowed`, refuses a follow-up with no previous answer (`NO_RESULT_CONTEXT`) or naming other layers than that answer (`FOLLOW_UP_MISMATCH`), and tells `LAYER_OFF`, `NOT_READY` and `FEED_UNAVAILABLE` apart from a real zero; when only some layers can answer the result is `partial` with `unanswered` ids. The Contacts-window path applies the same filters, ranking and item shape to one immutable panel snapshot. Each aircraft layer retains at most 20,000 rows; reaching that bound sets `complete: false` and the spoken/card count becomes “At least”, never an exact claim. A superseded query never replaces follow-up memory, while sibling analyst calls from one assistant response do not cancel one another. Items carry `lat`/`lon`; the feed window (earthquakes and FIRMS: last 24 h), the precise scope and any caveat sit in `display`, which is on-screen detail rather than something the model recites. "In view" is still a radius around the view centre, not the visible footprint. Satellite distance is ground distance.
|
||||
|
||||
Keyless terrain tiles retry when Re:Earth throttles them. The browser fetches
|
||||
`terrain.reearth.land/cesium-mesh/ellipsoid/{z}/{x}/{y}.terrain` directly; no
|
||||
@@ -353,6 +366,70 @@ replacement session; audio meters release failed initialization and reject revok
|
||||
frames. Delayed action results and post-capture continuations cannot resume a
|
||||
stopped conversation or send output into a replacement. See [voice ownership](VOICE-OWNERSHIP.md).
|
||||
|
||||
Contacts nearest-aircraft follow-ups retain the snapshot's distance basis even
|
||||
after the camera moves. An explicit new scope replaces that basis. Provider
|
||||
instructions require an analyst query for requested lists and use the requested
|
||||
radius rather than substituting the panel's fixed window. Analyst speech carries
|
||||
stale/degraded feed status and does not speak an authoritative unavailable count.
|
||||
The existing NOTES disclosure deduplicates coverage/source caveats and retains
|
||||
their full text in at most six rows, grouping analyst overflow in the final row;
|
||||
ordinary tool-card limits are unchanged.
|
||||
|
||||
Voice speech: `src/voice/speech.js` adds `{ say, display, referents?, schedule? }`
|
||||
to layer toggles, fly_to_location, frame_overhead, select_nearest_aircraft,
|
||||
get_entity_context, annotate_map and analyst_query. Analyst speech and the card
|
||||
share one deterministic count/scope headline; lower bounds use "At least" and
|
||||
partial answers name the unanswered layers. `get_current_view_state` lists enabled layers only.
|
||||
The voice card nested in the mic control (`voiceCard.js`) shows captions, plan
|
||||
steps and the result. `resultDisplay.js` is the one adapter from a result to
|
||||
the card: builder results show as built, and analyst results show a title
|
||||
with their scope, window and caveats. Caveats are on the card; the model speaks
|
||||
one only when it changes the answer, and always says lower bounds and partial
|
||||
answers. `narration.js` speaks one
|
||||
code-authored line for the current step of a tool still running at 1.5 s
|
||||
(out of band, never after the result). Tools that report steps: layer
|
||||
toggles, place lookups, select_nearest_aircraft and annotate_map (finding,
|
||||
outlining). Other tools get one "still working" line at 8 s. The
|
||||
earcon plays in push-to-talk only. A claimed Space hold while the assistant
|
||||
speaks is a barge-in (WebRTC cancel + audio clear), refused while Radio holds
|
||||
the speaker (`mayVoiceClaimSpeaker()`). Progress lines stay outside the reply
|
||||
lifecycle and Radio handoff. `turn.span` debug records carry generation and
|
||||
playback latency, silence, preamble and word-count figures. Caption
|
||||
transcription (`OPENAI_REALTIME_TRANSCRIBE_MODEL`, default on) is metered into
|
||||
the session cost and cap. The debug log omits transcripts, text, tool arguments
|
||||
and complete tool-result bodies (including serialized function outputs) unless
|
||||
`GEV_VOICE_LOG_CONTENT=1`.
|
||||
Tool names, call IDs, protocol event metadata and usage remain available.
|
||||
Numbered analyst targets resolve from current layer records, including layers
|
||||
without pick/context lookup; numbered annotations retain their resolved coordinates.
|
||||
Requested analyst lists and rankings may speak up to three returned items and
|
||||
values in result order alongside the count and its caveats. A rejected current
|
||||
action emits a failure result to settle its card; cancelled turns remain silent.
|
||||
Coverage grading validates calls before accepting an expected capability match.
|
||||
The voice manifest includes Street Level visibility toggles; its imagery has no
|
||||
analyst query or entity-context records.
|
||||
|
||||
Point and ask: `pointerContext.js` reads what the cursor is on. A Space hold
|
||||
is the pointing gesture: its keydown snapshot (released with the key) is sent
|
||||
as an inert `pointer_context` item with the target, with reticle and chip.
|
||||
Open-mic speech and typed turns count only a pointer that moved on the map in
|
||||
the last 5 s and send only the kind (`pointing:"aircraft"`/`"ground"`); the chip appears when a tool
|
||||
resolves it. Losing the pointer sends one `target:"none"` item. `deixis.js` resolves `'pointer'` in
|
||||
track_entity/fly_to_location queries, get_entity_context scope, analyst_query
|
||||
`scope.kind` and annotate_map targets, plus `referent:n` from the latest
|
||||
numbered result (`referents.js`, cleared at session end). A new result set (an analyst count) replaces
|
||||
the numbered list even when it is empty. Only the five rows numbered on the
|
||||
card are resolvable; `-1` means the fifth/last visible row. `track_entity`
|
||||
accepts either a named query or a referent, while an empty target is rejected. A reticle marks the
|
||||
point during the turn and the voice card shows "THIS"/"HERE"; both hide in
|
||||
Clean-UI and recording. A ground-only pointer lookup at local/city scale sends a ringed 512 px crop in
|
||||
the one retained image slot, dropped if the camera moved or a newer capture or
|
||||
turn started. The pointer path makes at most two bounded fresh-frame requests so
|
||||
a slow render loop can recover without accepting a stale frame; a missing camera
|
||||
identity, expired snapshot, invalid geometry, black frame or oversized payload
|
||||
still fails closed. screenX/screenY against the crop are mapped back to the canvas. Harness: `qa-voice-routing.mjs --layer deixis`,
|
||||
`--layer deixis-live`, `--layer behavior --deixis-only`.
|
||||
|
||||
The application shell composes focused state owners for navigation, destination
|
||||
lookup/orbit, Cockpit, visual settings, panel layout, aircraft display and layer
|
||||
bindings. Keyboard/display subscriptions have a separate lifetime; existing
|
||||
@@ -419,9 +496,11 @@ Reference feed construction is exported through `sources/reference`; the cable s
|
||||
|
||||
Source factories have dedicated `layers/<family>/source` exports. ALPR and earthquake record normalization and CCTV source policy no longer pull rendering into source consumers. Catalog construction and voice feed reads use their focused owners; compatibility entries remain available. Settings filesystem hardening lives under `server/standalone/`. Import-direction checks complement export ownership checks; source behavior, settings policy and rendering are unchanged.
|
||||
|
||||
Voice controls bind to a protocol-independent session factory. The default WebRTC adapter preserves the existing Realtime connection, push-to-talk, cost controls and radio handoff. Session subscriptions expose state, transcript, action call/result, interruption and completion events; stopping or replacing a session cancels pending actions. Alternate adapters can use the same controls and action runner.
|
||||
Voice controls bind to a protocol-independent session factory. The default WebRTC adapter preserves the existing Realtime connection, push-to-talk, cost controls and radio handoff. Session subscriptions expose state, transcript, action call/progress/result, interruption, completion and turn-metrics events; stopping or replacing a session cancels pending actions. Alternate adapters can use the same controls and action runner.
|
||||
|
||||
Voice action argument schemas have one portable owner under `src/voice/actionSchemas.js`. The Realtime provider builds 29 tools, retaining the existing 28 names and argument contracts apart from the three additive analyst-layer enum values using separate description-only metadata. Description customization cannot replace argument types, enum values or required fields.
|
||||
Voice action argument schemas have one portable owner under `src/voice/actionSchemas.js`. The Realtime provider builds 30 tools using separate description-only metadata. Description customization cannot replace argument types, enum values or required fields.
|
||||
|
||||
`src/voice/layerManifest.js` declares each catalog layer's voice capabilities: spoken aliases, `toggle`, in-view `context`, `track`, and analyst `query` fields with type and unit, or `noQuery` with the reason. The `set_layer_visibility`, `show_data_layers_menu`, `get_entity_context` and `analyst_query` layer enums, the runner's alias table and the analyst field hints are generated from it. `src/voice/layerManifest.test.mjs` fails when a catalog layer is neither listed nor named in `VOICE_OFF_LAYERS` (today only the two scene-driven Bhote Koshi layers). Global Context is listed with `toggle: false`; `set_context_mode` reaches it. `set_panel_open` also opens `weather-panel` and `recent-imagery-panel`.
|
||||
|
||||
Portable source exports provide Radio Browser station normalization, CCTV feed types and regional records independently of HTTP middleware. Radio normalization accepts an explicit URL policy; the standalone directory retains its existing HTTPS rules. Tile coordinate validation accepts explicit zoom bounds with unchanged traffic defaults. Cache, request and rendering owners remain unchanged.
|
||||
|
||||
@@ -464,7 +543,18 @@ clears caches and removes map-stack listeners. Standalone setup supplies the
|
||||
existing service clients. HUD summaries, regional brief, cockpit weather, location
|
||||
framing and annotation boundaries receive their service instances explicitly.
|
||||
Compatibility entrypoints retain defaults for direct callers; normal startup does
|
||||
not change global service slots. Analyst follow-up memory belongs to its voice runner.
|
||||
not change global service slots. Analyst follow-up memory belongs to its voice
|
||||
runner and ends with the voice session: stopping voice invalidates writes still in
|
||||
flight and forgets the last answer, the pointer and the numbered list; removing
|
||||
voice disposes the runner.
|
||||
|
||||
Analyst result memory is committed only after any Contacts-window projection
|
||||
finishes and the call is still current. Cancelled or superseded queries cannot
|
||||
return success or replace follow-up memory; Contacts follow-ups filter the same
|
||||
cohort that was shown, and partial/unanswered coverage remains attached when a
|
||||
remembered result is narrowed.
|
||||
The narrowed answer retains the remembered scope label and detail, including
|
||||
the Contacts-window attribution, unless the follow-up supplies a new scope.
|
||||
|
||||
Application startup constructs fresh layer instances from explicit source objects.
|
||||
Standalone composition selects the existing providers. Controls, launch orbit
|
||||
@@ -1478,10 +1568,10 @@ This is the current runtime/source-of-truth snapshot for the project.
|
||||
> samples, `enabling` throughout, panel non-numeric) and across a failing
|
||||
> one. Its `status: 'idle'` is not what saves it — the lifecycle is; the
|
||||
> module has no `loading` status at all.
|
||||
> Any new dependency that can be slow must report `loading` and `lastUpdate`
|
||||
> honestly for the contract to hold, and must be pinned against the shape its
|
||||
> own module really returns — a fixture that invents a status the module cannot
|
||||
> emit guards nothing (that is exactly how a hole here survived a green suite).
|
||||
> Any new dependency that can be slow must report `loading` and `lastUpdate`
|
||||
> honestly for the contract to hold, and must be pinned against the shape its
|
||||
> own module really returns — a fixture that invents a status the module cannot
|
||||
> emit guards nothing (that is exactly how a hole here survived a green suite).
|
||||
> - **A held ground snap is dropped when measured ground contradicts it
|
||||
> (2026-08-23):** the WARM hold described below answers on DISTANCE travelled,
|
||||
> which is only a proxy for whether the value still describes the ground. A
|
||||
@@ -2876,7 +2966,7 @@ test:track` 43 tracking invariants · headless QA harnesses under
|
||||
> ISS pass prediction, and per-layer data attribution. Gate at close: unit 98/98, build clean,
|
||||
> track 19/19, + five QA harnesses (heading 16/16, sprites 9/9, cctv 5/5, failstate 5/5,
|
||||
> attribution 18/18). New modules: `src/data/{motionModel,aircraftMeta,aircraftClass,aircraftIcons,issPass,routePlausible,dataCredits}.js`.
|
||||
> The live runtime now declares 29 voice tools; the 17→20 count above is retained only as milestone history.
|
||||
> The live runtime now declares 30 voice tools; the 17→20 count above is retained only as milestone history.
|
||||
|
||||
## Canonical Docs Order
|
||||
|
||||
@@ -3951,7 +4041,7 @@ and unreachable upstream (502/504) separately from road geometry.
|
||||
|
||||
- **Token flow**: browser fetches a short-lived client secret from `/api/realtime/token`; the Vite middleware holds `OPENAI_API_KEY` and posts the full session config (instructions, tool schemas, VAD, truncation) to `api.openai.com/v1/realtime/client_secrets`. SDP exchange goes directly to `api.openai.com/v1/realtime/calls` with the ephemeral token.
|
||||
- **Session defaults** (env-tunable): model `gpt-realtime-2` (or `gpt-realtime-2.1-mini` when the MINI tier is selected — see the model-tier entry below), voice `marin`, reasoning effort `low`, semantic VAD with low eagerness, no response interruption, context window truncated to ~3,000 post-instruction tokens with 0.5 retention ratio — the conversational window stays short because map state is fetched live per turn.
|
||||
- **Twenty-nine tools** (argument schemas in `src/voice/actionSchemas.js`, served with their descriptions by `server/providers/openai/tools.js`, executed client-side in `src/voice/gevActions.js`): `fly_to_location`, `select_nearest_aircraft`, `adjust_camera_zoom`, `zoom_to_globe`, `set_layer_visibility`, `show_data_layers_menu`, `set_panel_open`, `set_visual_style`, `get_entity_context`, `get_current_view_state`, `set_hud`, `set_detection`, `set_map_stack`, `set_post_processing`, `control_scene`, `control_cctv`, `set_context_mode`, `control_cockpit`, `control_radio`, `track_entity`, `stop_tracking`, `frame_overhead`, `annotate_map`, `clear_annotations`, `move_camera`, `fly_route`, `analyst_query`, `next_iss_pass`, and `next_satellite_pass`.
|
||||
- **Thirty tools** (argument schemas in `src/voice/actionSchemas.js`, served with their descriptions by `server/providers/openai/tools.js`, executed client-side in `src/voice/gevActions.js`): `fly_to_location`, `select_nearest_aircraft`, `adjust_camera_zoom`, `zoom_to_globe`, `set_layer_visibility`, `show_data_layers_menu`, `set_panel_open`, `set_visual_style`, `get_entity_context`, `get_current_view_state`, `set_hud`, `set_cyber_sonar`, `set_detection`, `set_map_stack`, `set_post_processing`, `control_scene`, `control_cctv`, `set_context_mode`, `control_cockpit`, `control_radio`, `track_entity`, `stop_tracking`, `frame_overhead`, `annotate_map`, `clear_annotations`, `move_camera`, `fly_route`, `analyst_query`, `next_iss_pass`, and `next_satellite_pass`.
|
||||
|
||||
> **Reading `npm test` totals:** the count depends on the Node major. The two
|
||||
> GC-bracketed allocation microbenchmarks (`src/data/focusAllocations.test.mjs`
|
||||
@@ -3973,7 +4063,7 @@ and unreachable upstream (502/504) separately from road geometry.
|
||||
- **Analyst → track handoff carries a key, not just a label** (2026-08-21). `analyst_query` items include `icao24`/`mmsi` alongside the display `id`, and contact lookup uses the shared tiered ranking in `src/data/contactMatch.js`: hex exact → callsign exact → registration exact → callsign prefix → registration prefix → callsign substring → registration substring. The tiers keep an exact callsign ahead of a colliding registration regardless of feed order, and registrations compare separator-insensitively (`G-ABCD`/`GABCD`, `05-8152`/`058152`, `N123AB`/`N-123AB`).
|
||||
- **A typed command supersedes the turn it interrupts** (2026-08-21). `sendTextCommand` defers its `response.create` behind an active response instead of colliding with it, marks that response superseded so a late function call from it is refused rather than dispatched, and drops the old turn's queued follow-up. A refused call is still ANSWERED — a terminal `{ok:false, superseded:true}` `function_call_output` — because an unanswered `function_call` strands a pending call and deadlocks the model; the refusal creates no response of its own. A burst of typed commands coalesces into one response while keeping both conversation items.
|
||||
- **Subject reconciliation across satellite catalog rebuilds** (2026-08-21). A dense↔core toggle or TLE refresh clears and repopulates the catalog, so the published subject is re-resolved against the new satrec; a subject that did NOT survive releases the slot. The per-frame refresh cannot do this itself — `_getTrackedFramePosition` returns early once the satellite has no catalog entry — so the reconcile runs at rebuild completion. An empty catalog is a rebuild in flight, not a disappearance.
|
||||
- **One aircraft-proximity engine** (2026-08-22). `collectAircraftProximityWindow` (`src/data/militaryAwareness.js`) is the single computation behind both the Contacts panel window and the voice analyst's entity-centred "how many nearby", so the panel readout and the spoken count for one centre are identical by construction. **Invariant: do not re-derive a proximity count anywhere else.** They diverged before because the panel read live billboard positions (20,000 cap) while the analyst used last-fix coordinates over a 2,000-record slice — 111 on screen, 15 spoken. Explicit regions and arbitrary points deliberately keep the general record engine. Entity-centred results carry `window: {engine:'contacts-window', centeredOn, radiusKm, flights, military, aircraft}`.
|
||||
- **One aircraft-proximity snapshot** (2026-08-22; hardened 2026-09-30). `collectAircraftProximityWindow` (`src/data/militaryAwareness.js`) computes the Contacts panel cohort once. The voice analyst reads the exact retained snapshot and evaluation timestamp instead of re-scanning live layers, so the panel readout and spoken count for one centre cannot cross snapshots. **Invariant: do not re-derive a proximity count anywhere else.** Each layer retains 20,000 rows and samples one row beyond the cap; a saturated cohort reports `complete:false`, `truncated:true`, and is spoken as a lower bound. They diverged before because the panel read live billboard positions while the analyst used last-fix coordinates over a 2,000-record slice — 111 on screen, 15 spoken. Explicit regions, arbitrary points, and a radius different from the panel radius deliberately keep the general record engine. Entity-centred results carry `window: {engine:'contacts-window', centeredOn, radiusKm, flights, military, aircraft, complete, evaluatedAt}`.
|
||||
- **Centre precedence for nearby asks**: explicit place in the question > Contacts subject (a selected non-contact entity never silently becomes the centre) > an entity the user names > the current view, said aloud. Contacts active with no subject uses the view rather than reading an empty panel.
|
||||
- **Contact-match ties break on hex ascending.** `track_entity` is a mutation fulfilling "follow that one", and the model's observed answer to a non-ok track result is to retry with guesses rather than ask, so the lookup always commits rather than returning an ambiguity. What it owes the caller is stability: hex is unique and always present, so the same query resolves to the same contact for as long as both are loaded.
|
||||
- **Visual grounding**: at `local` view scale with no structured identity, the client captures the Cesium canvas (≤1200px JPEG, black-frame detection, double-render for freshness) and sends it as `input_image` with a strict "do not invent labels" instruction.
|
||||
@@ -3990,8 +4080,8 @@ and unreachable upstream (502/504) separately from road geometry.
|
||||
- **Reliability**: tool-call dedupe (2.5s window across call/item/args keys); response-create queueing that respects active responses and defers follow-ups when the user starts speaking; per-tool follow-up instructions so the agent confirms only what actually happened (zoom confirms only on `ok=true`).
|
||||
- **Aircraft identity honesty:** “What is this aircraft?” reads callsign, operator, registration, type, and route only from the selected contact context. Missing operator, route, or type enrichment is named explicitly rather than silently omitted or inferred from the callsign.
|
||||
- **Diagnostics**: every client/server event is posted to `/api/realtime/debug-log` and appended to `.gev-logs/realtime-conversations.jsonl` (gitignored) with secret/image redaction; last 30 errors persist in `localStorage` (`gev-realtime-errors`); `window.__gevVoiceCommands.getDiagnostics()` in the console.
|
||||
- **Counting semantics ("near")** — a CONTRACT; new count-bearing tool work inherits it. Three honest numbers exist for one question: the Contacts cohort (250 km around the subject, what the panel shows), `analyst_query`'s count of _currently-loaded_ records for the requested scope, and the layer-wide loaded total in `coverage.layersQueried[].records`. They diverge legitimately — the flights layer loads by viewport, so after a camera dive the loaded set can hold a fraction of the cohort (field case: panel 42, analyst 8). The contract:
|
||||
1. **Contacts ACTIVE** → "near / nearby / how many aircraft" means the **Contacts window** — the panel's numbers, spoken verbatim. Mechanism: `contactsWindow` (`{centeredOn, radiusKm, flights, military, vessels}`), carried by both `analyst_query` and `get_current_view_state`, derived by `contactsWindowFromSnapshot()` from the same snapshot the panel renders so the two cannot drift. A cohort whose feed cannot answer reports `'unknown'`, never a confident zero.
|
||||
- **Counting semantics ("near")** — a CONTRACT; new count-bearing tool work inherits it. Three honest numbers exist for one question: the Contacts cohort (250 km around the subject, what the panel shows), `analyst_query`'s count of _currently-loaded_ records for the requested scope, and the layer-wide loaded total in `coverage.layersQueried[].total`. They diverge legitimately — the flights layer loads by viewport, so after a camera dive the loaded set can hold a fraction of the cohort (field case: panel 42, analyst 8). The contract:
|
||||
1. **Contacts ACTIVE** → "near / nearby / how many aircraft" means the **Contacts window** — the panel's numbers, spoken verbatim. Mechanism: `contactsWindow` (`{centeredOn, radiusKm, flights, military, vessels, complete}`), carried by both `analyst_query` and `get_current_view_state`, derived by `contactsWindowFromSnapshot()` from the same snapshot the panel renders so the two cannot drift. Voice filtering and follow-up memory use that immutable snapshot too. A cohort whose feed cannot answer reports `'unknown'`, never a confident zero; a cohort at the 20,000-row retention bound reports a lower bound.
|
||||
2. **Contacts OFF** → "nearby" means **in view**; "near \<place\>" means a radius around that place. A radius query with Contacts active and no explicit centre is centred on the **active contact**, not the camera.
|
||||
3. **Every count names its scope in words** — "42 in your window", "8 in view", "about 30 within 250 km of Austin" — never a bare number. `analyst_query` returns `scopeLabel` so this is mechanical. Two different numbers with named scopes are not a contradiction.
|
||||
4. **The loaded-data caveat is stated once when relevant**: counts cover loaded data, and the flights layer loads where you look (appended to `coverage.note` for radius/view scopes over viewport-loaded layers).
|
||||
@@ -4064,6 +4154,15 @@ are omitted rather than framing the wrong part of the globe.
|
||||
retrying. Missing capability never synthesizes an outline from a radius.
|
||||
Manual geometry, bundled neighborhoods, Natural Earth regions and bundled
|
||||
state/province/county outlines remain.
|
||||
- The shared default place search resolves unqualified `Alps`, `the Alps`
|
||||
and the `Alps mountains` forms from the bundled European Natural Earth
|
||||
range before network geocoders. Navigation uses its contained anchor and
|
||||
region viewport; annotations still require the existing proximity and
|
||||
outline-containment checks. Coordinates and supplied presets keep priority;
|
||||
geographic qualifiers, local POI names, other ranges and custom geocoder
|
||||
arrays retain their existing resolution. A failed Alps pack load reports a
|
||||
search failure rather than caching an unrelated peak as the range, and the
|
||||
bundled loader retains its normal retry cooldown.
|
||||
- County queries rank eligible US counties and international admin-1 units together, retaining exact aliases and country/state qualifiers.
|
||||
- Bundled administrative outlines (`src/data/adminBoundaries.js`): states and
|
||||
provinces worldwide (Natural Earth admin-1,
|
||||
@@ -4926,7 +5025,6 @@ Temperature uses stronger fixed −40..50°C colors; the underlying 1° forecast
|
||||
numeric inspection values are unchanged. No volumetric cloud height or local rain
|
||||
arrival prediction is claimed. NOAA source limits are documented in DATA_SOURCES.
|
||||
|
||||
|
||||
Traffic source refinements: ALPR admits z9-z12 detail only when the view fits 16 tiles,
|
||||
returning explicit zoom guidance before I/O and allowing the next smaller view to
|
||||
load normally. Outside the US/Canada extracts the row reads “No ALPR data for this
|
||||
|
||||
Reference in new issue
Block a user