Commit graph

1522 commits

Author SHA1 Message Date
Doxa Maps
72fb327951 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:30:10 +00:00
Doxa Maps
2eac0fb3c1 Gospel leaves: numbers follow the reader's locale, not the browser's
toLocaleString() with no argument formats for the JS runtime's locale, which has
nothing to do with the locale the plugin was asked to render in. The Arabic build
on an English browser got English grouping and the same page on a French browser
got French grouping: one plugin, one locale, two different numbers. All four
leaves now format with the locale i18n actually resolved.

numberingSystem is pinned to latn, and the obvious justification for that is
wrong, so here is the measured one. Against full ICU, the eleven tags this bundle
ships all resolve to latn already — plain "ar" included — so for them the pin
changes nothing. It earns its place only if a host passes a region tag: ar-EG
resolves to arab and fa to arabext, and those would switch the digits. Numeral
format is held for the Driver, so the pin keeps that his decision rather than a
host's.

What does change is grouping, and it is visible: Hindi groups in lakhs, so
1234567 reads 12,34,567, and French and Russian use a space. Those are correct
for the locale and differ from what shipped before.

The bare calls left in the built bundle are in library components this bundle
does not render — LegendProgressBar and PosterWall — and belong to whoever owns
library, not here.
2026-09-26 01:29:52 +00:00
Doxa Maps
05b3c3217b Rebuild pplr-data-maps, and regenerate the tree
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:26:26 +00:00
Doxa Maps
0776443961 PPLR data maps: the Globe/Mercator toggle works on MapLibre too
Three views called map.setProjection(projection.value) with the bare name ('globe'|'mercator'),
unguarded, including inside style.load handlers. Mapbox takes the name; MapLibre 5 takes a
specification object ({ type }), so under provider=maplibre the toggle did nothing or threw
mid-restyle. setProjectionFor(map, name) passes the engine's shape and is guarded; all six call
sites use it. Found by the engine-asymmetric API sweep (universal-props matrix, new column).
Headless: a fake-map unit test (MapLibre gets {type}, Mapbox the string, a throw is swallowed,
null/empty no-op) 5/5; BUNDLE=pplr-data-maps builds. Plugin-local: pplrData.js has no other consumer.
needs eyes: PPLR Religion view with ?provider=maplibre: the 🌐/🗺 button switches globe and mercator.
2026-09-26 01:23:15 +00:00
Doxa Maps
6d7da1c0f7 plugin-designs/README: the tree is dx-maps, and a bundle's tag is its folder name
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
Four path lines said public/doxa-maps/ (the folder was renamed in 09014f8a), and the embed
example used a <doxa-map> tag, but a bundle registers the tag named after its folder
(template-bundle/index.js), so the example is <your-map>.
2026-09-26 01:19:53 +00:00
Doxa Maps
f4833def5b Rebuild doxa-vision-card, and regenerate the tree
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 01:14:53 +00:00
Doxa Maps
504be20040 Doxa Vision Card: take the page language from profile-config lang as well as locale
Composites forward the page language as `lang` (dashboard-plus-grid, research-map-plus-grid,
the mfes). The card read only `locale`, so nested in one it fell back to English. Now locale,
then lang, then ?lang, then <html lang>, per the universal-props contract. Headless: the bundle
builds. needs eyes: a vision card inside a composite with lang=ar renders in Arabic, right-to-left.
2026-09-26 01:10:51 +00:00
Doxa Maps
6104b10fc0 Gospel map: read the Mapbox token through the library's channel
resources-map read profileConfig.tk || window.DOXA_TOKEN. DOXA_TOKEN is set by a
few dev pages and nothing else, so in the studio and on every built page this map
ignored the page's token entirely. It now takes profile-config tk, then
ProfileLoader's injected mapboxToken, then window.MAP_TOKEN, as the
universal-props contract says.

The pattern is copied from the same fix on cities-internet and key-cities
(1cf57f7a) rather than re-invented. Three raw maps each deciding for themselves
how to find a token is how all three came to be wrong in the same way.

Headless: the built bundle no longer contains DOXA_TOKEN at all, and carries the
injected token and MAP_TOKEN instead.
2026-09-26 00:58:02 +00:00
Doxa Maps
8e49ec41d6 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:52:04 +00:00
Doxa Maps
b5068166ac The theme toggle picks a style the running engine can load
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
The map booted correctly under ?provider=maplibre and then went blank
the first time a reader touched the light/dark toggle: handleToggleTheme
called setStyle with a hardcoded mapbox:// URL, which MapLibre cannot
load at all. The boot path two hundred lines below already did this
properly — resolveNamedStyle('paper', upgProvider) — so the file
disagreed with itself about how a style is chosen.

