From ea1b0d8d5506722e5672d685b5b0fe251e6ce3d0 Mon Sep 17 00:00:00 2001 From: Aditya <205600203+Rohilalala@users.noreply.github.com> Date: Tue, 27 Oct 2026 15:54:36 +0530 Subject: [PATCH 1/3] fix(voice): leave out an unreported altitude instead of saying 0 feet select_nearest_aircraft passes altitudeM: null for an airborne contact without a barometric altitude (military rows from adsb.lol can lack alt_baro). The speech builder coerced it with Number(), and Number(null) is 0, so the reply said "..., 0 feet." and the voice card showed "Altitude 0 feet". Read the altitude only when it is a finite number, so an unknown one is left out as the builder already intends. --- docs/CURRENT-STATE.md | 2 ++ src/voice/speech.js | 6 +++--- src/voice/speech.test.mjs | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 0cb46940c..2a77faaf0 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -5115,6 +5115,8 @@ and unreachable upstream (502/504) separately from road geometry. cannot race the nearest-aircraft query ahead of layer enablement. A healthy fallback feed is queried normally and its source is returned with the selection; fallback with no airborne records remains an honest no-data result, not an enable failure. + The spoken reply and the card leave out an altitude the feed did not report + rather than reading it as 0 feet. - Voice treats the parent Context panel and Contacts as separate intents. An explicit request to open Context expands only `global-context-panel`; it does not choose a mode. An explicit request to open Contacts expands that parent diff --git a/src/voice/speech.js b/src/voice/speech.js index c53881595..d698d863e 100644 --- a/src/voice/speech.js +++ b/src/voice/speech.js @@ -74,9 +74,9 @@ function listPhrase(items) { } function feetRounded(meters) { - const value = Number(meters); - return Number.isFinite(value) - ? Math.round((value * 3.28084) / 100) * 100 + // A missing altitude is unknown, not sea level: Number(null) is 0. + return Number.isFinite(meters) + ? Math.round((meters * 3.28084) / 100) * 100 : null; } diff --git a/src/voice/speech.test.mjs b/src/voice/speech.test.mjs index 36482290d..b280b2ebc 100644 --- a/src/voice/speech.test.mjs +++ b/src/voice/speech.test.mjs @@ -217,6 +217,20 @@ test('nearest-aircraft results name the aircraft, distance and altitude briefly' assert.equal(stale.say, 'Selected AAL1, 3.3 km from Austin, stale.'); }); +test('nearest-aircraft results leave out an altitude the feed did not report', () => { + // gevActions sends `altitudeM: null` for an airborne military contact + // without a barometric altitude; that is unknown, not sea level. + const unknown = envelope('select_nearest_aircraft', { + ok: true, + location: 'Ramstein', + layerId: 'military', + feed: { state: 'nominal' }, + aircraft: { callsign: 'RCH123', altitudeM: null, distanceKm: 8.2 }, + }); + assert.equal(unknown.say, 'Selected RCH123, 8.2 km from Ramstein.'); + assert.deepEqual(unknown.display.lines, ['8.2\u00a0km from Ramstein']); +}); + test('frame_overhead keeps the essential scope audible and lists referents', () => { const framed = envelope('frame_overhead', { ok: true, From 5d9264e65f4c4c8d2e527a0e2ad9e1ab1ab4739a Mon Sep 17 00:00:00 2001 From: Aditya <205600203+Rohilalala@users.noreply.github.com> Date: Tue, 27 Oct 2026 21:57:27 +0530 Subject: [PATCH 2/3] docs(changelog): add #1434 fragment --- changelog.d/1434-voice-unknown-altitude.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog.d/1434-voice-unknown-altitude.md diff --git a/changelog.d/1434-voice-unknown-altitude.md b/changelog.d/1434-voice-unknown-altitude.md new file mode 100644 index 000000000..229d31800 --- /dev/null +++ b/changelog.d/1434-voice-unknown-altitude.md @@ -0,0 +1,3 @@ +- Selecting the nearest aircraft by voice no longer says "0 feet" for a contact + whose feed reported no altitude; the reply and card leave the altitude out + (Aditya, @Rohilalala, #1434). From 3321affaa6351a5771018b21c966b5c22e3ed810 Mon Sep 17 00:00:00 2001 From: Aditya <205600203+Rohilalala@users.noreply.github.com> Date: Wed, 28 Oct 2026 15:02:55 +0530 Subject: [PATCH 3/3] test(voice): check a sea-level altitude is still spoken --- src/voice/speech.test.mjs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/voice/speech.test.mjs b/src/voice/speech.test.mjs index b280b2ebc..345823064 100644 --- a/src/voice/speech.test.mjs +++ b/src/voice/speech.test.mjs @@ -229,6 +229,20 @@ test('nearest-aircraft results leave out an altitude the feed did not report', ( }); assert.equal(unknown.say, 'Selected RCH123, 8.2 km from Ramstein.'); assert.deepEqual(unknown.display.lines, ['8.2\u00a0km from Ramstein']); + + // A reported sea-level altitude is still spoken. + const seaLevel = envelope('select_nearest_aircraft', { + ok: true, + location: 'Ramstein', + layerId: 'military', + feed: { state: 'nominal' }, + aircraft: { callsign: 'RCH123', altitudeM: 0, distanceKm: 8.2 }, + }); + assert.equal(seaLevel.say, 'Selected RCH123, 8.2 km from Ramstein, 0 feet.'); + assert.deepEqual(seaLevel.display.lines, [ + '8.2\u00a0km from Ramstein', + 'Altitude 0 feet', + ]); }); test('frame_overhead keeps the essential scope audible and lists referents', () => {