Commit Graph
939 Commits
Author SHA1 Message Date
Sameh Khamis 0d32f59b40 Merge branch 'main' into manjunath/hal-769-range-ring-visibility
# Conflicts:
#	scripts/format-scope.json
2026-11-03 10:33:19 -08:00
Sameh Khamis 553f0c06ee Merge branch 'main' into feat/voice-geometry 2026-11-03 09:49:42 -08:00
Manjunath acd87e6cf1 Merge branch 'main' into feat/voice-geometry
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.
2026-11-03 22:55:34 +05:30
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
Sameh Khamis d5a568e55f Merge branch 'main' into fix/zoom-out-runaway 2026-11-03 09:04:51 -08: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 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
Said Turksever a0924c00d7 fix: resolve review findings and refresh PR #1518 against main 2026-11-03 16:17:30 +00:00
Said Turksever 34906c9abb Merge branch 'main' into codex/overpass-admission-review-fixes 2026-11-03 15:07:08 +00:00
Said Turksever 8e40d2689b Merge branch 'main' into prereq-10-osm-overlays 2026-11-03 14:34:32 +00:00
Said Turksever a236504347 fix: respect camera ownership and finish outward zoom framing 2026-11-03 14:32:30 +00:00
Manjunath 34647758fc test(osm): cover the place-search client and the follow-up handoff
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.
2026-11-03 19:36:40 +05:30
Said Turksever e6a6ba0126 fix: keep the globe on screen when zooming out from a tilted view
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.
2026-11-03 13:50:16 +00:00
Manjunath d18fdfa47f Merge branch 'main' into feat/voice-geometry
Picks up the HUD summary locale work (#1488). No conflicts; it changes no
voice prompt or tool description.
2026-11-03 17:31:36 +05:30
Manjunath 05edae0606 Merge branch 'main' into feat/voice-geometry
Picks up the Radio Next/Previous fix (#1474) and the Codespaces docs
(#1515). The one conflict is the Radio cycle assertion in
gevActions.test.mjs: main's new fallback flag is kept in this branch's
layout.
2026-11-03 16:40:39 +05:30
Manjunath 2a629f0987 fix(awareness): make the 250 km range ring readable on any ground
The Global Context range ring was a Cesium ellipse outline at 1 px in
rgba(98,181,255,0.72). WebGL ignores larger ellipse outline widths, so it
could not be thickened, and it vanished over desert and snow and under the
FLIR, NVG and CRT styles.

Draw it as a polyline instead: a 4 px line with a 2 px Context-blue core
inside a 1 px dark halo on each side (PolylineOutlineMaterialProperty).
The halo gives luminance contrast on light and dark ground, which the
monochrome styles keep. The ring sits at the same 2.5 km height and
follows the subject on the same 250 m threshold. Positions come from a
new awarenessRangeRingPositions helper that stays within 50 m of 250 km.

Style values live in AWARENESS_RANGE_RING_STYLE (awareness/policy.js).
Adds rangeRing.test.mjs (geometry at equator, Sahara, Greenland and the
antimeridian; contrast; entity shape; follow threshold) and a
CURRENT-STATE note.
2026-11-03 16:30:20 +05:30
German Khokhlov d413362467 Merge branch 'main' into german/hal-623-hud-summary-locale 2026-11-03 14:55:40 +04:00
German Khokhlov 238a3d0634 Merge remote-tracking branch 'origin/main' into fix/hal-722-radio-next-no-autoplay 2026-11-03 14:33:12 +04:00
German Khokhlov 33381c5981 Merge remote-tracking branch 'origin/main' into german/hal-623-hud-summary-locale
# Conflicts:
#	src/voice/gevActions.test.mjs
2026-11-03 14:28:10 +04:00
Manjunath 2a13a06def fix(voice): bound OpenStreetMap text before it reaches voice results
- strip control and format characters from OSM tag values, keeping the
  zero-width (non-)joiners Persian and Indic names spell with, and cut
  them at 120 code points so a name cannot steer or flood the model
- adopt the nine new geometry test files in format-scope.json; five of
  them change by formatting only
2026-11-03 14:33:51 +05:30
Manjunath ecaddd838b Merge feat/voice-geometry onto main
Both stack parents (#837, #842) are on main, so the voice geometry branch
now builds on main directly. Conflict resolutions keep main's behaviour and
add the geometry work on top: osm_query gating on every provider, restored
admin identity for Nominatim outlines, merged analyst follow-up memory, and
the cancelled Globe View reset instruction ahead of the generic cancellation.
2026-11-03 14:33:34 +05:30
Sameh Khamis b9f3dd649e merge feat/voice-outlines 3ac3499e into the review fixes 2026-11-02 13:14:02 -08:00
manjunath 3ac3499e4a merge main 43a67f9 into feat/voice-outlines 2026-11-03 00:26:40 +05:30
Said Turksever bd7ef69843 Merge branch 'main' into prereq-10-osm-overlays 2026-11-02 17:48:19 +00:00
Said Turksever c35eba1704 Merge main into prereq-10-osm-overlays 2026-11-02 17:27:07 +00:00
Sameh Khamis c059e12a11 merge main 17daf897 into feat/voice-outlines 2026-11-02 09:06:21 -08:00
Said Turksever f38961ef1e Merge main into the Utilities panel 2026-11-02 17:01:52 +00:00
Said Turksever 672a145254 Keep Contact folded until both Cockpit left panels close, and keep focus in a renamed row
Opening Utilities while Data Layers is open no longer forgets that Contact
was folded for the first, and closing one of them leaves Contact folded
while the other is still open. Enter and Esc in a drawn shape's name keep
focus in the field instead of dropping it to the page. The draw tool's
destroy test now checks it stops following the board, and the Draw gate's
amber-count comment sits on its function again.
2026-11-02 17:01:31 +00:00
Sameh Khamis a61d0f4c2a tighten the remaining voice outline review items
- One place-name key for server and tiles, so "St. Paul" and "Saint Paul"
  agree in Nominatim name checks.
- Tile street names: a lone letter is a direction only beside another name
  word ("E Street" is not "East Street"), and a trailing quadrant ("E St NW")
  may go unsaid in the ask.
- A building cut at the tile edge that is nearer the point than any whole
  one leaves the point instead of a farther neighbour standing in; an edge
  without a tile buffer counts as a cut, so a cut area never answers grounds.
- A batch building install re-judges only results that installed; a late
  timeout during caption conversion keeps the pending point drawn; a failed
  plain recaption keeps the old mark addressable.
- An interrupted Nominatim dispatch is reclaimed by the next lock owner ten
  minutes after the start its marker names; node:sqlite loads on first use
  without its experimental warning.
- PHOTON_URL accepts only https, which the page's connect-src allows.
- Shared OpenFreeMap tiles decode each layer when a consumer first selects
  it; outline selection reuses the shared ring area and simplification, and
  ground probes the shared ring centroid; the grounds word list lives once.
2026-11-02 08:50:05 -08:00
Said Turksever 345d5db593 Point the Draw and layer panel gates at Utilities and at what is drawn
qa-draw-tool drives the rows, waits on a mark's state instead of fixed
sleeps, checks that fly-to centres the line, and compares two screenshots to
show a hidden Line's pixels go and come back. Its clicks and pixel clip stay
clear of the Utilities panel beside the left rail. qa-layer-panel checks
that Directions returns to the Utilities list after a reassembly.
2026-11-02 16:43:49 +00:00
Said Turksever 4ebb287d36 Merge main into the Utilities panel, rebuilt on the Vue panel rail
main moved the panels to Vue views and a one-open-panel rail, and removed
the two templates this branch edited. This merge carries the branch onto
that architecture; it adds no behaviour of its own beyond the port.

- The Utilities panel is a RailPanel in LayerPanelsView with its own rail
  item (handyman). LayerPanel renders the Directions rows into its list with
  LayerRows, and falls back to Data Layers without it.
- Draw leaves DisplayPanel for DrawControls, DrawMarkList and DrawSwatches,
  which render what the draw tool publishes to the display store and call
  its actions, as GeoImport does. drawMarks.js words the rows; the DOM-built
  drawMarkList.js is gone. A row's fly-to is an immediate navigation like
  Import's ('drawing' gets its Cockpit refusal), the name field keeps a
  draft through v-field-value, and the colours are one radio group with a
  single tab stop.
- UiSegmented draws an option's icon, named by its label, for the shape
  buttons.
- The catalogs take main's languages with this branch's strings, Arabic
  included, and the tests follow the views to their new homes.
2026-11-02 16:43:29 +00:00
Sameh Khamis d411802d8c Merge branch 'main' into fix/node-24.22.1-security-release 2026-11-02 08:05:41 -08:00
Said Turksever ce1ad3b95a Merge main into prereq-10-osm-overlays and port Open Map Overlays
Main moved on since this PR opened; the overlay layer is ported to the
current contracts:

- Layer-state token 6 (j belongs to transit; new single-character
  tokens are digits) with a reservation-ledger row, and the option owner
  renamed to the layer id so the compact share codec can encode it.
- Constructed per catalog by createOsmOverlaysLayer() in
  constructCatalog.js; src/standalone/data.js no longer registers layers.
- Drapes through maps/imageryHost.js, so the overlays show on Google 3D
  (tileset imagery) as well as the globe stacks, and follow map-stack
  switches. Imagery layers are created on enable and destroyed on
  disable/destroy.
- Translated chip labels and layer name in every locale, LAYER_NAME_KEYS,
  Infrastructure panel group, voice manifest entry.
- Attribution: OpenSeaMap tiles CC BY-SA 2.0, OpenSnowMap credit as
  required, OSM ODbL credit for both; bulk-download note in DATA_SOURCES.
- CURRENT-STATE row, changelog fragment, share-codec absent defaults,
  updated token-ledger fixtures and voice schema pins.
2026-11-02 15:55:40 +00:00
Sameh Khamis 16756bb790 Align the doctor, state doc and bug template with the 24.22.1 pin, and credit the author 2026-11-02 07:06:14 -08:00
Sameh Khamis 31013d2201 Merge branch 'main' into security/cross-site-gate-overpass-military 2026-11-02 07:04:15 -08:00
German Khokhlov cfc83a6078 Release the tuner noise graph after a silent dial release
A release that only selects a station now stops the looping noise source and suspends its AudioContext. The qa-radio dial scenarios start from an active stream, or expect a silent release from a stopped Radio.
2026-11-02 17:19:53 +04:00
German Khokhlov 818d2c8295 fix(hud): keep localized summary words whole and drop padding
- The proxy keeps combining marks, in-word apostrophes and name dots
  (ar vowel signs, fr d'Orléans, ja ・), normalizes to NFC, caps every
  summary in characters and cuts at a word boundary.
- feedState is nullable instead of a `none` token, and the summary has at
  most five words: "exactly five" made the model pad short views with
  "no data" or "unavailable".
- The HUD caches only the model's words and adds the current warning on
  every paint; an RTL locale gets a leading right-to-left mark.
- The echo check also rejects an all-Latin reply in a non-Latin language,
  translated layer ids and, with every feed healthy, the UNAVAILABLE word;
  places are matched by word and one-word layer names are skipped in
  Latin-script locales.
- The warning tag names the worst layers first; a partial analyst card
  shows one partial chip.
2026-11-02 13:44:53 +04:00
German Khokhlov 857b007fb1 Keep the Radio tuning dial silent unless a stream is playing
Releasing the tuning dial always started the chosen station, plus tuning
static, even when nothing was playing. It now follows the Previous/Next
rule: the release plays only if a stream was loading, buffering or playing
when the drag began; otherwise it just selects the station.

The privacy note no longer lists finishing tuning as a way to connect and
now names voice instead, in all locales. Docs, changelog and comments are
tightened to match.
2026-11-02 13:27:55 +04:00
German Khokhlov a2be947aba Merge origin/main into fix/hal-722-radio-next-no-autoplay
main moved the Radio markup into Vue views and rebuilt the UI tests on
stores. Resolved:
- src/ui/templates/context.html: deleted in main; the new privacy note now
  lives in src/ui/views/panels/RadioPanel.vue.
- src/ui/radioControls.test.mjs: main's store fixture; the Next/Previous
  autoplay test drives store.act('cycleRadio').
- src/voice/gevRealtime.test.mjs: main's createTestVoiceUi; the stop and
  select handoff cases stay one table-driven test.
- src/data/radioNextState.test.mjs reads the published gev-radio view.
- src/i18n/locales/ar.json: the new note translated for the Arabic locale.
2026-11-02 12:36:31 +04:00
Sameh Khamis d479c1c6f6 Read an ADS-B vertical rate from one shared field reader 2026-11-02 00:09:18 -08:00
German Khokhlov 0d3c1ef1d9 fix(hud): ask again in the new language after an in-place switch
- _relocalize() now drops the received reply and aborts one in flight, so
  the next tick asks in the new language instead of keeping old-language
  text under the new-language state tag.
- The English-echo check also allows state words inside a place label
  (Estación Loading Dock).
- Reword the non-English instruction so it reads for every language name.
- Add the two new test files to the format scope.
2026-11-02 12:00:44 +04:00
German Khokhlov 1a6687632d Merge remote-tracking branch 'origin/main' into german/hal-623-hud-summary-locale
# Conflicts:
#	src/hud.js
#	src/hudAltitudeDatum.test.mjs
2026-11-02 11:59:08 +04:00
Sameh Khamis d14205160a Format every metre/kilometre distance through one shared helper
Directions, the Contacts marker and panel, placed annotation labels, the
drawn-line measure, the Cockpit and formatRouteDistance each chose the unit
and precision on their own, and most chose before rounding: #1450, #1433 and
formatDistanceText or kilometreDigits from src/data/distanceFormat.js, which
cut after rounding. Each keeps its own metre step and rendering.

That also fixes the 10 km cut the Contacts marker and panel, the drawn-line
measure and the Cockpit still had (9,960 m read 10.0 km). The helper returns
kilometres already rounded, so the plain marker and the localized panel no
longer disagree on half-tenths such as 1,450 m.

A negative annotation distance now leaves the label without a distance, and
a drawn line with a coordinate that is not a number shows no measure, rather
than printing 0 m or NaN km. The HUD altitude tag and the spoken view height
keep their own unit choice.
2026-11-01 22:40:28 -08:00
manjunath d9a460658d merge main 0c28dc7 into feat/voice-outlines 2026-11-02 11:39:21 +05:30
Sameh Khamis 639a7fb23a Merge branch 'main' into fix/e-context-heading-north 2026-11-01 21:58:41 -08:00
Sameh Khamis 7d236a1174 build: cache compiled components and load them on the test thread
Since the UI moved to single-file components, every unit-test process
compiled the views it imports from scratch, and the loader ran off-thread
(module.register), adding a round trip to every module a test imports,
including the ones that are not components. Core's unit tests took about
twice as long, and a host running Core's suite on smaller runners passed
its CI time limit.

register-vue now installs synchronous hooks on the loading thread
(module.registerHooks). Compiled components are kept in the system temp
directory, keyed by the file's path and text, the Vue version and the
loader's own code, so each one compiles once across test processes; the
compiler itself loads only on a cache miss. Cached modules run as code, so
the directory is used only when it is a real directory owned by the current
user and writable by no one else; on Windows it lives in the user's local
app data instead of a temp directory that may be shared. The cache never
sits inside the package tree, and GEV_VUE_CACHE=0 compiles every time.

On four cores the full suite went from 441 s to 240 s from a cold cache.
2026-11-01 21:50:25 -08:00
Sameh Khamis 0e90a03de7 Round every heading readout through one shared helper
The transit, ALPR, vessel, CCTV and flight/military context fixes each
wrapped 359.5° to north with an inline Math.round(x) % 360. They now call
roundHeadingDegrees in src/data/headingDegrees.js, which also wraps negative
and multi-turn bearings. normalizeHeading moves there with it, and
cockpitMath re-exports it so existing imports keep working. It now adds a
turn only to a negative remainder, so a bearing just under half a degree
keeps its precision.

The awareness, Local ADS-B, cockpit wind, cockpit heading and Street Level
readouts use the same helper. The Cockpit's TRACK ACQUIRED signal rounded
without wrapping and could read COURSE 360°; it now uses
formatHeadingReadout, which shows --- for a track that is not finite.
2026-11-01 21:41:49 -08:00
manjunath c5aa0d28c3 merge main 07094d9 into feat/voice-outlines 2026-11-02 11:05:08 +05:30
Sameh Khamis 1f9a453bc4 i18n(ar): own the Arabic catalog in the application package; mirror select chevrons
The application package boundary owns src/i18n/locales/ar.json beside the
other catalogs, and the style.css shim test checks that the shim holds only
import statements rather than counting its lines, so adding rtl.css to it
does not read as rules.

Selects pad the chevron's side with padding-inline-end, as do the Radio
filter, the SDR gain select and the voice timeout select, which set their
own padding; rtl.css moves the chevron to the left, where an Arabic field's
text ends. A rail legend's range keeps left-to-right order under its colour
ramp, which always runs low to high from left to right.
2026-11-01 20:22:51 -08:00
Sameh Khamis bc5d038afd Merge Core main into german/hal-644-ar: Arabic on the Vue UI
Main moved the UI to Vue views and Pinia stores, so the Arabic changes to
the old DOM controllers now live in their views: the rail legend range
comes from formatScaleRange (keeping units a source supplies as given),
the voice timeout options are worded by Intl unit formatting in
VoiceControl, and the scene editor's JSON fields stay left to right in
SceneDialog. Main's CCTV status line, launch panel and calibration values
keep the Arabic isolates and Western-digit formatting.

isolate() and keepCodesWithValues() read the locale through getLocale(),
which follows the page's vue-i18n instance, and the Intl formatters take
intlLocale(getLocale()). A language switch now applies in place, and
applyDocumentLanguage sets <html dir> on every switch, so the page mirrors
without a reload.

The icon rails and their tips are placed with logical properties, so they
stay on the outer side of the mirrored stacks; Cyber's new stack offsets,
padding and edge lines are logical too, and rtl.css moves Cyber's right
stack to its new rail clearance. Main removed the Context mini radio, so its
right-to-left rules and test go.

The Arabic catalog gains main's new strings and drops the ones main no
longer uses; the other catalogs keep main's new keys and the branch's
landing labels.
2026-11-01 20:15:02 -08:00