The registry names the same INTENT for both engines: 'paper' is light
(mapbox light-v11 / OpenFreeMap positron), 'ink' is dark (dark-v11 /
OpenFreeMap dark).

BEHAVIOUR-PRESERVING ON MAPBOX, and checkable rather than asserted:
resolveNamedStyle returns URLs byte-identical to the literals this
replaces — 'paper' -> light-v11, 'ink' -> dark-v11. Only the MapLibre
branch changes, from an unloadable URL to a real one.

⚠ A STRING-PRESENCE GREP CANNOT PROVE THIS LANDED, which is worth
recording because it nearly satisfied me. The built bundle already
contained openfreemap.org/styles/dark BEFORE the change — the registry
is compiled in for the boot path — so "is the MapLibre URL in the
bundle" answers yes either way. The falsifiable question is what the
CALL SITE references, and at the compiled layer:

  before  setStyle(f.value?"mapbox://…/dark-v11":"mapbox://…/light-v11")
  after   setStyle(f.value?vi("ink",s).style||"mapbox://…/dark-v11"
                          :vi("paper",s).style||"mapbox://…/light-v11")

where vi is the minified resolveNamedStyle(name, provider). Measured by
building both ways.

The `||` fallbacks keep the old literals as a last resort if a name ever
stops resolving, matching the boot path's own guard rather than
inventing a second policy.
2026-09-26 00:47:51 +00:00
Doxa Maps
b76cf8f74f The partner-embed check becomes something a person can open
Under the Playwright policy only rega runs a browser here, so this
check's result has to come from someone else's eyes. But the partner
page only ever existed INSIDE check-embedded-rtl — two createServer calls
on ephemeral ports — so "open a partner page at a foreign origin" was not
a thing anyone but the gate could do. NEEDS-EYES rows 3, 4 and 6 name a
runnable probe or an exact URL; row 7 was mine, and it named a construct
that lived in my own process.

--emit writes the same pages to disk, with the two-terminal recipe and
what to look at, so the item is reproducible by whoever has the browser.

⚠ THEY GO IN documentation/, NOT _qa-cycle/. I wrote them there first and
then checked: _qa-cycle is gitignored (.gitignore:113), so the files
could never have travelled to the person who needs them — which is the
entire point. documentation/ is tracked and already carries
README-embed-example.md.

⚠ AND THE ?lang=ar FIXTURE CARRIES NO locale IN ITS profile-config —
1100 bytes against 1114. The two channels reach the document-direction
code by different routes and detectLocale() reads the URL FIRST, so a
config that also supplied the locale would let a reviewer believe the URL
had done it when it had not. The first emit produced all three files
BYTE-IDENTICAL, which would have handed someone three pages they could
not tell apart; I only caught it by checking the emitted sizes rather
than trusting that the flag had taken effect.

The CASES array now carries the ?lang= row itself, so this stands alone:
the emit produces every fixture committed beside it. It previously
depended on the library/ commit for that row, which left the repo with a
fixture the tool would not regenerate — worse than either half.

