Commit graph

31 commits

Author SHA1 Message Date
Doxa Maps
d314c44043 internal/ keeps the reason and drops the speaker: no gate quotes or cites the Driver
Every reference to the Driver in internal/ is reworded the same way as in
library/: the reason stays, the speaker and the quote go, an open decision
reads "provisional, pending a product decision", and agent names and decision-
sheet rows are dropped. Where a gate printed the word, its message now names
the reviewer or the ruling instead.

Three spots were code, not comments, and changed with their callers:
- the element census's allowlist field `driver` is now `ruling`, in the gate
  and both presets (same validation: match, ruling, date and card required);
- check:i18n-never-translated's DRIVER-GATED marker is DECISION-PENDING, in
  the entries and in the regex that counts them (its output is otherwise
  byte-identical);
- the package.json description of the census says "ruling".

public-hygiene-check keeps its two patterns for the word: they are what keep
it out of the served folder.
2026-09-29 05:26:25 +00:00
Doxa Maps
fbc517c94a A browser gate refuses to launch outside the browser slot; check:browser-gates-guarded keeps it that way
Only the browser seat runs browsers, and only inside internal/browser-slot.sh.
That rule was remembered, not enforced: an agent ran a gate it took for a
headless source check and it launched Chromium outside the slot.
internal/lib/playwright-guarded.mjs is now the one way a repo file reaches
playwright: its launch(), launchPersistentContext(), launchServer(), connect()
and connectOverCDP() exit 75 (NOT MEASURED) with a message naming
browser-slot.sh unless DOXA_BROWSER_SLOT is set, and browser-slot.sh exports it
for the command it runs, so a bash -c grandchild inherits it. All 72 files that
imported playwright switch to it (internal/lib/browser.mjs and 64 internal gates;
plugin-designs scripts: doxa-research-map 3, my-upg-100-list 2,
research-map-plus-grid 2, research-dashboard 1): a mechanical import swap.
check:browser-gates-guarded (gates:pre) fails a direct import;
bun run browser-gates lists the 97 scripts that launch a browser. isBrowserGate
moves to internal/lib/browser-gates.mjs so the runner and the check share it.
2026-09-28 08:20:21 +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
9c683f1310 README shots wait on the map, not a clock: style + tiles loaded and our layers actually drawn (cap 60 s)
A fixed 7 s wait shot the upg-100-list counter over a bare basemap: that leaf paints 9.5-16.5 s after
load (rega, 3 cold loads at fc2fa2e4). Every map a shot's page or frames create is now recorded (an init
script on the engine global's Map.prototype.setStyle, as in rega's probe), and the capture waits until
every visible map has its style and tiles loaded and has drawn features on OUR layers (GeoJSON sources;
the basemap's are vector tiles), capped at 60 s with a WARN naming the unready map. Each shot's `wait`
becomes a 3 s floor, and the full fallback for a surface with no map. Not browser-run here (browsers are
rega's): the next shot run is the proof.
2026-09-26 08:39:54 +00:00
Doxa Maps
3113344e6a readme-shots: wait 20 s for the UPG-100 list leaf, which paints at 9.5-16.5 s (its counter shows before the paint)
rega measured it at fc2fa2e4 (3 cold loads, tokenless, judged by rendered features on the leaf's own
layers): first paint +9.5 to +14.3 s, idle +12.1 to +16.5 s. The 7 s wait then network-quiet plus
1.5 s made the English shot a coin toss; the Arabic shot of the same leaf (12 s) only won it. Both go
to 20 s. A stopgap: the lasting fix is to wait on the map (style + tiles loaded, rendered features)
rather than a timer.
2026-09-26 08:39:53 +00:00
Doxa Maps
0ca857ff08 readme-shots: tokenless by default, so the README shows the MapLibre look keyless embeds get
The engine default is now auto (c8fee416): no token means MapLibre, which is what every keyless
partner embed shows, and the Driver wants the README pictures to show that. The script no longer
reads a baked token or fetches doxa.life's, and appends no ?tk=. SHOTS_WITH_TOKEN=1 restores the
old token ladder for Mapbox shots.

Checked headless: vite.doxa-maps-build-config.json tokenUrl is empty and the in-process server has
no /api/maps/token, so a leaf's token ladder ends empty and generate-tree's auto branch mounts
MapLibre with no warning banner (TOKEN_FREE, no 'Token fetch failed' text). node --check passes.
2026-09-26 04:38:13 +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
44ef31b2c6 Tooling reads the tree's name from the build config, in one place
The output tree's name has always been configurable (vite.doxa-maps-build-config.json "name"),
but 61 tooling files ignored it and hardcoded 'doxa-maps' (181 literals), so a rename would have
moved the build while the gates kept reading the old folder.

- internal/_tree-name.mjs reads it once (validated as one URL-safe path segment; falls back to the
  historical name) and exports TREE_NAME / TREE_NAME_RE; `node internal/_tree-name.mjs` prints it
  for shell scripts.
- A codemod rewrote 171 literals in internal/ to TREE_NAME; the regex literals, messages with
  backticks, atomic-public-swap.sh (fails loudly if the name cannot be read), build-lock.sh and
  vite.config.js (its duplicate readMfeName is gone) were done by hand.
- The name is unchanged: old and new tooling produce all 1408 files under public/ byte for byte.
  Code lines still naming the tree in internal/ + vite.config.js: 2, both intended (the helper's
  fallback, the private-repo-name pattern in public-hygiene-check).

This renames nothing visible; the eventual rename becomes a one-line config change.
2026-09-25 16:25:22 +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
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
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
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
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
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
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
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
c46a9a04bd README: lead with the objectives, showcase the Research Gallery, teach the agent swarm
Some checks are pending
build-gate / build (push) Waiting to run
- Opens with what dx-maps is for: seven objectives, each paired with the gate
  or section that proves it is met.
- New Research Gallery section: the cap-5 app shell and the tree of cap-4..1
  plugins it nests, each still independently embeddable.
- Plugin Studio: clone main (the old branch was 198 commits behind), a command
  table, and a fresh studio screenshot (the old one showed a retired nav and
  tofu icons).
- Agent swarm: renamed to industry terms (trunk-based development, merge queue,
  maintainer), a laptop recipe (worktrees, strict ports, one builder, flock as
  the queue), and a redrawn diagram whose inner ring is an actual queue with
  one gate. SVG source committed next to the PNG.
- MapLibre is now described as it is: a one-prop, token-free engine.
- Removed internal credential/push instructions (AGENT-BRIEF.md covers agents).
- documentation/: fixed 19 dead links left by the docs/ move, removed internal
  references, and listed the working docs in the index.
- readme-shots: ONLY=<name> retakes a single image.
2026-09-24 18:34:02 +00:00
doxa-maps-88655c70
bd504063a1 Shoot the README with the token the bundles ship, and make the fidelity gate ask
Two related fixes, both about a measurement that had outlived the thing it
measured.

The shot harness fetched its Mapbox token from doxa.life/api/maps/token on every
run. That token belongs to the Mapbox account `doxalife` and is URL-restricted
to doxa.life, which is why the harness also had to spoof a Referer header to get
any tiles at all. Meanwhile the built bundles carry a different token entirely —
`gosystems`, baked in from vite.doxa-maps-build-config.json — and that one is not
restricted. Measured with no Referer: mapbox-streets-v8, country-boundaries-v1
and bathymetry-v2 all return 200 on the baked token and 403 on the fetched one.
The harness was doing extra work to use the weaker of the two.

It now reads the build config first and keeps the fetch as a fallback. Beyond
simply working, a README image is evidence about the SHIPPED artifact, so it
should render with the credential the artifact ships with; rendering with a
different token means the picture stops proving what a reader downloads. The
local read is also deterministic — the network path degraded silently, setting
the token to empty when doxa.life was slow, after which every shot was taken
token-limited and still written to disk.

check:shot-fidelity had the same problem one layer up. It fired its tileset
findings whenever any file referenced a mapbox:// tileset, and printed
"Referer doxa.life -> 200 · 127.0.0.1 -> 403 · no referer -> 403" as though it
were a live reading. It was one, on 2026-09-21, against the token that shipped
then. After the token swap in 1b6316a the sentence kept printing — warning about
a blank void while the shots came out fully painted. A gate that states a
measured fact has to re-measure it, or it becomes a confident lie at exactly the
moment someone fixes what it describes. It now fetches one real tile with the
baked token and no Referer, and suppresses the tileset findings when that
returns 200.

Network failure is deliberately not treated as a restriction. An offline box
cannot tell "restricted" from "unreachable", and asserting a restriction that
may not exist is the defect being repaired.

Negative-tested: pointing the probe at the restricted doxalife token makes the
gate report RESTRICTED and fire all three findings; the shipped token makes it
report REACHABLE and suppress them. The first attempt at that test proved
nothing and is worth recording — the poison never applied, because doxa.life
returns 403 to Python's default user agent, so the copy was never written and
the unmodified gate ran and "passed". A negative test that cannot fail is the
same defect in miniature. Re-run with a browser UA, it discriminated correctly.

The 12 regenerated screenshots are the point of all this. cap3-monolithic-research
was read as an image, not inferred from the generator's exit code: it now shows
coastlines, country borders, place labels, ocean names and Mapbox/OpenStreetMap
attribution, with the 2,107 data dots sitting on real geography instead of an
empty void. Note the PNG got 67KB SMALLER while gaining all of that, so file size
was never going to answer the question.

check:shot-fonts still fails, and that is pre-existing and honest: this box has no
emoji font, so six bundles shoot tofu boxes. Verified by stashing these edits and
re-running — exit 1 either way. The markup is correct; the fix is a font on the
shot machine, never removing emoji from the product.
2026-09-23 06:26:39 +00:00
doxa-maps
8c3b18a5ee Give the README map screenshots their basemap back
Some checks are pending
build-gate / build (push) Waiting to run
Every map image shipped data floating on an empty navy void — no coastlines, no
borders, no labels. Two cards had this blocked on the Driver adding origins to
the Mapbox token's allow-list, for four ticks.

It did not need the Driver. Measured both directions: a tile request with no
Referer returns 403, the same request with the doxa.life Referer returns 200,
and the style document returns 200 either way, which is why the map still booted
and every gate passed. The shot harness serves from 127.0.0.1 and so sent no
Referer at all. These are doxa.life's own documentation images, generated by its
own repo from its own token; the restriction exists to stop third parties burning
the Driver's quota, and it was blocking the owner.

Route interception looked like the careful way to scope it and silently does not
work — Chromium ignores a referer supplied through route.continue, so tiles still
403'd. Only the context-wide header applies, and that breaks same-origin iframes:
the iframe-host shot went from 187 elements to 15.

So it is opt-in per shot, and the predicate is architectural rather than
anecdotal: any surface that nests content in an iframe opts out. I set it for the
one shot that failed first, then watched both cap-5 shells collapse on the next
run, and generalised. Map leaves get their basemap; shells keep their content.

Verified by reading the images, not the file sizes — a size jump had already
misled me once this tick.
2026-09-22 10:16:54 +00:00
doxa-maps
f3a5b228ee Make the flagship capability-5 screenshot show the studio doing something
Some checks are pending
build-gate / build (push) Waiting to run
It showed an empty pane reading "Choose an element from the list." The README's
headline image for the highest capability level demonstrated nothing, and every
shot gate passed it, because freshness, distinctness and element counts are all
satisfied by an empty pane. The shot now selects the first rail row before
capturing, so the picture shows what the studio is for: a nested SPA rendering
inside the shell that lists every element by capability. The file went from 167KB
to just over a megabyte, in line with its sibling.

Found by reading the image, the same way the mobile error card was found
yesterday. Reading one picture has now caught two defects that eleven gates
passed.

Add check:shot-fonts. The studio labels each row with a capability emoji, and
this machine has no emoji-capable font, so all 28 rendered as tofu boxes in the
committed PNG. The markup is right and the product is fine in a real browser —
the shot machine could not draw it — so the fix is not to strip the emoji. The
gate asks fontconfig whether this system can render the glyphs the UI actually
uses, and names the font install rather than the markup.

It is deliberately not in build:unlocked: it reports an environment condition
that is currently true here, and a gate that always fails in the build makes the
build useless. Its first version also flagged the star this repo uses as a
comment marker, which every text font renders; the range is now narrowed to the
pictographic planes.
2026-09-22 09:48:20 +00:00
doxa-maps-88655c70
9dc4dda8cf consolidate docs into documentation/ and deployment shells into deployment/
Some checks are pending
build-gate / build (push) Waiting to run
Driver 2026-09-21: 'a folder called deployment which will store the capacitor
folder, wordpress folder and tauri folder', and 'a folder called documentation
to store the contributing folder so docs are in one place'.

docs/ + contributing/ + CONTRIBUTING.md -> documentation/ (three doc homes into
one). capacitor/ + wordpress/ + src-tauri/ -> deployment/.

The public/ -> dist/ rename the Driver asked about is NOT here: after seeing the
measured blast radius (855 tracked files, 54 source refs, and public/ is the
served web-root four consumers point at) the Driver withdrew it - 'keep the
public folder the same'.

Path references were rewritten mechanically (258 across 87 files), but three
classes needed hand fixes because a prefix regex cannot see them:
  - join(ROOT,'docs',...) in 10 internal scripts - a quoted SEGMENT, not a prefix
  - tauri frontendDist '../public' -> '../../public', since src-tauri is now one
    level deeper; check:tauri caught this exactly as the card predicted
  - the WordPress contract test's dirname(__DIR__,2) -> 3, same reason

Also reverted one over-reach: the rewrite renamed a FINDING-CATEGORY label
'docs' in public-hygiene-check.mjs, which is a rule name in its own header, not
a path.

Verified: full build ALL GUARDS PASS, SRI consistent; check:tauri, check:mobile
(cap sync + webDir OK), check:wp-embed, quoted-scripts, capability-citations,
capability-exemplars, library-index, public-hygiene, parse and drop all pass.
2026-09-21 23:23:23 +00:00
doxa-maps-88655c70
c7a228e941 shoot a real cap-1 element and gate README capability claims against the manifest
The CAP 1 slot shot doxa-vision-card, which is not a single element: it ships
doxa-vision-card.instances.json with two instances, so discover.mjs types it
parameterized and manifest.json records "parameterized" — capability 2.

The same error had already been found and fixed in verify-5-capabilities.mjs, whose own
comment records that it had been sampling cap-2 twice and cap-1 never. That fix landed in
the gate and never reached the README: two artifacts encoding one fact, with nothing
forcing agreement. Fixing one copy was not fixing the fact.

all-people-groups is a genuine cap-1 — one .vue, no instances file, manifest type single.
The README now also says what decides the tier, since the folder's apparent simplicity is
the trap: doxa-vision-card looks like the lightest thing in the repo.

check:capability-citations compares every README capability claim against the manifest,
blocking in CI. Its first matcher used \Z, which is not JavaScript, so it matched zero
sections while still reporting a citation count — a gate reporting a number it had not
verified. It now splits on headings and the count reflects real matches.
2026-09-21 12:02:18 +00:00
doxa-maps-88655c70
dfe6c3d1fa correct the "research-dashboard owns no map" premise and gate the blank-tileset class
A previous reader measured ZERO <canvas> on research-dashboard and concluded the surface
owns no map, recording it as an architectural fact and relaxing the shot's readiness
check to match. The measurement was real; the inference inverted it. The page imports
useMapInstance, injects mapboxToken and adds a vector source, and re-measured live it
builds a mapboxgl-canvas at 878x445. Zero canvas meant the map failed to initialise.

The cost was not the blank image. A weakened assertion that makes a failing check pass
promotes a defect to a design note, and the README's deploy-3 proof has shown a blank
grey map pane since.

Why it is blank, measured: the shared pk. token is URL-restricted to doxa.life. Against
country-boundaries-v1, Referer doxa.life returns 200 on three attempts, 127.0.0.1 and no
referer return 403. The style endpoint returns 200 from every origin, which is why most
maps paint here and only the tileset-backed choropleth blanks. A first reading of that
asymmetry looked like a missing tileset scope; re-testing with the doxa.life referer
disproved it.

check:shot-fidelity now reports this class alongside the missing emoji font, and no
longer exits early after the first finding.
2026-09-21 11:39:06 +00:00
doxa-maps-88655c70
15ce17f907 fix the impossible 27/26 zone badge and replace a faked page-2 shot with the real third profile
The badge read "27/26 zones" — a count exceeding its own total — in two shipped README
screenshots. 26 was the leaf count before slice 09b-6 added the Frontier-Asia uncovered
rows; the literal was never updated, so it drifted the moment the data grew. The
denominator is now derived from perZone.size, which tracks the zone list automatically
and cannot disagree again. Measured from clusters.json: 13 regional + 12 asia + 2
uncovered + 1 deaf = 28. The corrected badge also surfaces 1 genuinely unresolved zone
that the stale denominator was masking.

legend-tree.js asserted "33 leaves" and "7 Frontier-Asia uncovered" in a comment; the
shipped data carries 28 and 2. Corrected to point at the arrays instead of a count.

README showed "List — page 1" and "List — page 2" as the same picture. The shot loaded
one URL twice and tried to reach a page 2 by scrolling and clicking Next; neither exists,
the list has no pagination, and every attempt sat in try/catch so the miss was silent.
The PNGs differed by 0.16% render noise, so no checksum would have caught them. Mean-
while poster-wall — a real manifest-listed profile — had no screenshot at all. Shoot the
real third thing rather than fake a fourth.

check:shot-distinctness gates this, blocking in CI. It keys on url+viewport, so the
deploy2 mobile shot of the same SPA stays legitimate rather than a false positive.
2026-09-21 11:29:25 +00:00
doxa-maps-88655c70
5567134978 shoot the plugin-studio element and stop captioning the product SPA as the studio
README drew the two cap-5 products apart in prose and even warned that captioning a
studio shot as the product SPA is a documented mistake — then filled its plugin-studio
slot with cap5-doxa-maps-spa.png. Both cap-5 figures showed the same app and no
plugin-studio screenshot existed anywhere in the repo.

A slot filled with the wrong real image looks exactly like a correct one; nothing 404s.
So the fix is to shoot the missing artifact, not re-caption around the gap. Both cap-5
slots now use generated, freshness-gated images.

Also adds check:shot-fidelity. The shot run reported 13x OK while every emoji rendered
as a tofu box: this machine has no emoji font. Measured rather than assumed — the DOM
carries 27 correct codepoints, so the markup is right and the defect belongs to the shot
machine. Reports by default because installing a font is a Driver call; --strict blocks
once one is present.
2026-09-21 10:59:28 +00:00
doxa-maps-88655c70
7276ade0e6 wait for svg not canvas on the chart dashboard; refresh all readme shots 2026-09-21 06:58:48 +00:00
doxa-maps-88655c70
924deaeede re-shoot all 12 readme images with real WebGL; fix three defects in the shooter
- add SwiftShader launch args (maps previously shot with no GL context)
- point cap5 and deploy2 at the doxa-maps-spa element, not the gallery page
- serve the deploy1 iframe host page from memory (it never existed; the shot was a 404)
- add a readiness guard before every screenshot plus a non-zero exit on failure
- per-shot minElements and iframe frame-counting for the two legitimate outliers
2026-09-20 06:45:21 +00:00
doxa-maps-88655c70
ea0c47b277 Brand-neutral shared VerticalTabsLayout with lazy nested-element hosting; fix cap-5 prayer tab leaf path; neutralize library identifiers; add Forgejo CI build-gate workflow
Some checks failed
build-gate / build (push) Has been cancelled
2026-09-19 17:24:30 +00:00