doxa-maps/plugin-designs/research-map-plus-grid/scripts
Doxa Maps b6abe30698 Link language on the ISO code, not the display name, because the name moves with the locale
Localizing the grid's data (ae5e27c3) would have broken the language link
silently, and the shepherd asked me to prove the coupling with a test. Measuring
it first showed the coupling should not exist.

MEASURED against the live API, en vs ar, 2,107 records:

    primary_language  LABEL  864 names in en, 864 in ar, ZERO shared → localized
    primary_language  VALUE  864 codes, ALL 864 shared               → stable
    religion / wagf_region VALUE also identical across locales

So the fix is not "make both halves fetch the same locale and test that they do".
It is to link on the form that does not move. Region already links on a slug and
religion on a family letter; language was the one facet still travelling as a
display name.

The map now emits `languageCode` alongside `language`, the composite carries
{value, label} for language as it always has for region, the GRID is driven by
the code (valueMatches compares the normalized value as well as the label, so a
code matches in every locale) and the MAP is still driven by the name, because
its legend selects by name. Each half gets the form it can actually use, and
neither depends on the other's locale.

★ THIS TREE HAD ALREADY PAID FOR THIS ONCE. deriveLanguageFamily in useMapData
carries a comment about the 2026-06-22 locale colour bug: deriving a family from
the localized label collapsed every pin onto one bucket, and the fix was to use
primary_language.value. Same trap, one facet over, three months later.

check:linked-vocabulary now runs per LOCALE as well as per provider — en as the
control, ar as the case that would have broken in silence — and asserts the
language facet with a poison case (a language that cannot exist must NOT narrow
the grid). It is a browser gate, so rega runs it; I have not.

★ AND check:no-free-identifiers CAUGHT MY OWN BUG IN THIS COMMIT on its first
outing: I wrote `rows.find(...)` in the emitter where no `rows` was in scope. The
gate named the file and line before anything was built. That is the class of
mistake that broke both composites yesterday, found in seconds this time.
2026-09-26 08:07:39 +00:00
..
check-composite-locale-leaks.mjs Five more gate scripts read the tree's name from the build config 2026-09-25 16:25:22 +00:00
check-linked-vocabulary.mjs Link language on the ISO code, not the display name, because the name moves with the locale 2026-09-26 08:07:39 +00:00
check-no-free-identifiers.mjs A gate for the mistake I shipped: a name used but never bound 2026-09-26 03:29:51 +00:00