Also: --emit was being consumed as the baseUrl positional ("SKIP —
nothing served at --emit"). Flags are filtered out of it now. That is the
same bug, in the same shape, that check-leaf-english-leaks had three days
ago — worth knowing it recurs in any gate that takes both a positional
and flags.
2026-09-26 00:47:12 +00:00
Doxa Maps
c534781bac MapLibre region fills drew nothing: the worldview clause filtered out every feature
rega measured it by eye at b0cd3140 on the built tree: regions-mfe under
?provider=maplibre draws the basemap and 2,107 pins, the boundary geojson returns
200, and the fill layer holds 0 features. Mapbox draws 156. A filter that admits
nothing looks exactly like data that never arrived.

countryFilter() is two clauses ANDed. The ISO half was fine — the field bridge
three lines above it already copies iso3 -> iso_3166_1_alpha_3 onto every geojson
feature before setData, so one name is read everywhere. The WORLDVIEW half has no
bridge and cannot have one: it exists because the Mapbox tileset repeats a country
once per worldview and the highlight would otherwise draw two or three times over.
The geojson has no such duplication and carries no worldview property at all, so
both sides of the `any` were false on every feature and the `all` emptied the
layer. It is Mapbox-only, not something to translate, so MapLibre now gets the ISO
clause alone.

I NEARLY FIXED THE WRONG HALF. Reading the RAW geojson I saw { iso3, shapeGroup,
shapeName }, concluded the ISO key was wrong too, and branched it — adding a
second name for a fact the bridge already normalises. The bridge was three lines
above the filter I was editing. Reverted; the ISO clause is untouched.

Proven headless, fail-first, by EVALUATING both filters against the real 162
features with MapLibre's own parser after applying the bridge:
  OLD filter admits   0 / 162   <- rega's bug, reproduced without a browser
  NEW filter admits  14 / 14    <- every requested country
  Mapbox path unchanged: still 14/14, and still drops a duplicate worldview copy
The control asserts the OLD filter still admits 0, so the check reports when it
has stopped demonstrating the bug it was written for.

Needs eyes: rega to re-shoot row 13 on this sha.
2026-09-26 00:38:15 +00:00
Doxa Maps
4bb0dbed47 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:37:30 +00:00
Doxa Maps
e02f50ad41 Rebuild cities-internet key-cities country-posters, and regenerate the tree
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:34:05 +00:00
Doxa Maps
0d2f83c9f8 Country posters: "Export poster…" opens the dialog again
countries-map mounted <PosterDialog v-if="showPoster"> with :poster and :active-tab, props the
dialog does not declare, and without v-model or getMap. PosterDialog shows only while its
modelValue is true, so the button opened nothing, on both engines. It now passes v-model and a
getMap accessor, and unwraps the legend-rows ref. loadPoster() also called useMapPoster with an
options object; useMapPoster(getSourceMap) takes the map accessor. Headless: the bundle builds.
needs eyes: country-posters map > menu > Export poster… shows the dialog, and Render downloads.
2026-09-26 00:29:30 +00:00
Doxa Maps
295e6a7909 Cities with Internet + key-cities: read the Mapbox token through the library's channel, not window.DOXA_TOKEN
Both raw maps read profileConfig.tk || window.DOXA_TOKEN. DOXA_TOKEN is set only by a few dev
pages, so in the Plugin Studio and on every built page these maps ignored the page's token
(window.MAP_TOKEN, the shared token). They now take profile-config tk, then ProfileLoader's
injected mapboxToken, then window.MAP_TOKEN, as the universal-props contract says. Found by the
draft check:universal-props (TOK-GLOBAL). Headless: both bundles build, and DOXA_TOKEN no longer
appears in either shipped file.
2026-09-26 00:29:30 +00:00
Doxa Maps
b0cd3140bd Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:19:52 +00:00
Doxa Maps
0f839f1071 MapLibre: reading the projection threw, so a region dashboard never framed
Driver, on MapLibre: opening a region dashboard does not zoom to the region the
way Mapbox does. This is why.

fitTheirWay read `m.getProjection().name` OUTSIDE its try. The two engines
disagree about both halves of that API:
  Mapbox    getProjection() -> { name: 'globe' }    setProjection('mercator')
  MapLibre  getProjection() -> { type: 'globe' } | undefined
                                                  setProjection({ type: 'mercator' })
MEASURED in maplibre-gl@5's own source, which we load from jsDelivr:
Map.getProjection() returns `this.stylesheet?.projection`, and the OpenFreeMap
style we hand MapLibre declares no projection key at all — its top level is
version, sources, sprite, glyphs, layers. So getProjection() is UNDEFINED there
and `.name` threw a TypeError.

Because the read sat outside the try, the throw escaped fitTheirWay AND escaped
applySubject(), of which it is the last statement. The camera was never framed:
the map stayed wherever it was instead of flying to the region.

The read is now defensive and accepts both shapes, and the WRITE is
engine-correct: Mapbox takes the bare string, MapLibre reads e?.type, so handing
it a string would set undefined rather than fail loudly.

It was wrong in a second way worth recording: on a MapLibre style that DOES set
globe, the old read returned null and silently skipped the mercator correction
that exists to stop the fit pulling back. So it both crashed on one shape and
under-corrected on another.

Proven headless per the Playwright policy, with the old expression run against
the same stubs as the control: it THROWS TypeError on the real MapLibre shape and
returns null where it should see globe, while the new one returns 'globe',
'mercator', 'globe', null, null across the five engine shapes. A check that
cannot be shown to fail proves nothing, so the check fails if the old expression
ever stops throwing.

Needs eyes: MapLibre, region dashboard — does it now fly to the region.
2026-09-26 00:19:26 +00:00
Doxa Maps
15d9d47a05 Rebuild pplr-data-maps, and regenerate the tree
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:17:24 +00:00
Doxa Maps
2be2debe47 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work 2026-09-26 00:16:45 +00:00
Doxa Maps
c5fbb24aba Gospel list: name the translator on the language rows too
The map sheet and both bridge panels say who produced the Scripture; the language
list was the one surface a reader can arrive at that still answered "where"
without "who". 757 of the 5,067 rows now carry the organisation and year beside
the language.

A name rather than a link, for the same reason as everywhere else: the doctrine
screen is an allowlist, and a publisher must not enter this map as a side effect
of a data refresh. Measured after the change — 16,963 links, unchanged, and not
one credit contains a URL.

It needs no catalogue entry because an organisation's name is the same in every
locale. That is also why it can sit beside the translated labels around it
without leaving a hole in them.
2026-09-26 00:16:22 +00:00
Doxa Maps
0de6a7c2f8 PPLR data maps: keep the loading globe up until the pins are drawn, not merely added
Six views set dataReady (which removes the LoadingGlobe) straight after addSource(). The engine
then still tiles tens of thousands of points in its worker, so the globe vanished and the map sat
empty with a full legend. Measured on the DX-life gallery: 0 features for 20 s, then 19,376.
whenGeojsonDrawn(map) resolves once every GeoJSON source is loaded AND a frame has rendered
(not 'idle', which an animating map may never reach), with a 45 s cap so it can never hang.
Religion, pins, coverage, translations, language families and Rosetta cards await it before
dataReady. Plugin-local: pplrData.js has no consumer outside pplr-data-maps.
Headless proof: a fake-map unit test (already loaded / last source late / never loads -> false at
the cap / style mid-swap / no map), 9/9 pass; BUNDLE=pplr-data-maps build + tree + check:sri PASS.
2026-09-26 00:14:16 +00:00
Doxa Maps
8dcd407e29 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:10:55 +00:00
Doxa Maps
2070b0c6f1 Gospel leaves: one active-tab colour, and it is the house one
#10b981 is Tailwind emerald and is not in this product's palette. Worse, the four
gospel leaves did not agree with each other: the map's active mode button was
near-black while the list, the tables and the charts were emerald, so the same
control looked like two different controls depending on which tab you were on.

Light is now the house dark on white, dark is the house sage on near-black, and
all four leaves share it. Contrast measured rather than eyeballed, since this
cannot be checked in a browser here: 9.86:1 and 7.89:1, both well past AA for
12px bold. Sage with #3b463d text was the obvious pairing and was rejected at
4.20:1, under the 4.5 this size needs.

The chart COLOURS are deliberately untouched. They encode meaning — scripture,
film, found, nothing, unresolved — and have to stay distinguishable from each
other, which is a different constraint from matching a palette. Recolouring them
is a judgement about legibility and belongs in its own change with someone
looking at it.
2026-09-26 00:09:22 +00:00
Doxa Maps
7f707807d6 Merge remote-tracking branch 'origin/main' into rega/research-gallery-embed
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-26 00:05:06 +00:00
Doxa Maps
8f5bd5efb4 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work 2026-09-25 23:57:06 +00:00
Doxa Maps
7ab9a6d187 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work 2026-09-25 23:50:44 +00:00
Doxa Maps
0b54b0354e Gospel checks: one dev-assets gate, and cover the gap it leaves
The gospel-only dev-assets check is gone in favour of the shared one, which is
better at the job: it tests the /__leaf/<bundle>/<profile> prefix — the one that
actually broke — across all seven map bundles, and confirms each leaf hands its
element the base it claims. The gospel version never looked at that prefix, so
keeping both would have meant two implementations and the weaker one still green
while the map was broken.

What the shared gate samples is the POOL, the files every map shares. It cannot
know this leaf also fetches gospel tables by name, so a table that stopped being
staged would leave it green and this map fetching a 404. That is the only gap
left, and this covers exactly it.

The wanted list is parsed out of resources-map.vue rather than written down,
which immediately earned itself: the hand-written list it replaces was already
two short — pray-index and gospel-link-verification were being fetched and were
not in it. A list maintained by hand is the field-list-goes-stale bug, and this
bundle has produced that three times in one day.

Poison-tested by unstaging a real table: FAIL, exit 1, then restored.
2026-09-25 23:50:31 +00:00
Doxa Maps
13e0e02c9d Rebuild the consumers main left stale (build owner, README rule 5)
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
check:composite-freshness found stale on main: none. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
2026-09-25 23:49:02 +00:00
Doxa Maps
87ebbace9b Leaf pages load only the engine their provider asks for: no Mapbox requests under MapLibre
A generated map leaf chose its engine at BUILD time and hard-linked it in <head>: mapbox-gl.css,
the geocoder css, mapbox-gl.js and the geocoder js from api.mapbox.com. The provider is chosen at
RUNTIME (profile-config.provider → ?provider= → window.MAP_PROVIDER), so a partner embedding a leaf
with ?provider=maplibre still had every visitor's browser make 4 requests to Mapbox.

- generate-tree: no static engine tags on map leaves; the element's own runtime loaders
  (ensureEngineScript / ensureEngineCSS, the geocoder's on-demand loader) load exactly the engine
  asked for, the path composite leaves already ran on. The forge page drops its api.mapbox.com
  preconnect. A leaf opened with provider=maplibre (same ladder as resolveMapProvider) is token-free,
  so the public copy no longer asks a MapLibre visitor to paste a Mapbox token.
- check:leaf-engine-per-provider (new, browser): every leaf at ?provider=maplibre makes 0 requests
  to *.mapbox.com and still draws; at its default every map leaf draws with the engine it drew with
  before (--baseline <tree> compares against another tree).
- check:dashboard-geocoder-provider is wired into gates:post alongside it; it had been held out
  because this generator's tags made it red.
- verify-map-paint: optional GATE_VIEWPORT for a phone pass.

Measured before this landing (browser runs made before the headless rule): leaf-engine vs main's
tree PASS, 56 leaves, 0 Mapbox requests under MapLibre, same default engine. Pins, region popup,
PPLR search and key-cities PASS on both engines with 0 Mapbox requests under MapLibre. RTL shaping
PASS on both engines wherever RTL labels rendered. Paint under MapLibre: the same 4 leaves fail as
on main (country-posters-mfe, upg-100-mfe, regions-mfe, flower-mesh). Pre-existing, not caused here.
Poster "Render" is missing on country-posters and doxa-research-map under BOTH engines. Pre-existing
on main, read from source: countries-map.vue renders <PosterDialog v-if="showPoster"> without
v-model or getMap, and PosterDialog shows only when modelValue is true.
Headless, on this commit's regenerated tree: 57 leaves, 0 carry api.mapbox.com engine tags (main's
doxa-simple-map leaf carried 5), 56 carry the runtime provider check, check:sri PASS.
2026-09-25 23:44:04 +00:00
Doxa Maps
3ab1d7aad5 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work 2026-09-25 23:41:23 +00:00
Doxa Maps
a8eb431c2f Merge remote-tracking branch 'origin/main' into rega/research-gallery-embed 2026-09-25 23:41:19 +00:00
Doxa Maps
f6571ed4ea Research Gallery: PPLR Data Maps and Wall of People Groups are named in all 11 languages
The two discovered Experimental tabs fell back to their English bundle titles in every
locale (Arabic rail: 'Pplr Data Maps', 'Wall Of People Groups'). Only doxa-maps-spa's own
bundle is rebuilt; its SRI refreshed in both manifests.
2026-09-25 23:41:17 +00:00
Doxa Maps
c97876b3da Gospel access: the translator's name travels with the exported row
The sheet names who translated the Scripture, and a team printing posters or
building QR codes exports the CSV and never opens the sheet. A lead that only
exists on screen is a lead that does not reach the people doing the work, so
"Translated by" and the year are columns now: 864 of the 2,107 rows carry a named
body across 33 organisations.

Left empty rather than filled where the catalogue names a licence instead of a
translator. The column says who to ask; "public domain" answers a different
question and would read as an answer to this one.

Two pools were considered and deliberately not attributed. Faith Comes By
Hearing puts the producer inside a free-text version name — "Okpe, Delta - Bible
Society of Nigeria" has it, "Malkus Mawyon" does not — and splitting on the dash
would invent an organisation for the rows that have none; its own API, which
would answer properly, needs credentials this build does not have. Door43's URL
owner IS authoritative but is frequently a catalogue or a language namespace
rather than a body, so "translated by Door43-Catalog" would be false for 116
entries. A name nobody can act on is worse than a blank.
2026-09-25 23:41:11 +00:00
Doxa Maps
9a7c6304f7 README: what the library gives every map — two engines, a key or a key service, 11 languages, web components, maps that talk to each other, tree-shaken bundles, one build, three outputs
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-25 23:39:36 +00:00
Doxa Maps
d8a9811a4e Rebuild regions-dashboard after resolving artifact conflicts 2026-09-25 23:39:33 +00:00
Doxa Maps
9272f1f9b7 Gospel map: name the people who translated it
The brief asks for real leads — real translators, the real organisations that do
the work — and the map had only URLs. A mobiliser who finds a neighbouring
language already has Scripture wants to know who produced it, because that
organisation has the linguists, the relationships and very often a team already
in that country. The link answers where; this answers who to ask.

eBible publishes its catalogue with a copyright line on every row and the join is
exact: 964 of the 964 eBible links in this index match a catalogue row by
translation id, none unmatched. 929 resolve to a named body across 137
organisations — Wycliffe Bible Translators, The Word for the World, Biblica,
Pioneer Bible Translators, the Seed Company, World Bible Translation Center. It
shows on the group sheet and on both bridges, where "who do I ask about this
language" is the sharpest question on the page.

NAMES ONLY, NO NEW LINKS. The catalogue also carries each publisher's domain, and
shipping it would put hosts into this map that the doctrine screen has never
seen — the screen is an allowlist precisely so a new publisher cannot arrive as a
side effect of a data refresh. Measured after the change: 16,963 links scanned,
the same count as before, and not one credit contains a URL.

A licence is not a translator. 35 rows reduce to "public domain", which says how
the text may be used and nothing about who made it; answering "who to ask" with a
legal status would be worse than saying nothing, so those are dropped and counted
separately from the rows that have no catalogue entry at all.
2026-09-25 23:38:12 +00:00
Doxa Maps
6f66625e88 Map controls were unclickable: the scroll strips sat on top of them
Driver, on Mapbox: the region dashboard zooms and draws correctly, but zoom in,
zoom out and fullscreen cannot be pressed at all.

CAUSE. .map-scroll-edge is a 40px full-height strip down each side with
pointer-events:auto and z-index:2 — the affordance that lets a vertical drag
scroll the PAGE instead of panning the map. Both engines place their control
groups in the very corners those strips cover, and at equal z-index the element
later in the DOM wins. The strips are rendered after the map container, so they
covered every control.

The strips must keep their pointer events, or the scroll affordance dies with
them, so the controls are lifted above the strips instead of the strips being
made inert.

ALL FOUR CORNERS AND BOTH ENGINE PREFIXES, deliberately: the left strip covers
the two left corners exactly as the right covers the right, a control can sit in
any of them, and naming mapboxgl- and maplibregl- together is what makes this
survive a provider swap — which is the whole point of the provider prop.

Proven headless, per the new Playwright policy: the shipped bundle carries the
rule for both prefixes and the strips still carry
touch-action:pan-y;pointer-events:auto. Whether the buttons are now clickable is
a drawn behaviour and goes out as needs-eyes.

NOT LANDED YET — main is held for studio's freshness rebuild.
2026-09-25 23:37:52 +00:00
Doxa Maps
1008001ea5 Gospel map: publish a tier per language, so a language with no pin still has one
Gazan Arabs — 2,315,000 people, the second largest population this map draws —
was painted red as "nothing found" while the index held a Scripture Earth PDF and
a Zume course in South Levantine Arabic, and the access table beside it already
said "read". Because of that stale zero it was also the one group on the map
shown as having nothing AND no way in.

The cause is structural, not a typo. The tier existed only ON A PIN, and `codes`
is keyed from the resource pools while `pins` comes from the people-group
dataset, so a language can be fully researched and carry no pin at all: zero pins
speak ajp. With no tier to read, the map fell back to the roster's stored copy,
captured when that file was written and never refreshed since.

So the tier is computed for every code the index knows and published as `tiers`,
from one definition that also tiers the pins. The map reads it. It does not
re-derive a tier from the resource fields — that is the drift the surfaces gate
exists to stop, and a roster keeping its own copy is the same drift with extra
steps.

The gap is 369, not 370, and not one of them is left without a way in — so the
legend now says "every one of those 369" rather than "369 of those 369", which
read like a coincidence. Both halves still hold: every group has somewhere to
start, and none of them has the gospel in their own language.
2026-09-25 23:32:33 +00:00
Doxa Maps
eff0ee13c5 Rebuild the consumers main left stale (build owner, README rule 5)
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
check:composite-freshness found stale on main: all-people-groups
big-picture
cities-internet
country-posters
dashboard-plus-grid
demo-map
doxa-research-map
doxa-simple-map
key-cities
my-upg-100-list
people-groups-grid
pplr-data-maps
prayer-walk-planner
regions-dashboard
research-dashboard
research-map-plus-grid
template-bundle
upg-neighbor
wall-of-people-groups. Rebuilt, tree + SRI
regenerated; the landing precondition (fresh, one folder, SRI) passed in main-capture scan.
2026-09-25 23:31:56 +00:00
Doxa Maps
229921c94f Gospel map: the Arabian peninsula gets an Arabic bridge, not Urdu
Five countries fell back to the weak pins proxy, and Saudi Arabia fell back to
URDU. The reason is a join asking for a code no publisher uses: CLDR reports
Arabic (ara) at 100% of Saudi Arabia, 81% of Oman, 74% of Libya and 100% of
Kuwait, but ara is a MACROLANGUAGE and nothing is published under it — the
Scripture and the film sit under arb. Taiwan had the same shape: zho empty, the
resources under cmn. The five countries this hit are among the least reached on
earth, which is where a wrong bridge costs the most.

Resolved through SIL's own macrolanguage membership, never by name, reusing the
table already read for the related-variety note. Every one of the 1,175
candidates now comes from published language data and none from the proxy; 211
resolve through a macrolanguage.

The share keeps the name it was measured under. CLDR measured Arabic, not
Standard Arabic, so the sheet says Arabic is spoken by 100% of this country and
that Scripture and the JESUS Film are published in Standard Arabic. Claiming the
percentage for the variety would be a figure CLDR never produced.
2026-09-25 23:24:42 +00:00
Doxa Maps
17dc7bad87 check:dev-assets: every leaf of the seven studio maps, with bytes that parse and a bogus-path control
Each leaf's dev page must hand its element assetsBase "/assets"; a boundary file and a table under
that base must answer 200 with bytes that JSON.parse (never an HTML fallback), and a bogus file
under it must be a real 404.
2026-09-25 23:22:27 +00:00
Doxa Maps
9dc4ce5ecf Gospel map: a headless check that the dev server holds the assets the map fetches
Every gate for this bundle measured the built tree, and the map was found broken
where none of them look: the dev server. Boundary polygons were missing there on
five maps at once, this one included, while every built-tree gate stayed green —
the thing that differs is how a leaf resolves its asset base, not what the build
produces.

Measured without a browser, which is also why it can run on every change rather
than when a slot is free: /assets/boundaries/world-adm0.geojson answers 404 in
dev while /dx-maps/assets/boundaries/world-adm0.geojson answers 200 with 1.9 MB.
The file is there; the base is wrong.

It asserts bytes and JSON, not just status, because a dev server that answers 200
with an HTML fallback for a missing .geojson is the shell trap this repo has been
caught by twice. A bogus asset path is requested as a control: if that also
answers 200 the gate reports NOT MEASURED, since a server answering everything
cannot tell a present asset from a missing one.

It does not prove the leaf asks for the right path. That fallback lives in
library/ and belongs to studio; this is the other half — whether there is
anything at the end of the base once the base is right.
2026-09-25 23:18:50 +00:00
Doxa Maps
c43a8b793c Dev server: every plugin reaches the asset pool again (no polygons, previews, fonts or tables in dev)
Reported from a laptop running `bun run dev`: under the Plugin Studio, maps drew with no boundary
polygons and UPG-100 had no posters. The built tree was fine, and every gate measured the built tree.

Cause: a dev leaf page is /__leaf/<bundle>/<profile>. A plugin that falls back to the page-relative
'./assets' asked for /__leaf/<bundle>/assets/…, and the leaf route answered with its own HTML at
HTTP 200, so JSON.parse failed and the map drew without our data. /<tree>/assets/ was not served
in dev at all. The built leaf never hits this because its page passes assetsBase "../../assets".

- dev-plugin serves the pool at /__leaf/…/assets/ and /<tree>/assets/ too, and the dev leaf page
  passes assetsBase "/assets" in its profile-config, as the built leaf passes its own.
- resolveAssetsBase's last rung is '/assets' under the dev server (import.meta.env.DEV, false in
  every build); the built tree keeps './assets'.
