Commit graph

20 commits

Author SHA1 Message Date
Doxa Maps
f9c621c647 The root build files keep the reason and drop the speaker
package.json's gate descriptions, vite.config.js, the build config's
comment keys, capacitor.config.json and .gitignore named or quoted the
Driver in 13 lines. They sit outside check:no-new-driver-references'
areas, but they ship in the giveaway all the same, so they are reworded
the same way as the sweep. The two left are the reference gate's own
description, which has to say what it checks.
2026-09-29 08:11:49 +00:00
Doxa Maps
867c559095 One server for a site and its maps: bun run dropin, and the drop-in goes straight into the site's public/
The drop-in was proven on a laptop with one server: the three DX Life branches rendered their maps,
7 of 7 checks passed, with internal/sync-dropin.mjs --from-config --dest <doxa-life>/public. This
makes that the default path:

- dropin.dest is ../doxa-life/public. The old ../doxa-life/public/embed/doxa-maps-build was stale.
- bun run dropin = sync-dropin --from-config; deploy:dev (build + drop-in) now uses it.
- The README gains "The easiest path": the studio for the work, dropin.dest at your site's public/,
  then build and drop in.

One hazard came with the new destination, and it is closed here. --prune deletes every file in the
destination outside the drop-in's allowlist, which was right while that was a folder of its own. Into
a site's public/, it would delete the site. deploy:dev passed --prune, so it no longer does, and
sync-dropin refuses --prune into any folder named public/. Measured in a scratch site: --prune into
site/public exits 1 with the reason; a plain drop-in copies dx-maps/ and leaves the site's own
file in place.
2026-09-29 03:03:51 +00:00
Doxa Maps
e57f64b64b The prayer packet prints its map: the dx-maps tree ships the 28 poster sources
Page 1 of every UPG-100 prayer packet is the zone map, drawn from
<tree>/assets/posters/<id>.html. The tree shipped no posters/ at all:
generate-tree gates the folder behind posterSources and bundlePosters, both
default false, so the fetch 404'd and the packet, which rightly keeps printing
without its map, printed page 1 blank.

