- i18n scanner: lastError sink, no false sinks on defaults and ternaries
- shared src/i18n/marker.js for modules that only mark strings
- wind field messages move to wind/fields.js; CITY_POIS imports from cityPois.js
- drop review IDs, change history and stale references from comments and docs
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Fixes the 51 P0–P2 findings from the full review of the i18n branch and
the issues found while checking every new string on screen in ru and es.
- Translate errors and statuses that still reached ru/es in English:
feed and tile errors, provider statuses, the ALPR chip, the traffic
mode chip, voice plan step labels, fire feed values, receiver bands,
scene save reasons and the Cesium attribution link.
- Show preset city names in the UI language (src/ui/placeNames.js);
data and everything sent to the model stay English.
- Share layer names between the layer panel, HUD and voice card
(src/ui/layerNames.js).
- Keep long ru/es strings whole: voice card error lines, analyst
titles, the voice tier status, the Nepal evidence button, the ALPR
retry chip. English layout is unchanged.
- Ask before a language switch drops unsaved work.
- Catalog fixes: glossary terms (пуск, пресет), gender agreement and
consistent "peticiones" in es, fewer calques in both languages.
- Fix English text that was itself wrong (e.g. "Exit cockpit to fly to
a weather", raw tool ids in voice plan steps).
Catalogs: es/ru 2535 messages each, complete.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Conflicts resolved by keeping both sides: the Events group gains
gnss-integrity with a translated label, the cockpit aircraft line shows
main's transponder emergency through a localized formatter (cockpitMath.js
stays i18n-free, like the Context scope line), and the boundary lists keep
both the i18n modules and main's new data modules.
Main's new UI is translated into es and ru: the GNSS Integrity row, legend
and notes; geo file import (button, hints, list actions, every import
error, with numbers passed as placeholders); transponder status names.
Also formats kartaview/viewer.js so format:check passes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
isoTime returned toISOString() for any finite number, which throws past ±8.64e15 ms, so one bad record (e.g. a bike-share last_reported) failed the whole tool answer. Such timestamps are now null. The voice analyst's result rows had the same conversion and get the same guard.
Co-authored-by: Sameh Khamis <[email protected]>
- The Space Missions cancellation failure toast read "[object Object]" in
every language: the options object was passed as the message. The English
message is the second argument again, the translation the third.
- Header text is translated before panel chrome builds its collapse labels,
so the dock and display toggles no longer read "Expand VISUAL PRESETS" in
another language.
- The voice "show data layers" result keeps the English layer name
(row data-layer-name), not the translated row text.
- The Google 3D unavailable reason is translated in full.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Mark every UI string the unmarked-text check reported (534) plus text it
cannot see (helpers, joined labels, runtime-built panels), and translate
the result to Spanish and Russian: 1,679 messages each.
- Kept on purpose, with the reason where the text lives: provider and
product names, place and camera names, codes and units, dB values, the HUD
terminal readouts, demo shot titles that saved projects look up by title,
and text for AI tools and the voice model.
- Modules shared with the server or AI tools stay free of the i18n import
(local msg); the wind reading and voice session stay English and are
translated where the page shows them.
- npm test now runs the unmarked-text check.
- Fixes on the way: a duplicated radio privacy paragraph, the contact panel
toggle saying Expand while open, the CSS filter mistaking & for CSS.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Keeps the voice-core prompt rules and adds main's world-query and
vessels-vs-visuals rules; the tool catalog wraps the deixis-aware runner.
Also fixes two things the branch had before the merge:
- Live voice could not start: OpenAI rejects track_entity's top-level
anyOf. Model-facing tools now omit top-level combinators; the runner
and benchmark still require a query or a referent.
- The Contacts-centred analyst answer dropped the viewport coverage note.
keep contacts counts, rows, scope and provenance on one retained snapshot
report capped cohorts as lower bounds
separate sibling tool cancellation from newer user turns
align track_entity validation across runtime and benchmark paths
- Voice layer manifest (src/voice/layerManifest.js) generates the layer enums,
aliases and analyst field hints; a test fails when a catalog layer has no entry.
- analyst_query validates fields, operators, units, values and scopes, counts up
to 250,000 loaded records per layer, reports complete/partial/unanswered, tells
LAYER_OFF / NOT_READY / FEED_UNAVAILABLE apart from zero, refuses mismatched
follow-ups and never lets a superseded query replace follow-up memory. Seven
more layers expose analyst records.
- Tool results carry a code-built say line and a display card; the voice card in
the mic control shows captions, plan steps and the result
(src/voice/resultDisplay.js is the one adapter). Slow tools narrate their
current step out of band; holding Space while the assistant talks cuts it off.
Turn spans go to the debug log; caption transcription is metered; the log
omits what was said unless GEV_VOICE_LOG_CONTENT=1.
- Point and ask: the Space-down pointer snapshot resolves "this", "that one" and
"around here" through 'pointer' targets, and "the second one" through
referent:n from the last numbered list.
- Prompt states each policy once (instructions + tools 48.5k -> 46.7k chars).
- Voice benchmark harness (scripts/qa-voice-bench.mjs, scripts/voice-bench/)
shares its phrase table and grading with scripts/qa-voice-routing.mjs.
The Natural Earth and neighborhood packs were loaded with a JSON-attributed
import(). The Vite dev server answers that request with a JavaScript module,
which the browser rejects, so every analyst region scope failed and fell
through to a geocode lookup that could take 12-28 s.
- src/data/bundledJson.js fetches the pack from a new URL(..., import.meta.url)
asset in the browser; under Node the caller's attributed import runs.
- resolveRegionRingForQuery caps the geocode + admin-boundary rung at 3 s and
returns { error: 'region-timeout' }; the lookup keeps running and fills the
cache. The analyst query reports it as code 'region-timeout'. The Nepal
locator opts out of the budget.
- Unit tests for the loader, the timeout and the analyst error; the behavior
harness checks the Gulf of Mexico scope and retries Texas on region-timeout.
Co-authored-by: Bilawal Sidhu <[email protected]>
Adds MODIS NRT to Active Fires and a keyless Fire Perimeters layer (NIFC WFIGS) with
InciWeb incident links, served through a capped, cached /api/fire-perimeters proxy.
Co-authored-by: Gustavo Beneduzi <[email protected]>
Co-authored-by: James Cooke <[email protected]>
Adds a Local ADS-B layer fed by your own receivers: a browser WebUSB
RTL-SDR (with FM listening) and local 1090/978 MHz decoder feeds
(LOCAL_RECEIVER_FEEDS, local and private addresses only). Local aircraft
draw in magenta with class, silhouettes, 3D models, trails and a position
sanity filter; the click card names the band and input that heard them.
Builds on Sameh Khamis's SDR prototype and the initial GEV port by
Mazeyar Moeini Feizabadi (#134); the decoder-feed design follows the
notes on #57. Closes#57.
Co-authored-by: Sameh Khamis <[email protected]>
Co-authored-by: Mazeyar Moeini Feizabadi <[email protected]>
Wind (NOAA GFS and ECMWF IFS: animated particles, colour field, a reading at map centre), observed weather (NOAA MRMS radar, GOES and NESDIS infrared clouds, lightning density) on one shared history timeline, NHC and CPHC cyclone advisories with tracks and cones, and a WEATHER panel in the right rail. On 3D Tiles the observed products render as raised shells with a sharper window around the view.
Co-authored-by: Gustavo Beneduzi <[email protected]>
Co-authored-by: Daniel Slay <[email protected]>
Co-authored-by: Rehaan Delmotra <[email protected]>
Co-authored-by: Cursor Agent <[email protected]>
The keyless fallback landed on the LOCATION search box only. Two other places
forward-geocode a name and neither had it: the annotation resolver returned
null, so an annotation silently failed to anchor, and the Radio layer THREW,
which surfaced as a failed voice turn rather than as a station it could not
place. src/keylessGeocoder.test.mjs now COUNTS the call sites instead of
checking them file by file, so a second seam added to a file that already has
a fallback fails the suite too.
The annotation path carries the feature's own name out of Photon. Footprint
scoring matches OSM on that canonical name rather than on the user's words, so
incidental locality tokens cannot win: "the monument near the Texas Capitol,
Austin" scored on the raw utterance picks a downtown building that shares only
"Texas", "Capitol" and "Austin".
Photon's country is deliberately NOT re-exported. It comes back in the
feature's own language — "Việt Nam", "日本", "Россия" — and
normalizeRadioCountryInput fails CLOSED on a name it cannot map, so forwarding
it would filter the station list to nothing for exactly the places the lookup
had just resolved. The composed label still names the country. A keyless
lookup must not apply a filter the keyed one never applies.
A not-found is now remembered only when every source consulted returned a
verdict. Photon not replying is a network blip, not "no such place": memoizing
it kept the query answering not-found for the rest of the session on a network
that had since recovered — the same conflation the Overpass disk cache had to
be repaired for. geocodeMissIsDefinitive states the rule once and both entry
points use it, and the adapter's own memo follows it as well.
Reverse geocoding stays out of scope: the street-label reader consumes
Google's ranked address_components, and Photon's /reverse cannot reproduce
that shape.
The first formal release.
- One-click install via Pinokio; keyless boot lands on a live Esri World
Imagery satellite globe with keyless terrain, with automatic OSM fallback
and graceful degradation when terrain is unavailable.
- Provider Settings (the POWER UP panel): add, replace, or remove API keys
inside the app; credential files made owner-only before any secret is
written; external keys shown read-only; the panel refuses shared or proxied
servers.
- Keyless capability responses for the optional HUD summary and place search.
- Aircraft-identity voice answers cover operator, type, and route, and say so
plainly when enrichment is unavailable.
- README rewritten keyless-first; concise 0.1.0 changelog section; CI
workflow included.
Gates: 2,672 unit tests pass / 0 fail, build clean, tracking regression
108/108, map-source tray QA pass, setup doctor ready.