- check:dev-assets (headless): starts a short-lived dev server for this checkout, requires
  boundaries/previews/fonts/images/tables to answer 200 and not HTML at every prefix a dev page can
  produce, and requires the dev leaf to carry the root-absolute assetsBase. It fails on the parent
  commit (4 prefixes and both leaves) and passes here.
2026-09-25 23:17:35 +00:00
Doxa Maps
58326f2d82 Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
# Conflicts:
#	internal/check-gospel-rtl-shaping.mjs
2026-09-25 22:55:49 +00:00
Doxa Maps
40d5d8e6bf The docs stop handing the next reader a 404
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
Last tick I fixed the one executable literal the tree rename broke, and
wrote that the remaining mentions "will mislead the next reader but
break nothing." That second half was wrong, and worth correcting rather
than leaving.

Six of them are RUNNABLE COMMANDS — usage lines, a --leaf example, two
PROBE_PATH invocations, a BASE= export. Copy-pasting one aims a probe at
a folder that no longer exists, and the failure is silent: a 404 loads
as an empty document and every gate then reports whatever "nothing"
looks like in its own vocabulary. That is exactly how I produced three
confident fake findings in a single sitting last tick — a frame probe
reporting "0 images, no wall" on two different leaves, and a basemap
gate reporting "map never finished its style". A comment that names a
path a reader will then USE is not inert documentation.

