Commit graph

112 commits

Author SHA1 Message Date
Doxa Maps
05ab8b9da1 Place search makes no Mapbox call without a real token, and says so
(cherry picked from commit cd03a2c6d0)
2026-09-26 03:34:31 +00:00
Doxa Maps
ab17c9b6aa The default engine is auto: Mapbox when a token is available, MapLibre when none is
(cherry picked from commit 3cb89eae52)
2026-09-26 03:34:12 +00:00
Doxa Maps
a2f0d90424 Reference: the universal-props contract (engine, locale + dir, Mapbox token, token-service URL)
One page that says, for each prop the Plugin Studio header sets for every plugin, which channels
can carry it (header, profile-config, URL, window, attribute), which one wins, and the default;
how the studio hands it to a pane; and the rule a plugin follows to honour it. Ends with the open
points found while writing it down (tokenUrl has no reader, the token-clear bridge, raw maps on
window.DOXA_TOKEN, ladders that disagree), each routed as a defect. Scope is the four props the
header sets today; anything wider is DECIDE-UNIVERSAL-PROPS-SCOPE.
2026-09-26 02:38:06 +00:00
Doxa Maps
694dad7bab Docs: an iframe updates itself; a script embed's integrity hash pins the bytes, so re-copy it after each release
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
From the critic's SRI check. how-to's embed section had no word on it; the CLI section said the
hash changes on every build, which is only true when the bundle's bytes change.
2026-09-26 02:07:14 +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
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-88655c70
2ff0ecba35 README screenshots retaken after d1af039a; freshness-gate comments name the tree, not the old folder
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:05:39 +00:00
doxa-maps-88655c70
94f0e55444 README screenshots retaken on the dx-maps 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-25 21:07:11 +00:00
doxa-maps-88655c70
2509a6e347 README: three outputs, not five methods; a Languages section; screenshot gates see every shot again
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
- Deployment is now organised around what the build makes: (1) one web
  folder (536 files, 76 MiB), embedded by iframe and JavaScript (proven) and
  WordPress (just for fun); (2) the mobile app (Capacitor, built); (3) the
  desktop app (Tauri, proof of concept). A hosting table says where the folder
  can go: dx-life's public/, Cloudflare Pages drag-and-drop (fits its 1,000-file
  / 25 MiB limits), GitHub + jsDelivr (JS embeds only: measured, jsDelivr serves
  HTML as text/plain), or any web server, with the one _headers line JS embeds
  need. No Docker. The diagram and the map-cruncher picture say three outputs.
- Languages: 11 locales via ?lang=, Arabic right to left, with an Arabic shot of
  UPG-100 (Big Picture still leaks English in Arabic; reported). The partner
  profile-config locale is deliberately not documented until it is fixed.
- check-shot-freshness and check-shot-distinctness parsed only '...' paths, so
  after 44ef31b2 turned them into `/${TREE_NAME}/...` templates they saw 2 of 26
  shots: distinctness failed, freshness passed vacuously and hid 22 stale shots.
  Both now accept either form and resolve TREE_NAME, and exit 75 (NOT MEASURED)
  unless every `await shot(` call is parsed (the one dynamic dx-life call is
  marked). Negative-tested. The 22 shots are retaken and checked by eye.
- how-to: the shell no longer overwrites the Studio (it now lives in the output
  folder); README serve line points at doxa-maps/index.html.
- Docs follow the rename to dx-maps (09014f8a): every output-folder path and URL in
  README, how-to, reference, CONTRIBUTING, the CLI section and the develop guide now says
  public/dx-maps/. The repo name, the config file name, the WordPress plugin folder and
  the doxa-* tag names are unchanged (tags are a separate landing).
- Hosting: a live example, the dx-life branch research-gallery, which drops the folder
  into dx-life public/ and fills /research with the Research Gallery.
2026-09-25 19:40:03 +00:00
doxa-maps-88655c70
09014f8a03 Rename the output folder to dx-maps
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
Driver decision: no embeddable URL carries "doxa" in its folder. The tree's name is one line in
vite.doxa-maps-build-config.json ("name": "dx-maps"); everything else follows it.

