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.
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.
Card 1 Step 1 asks that the merge lose nothing. No gate owned that. A local
bundle that 404s live was counted "unreachable" and skipped, and unreachable
never gated the exit, so a catalog with an entire plugin deleted passed:
CATALOG-CURRENCY: 17 current - 0 STALE - 1 unreachable (of 18 local bundles)
CATALOG-CURRENCY: PASS <- exit 0
Proven by deleting one bundle from a copy of the catalog and pointing the
gate at it. The hole fell between two checks that each answered their own
question correctly: identity proves the live bytes are self-consistent, and
currency proves they are the same build; neither asked whether anything was
absent. The tell was in the PASS text itself -- "every REACHABLE live
bundle". A qualifier inside a success message describes what a check does
not cover.
MISSING is now distinguished from UNREACHABLE. A 4xx is the server stating
the file is not there, which is a publish defect and fails. A connection
error or timeout is an environment condition and still counts as
unreachable, so an offline box still SKIPs and never fails a build.
Negative-tested four ways: the real catalog still PASSES (18/18, 0 MISSING);
a deleted bundle now FAILS exit 1 naming the exact URL probed; a tampered
bundle still FAILS as STALE; offline still SKIPs. Also fixed a reporting bug
introduced en route -- the failure printer rebuilt a .js path from the entry
name, mangling leaf URLs, and a wrong URL in an error message sends the
reader hunting for a file that was never requested.
check:catalog-identity hashes each live bundle against the CATALOG'S OWN
manifest - deliberately, per its header. That proves the served tree is
internally consistent; it can never prove it is current. A catalog three
publishes behind is perfectly self-consistent and passes clean.
Measured today: after baking the Mapbox token, catalog-identity reported '17 of
17 identity-proven - PASS' while every live leaf still served BAKED_TOKEN = ''
and every map on the platform was broken.
The two gates answer different questions and neither subsumes the other:
identity is the live catalog consistent WITH ITSELF? (tamper/corruption)
currency is the live catalog the SAME BUILD as ours? (staleness)
It checks BOTH bundles and leaf pages, because a bundle-only version of this
gate also passed: baking the token changed 37 leaf HTML pages and ZERO .js
bundles. generate-tree owns the leaves, vite owns the bundles, and a publish can
change either independently.
Current reading: bundles 17 current, leaves 17 STALE.
Negative-tested: unreachable catalog SKIPs (offline must not fail a build), a
manifest yielding 0 integrity values FAILs rather than passing vacuously, and a
missing local build SKIPs.