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.
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.
- 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.
golden-path-check is the capability-1 element that IS the
develop-a-plugin-and-see-it-live walk: authored from the documented 3-file
minimum, built, published, and then reading the manifest it shipped beside. It
was named in two reference docs and NOT in the golden-path document itself, so
the one artifact that proves the path worked was missing from the page that
teaches the path.
Step 5 ended with "Done = the live site shows it, not a green build", which is
the right instruction and leaves the reader with no reference point — they can
only check their own plugin, and if it fails they cannot tell a mistake in their
plugin from a broken platform. The self-test separates those two questions.
Verified on the live catalog before writing it down, as an inheritor would:
HTTP 200, zero console errors, and it reports 19 bundles, 28 profiles, 28 of 28
self-describing, this plugin listed = yes. Cross-checked by two independent
measurements rather than trusting the element — the live bundle is
byte-identical to local at 73,693 bytes, and fetching the live manifest directly
gives the same 19 and 28 from a different path.
The note also states what the self-test does NOT claim, because that is the way
it could mislead. Its four rows are questions about the catalog's SHAPE, so it
stays green even when bundle CONTENT is stale — my own fixes this flight changed
bytes and not counts, and it reports identically on both trees. Freshness is
check:catalog-currency's job, which compares every live bundle's bytes against
the build. The doc now tells the reader to run both and says which answers what.
The URL printed in the doc was fetched before committing: 200. Three separate
gates this flight were failing because they navigated to a URL nobody had
checked, and a doc that sends a reader to a 404 is the same defect with a slower
feedback loop.
The golden-path doc's Step 4 gave the reader a copy-pasteable publish sequence
with no `set -e`, and its verification step was a COMMENT — "# 3. VERIFY every
manifest bundle's <name>/<name>.js resolves BEFORE push". A comment does not
verify anything. Pasted as written, the block clones, rsyncs with --delete, does
nothing, and pushes.
That is both halves of an incident this project already paid for, recorded as
AP-publish-verify-not-gating-plus-midchurn-rsync in the deploy-cycle notes: the
verify was chained into a compound command so a failing check still fell through
to the push, and rsync --delete ran from a source a concurrent build had just
emptied, faithfully mirroring that emptiness into the catalog. The live maps
catalog went to 404.
Step 3 is now three real commands — check:sri, check:embed-targets, and a git
diff that aborts if anything outside app/doxa-maps changed — and `set -e` is the
first line so any of them aborts before the push. Added `bun run check:settled`
as step 0, because `clean` empties public/doxa-maps at the START of every build,
which is what makes --delete catastrophic rather than merely wrong: it deletes
the live tree to match your momentarily-empty one.
The doc was already right to stay narrow ("the fuller runbook with every gotcha
lives in the project's deploy-cycle notes"), and it already carried postBuffer
with a good explanation. `set -e` is not a gotcha to defer — it is what makes
the four-step block safe at all, so it belongs with the block it protects.
Verified rather than assumed: all three commands exist in package.json, the
block extracted on its own passes `bash -n`, and the exclude-pathspec abort was
run against a real diff — it correctly passes when the diff is scoped and would
fire otherwise. Five gates pass.
Also corrected the runbook's own first instruction while checking it, in the
_qa-cycle notes (not a tracked file). It read "EXIT 0 + all 6 DX guards PASS".
No subset called "DX guards" exists anywhere in the repo, and the count was
wrong besides — build:unlocked chains 32 steps including 25 distinct check:*
gates, and that set grew by five in one flight. A hardcoded gate count is a
snapshot of a moving target. The chain is &&-joined under set -e, so EXIT 0
already means every step passed; that is the assertion that stays true as gates
are added, and the note now says so and gives a one-liner to list the current
set rather than copying it.
Two docs understated deploy method 5. README-SECTION-3 headed the section "built
+ contract-proven; no binary emitted", and develop-a-plugin closed its table
with "2, 4 and 5 are scaffolded but no binary/install has been shot".
Measured: `cargo tauri build` has run and its outputs are on disk.
deployment/src-tauri/target/release/doxa-maps-desktop is a 67,379,880-byte ELF
64-bit LSB pie executable, and target/release/bundle/deb/ holds a 60,554,898-byte
.deb. Eight source files are git-tracked under deployment/src-tauri/, and
check:tauri exits 0.
So "no binary emitted" is false. What is true is narrower and worth stating
precisely: no window has been opened, because this build box is headless with no
Xvfb, so nothing has confirmed the app paints rather than launching to a blank
frame — the exact soft failure the section below already warns about. "Not shot"
means nobody has watched it run; it does not mean nothing was produced. The
closing sentence now separates the three built-not-shot methods, because what is
missing differs for each: no APK for mobile, no captured install for WordPress,
and for Tauri artifacts that exist but have never been launched.
The bodies of both sections were already accurate and are untouched. Only the
status labels were wrong, which is the part a reader skims.
Found while reconciling the ideation sources. The 5-cap spec
(01-ideation-research/coolest-ideation/5-cap-5-deploy.md, 2026-09-22) is CURRENT
and correct on all five rows — verified each: 43 embed.iframe entries in the
manifest, 19 SRI hashes, capacitor.config.json with check:mobile green, the
WordPress PHP with check:wp-embed green, and the Tauri artifacts above.
The /plugin-designer skill is now the stale one, and the direction of the error
has reversed. It says method 5 is "ASPIRATIONAL — not scaffolded. No Tauri
config/dir exists in the repo", and instructs the reader not to repeat the
spec's claim. That catch was CORRECT when written: the spec then said "proven
POC", which was unbacked. The spec has since self-corrected, carrying a dated
2026-09-22 block reading "BUILT, not shot ... only the window LAUNCH is
unverified", which matches the files. The skill's correction froze at the old
reading and over-swung from overclaimed to nonexistent.
That is a hazard worth naming: a correction record — "document X is wrong about
Y" — becomes wrong itself the moment X is fixed, and nothing re-reads it.
Correction notes need the same staleness discipline as the claims they correct.
The skill lives in the session config directory with no git repo, so the fix is
surfaced on BUILD-PLUGIN-DESIGNER-SKILL-MEANS-REAL-WORK as a single precise edit
rather than made here.
Seven gates pass, including check:tauri, check:capability-citations,
check:capability-exemplars, check:doc-scripts and check:quoted-scripts.
The golden path told a new author to fetch a token from doxa.life/api/maps/token.
Measured: that token is URL-restricted to doxa.life, so a tile request without
that Referer returns 403 and every basemap in their smoke test renders blank
while the pins draw fine. That is exactly the symptom the Driver reported as
loading the pins but not the underlying map, and it is why tokenUrl was emptied
in the build config the day before. The first command in the hand-off doc
reproduced a known bug.
It now reads the token from the build config, which is the source that works:
same tile request, config token 200, endpoint token 403. That is a pk. public
key baked deliberately, protected by URL restrictions rather than secrecy, and
check:public-hygiene allows pk. while failing the build on sk. and tk. -- so it
is safe to read and never a secret to guard. The doc shows the command, not the
key.
The aggregator had the same bug and a worse symptom: it fetched from the same
endpoint and printed "token present", which meant a string had been obtained,
not that it worked. So a run could report a present token while every map gate
measured a blank basemap. It now prefers the config token, falls back to the
endpoint, and validates whichever it gets with one tile request.
Verified in all three states: the config token reports "present and serves
tiles", a fabricated token reports "tiles 401 - basemaps will be blank", and the
old endpoint token reports "tiles 403 - URL-restricted?". The banner reports
what was measured rather than what was fetched.
develop-a-plugin-and-see-it-live.md is the path an inheriting agent follows
end to end, and it mentioned the plugin studio once while sending every
iteration through a full build. Step 3b already argues well that a green build
proves nothing about mounting -- it just pointed only at smoke:embeds, which
needs the build first.
Adds Step 3a: bun run dev, then bun run smoke:studio. Measured 4.7s for 29
tabs with 0 failed requests, against a full build of 43s to 4min on the same
box -- 19 sequential bundles, queued behind any other build, so the spread is
real. An order of magnitude either way, which is the point.
A first draft said "roughly fifty times faster", derived by dividing by a
remembered 4-minute constant rather than by what the build log actually showed
(43s). Replaced with the measured range. That is the same defect this session
flagged on the Forgejo card an hour earlier: a stored number that rots, quoted
as if it were evidence.
Also states why both steps exist rather than one replacing the other: the dev
manifest hands rooted refs and the built manifest hands relative ones, so a
base-join bug is invisible in one surface and fatal in the other.
And names the single staging environment explicitly, pointing at /__gallery as
the archived index kept only because the dev server imports its renderer --
so a reader who stumbles on it does not mistake it for a place to review work.
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
Renamed from docs/develop-a-plugin-and-see-it-live.md (Browse further)