- __DOXA_TREE_NAME__ (the vite define rega landed, from MFE_NAME = internal/_tree-name.mjs) bakes the name into the
  bundles for the runtime code that must recognise the tree in a URL. StackLayout.vue's
  resolveBundleSrc anchored on a literal /doxa-maps/ and would have broken every composite's nested
  bundles on a renamed tree; it now anchors on the define. The Research Gallery's dev fallback uses
  it (one reader: rega's define, not a second one).
- The native shells follow via internal/sync-app-shells.mjs: capacitor webDir public/dx-maps, Tauri
  frontendDist ../../public/dx-maps (its window url is tree-relative since the one-folder landing).
- The WordPress contract test reads the name from config instead of carrying three literals.
- check:locale-reachable extracted detectLocale alone and died with "localeFromUrl is not defined"
  after 09d03c60 factored a helper out; it now follows the calls it makes (already red on main).
- generate-tree removes its temp asset pool even when it crashes (a failed build leaked ~50 MB into
  /tmp each time; measured on a full disk).
- Capability exemplars regenerated for the new paths.

Proof: rm -rf public && bun run build -> public/ = README.md + dx-maps/; the 25 built bundles carry
zero 'doxa-maps/' paths (scanned); check:sri, check:drop, check:parse, check:public-hygiene PASS.
Tag names (doxa-* -> dx-*) are the next, separate landing.
2026-09-25 19:26:14 +00:00
doxa-maps-88655c70
652b5a5c95 Integrate main into bundler-2/work
# Conflicts:
#	documentation/README-SECTION-3-cli-commands.md
#	package.json
#	public/doxa-maps/dashboard-plus-grid/dashboard-plus-grid/default/index.html
#	public/doxa-maps/dashboard-plus-grid/dashboard-plus-grid/index.html
#	public/doxa-maps/doxa-maps-spa/manifest.json
#	public/doxa-maps/doxa-research-map/doxa-research-map.js
#	public/doxa-maps/doxa-research-map/research-map/index.html
#	public/doxa-maps/doxa-research-map/research-map/maplibre/index.html
#	public/doxa-maps/index.html
#	public/doxa-maps/manifest.json
#	public/doxa-maps/research-dashboard/research-dashboard/index.html
2026-09-25 18:21:45 +00:00
doxa-maps-88655c70
7965b8dbcd The pin-dim slider works, and it composes with legend dimming instead of fighting it
Dragging the side menu's pin-dim slider changed nothing: it wrote a store field
that did not exist, the same defect as the clustering picker beside it and found
while fixing that one.

The obvious fix would have created a worse bug. The pin layer's circle-opacity
already has an owner — legend dimming writes a ['case', …, 1, 0] expression — so
a flat slider value from a second writer would silently erase dimming, or be
erased by it, depending on which control the reader touched last. Nothing would
have looked broken; the map would just have stopped answering one of them.

So there is now exactly ONE writer and the value is the PRODUCT:

    opacity = slider × (1 for a matched pin, 0 for a dimmed one)

The slider scales the whole layer, dimming still dims relative to it, neither
wins. Seven call sites that each wrote opacity by hand now go through it.

MEASURED, reading the live paint property rather than the store:

    clustering off          1
    clustering on, 0.5      0.5
    + a dimming selection   ['case', <religion is B>, 0.5, 0]
    slider back to 1.0      ['case', <religion is B>, 1, 0]

One thing the gate had to learn, and it is written down in it: a REGION
selection does not dim at all — it sets a layer filter, so non-matching pins are
removed rather than faded. Testing that path would have reported "the slider
erased the dimming" about code that never writes opacity.

★ ALSO: the Globe/Flat control's 24px touch target now applies at EVERY width.
The first fix scoped it to `@media (pointer: coarse)`, reasoning that a mouse
needs no touch floor. Wrong twice: WCAG 2.5.8 is a TARGET SIZE criterion, not a
touch one, and the query meant phones passed at 34px while desktop stayed at
73.5×23 — the same one-pixel failure, now invisible to a phone sweep. Measured
after: 73.5×34 at 390, 430 and 1440.
2026-09-25 18:20:53 +00:00
doxa-maps-88655c70
79bd6d2ac3 public/ is one folder: the output tree plus a README, with the Plugin Studio as its front page
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
Driver decisions (cards BUILD-OUTPUT-IS-ONE-FOLDER, BUILD-PLUGIN-STUDIO-IS-THE-OUTPUT-FRONT-PAGE).

- public/ holds only <tree>/ and a generated README.md. The build no longer writes public/index.html,
  public/assets/ or public/__gallery/; `rm -rf public && bun run build` recreates exactly these two.
- The Plugin Studio is <tree>/index.html (tree-base "."), replacing the staging-forge chooser; nothing
  is written above the tree. check:staging-lang, which tested that chooser, is retired with it.
- Assets are gathered in a temp directory and the fetched allowlist staged into <tree>/assets/ as
  before. fonts/, images/, brand/ and legacy/ existed ONLY in public/assets: they are sources and move
  to data/ (git mv). Poster previews keep their tracked sources in plugin-designs/*/assets/previews
  (all 378 verified present).
- __gallery/ is archived out of public/ (a copy kept in the umbrella's _qa-cycle/archive) and out of
  the build; generate-gallery renders only on request, into a directory you name, never public/.
- Native shells load the output folder: capacitor webDir public/<tree> (cap copy needs an index.html
  there), Tauri frontendDist + window url relative to it. internal/sync-app-shells.mjs keeps both in
  step with the tree's name on every build, so the coming rename stays one config line; the Capacitor
  start page resolves its leaf tree-relative.
- dropin.include now lists only extras (README.md): the tree is always shipped and never named twice;
  excludes are tree-relative ({tree}/...). clean.mjs removes the old root entries from existing
  checkouts; the build lock and public/.gitignore's rules move out of public/.
- check:wp-embed read the BUILT manifest from gates:pre, before the build, so a from-scratch build
  could never pass; it runs in gates:post and reads the tree name from config.
- Stale bundles refreshed by the clean build (key-cities, template-bundle, wall-of-people-groups);
  the CLI doc's quoted scripts re-synced; capability exemplars regenerated; the '#' note leaves
  check:stale-sweep-claim's command (it was already in //scripts).

Proof: rm -rf public && bun run build -> public/ = README.md + doxa-maps/; check:sri, check:drop,
check:parse, check:public-hygiene, check:quoted-scripts, check:capability-exemplars PASS; all 57 pages
(the front page + 56 leaves) mount under /doxa-maps/ on this tree. check:facet-cascade is red as on main.
2026-09-25 17:41:56 +00:00
doxa-maps-88655c70
849cd61022 Make the map's clustering picker real: four options, four different maps
Choosing "Native" in the research map's side menu drew nothing. So did MST, and
so did Network. A control that does nothing is worse than one that is absent:
it tells the reader the map cannot do what it can.

TWO CAUSES, AND FIXING EITHER ALONE WOULD HAVE LOOKED LIKE A FIX.

  1. mapStore never declared `clusteringMode`. The picker wrote to a property no
     reactive system was watching, so useMapClustering's `mode` kept its own
     internal default and the click changed nothing.
  2. The legend's Clusters checkbox force-set 'mst' "regardless of what's in the
     store", with the mode watcher "kept as a no-op for forwards compat" — its
     own words. Even with (1) fixed, one tick of that checkbox would have snapped
     Native back to MST: a control that works until you touch the other one.

So the two controls are now two views of one state. clusteringMode IS the state
('off' means disabled); the picker sets it; the checkbox maps onto it, promoting
only 'off' to 'mst' so the checkbox alone behaves exactly as it always has. They
can no longer show different things. The dim-slider's clusterPinOpacity got a
real home in the same pass, for the same reason it was missing.

★ THE GATE ASSERTS ON WHAT IS DRAWN, NOT ON WHAT IS SET. `clusteringMode ===
'mapbox'` would have passed the moment (1) was fixed, while the map still drew
MST lines — state was exactly the evidence that let an inert control ship. The
map now reports, per clustering layer, whether it exists, whether it is visible
and how many features are rendered; the gate clicks the real buttons and reads
that. MEASURED, before and after, on the same tree:

    before   off 0/0/0   native 0/0/0     mst 0/0/0       network 0/0/0
    after    off 0/0/0   native 37/37/0   mst 0/0/1700    network 0/0/23896
                        (circles/counts/lines)

It also asserts no orphan layers between modes, and that MST and Network differ
— two labels for one behaviour is the same defect as a dead option.

One measurement bug caught on the way, worth recording: a fixed 6-second pause
reported MST as drawing nothing while Network drew thousands of lines. MST over
~2,100 pins is quadratic and had simply not finished. The gate now waits for the
drawing to settle rather than guessing a duration — a gate that calls a slow
feature broken is worse than no gate.
2026-09-25 16:16:46 +00:00
doxa-maps-88655c70
d78a42f2df Integrate 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
# Conflicts:
#	public/doxa-maps/index.html
2026-09-25 12:21:20 +00:00
doxa-maps-88655c70
471bd05cea Stop showing English where the catalogue already holds the translation
A reader on an Arabic page saw a handful of English words among the Arabic:
the table's "People Groups" title, its count line, the Engagement column, the
Gospel Access chart title, and the side drawer's close button. Every one of them
had a correct Arabic entry sitting in the catalogue; nothing looked it up.

THE CHECK CAME FIRST, AND IT REPLACES A SWEEP THAT PASSED A BROKEN TREE.
The old method sorted every rendered string into third-party / data / chrome and
counted only chrome. That split is a guess, and it guessed wrong exactly where
the defect lived: single words like "Region", "Prayer" and "Country" are as
plausible as values as they are as labels, so they scored as data and the sweep
reported zero on a page that was visibly leaking.

check:composite-locale-leaks asks a question with an answer instead:

    the English catalogue holds this exact string as a value, AND
    this locale holds a DIFFERENT value for that key, AND
    the page still renders the English one.

No judgement about what kind of word it is — if the translation exists and the
reader is not getting it, that is the defect. The two surfaces a lookup cannot
judge (vendor map chrome, and table/facet cells carrying API values) are muted
by NAME with a stated reason, never by word, so muting one can never hide the
next real leak that happens to reuse it. The gate failed on this tree naming 9
strings before any of them were fixed.

Also threaded here: both composites now accept `lang` / `locale` in
profile-config and pass it to the children they mount, alongside `tk` and
`provider`. A partner writing {"lang":"ar"} reached nothing before — the knob
was documented and read by nobody.

The prayer facet's label in DashboardResearchFilters is now a catalogue getter
too. Measured before touching it: dashboard.config.js does define prayer_level
and FACETS spreads the config last, so that literal never rendered for this
config — it is a default for a config that omits the facet, and it stays, with
the merge order written down so the next reader need not re-derive it.

Four strings remain English with no catalogue entry at all — "Top countries",
"Select all {n}", the table dock's title, and the singular "group". They need
wording in ten languages that cannot be composed from existing entries, so they
are a DECIDE card for the Driver rather than translations invented here.
2026-09-25 12:16:59 +00:00
doxa-maps-88655c70
a2be2396b9 README: the Experimental shelf, with Wall of People Groups and the Prayer Walk Planner
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
A new "Experimental shelf" section pictures the two newest shelf plugins, each
shot from its own page after it finished loading: the Wall of People Groups
(all 2,107 groups as photo cards on one zoomable prayer wall, 7fec7426) and the
Prayer Walk Planner (full screen from any embed and a sharp HD print,
30e6e569). The Research Gallery tree now lists all seven shelf plugins
(adds pplr-data-maps and wall-of-people-groups). Shots staled by 92a81ed2 and
later rebuilds are retaken.
2026-09-25 11:22:52 +00:00
doxa-maps-88655c70
78efae4eae Integrate main into bundler-2/work
# Conflicts:
#	public/doxa-maps/dashboard-plus-grid/dashboard-plus-grid.js
#	public/doxa-maps/dashboard-plus-grid/dashboard-plus-grid/default/index.html
#	public/doxa-maps/dashboard-plus-grid/dashboard-plus-grid/index.html
#	public/doxa-maps/doxa-maps-spa/manifest.json
#	public/doxa-maps/doxa-research-map/doxa-research-map.js
#	public/doxa-maps/doxa-research-map/research-map/index.html
#	public/doxa-maps/doxa-research-map/research-map/maplibre/index.html
#	public/doxa-maps/index.html
#	public/doxa-maps/manifest.json
2026-09-25 10:20:57 +00:00
doxa-maps-88655c70
16629f4906 Link religion and language between the map and the grid, by the one table they already share
A reader who picks a religion family on the map now sees the grid narrow to the
same peoples, and a language selection travels the same way. Region already
linked; these two did not, because the two halves do not name a religion the
same way and nothing yet proved what the honest translation was.

The map filters religion through its legend's flat tab, keyed by the FIRST
LETTER of the religion code ('B'); the grid filters through a derived axis that
runs library/colors/religion.js forward per row ('BLA' -> 'Buddhism'). One
shared table, read in opposite directions, copied by neither half — so the wire
carries the family NAME and each side resolves it against its own data.

Two measurements changed the design on the way:

  - mapStore.filters.religions, which the map's filter panel writes, is read by
    NOTHING: the mapLayers.applyFilters() it was meant to reach is called and
    never implemented anywhere in the tree. A link routed through it would have
    set state, passed a smoke test and dimmed no pin.
  - the map's legend selections are mutually exclusive by design, so it can
    light exactly one of region/religion/language. The composite mirrors that
    rather than letting the grid hold three facets the map cannot show.

Religion links at the FAMILY and not at the code, deliberately: a map cannot
distinguish 'BLA' from 'BMA' — both dim as Buddhism — so linking at the code
would promise a precision one half cannot keep.

check:linked-vocabulary proves it by measurement rather than by reading: it
compares the total reached over the composite's wire against the total the grid
gives for the same facet on its own (83 of 2,107 both ways), and runs the MUTANT
first — the legend key 'B' instead of 'Buddhism' — failing as NO-TEETH if the
wrong mapping scores the same as the right one. Measured: mutant 0, real 83.

The CLI doc's apk:debug quote was realigned in passing; package.json had gained
app:start-page and the doc still described the older chain.
2026-09-25 10:20:27 +00:00
doxa-maps-88655c70
85bd7ed1e9 README: Simple Research and the Research Gallery join the phone row; stale shots refreshed
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
simpleresearch fixed the phone toast (2221d11b): at 390x844 the "Tap a
coloured dot" prompt now sits above the Progress sheet and the legend reads in
full (checked by eye). The phone row now shows seven maps in two rows of four;
Big Picture keeps its note (desktop by design; on a phone the Research Gallery
opens on Simple Research). Gospel Resources shots retaken after its bundle was
repaired on main (57fecfd0 replaced a bundle committed with merge-conflict
markers in 52ab6089). Other stale shots refreshed from the latest builds.
2026-09-25 10:09:12 +00:00
doxa-maps-88655c70
8e6fde19ae README: the production maps on a phone
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
A row of phone screenshots (390x844, taken after each map finished loading)
under the production gallery: Regions, UPG-100 List, Prayer Progress, Cities
with Internet and Gospel Resources. Big Picture is desktop-only by ruling, and
Simple Research is left out until its phone layout is finished: its "Tap a
coloured dot" prompt still covers the Progress legend at 390px. The README
says both plainly.
2026-09-25 09:12:16 +00:00
doxa-maps-88655c70
fdc2904354 README: refresh all 14 stale screenshots from the latest builds (after the 9dc0e90d tree rebuild)
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 09:05:44 +00:00
doxa-maps-88655c70
2a062c1ca0 README: the 7 production maps up front, one capabilities x deploy table, the library tree and rule
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
- A gallery of the seven production maps (Big Picture, Simple Research,
  Regions, UPG-100 List, Prayer Progress, Cities with Internet, Gospel
  Resources) plus the Research Gallery, each shot from its own standalone page
  after its map finished loading. Five new shot definitions in readme-shots.
- One 5 x 5 table: every capability ships every way (iframe, mobile and JS
  embed today; WordPress and desktop proven, not yet in production).
- The "map cruncher" converge/diverge picture, folded.
- Repository layout shows the plugin-designs and shared library trees, and a
  folded "plugin or library?" section states the rule: write your app in its
  own plugin; put code in the library only if it is reusable and parameterized.
- Stale shots retaken from the latest builds.
Closes the README parts of DOCS-README-FOR-A-VISIONARY and BUILD-README-COMPLETE-HANDOFF.
2026-09-25 08:45:04 +00:00
doxa-maps-88655c70
9b99e7fa9b README: retake all-people-groups (new light map) and the research map from their latest builds
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 07:24:37 +00:00
doxa-maps-88655c70
c096f35023 README: retake the UPG-100 shots after its phone fix (b197055b): one poster per row on a phone again 2026-09-25 07:24:37 +00:00
doxa-maps-88655c70
a78eb4428a README: retake the three prayer/engagement/adoption preset shots from the latest doxa-simple-map build 2026-09-25 07:24:36 +00:00
doxa-maps-88655c70
0c8244aca1 README: retake the UPG-100 shots after its map resize (89bd9c5d)
Shot from the rebuilt bundle at 89bd9c5d, after its owner marked the resize
done, with the wait-for-loading fix: the map shows every region, all 27 zones
and all 2,107 pins; the composite and phone shots show the new banner cards.
The mobile dropdown no longer claims "one poster per row", which the phone
layout no longer is.
2026-09-25 07:24:36 +00:00
doxa-maps-88655c70
f0b1836682 Regenerate the capability exemplars after the merge
The derived table drifted from the manifest when main's bundles arrived — two
rows moved and one fell off the end. It is generated, so the fix is to regenerate
it rather than to hand-edit: 33 rows now match what the build computed.
2026-09-25 06:27:29 +00:00
doxa-maps-88655c70
e7638747f8 README: retake the Research Gallery shot from the latest doxa-maps-spa build
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 05:56:22 +00:00
doxa-maps-88655c70
40750a153e Screenshots wait for the maps to finish loading
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
readme-shots captured on a fixed timer once the page's elements existed, so
maps were caught mid-load: the Big Picture globe came out as a bare white ball
and the UPG-100 map without its resources. Every request is now tracked, and
the capture waits until nothing has been in flight for 4 s (capped at 60 s,
with a warning if the cap is hit), then 1.5 s for the last tiles to paint.

Retaken with the new wait and checked by eye: Big Picture (country shading and
people-group dots on the globe), the research map, the three prayer /
engagement / adoption presets, all people groups, the Plugin Studio and the
iframe host. The UPG-100 shots are deliberately NOT retaken yet: its owner is
still resizing that map.
2026-09-25 05:52:09 +00:00
doxa-maps-88655c70
4314f0e2f6 README for vibe coders: the Goal, pictures first, everything else folded away
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
- The Goal and Isaiah 40:3 lead the README, byte-for-byte as written on the
  public repo (driver-web-edits.patch), so the next export keeps them.
- Each of the 5 capabilities and 5 deployment methods is now a one-line
  summary, its picture, and a collapsed "More about…" dropdown. 16 dropdowns,
  none open by default, so a reader can scroll the pictures and summaries.
- WordPress / Disciple Tools and desktop say what is true in plain words: we got
  a JAMstack map running there; proven, not yet a production feature; the
  Research Gallery could become a strong desktop app. Their cards match.
- The agent-swarm section explains the problem in plain words (one shared
  library and one build means one bad change breaks every map), with a git
  glossary and the commands folded away.
- Get it running now includes your own free Mapbox token (the public copy
  ships without one), and a dropdown on changing the studio itself.
- The diagram has eight plugin nodes, main at the centre behind a padlocked
  merge-queue ring, and a plain-language "How main is protected" strip.
2026-09-25 05:44:14 +00:00
doxa-maps-88655c70
4d773d6ee8 Move internal files out of the repo; fix five dead links; a fuller delegation diagram
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
Moved out (kept outside the repo, in the team's internal tracker):
- AGENT-BRIEF.md: operating rules for the team's own agents
- documentation/slide-deck-outline.md, documentation/README-longform.md:
  internal pitch material; the README and why.md cover the same ground
- plugin-designs/gospel-resources/SOURCES-CHECKED-AND-REJECTED.md: research log
- .claude/ (an editor status line), .forgejo/ (a CI workflow that never ran),
  _archive/ (a retired staging page; already gitignored but still tracked)
Seven code comments that named these files now describe the rule instead.

Fixed five dead links left from the docs/ -> documentation/ move, including
the one in template-bundle that every new plugin inherits.

The delegation diagram now shows the whole model: the Plugin Studio with the
shared library and the merge queue into main, seven production plugins with
capability badges and the Experimental shelf, one agent per plugin (a roaming
agent for the shelf), the shepherd's oversight ring, a legend, and the five
ways a build ships.
2026-09-25 05:14:10 +00:00
doxa-maps-88655c70
8836182db2 README: every deployment method has a picture; current studio screenshot
Some checks are pending
build-gate / build (push) Waiting to run
- Methods 4 (WordPress / Disciple Tools) and 5 (Tauri desktop) get a card with
  the platform's logo and a PROOF OF CONCEPT badge; logos are the CC0 Simple
  Icons marks, credited under the cards. SVG sources beside the PNGs.
- The Plugin Studio screenshot is retaken from the 03:43 studio rebuild, and six
  other shots that rebuilds had made stale are retaken; all checked by eye.
2026-09-25 04:14:54 +00:00
doxa-maps-88655c70
7d4be4e86a Reference: the "I want to…" table first, wrong facts fixed, history to a log
Some checks are pending
build-gate / build (push) Waiting to run
- The quick "I want to…" table moved from the bottom to the top, with
  BUILD_ALLOW=1 and the no-key MapLibre option.
- Wrong facts corrected: `bun run dev` serves the Plugin Studio at `/`, not
  the gallery; the build-config `token` row said "leave empty", the reverse of
  the baked public-token decision; `check:shots` now compares bundle hashes.
- Two table rows stranded after a code block rendered as stray pipes; they
  now sit in the preconditions table they belong to.
- Removed a `cd` into a retired branch folder, platform host names and an
  internal catalog repo name.
- The dated measurements moved to a "Notes and history" log. 7,255 -> 3,719
  words. Every link, anchor and script name checked.
2026-09-25 03:48:26 +00:00
doxa-maps-88655c70
ace9c396ff CLI matrix: one status per method that matches the README; history to a log
Some checks are pending
build-gate / build (push) Waiting to run
The per-method sections now lead with install + commands + the one thing that
matters, and the dated measurements move to a "Notes and history" log at the
end. Statuses match the README: iframe and JS embed production, mobile built,
WordPress/Disciple Tools and Tauri proofs of concept. The Tauri artifact sizes
disagreed within the doc (67/60 MB vs 65/58 MB); the log records both runs.
The package.json scripts block that check:quoted-scripts compares is untouched.
2,590 -> 1,922 words.
2026-09-25 03:31:05 +00:00
doxa-maps-88655c70
08dca05f63 Golden path: a six-step table first, the incident notes in a log at the bottom
Some checks are pending
build-gate / build (push) Waiting to run
The first doc a DX developer follows now opens with one table (what you do,
the command, what "done" looks like), then one short section per step with
its command. The nine dated measurement notes move, unabridged in substance,
to a "Notes and history" log at the end. 2,612 -> 1,501 words.

Also corrected two stale facts: the deployment status table now matches the
README (WordPress and Tauri are proofs of concept; mobile is built), and the
Experimental shelf is described as it works, not by a 2026-09-21 row list
that no longer matches.
2026-09-25 03:29:39 +00:00
doxa-maps-88655c70
8415e8e112 README: clone the public repo; no links the giveaway export deletes
Some checks are pending
build-gate / build (push) Waiting to run
- The clone line pointed at the private source repo. It now clones the public
  giveaway, doxa-open/doxa-maps, which clones anonymously (checked with
  ls-remote and no credentials), so a DX newcomer can onboard from the README.
- The README linked AGENT-BRIEF.md, which the giveaway export removes; it now
  points to documentation/CONTRIBUTING.md.
- README-longform's two SPA images were written relative to the wrong folder
  and rendered broken; fixed.
2026-09-25 03:27:17 +00:00
doxa-maps-88655c70
cbbebffb95 Docs: every build line a reader copies now carries BUILD_ALLOW=1
Some checks are pending
build-gate / build (push) Waiting to run
The build refuses (exit 75) without BUILD_ALLOW=1, so a DX developer
following the tutorial, the golden path or the CLI matrix hit a refusal on
the first build. The eight runnable lines now include the flag, and the
golden path says why it exists and how to build one plugin without it.
Also: the golden path said "From doxa-maps-plugin-studio/", a retired branch
name; a clone lands in the repo root.
2026-09-25 03:07:52 +00:00
doxa-maps-88655c70
ff0be67bca README: name what is on the Experimental shelf; retake eight stale shots
Some checks are pending
build-gate / build (push) Waiting to run
The Research Gallery tree said only "every other bundle". It now lists the
five the shell actually shows today, in its own order: prayer-walk-planner,
upg-neighbor, all-people-groups, country-posters, doxa-vision-card
(22 bundles - 7 curated tabs - 10 in NOT_EXPERIMENTAL).

Eight screenshots were shot from bundles that have since been rebuilt;
retaken from the current build and checked by eye.
2026-09-25 03:05:09 +00:00
doxa-maps-88655c70
66519288dc README: UPG-100 is the mobile app, shot at its owner's "ready at 88a566f"
Some checks are pending
build-gate / build (push) Waiting to run
Deployment method 2 now shows the UPG-100 prayer lists and posters at phone
size: one poster per row, print options wrapping in full. Shot from the
rebuilt bundle at 88a566f, not from source. The capability-4 shots are
retaken from the same build, so they show the print-option fix too.
2026-09-24 22:03:50 +00:00
doxa-maps-88655c70
bf7fc46dcd check:shots compares bundle content, not dates; retake the stale shots
Some checks are pending
build-gate / build (push) Waiting to run
A retake that came out byte-identical left the PNG unchanged, git dated it by
its old commit, and the gate called a correct, just-taken picture stale. No
clock can see that case. readme-shots now writes shot-bundles.json (shot ->
sha256 of the bundle it was taken from), and check:shots compares that hash
with the bundle built now; dates are only the fallback for unrecorded shots.

Negative-tested: one byte appended to the doxa-simple-map bundle fails exactly
the three cap2 shots; restoring it passes.

Also retook the eight shots a rebuild had made stale since e2beec9.
2026-09-24 21:54:08 +00:00
doxa-maps-88655c70
e2beec9a11 README: reshoot the Plugin Studio at f63d75e — the Explorer-tree rail
Some checks are pending
build-gate / build (push) Waiting to run
readme-shots now clicks the rail's first plugin row (.st-row[role=treeitem],
not a section heading), keeping .vtl-tab as a fallback. Without that, the walk
fell through to the nested gallery's own tabs.
2026-09-24 21:42:37 +00:00
doxa-maps-88655c70
d5aaa900e6 README: reshoot the Plugin Studio at 0740a94 — folding rail, Research Gallery first
Some checks are pending
build-gate / build (push) Waiting to run
Shot from the rebuilt studio bundle the studio agent marked stable (0740a94),
not from source: the redesign was on main for half an hour before its bundle was.
2026-09-24 21:14:35 +00:00
doxa-maps-88655c70
53308c546c Delegation diagram as rings of circles; stop showing Simple Research as the mobile app
Some checks are pending
build-gate / build (push) Waiting to run
- The diagram is redrawn as concentric rings of uniform circles, not filled
  bands: the Plugin Studio ring labels itself, the seven plugins sit on the
  plugin ring, one agent per plugin sits outside it joined by a line and an
  arrow ("each plugin has one agent responsible for building it"), and one
  shepherd sits outside the agent ring. The race framing is gone. SVG source
  updated with the PNG.
- Deployment method 2: Simple Research was never built for phones, so it is
  no longer the mobile example. UPG-100 is; its screenshot lands when its
  phone layout is finished. The shot is removed from readme-shots, with the
  reason and the planned replacement in a comment.
- Retook nine screenshots that the latest bundle rebuilds had made stale.
2026-09-24 21:08:52 +00:00
doxa-maps-88655c70
c276a2158e Gate the embed contract: a composite must pass tk and provider down
Four elements shipped with this broken and nothing could see it, because every
existing gate loads a composite on its OWN generated leaf — and that leaf bakes a
token and assigns window.MAP_TOKEN, supplying the very thing under test. The
failure exists only where there is no leaf: the partner page the published embed
snippet is written for.

The gate serves the built tree on one free port and a partner page on another, so
CORS is exercised rather than assumed, and asserts per composite:

  tk        given only {"tk": <the token this tree bakes>}, a canvas appears and
            api.mapbox.com actually serves it
  provider  given only {"provider":"maplibre"} and NO token, a canvas appears and
            there are ZERO requests to api.mapbox.com

Zero is the assertion, not "it rendered": a build that quietly fell back to
mapbox with a baked key renders perfectly and is exactly the regression this
exists to catch.

★ IT FAILS ONLY WHERE THE EVIDENCE POINTS AT THE KNOB. The first draft failed
NINE composites for "no map canvas under a minimal config" — an accusation it had
not measured, since several of those elements simply need a `profile` key to
choose which profile to show. It now distinguishes: a token WAS supplied and the
element still says there is none, or maplibre was asked for and mapbox tiles
still loaded — those are findings. No canvas and no complaint is UNMEASURED, and
says so with the reason. A gate that red-lights other people's plugins over a
claim it cannot support is worse than no gate.

COST, because a slow gate stops being run: a flat 14s-per-case wait became a poll
for the canvas, and the provider case short-circuits when that element's tk case
drew no map — there is nothing to compare against, so a second page load was pure
waste. 5m38 -> 3m15.

GREEN on the landed tree: dashboard-plus-grid, research-map-plus-grid, stack-demo
and plugin-studio all pass both knobs, every provider case at ZERO api.mapbox.com
requests. plugin-studio only reached zero once the cap-5 shell started setting
window.MAP_PROVIDER — profile-config alone reaches the child a composite writes
config for, while the global rung reaches a map nested at any depth, which the
studio-inside-SPA-inside-composite chain needed.

gates:post is 44 steps; the quoted CLI doc is updated to match.
2026-09-24 20:26:33 +00:00
dx-shepherd
0eb3390375 Regenerate capability-exemplars table (stale after legacy bundle; unblocks check:capability-exemplars) 2026-09-24 19:58:17 +00:00
doxa-maps-88655c70
d1fc658de4 README: screenshots first — one per capability, three deployments shown live, the studio last
Some checks are pending
build-gate / build (push) Waiting to run
- The five capabilities each lead with a current screenshot; the Research
  Gallery's composition tree folds into a <details> block.
- Deployment: (1) the prayer map in a host page's iframe, (2) the Simple
  Research dashboard as the phone app, (3) the whole Research Gallery
  JS-embedded on dx-life's research page. WordPress/Disciple Tools and Tauri
  are stated as proven proofs of concept, not production-ready.
- The Plugin Studio closes the README with its current screenshot, the
  four-command start and the command table.
- 4,151 -> 1,330 words. Every image retaken against the current build.
- readme-shots: deploy2 shoots research-map-plus-grid at phone size; deploy3
  shoots a running dx-life (DXLIFE_URL=...), skipped when it is not set;
  an http(s) path is used as-is. Retired four images nothing shows any more.
2026-09-24 19:55:24 +00:00
doxa-maps-88655c70
7ae1572c94 poster cards: the print-options row stays inside its own card
Some checks are pending
build-gate / build (push) Waiting to run
The repo-hygiene agent found this in a fresh 1440px screenshot, which is the
whole lesson: .pfs already had width:82%, so reading the CSS said it was fine.
Flex items default to min-width:auto and refuse to shrink below their content
width, so four controls — Prayer List, Card Deck, the stock select, Poster Map —
pushed the row open regardless of what the container declared. A constrained box
does not constrain flex children, and only geometry shows that.

Measured at 1440px on cap4-upg100-mfe: 27 of 27 cards overflowing, worst 110px
past a 212px card, 36 intrusions into a neighbouring card's box. After
flex-wrap:wrap plus min-width:0 on the children: 0 and 0, with all 108 print
controls still a usable size.

That second number is asserted deliberately. "Nothing overflows" is trivially
satisfied by a row whose buttons collapsed to zero width, which would be a worse
product than the overflow it replaced. check:poster-card-fits holds both, and is
mutation-tested: reverting the fix reproduces the reporter's exact figures.

Also adds check:backlog-refs — a card may not depend on a card that does not
exist, because a dangling depends_on can never be done, so the card can never
become ready and nothing says so.

Its first run disproved the finding that motivated it. I had censused three
dangling references, including the PRINCIPLE card the loop prompt lists as open
work. The gate came back PASS, and chasing the discrepancy rather than assuming
the gate was broken showed my census was wrong: it read only the builder
backlog, and all three cards exist in 01-ideation-research. Cross-phase
references are legitimate, and a single-backlog census structurally cannot see
them. Reporting three dangling refs would have sent someone hunting for cards
that were never lost.

It fails only for depends_on on an OPEN card; a dangling parent is reported and
passes, because failing on filing debt teaches people to delete the reference
rather than restore the card. Both severities mutation-tested.
2026-09-24 19:19:02 +00:00
doxa-maps-88655c70
6ab560e42f Merge remote-tracking branch 'origin/main' into rega/research-gallery-embed
Some checks are pending
build-gate / build (push) Waiting to run
# Conflicts:
#	public/doxa-maps/index.html
2026-09-24 19:06:54 +00:00
doxa-maps-88655c70
3a2cf0e8f2 Research Gallery: embed on someone else's page, in both modes
The gallery is going onto the DX-life research page, and nothing had tried
it on a page it didn't generate. From a second origin, a bare
<script> + <doxa-maps-spa> drew over the host's header, and 8 of 13 tabs
showed an error card.

Three causes, each fixed in the shell:

- No :host box. The layout root is position:absolute, so it anchored to the
  viewport instead of the element. :host is now a positioned block with a
  default height the host can override.
- A foreign page sets none of the globals a leaf page bakes. Every data call
  hit the host's own origin and got HTML back. The manifest now publishes a
  `runtime` block (apiBaseUrl + the public token every leaf already carries).
  The shell fills window.MAP_APP_API_URL / window.MAP_TOKEN only when the page
  hasn't set them, and forwards tk in profile-config.
- Nested elements resolved assets to <tree>/../assets, a sibling pool the
  publisher doesn't ship (404 live). The shell now forwards an absolute
  <tree>/assets. This also fixes the iframe mode, where Cities with Internet
  and Gospel Resources were failing the same way.

Also adds a `tab` attribute (plus ?tab=) to deep-link into one map, and a
`tab-change` event for the host.

check:gallery-embed drives every tab in both modes from a second origin. It
passes here and fails on the previous tree (7 findings).

EMBED.md documents the contract. The Traefik template now sends CORS for the
whole tree: live manifest.json answers without Access-Control-Allow-Origin.
2026-09-24 19:03:37 +00:00