So the six say <TREE_NAME> now, which is what the code reads and what
_tree-name.mjs exists to make authoritative.

WHAT IS DELIBERATELY LEFT ALONE, because rewriting it would falsify the
record: 19 mentions are historical narrative — "public/doxa-maps was…",
the census that motivated _tree-name.mjs, and check-catalog-identity's
citation of https://nuxtbase.app/app/doxa-maps/manifest.json returning a
200 sign-in page. That URL is EVIDENCE of a past false-200, not an
instruction; its code already reads TREE_NAME.

Live literals across internal/ are now zero, except public-hygiene's
doxa-life/doxa-maps, which is the private REPO name and correctly
unrelated to the tree.
2026-09-25 22:49:37 +00:00
Doxa Maps
5238c36573 Gospel map: the country gap list says where to start
The rows under "No resource found" carried a name, a language and a population
and nothing else, so the question a mobiliser opens a country to answer — what do
I do about these? — cost one click per group. 369 of the 370 groups with nothing
have a way in, and it was reachable only by opening each pin in turn. Mali's two
now read "way in: French"; Benin's one reads "way in: SUN (signed)".

Text rather than a link, and it could not be otherwise: these rows are button
drill-ins and HTML forbids an anchor inside a button — the parser hoists it out
and it stops being a link, which is why the rows that DO have resources are plain
containers instead. The row still opens the group sheet, and the sheet carries the
bridge's real links.