The dx-maps config now sets posterSources: the 28 sources, without the 41 MB of
.webp rasters. Measured: 27 MB raw, 7 MB gzipped. The copies are byte-identical
to the tracked data/posters/*.html, so git stores each blob once and a push adds
no new pack bytes. The code default stays false for other deployments.

check:poster-print-fallback now RUNS by default instead of skipping. Part 1 needs
no browser and runs in every wave: when the config ships sources, the built tree
must carry every data/posters/*.html, byte-identical (a stale copy prints an old
map just as quietly). It FAILs 28 of 28 on the tree before this change and PASSes
after. Part 2 clicks the real print control and is NOT MEASURED (75) outside the
browser slot; with no url it serves this checkout and opens the UPG-100 wall. The
skips that exited 0, which a wave reads as a pass, now exit 75. Registered in
gates:post.
2026-09-29 00:59:13 +00:00
Doxa Maps
f13075b1d4 Decouple the tooling: no host named in internal/ or the build config
Six tools defaulted to the live host's URL. They now read the published tree's location from
DOXA_PUBLISHED_BASE (environment, or the gitignored .env / .env.local) through internal/_published-base.mjs,
and with nothing set they report NOT MEASURED (exit 75) instead of measuring a host they were never told
about: check:catalog-currency, check:catalog-identity, check:published, verify:5-caps, verify:map-paint. An
explicit BASE / --base / PUBLISHED_BASE still wins. check:embed-base only needed an example URL for its
offline resolution table.

The public-hygiene leak detector builds the platform name from parts, so the file that catches it does not
carry it. Comments and the two build-config notes say the host platform or the live test host. From
repo's DECOUPLE round 2 list.
2026-09-27 01:16:50 +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-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
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
ce46d92998 Composite pages hand a ?tk= or pasted token to their nested maps, and ask when there is none
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
A composite's nested Mapbox maps read window.MAP_TOKEN, not the page's
profile-config. In a tree with no baked token (the public copy), the token-free
research-map-plus-grid page mounted before reading ?tk= or a stored token, so
its map stayed blank with no prompt. Now every leaf publishes the token it
resolves to window.MAP_TOKEN, and a token-free composite with no token renders
its content plus the paste-once prompt, then reloads with the token.

Verified in a browser against a tree regenerated with no token:
  research-map-plus-grid  no token: prompt shown | ?tk=: map drawn, Mapbox 6 OK / 0 errors
  dashboard-plus-grid     no token: prompt shown | ?tk=: map drawn, Mapbox 6 OK / 0 errors
Negative control (unpatched generator): research-map-plus-grid with ?tk= never
received the token (0 Mapbox requests) and showed no prompt without one.

Also: removed a personal health note the page template wrote into every leaf
page, and the Mapbox account names from three comments. Pages regenerated on
the latest main; nested-token, sri, hygiene, drop, parse, embed-targets pass.
2026-09-25 05:35:46 +00:00
doxa-maps-88655c70
38a7dbb939 Land the swarm's work: no iframes anywhere, a tree that keeps its shape, deeper facets
Some checks are pending
build-gate / build (push) Waiting to run
Checkpointing thirteen files of agent work that were sitting uncommitted while three
agents wrote to a live tree the Driver was watching through hot reload. Uncommitted work
is work at risk, and a tree being edited under an observer oscillates between states that
look like regressions and are really just partial saves.

The second capability-5 shell now mounts its tabs as real elements too, so no iframe
remains in either shell. It was the last holdout: eight tabs, all iframe mode, each
pointing at a hardcoded built-tree leaf that does not exist under the dev server.

The facet rail keeps its shape when a filter narrows it. Selecting one place took the
rail from sixty-six rows to twenty-one — forty-six rows deleted, none dimmed — so the row
a user was about to click vanished under the cursor, which is what "the buttons went
dead" actually was. Rows whose count falls to zero are now re-admitted at their original
slot and depth, dimmed and inert, which also restores the component's own promise to lose
nothing against the tree it replaced.

Expanding a branch and filtering by it are now separate, visible affordances: the whole
row filters, and expand is a real button with its own hit area and label. Rows that were
never clickable are unmistakably inert rather than silently ignored.

Three more facet axes reach the grid — affinity bloc, engagement status and primary
language — each verified to share a field with an existing prop rather than being mapped
on name resemblance. Two derived facets remain unmapped on purpose: they have no matching
row field, and mapping them would filter confidently to the wrong rows.
2026-09-22 14:51:52 +00:00
doxa-maps
1b6316a699 Bake a Mapbox token that is not URL-restricted, so basemaps actually paint
Some checks are pending
build-gate / build (push) Waiting to run
The Driver's report was exact: the pins load and the underlying map does not —
a grey field with data floating on it. That is the URL-restriction signature. The
baked token was scoped to doxa.life, so tiles returned 403 from nuxtbase.app,
from localhost, and from a bare origin, while the style document returned 200
everywhere. The map therefore booted, drew every dot, and showed no basemap.

The Driver supplied a token with no URL restriction. Measured side by side: it
serves tiles 200 with no Referer, from nuxtbase.app and from localhost, where the
previous one returns 403 in all three cases.

Also empties tokenUrl. It pointed at the endpoint that serves the restricted
token, and that endpoint sits above the baked token in the ladder — leaving it
set would fetch the broken token at runtime and overwrite the good one.

All 43 leaves rebuilt and carry the new token; none carries the old one. Verified
in a browser with no Referer sent, the way a real visitor arrives: nine of nine
tile requests returned 200.

This unblocks the interoperability work, which could not be judged while the map
underneath was blank.
2026-09-22 11:15:00 +00:00
doxa-maps-88655c70
3542a5bfc7 bake the public Mapbox pk so every map works out of the box
Driver 2026-09-21: 'all the maps need to have their mapbox token wired
properly according to the references - all the maps are not working yet until
that fix', then 'all maps can use the pk from the api, no problem - if they
want to set a mapbox sk they can'.

Every leaf already implemented a 6-rung token ladder; rungs 1-3 are used
directly with NO network call. On nuxtbase.app rungs 4-6 all failed: the
same-origin /api/maps/token 404s and the absolute doxa.life fallback sends ZERO
CORS headers. Rungs 1-3 were unset, hence 'No Mapbox access token provided' at
dashboard-plus-grid.js:605.

Setting build-config.token (rung 3) inlines the key into all 26 leaves, so a
map works on ANY host with no endpoint and no CORS.

This required splitting the hygiene rule, which lumped pk with sk/tk. A pk. is
a PUBLIC key: designed to ship in client code and protected by URL
restrictions, not secrecy (measured - the same pk. serves tiles 200 with a
doxa.life Referer and 403s with nuxtbase.app). Flagging it made rung 3
unbuildable, since that gate runs inside build:unlocked. sk. and tk. remain
flagged and were negative-tested: sk CAUGHT, tk CAUGHT, GitHub PAT CAUGHT, pk
allowed.

Verified: full build ALL GUARDS PASS, hygiene clean, SRI consistent across 58
leaf pages; 26 of 26 leaves carry the baked pk; and three maps mount with NO
token supplied by the harness - 0 'no token' errors.
2026-09-21 22:47:43 +00:00
swift-river542
b7d91e9aca Public data ships without working notes; unused data files stay out of the drop-in
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
- data/ tables and the people-groups file: meta blocks reduced to provenance (source, url,
  downloaded, rows, grain, attribution); the link-verification table keeps only state and detail
  per link; generators write the same shape
- dropin.exclude in the build config: people_groups.csv, open-doors.json, platform-reachability.json
  and tables/index.json are not shipped (nothing loads them); sync-dropin honours it
- public-hygiene --strict flags note-style meta keys in shipped data
- Rebuilt bundles and gallery
2026-09-16 20:16:08 -05:00
swift-river542
60ad81bf5f Drop-in destination declared once in the build config (dropin.dest); sync-dropin and deploy:dev read it, DOXA_DROPIN_DEST overrides
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-16 19:20:23 -05:00
swift-river542
12d1fee133 Public build folder is three entries: index.html, assets/, doxa-maps/
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
- index.html is generated by internal/generate-spa.mjs from doxa-maps/manifest.json: one
  self-contained page that lists every bundle, profile and instance, mounts the chosen one,
  and offers Open page / Copy embed; build ends with `bun run spa` (the material shell is no
  longer installed; nav.js, icons.js, languages.js, pane-wrapper/, external/ and _headers
  leave public/)
- The website drop-in follows the same contract: dropin.include in the build config,
  sync-dropin --from-config --prune, public-hygiene --strict fails on any other root entry
- Production bundles no longer carry CSS comments: a build-only Vite plugin strips them from
  every shadow-style block (about 140 per map bundle, 5% smaller); remaining comments reworded
- Share pages and the pin renderer drop their note-style comments
2026-09-16 18:23:14 -05:00
swift-river542
a876e5e97b Host-agnostic share links, token-endpoint chain, dev playground as reusable modules, share/asset gates, validated profile-type vocabulary
- ShareButton resolves its link from where the bundle is hosted (profile-config.shareUrl ->
  embedBaseUrl -> window.MAP_EMBED_BASE_URL -> the bundle's own script URL); profiles pass
  tree-relative embed pages, so links work in the playground, on doxa.life and on any CDN
- Generated leaf pages try token endpoints in order (override -> configured absolute URL ->
  same-origin) and only then offer the paste-once box; build config points at the canonical
  https://doxa.life/api/maps/token
- Dev playground extracted from vite.config.js into internal/playground/{discover,render,dev-plugin}.mjs;
  serves /assets/* like the built site so data-driven maps initialise; passes assetsBase +
  shareUrl to every element; header ladder with a Start-here primer and the five kinds of
  mounting files (single-element, preset-element, multi-view-element, composite-element, app-shell)
- New gates: smoke:playground (every element boots, with status text + data diagnostics),
  smoke:share (Share URL resolves and reopens the same map), sync:dropin (mirror public/ into a
  host checkout, never credentials), deploy:dev (build + sync)
- MapToolbar + ShareButton on every map profile; UPG-100 composite (map + prayer lists) on the
  pane layout; shared --map-radius token consumed by the legend components
- docs/reference.md: profile types table, profile-config assetsBase/shareUrl/embedBaseUrl, gates
2026-09-16 12:10:38 -05:00
doxa-maps
9c521f11d5 Public builds carry zero platform surface + copy-embed on staging
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
- Compile-time gate __DOXA_QA__ (default off): the QA corner and every string
  it carries are dead-code-eliminated from public bundles; platform builds
  opt in with DOXA_QA=1. Shell QA becomes ?qa=1 opt-in. Audit: zero platform
  strings across all bundles + shell.
- One Mapbox wordmark per page (first live map claims it; released on destroy).
- Coach-mark points at the need: 'Tap a red dot — someone still needs prayer.'
- Pray-click glow: locally-prayed groups render as Has Prayer for that visitor
  (localStorage, 7-day TTL) — lasting glow comes from the real signup via the API.
- Staging forge gains 'copy embed': snippet built at click time from
  location.href, so it carries the FULL URL of whatever host serves the tree.
2026-09-16 05:13:44 +00:00
doxa-maps
24b315afdd feat(qa): bake QA corner widget onto generated embed pages (go-base plugin surface)
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions
generate-tree now honors a qaWidget build flag (default true) and merges qa:true
into each generated embed page's profile-config, so standalone map plugins opened
in go-base show the QA corner widget too — not just the SPA. Partner embeds use the
copy-embed snippet with their own config, so they are unaffected. Opt out with
qaWidget:false in vite.doxa-maps-build-config.json.
2026-09-14 21:50:24 +00:00
doxa-maps
63bc1d77c1 feat(staging): gate profiles out of the generated tree (governance) + clean all-bundles staging
Some checks failed
Deploy to GitHub Pages / build (push) Has been cancelled
Deploy to GitHub Pages / deploy (push) Has been cancelled
Add a gatedProfiles config field (default [key-cities]) honored by the tree
generator: a gated bundle's .js still BUILDS via vite, but it never appears in
the staging root, the per-bundle staging pages, or manifest.json — the surfaces
generate-tree emits. This makes key-cities gated in ONE place for every surface
(convert.py already gates the go-base plugin index), instead of relying on the
box-side converter alone. The staging root now shows all 9 bundles + their
elements with no key-cities leak.
2026-09-13 00:52:24 +00:00
doxa-maps
30a516a6a3 feat: apiBaseUrl as a first-class build-config field — every generated page bakes window.MAP_APP_API_URL (default pray.doxa.life); one knob to hot-swap to the self-hosted campaigns-server on go-base later, no code change
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-12 03:15:36 +00:00
doxa-maps
d5ba21fa76 doxa-maps — portable bundler for embeddable JAMstack maps
Standalone repo that builds embeddable JAMstack map bundles (web components),
composes them into a lazy-loaded SPA via layouts/, and optionally wraps a
Capacitor Android/iOS app — one build, choose your output/CDN. Diátaxis docs.

History reset to a single clean commit; no PII, IPs, or internal terms.
2026-09-10 01:53:07 +00:00