fix(radio): resolve common country exonyms Intl.DisplayNames omits

The radio country parser builds its name->code table from the
Intl.DisplayNames primary English label, so common names and exonyms that
are not that exact label fell through to fail-closed. Requests like "play
radio in Turkey" (ICU renders TR as "Turkiye"), plus Myanmar/Burma, UAE,
Holland, Swaziland, East Timor, Cabo Verde and Vatican, returned no
stations -- and dataset stations whose country field uses those names were
dropped from country filtering.

Add each as an unambiguous alias to the existing bounded map. Ambiguous
names (bare "Congo", "Korea") are deliberately left to fail closed. Adds
unit coverage for the new resolutions and the preserved fail-closed
behavior.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Malek 2026-09-09 16:35:06 +01:00
parent 759652207f
commit 0f18bafe9e
4 changed files with 57 additions and 3 deletions

View File

@ -7,6 +7,11 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
### Fixed
- Radio country filtering and voice country requests now resolve common English
names and exonyms that `Intl.DisplayNames`' primary label omits, so requests
like "play radio in Turkey" no longer fail closed (Turkey → Türkiye, plus
Myanmar/Burma, UAE, Holland, Swaziland, East Timor, Cabo Verde, Vatican).
Ambiguous names such as a bare "Congo" or "Korea" still fail closed.
- Mapped-site outages show their scheduled retry countdown and distinguish
known Overpass rate limits, timeouts, and query failures. Search feedback no
longer claims a refresh succeeded while the layer is unavailable or loading.

View File

@ -1684,9 +1684,11 @@ preserves object identity for an idempotent repeat of the same generation, and
degrades without replacement if a fresh response presents an older generation.
Snapshot records mark community metadata as untrusted, and Radio tool results
omit station names so directory text never becomes model instruction context.
One bounded country parser maps recognized ISO codes and English/common names
through proxy metadata and final station selection, while malformed, non-ISO,
control-containing, and oversized inputs fail closed. Literal or resolved
One bounded country parser maps recognized ISO codes and English/common names —
including widely used exonyms the Intl display label omits (Turkey, Holland,
Burma, and similar) — through proxy metadata and final station selection, while
malformed, non-ISO, control-containing, ambiguous, and oversized inputs fail
closed. Literal or resolved
non-global IPv4/IPv6 targets are refused. Destroy fully releases the Radio audio
session, voice ducking/restoration, request state, filter, selection, volume,
accepted snapshot, and feed telemetry before re-initialization; monotonic

View File

@ -55,6 +55,22 @@ for (const [name, code] of Object.entries({
brunei: 'BN',
'cape verde': 'CV',
'the netherlands': 'NL',
// Common English names and exonyms whose code is not reachable through the
// Intl.DisplayNames primary label, so they would otherwise fail closed
// (verified against ICU 77): TR resolves only as 'Türkiye', MM only as
// 'Myanmar (Burma)', AE only as 'United Arab Emirates', SZ as 'Eswatini',
// TL as 'Timor-Leste'. Each maps to exactly one country; ambiguous names
// (e.g. bare "Congo") are deliberately left to fail closed.
turkey: 'TR',
turkiye: 'TR',
myanmar: 'MM',
burma: 'MM',
uae: 'AE',
holland: 'NL',
swaziland: 'SZ',
'east timor': 'TL',
'cabo verde': 'CV',
vatican: 'VA',
})) COUNTRY_NAME_TO_CODE.set(countryKey(name), code);
function canonicalCountryName(code) {

View File

@ -18,6 +18,37 @@ test('Radio country normalization maps ISO codes and bounded common names', () =
}
});
test('Radio country normalization resolves common English names/exonyms ICU misses', () => {
// Each of these fails closed against the Intl.DisplayNames primary label
// alone (e.g. TR is "Türkiye", MM is "Myanmar (Burma)", AE is "United Arab
// Emirates"), so a request like "play radio in Turkey" would return nothing.
for (const [input, code] of [
['Turkey', 'TR'],
['Turkiye', 'TR'],
['Myanmar', 'MM'],
['Burma', 'MM'],
['UAE', 'AE'],
['U.A.E.', 'AE'],
['Holland', 'NL'],
['Swaziland', 'SZ'],
['East Timor', 'TL'],
['Cabo Verde', 'CV'],
['Vatican', 'VA'],
]) {
const result = normalizeRadioCountryInput(input);
assert.equal(result.valid, true, input);
assert.equal(result.code, code, input);
}
});
test('Ambiguous country names still fail closed (no broadened selection)', () => {
// Two states share the name "Congo" (CD/CG), so a bare mention must not
// resolve to either — it stays low-confidence and fails closed.
for (const input of ['Congo', 'Korea']) {
assert.equal(normalizeRadioCountryInput(input).valid, false, input);
}
});
test('Radio country normalization rejects malformed, non-ISO, and oversized values', () => {
for (const input of [
'ZZ',