It names the bridge and claims nothing further. "Bambara" here does not say
Bambara reaches this group; that stays the local question the sheet spells out.
It turns a list of dead ends into a list with a first move against each one.
2026-09-25 22:49:05 +00:00
Doxa Maps
f978b2e579 README screenshots retaken after ce42977c
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-25 22:43:23 +00:00
Doxa Maps
85ac672f06 Merge main into bundler-2/work
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
2026-09-25 22:35:50 +00:00
Doxa Maps
29fc335b00 Prove the grid-under-map link on both engines, not just the one we happened to run
BUILD-INTEROP-CONTRACT-GRID-UNDER-MAP-BOTH-PROVIDERS asks for a provider matrix:
the same assertions, once per engine, with identical counts. Interoperability
that holds on one provider and not the other is not interoperability.

It is not a formality here. The map half of this link resolves a religion family
through its own legend, and the legend is drawn by the map engine — MapLibre
drops an entire layer in silence for one misplaced paint property, which would
surface as a link delivering nothing while the Mapbox run stayed green.

So the gate now runs the whole measurement under ?provider=mapbox and
?provider=maplibre, and then asserts the two agree: the same starting total, the
same rows for the same family, and the same rows over the composite's wire. A
per-engine pass with different numbers would mean the same choice narrows to
different peoples depending on which engine a partner embedded.

MEASURED, identical to the row on both:

    mapbox     2,107 groups · Buddhism 83 direct · 83 linked · mutant 0
    maplibre   2,107 groups · Buddhism 83 direct · 83 linked · mutant 0

The mutant still runs first on each engine, so a green here still means the gate
can tell a right mapping from a wrong one — twice over now.
2026-09-25 22:35:48 +00:00