- 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.
Last tick I fixed the golden path's token fetch and left the identical
403-fetching command in reference.md twice. Fixing the instance rather than the
class is the same mistake as scrubbing a string whose generator still writes it.
Both are corrected, along with a stale python3 -m http.server line that predates
serve-strict.
The doc had already MEASURED the restriction and kept prescribing its cause: it
recorded that tiles 403 from 127.0.0.1 and treated a blank basemap as the cost of
working here, while the command above it fetched exactly that token.
My first rewrite then overstated the fix, and the correction is in the doc rather
than hidden in a commit. Measured with the doxa.life token: curl gets 403 with no
Referer, 403 with a 127.0.0.1 Referer, 200 with a doxa.life Referer -- so the
restriction is real and does block the curl path. But a browser gate still
fetched 9 /v4/ tiles with zero failures, because the page resolves its token
through a ladder and the built bundle carries the working baked one. The fix is
to the shell commands; the browser gates were never affected.
Two things worth inheriting came out of checking it. The basemap is Mapbox Light,
pale by design -- I looked at a screenshot and briefly called it "not painting"
because I expected terrain and roads, when the labels and borders ARE the
basemap. And verify:map-paint passes under both tokens, since it asserts a live
GL context rather than loaded tiles, so it is not the signal to consult about
whether tiles arrived.
Five lanes had 465 insertions across 18 files sitting uncommitted, some for
15 minutes. That is the state that silently lost the shell-scroll fix earlier
today: a verified fix existed only in the working tree, a second agent's edit
to the same file overwrote it, and the reverted version got committed and
described as the fix.
Nothing here is finished and no card is being closed on it. This is a
snapshot so the work survives an overwrite, taken at a moment when every file
had been quiet 15s or more, so no agent was mid-write.
Verified coherent before staging rather than committed blind: template-literal,
mjs-parse, sfc-parse, no-orphan-gates, kpi-unit, composite-reg, script-flags,
quoted-scripts and backlog-status all PASS. check:synced-css fails on
PeopleGroupDetail.vue and doxa-simple-map.vue only -- the same two files and
the same counts as before the swarm started, both untouched by any agent, both
already carded.
Two untracked files included because both are load-bearing: internal/
check-facet-one-field.mjs is wired into package.json with a self-test, and
library/utils/viewportScrim.js is imported by DataTable, SemanticTreeLegend
and PosterDialog -- a shared helper for the modal-scrim fix rather than six
copies of the same workaround.
Three docs still told a reader to start a server on every interface: the
reference recipe for the share round-trip, the quoted scripts block, and
app-wrappers.md. Agents followed those recipes faithfully, which is how twenty
publicly bound http.server processes accumulated on this box. All three now
bind 127.0.0.1. check:quoted-scripts caught the second one on its own.
Also adds the gate-authoring constraint that just broke a build. Plugin and
library source is written for Vite, not Node, and fails two ways: the @map
alias is unresolvable (hit first), and import.meta.glob is undefined in 18
files including 11 of the 20 plugin index.js. A new check:facet-cascade
imported the dashboard config, reached library/colors/_registry.js
transitively, and threw -- while already wired into build:unlocked, so the
build failed for a reason unrelated to the code being built.
The counts in that section were measured, not estimated. A first draft said
"every plugin index.js" and the real number is 11 of 20; it also blamed the
glob when the first error is actually the alias.
States the two rules that follow: build:unlocked is only for gates that run
clean in plain Node with no browser and no network, and a gate gets run before
it gets wired in -- a broken gate in the build chain is worse than no gate,
because it goes red for the wrong reason and trains people to skip the step.
Records the other box constraints that have each produced a wrong answer:
Node 20 (no fs.glob), bfs find rejecting relative -newermt, no hardware WebGL,
and bunx not existing.
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.
Ran the browser-free gate suite inside a fresh clone -- the inheritor's
conditions. Five passed; check:dxlife went red with "clone not found at
/root-dx-life - nothing to check".
That is not a defect. The gate deliberately uses three values (0 unchanged,
1 drift, 2 no clone) because it exists after a check that returned the PASS
value BECAUSE IT FAILED: `cd root-dx-life && git status --porcelain | wc -l`
printed 0 for a directory that is not a git repo. Collapsing "cannot judge"
into "pass" is exactly the bug it was written to prevent.
But `bun run` and any && chain see only zero/non-zero, so the middle value
evaporates precisely where a reader consumes it. The fix belongs in the
documentation, not the gate: added a preconditions row stating what it needs,
what exit 2 means, and that it is NOT in build:unlocked, so a clone still
builds.
Verified the whole inheritor path again after the Cargo.lock change: clone
(2358 files, lockfile present) -> bun install exit 0 -> bun run build exit 0,
18 bundles / 27 profiles, with check:dep-names and check:no-abs-paths both
running inside the clone's own build.
Makes the cheap half of last tick's P0 automatic. A folder rename had
rewritten three npm package names, so bun install failed in a fresh clone
while everything here passed -- the real packages were already in
node_modules from before the rename, making the breakage invisible to every
build and every gate.
Checks two things, offline, in milliseconds: the declared name resolves under
node_modules/, AND the installed package's own name field equals the declared
key. The first alone catches the capacitor case; the second catches a name
that resolves to a DIFFERENT package, which a path-only check would miss.
Together they detect the corrupted-name class without a network round-trip,
which is what lets it run on every build rather than in a nightly job nobody
watches.
It does not replace the clone test. A gate can only see what is IN the repo;
only a clone sees what the repo fails to do on a clean machine.
Negative-tested four ways: recreating the EXACT P0 (the three
@deployment/capacitor/* names) FAILS naming all three; a name that resolves
to a package whose own name differs FAILS; an absent node_modules SKIPs
honestly rather than passing or failing; an empty dependency list FAILS via
the vacuous guard. Wired into build:unlocked and confirmed running inside a
full build (17 declared, 17 verified, exit 0).
The repo is clean -- git grep over every tracked file returns zero /home/
paths. That is a real hand-off property: a clone works on any machine, which
is what "the path Doxa inherits" requires. But nothing enforced it. Proven by
experiment: a /home/lk10x/... line planted in internal/settled-tree-gate.mjs
passed check:public-hygiene, check:parse AND check:quoted-scripts. The tree
was clean by accident, not by construction.
This is the worst failure shape for a hand-off. An absolute path works
perfectly for whoever wrote it and breaks only on the inheritor's machine, so
no test run by its author can catch it. The sibling ideation tree already
paid that cost: two docs cite a workspace root that no longer exists, so a
reader following them silently finds nothing.
Not a flag on check:public-hygiene, which already detects these patterns but
walks a SERVED tree where node_modules never exists -- pointed at the repo
root it produced 1,427 findings, nearly all from node_modules/.vite. Its
scope is right for its job. This scans `git ls-files`, the set a clone
actually receives, which excludes node_modules and build output with no
ignore list to maintain.
Negative-tested three ways: the exact planted path that beat three other
gates now FAILS with file:line; a /Users/ path in a doc FAILS; a checkout
with too few tracked files FAILS rather than passing vacuously. Wired into
build:unlocked and confirmed running inside a full build (783 files, exit 0).
It then caught its own documentation -- my reference.md row quoted the
literal patterns as examples. Rewrote the example rather than allow-listing
the file, which would have blinded the gate to a real path in the repo's
largest doc.
The OPEN WORK line asks for Playwright coverage over every plugin AND ALL
SHARING. Sharing had never been exercised across the set this flight: the
gate needs a served tree, a token, per-plugin --url flags and (on this box)
--browser chromium, so a bare `bun run smoke:share` only prints usage.
Derived the real coverage set -- grep -rln ShareButton plugin-designs/*/*.vue
gives 8 built leaves -- and ran it: 8/8 pass. Every Share button emits a URL
that resolves 200 text/html and reopens the correct element with a live
canvas.
The pass count alone would have proved nothing. The failure this gate exists
to catch, an SPA fallback or a host stripping the hash deep-link, renders A
map for every share URL, so all 8 pass while all 8 links are wrong. The
discriminating evidence is six DISTINCT reopened tags, each matching its own
plugin, canvas:y on all eight.
reference.md now carries the copy-paste invocation, verified by running it
verbatim from a clean shell (8/8, same six tags). It also corrects a detail:
the doc said Firefox, which is the default but stops on this box -- the tool
detects its own WebGL limitation and names the chromium flag in its output.
A standing work item reads "gospel-resources + cities-internet maps must
render with REAL resource links" -- one line batching two profiles whose
contracts are opposite. gospel-resources genuinely renders 155 real eBible
links. cities-internet renders zero, deliberately: its own header says
"PERSECUTION-SAFETY: this profile carries connectivity + population +
language only. It has NO gospel-resource, church or believer field and must
not gain one."
So taking that line literally means adding a gospel-resource field to a
profile whose header forbids exactly that. The instruction is stale in the
worst way -- not merely wrong, but pointing at work that would remove a
safety property.
The rule existed only as a comment in one .vue header. It now has a section
in reference.md under Data sources, with the measurement behind it: zero href
bindings across all three cities-internet profiles, 1,567 live nodes and 0
anchors, and a `source` field that is API provenance rather than a
destination.
Also recorded that "persecution-safe" means three different things in this
repo -- field separation here, placename precision in key-cities, a
dependency-free table in DashboardDataTable -- so nobody generalises one into
the others. Only the first governs what data a profile may hold.
Applying last tick's lesson systematically: swept every numeric claim about
the catalog across all docs. Only one had aged into something misleading.
"Measured 2026-09-21: 17 of 17 bundles identity-proven" was TRUE when
written, and the gate reads the live manifest so nothing was broken. But a
reader today sees 17 beside a catalog of 18 and cannot tell whether a bundle
went missing or the sentence simply aged. Re-ran check:catalog-identity: 18
of 18, PASS. Restated with the delta named.
The other three hits are fine and deliberately left alone: the "21 bundles"
in the CLI doc is prose explaining why a count was REMOVED, the 18 in
reference-capability-exemplars.md is auto-generated, and "5 plugin
capabilities" is a constant rather than a count.
Added the general rule beside the number: a dated measurement is not a stale
claim, but it still misleads once the underlying figure moves, so re-run the
gate and restate rather than leaving a reader to guess.
Running the gate list I completed last tick, two entries reported FAIL:
smoke:gallery and smoke:share. Neither is a defect. smoke:gallery needs a
dev server on :5174 and says so; smoke:share needs --url arguments and prints
usage. Both exit non-zero, so in a batch run they read exactly like the real
failures the list exists to surface.
A checklist that turns a precondition into a red line trains its reader to
ignore red lines, which is how a real failure gets skipped. Added a
preconditions table stating what each needs and what a bare run actually
does, measured by running them.
Also recorded that the token-dependent gates DEGRADE rather than fail:
without MAPBOX_TOKEN, smoke:embeds reports map profiles as timeouts -- it
once read 27/40 for that reason and 40/40 with a token. A timeout there means
"no token" far more often than "broken plugin".
Two claims corrected before shipping. I wrote that the token endpoint needs a
browser User-Agent; measured, a plain curl gets 200 identically -- that
requirement belongs to pray.doxa.life, a different host. And I tested rather
than asserted the limitation now in the doc: verify:map-paint PASSES on a
leaf whose tiles 403, because a live GL context, a sized canvas and
attribution are all true while the basemap stays empty. The gate is correctly
scoped; the name invites over-reading, so the scope is now written down.
26 gates live outside build:unlocked; only nine were listed in reference.md.
An inheritor reads that table as the list of what to run before publishing,
so seventeen checks were effectively invisible -- including the three that
caught the most defects this flight: catalog-currency, smoke:embeds and
verify:map-paint.
The cost was already being paid. Two unlisted gates were RED, and had been
for two sessions:
check:quoted-scripts the doc quoted a build chain missing the
check:descriptions step added two ticks ago
check:capability-exemplars the generated tier table predated golden-path-check
Neither is a product defect -- both gates were working exactly as designed,
comparing documentation against machine truth. Nobody ran them. That is the
failure mode a standalone gate has by construction, and the table is the only
mechanism that prevents it.
Fixed both (doc updated to match package.json; exemplars regenerated to 27
rows), then filled the table to 25 of 26 -- the one omission is an alias for
a script already listed. Each new row states what the gate catches and, for
the ones that cannot live in the build, why.
Corrected a number mid-edit: I first wrote "nineteen gates" from an earlier
tally that had excluded the regenerator helpers. Measured again: 26.
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.