Studio first run: dev lists what the build lists, and the self-test finds its manifest
Some checks are pending
build-gate / build (push) Waiting to run

Two gaps found by opening every plugin in the studio under the dev
server:

- key-cities is gated (vite.doxa-maps-build-config.json gatedProfiles)
  out of every public surface the build emits, but the dev manifest
  listed it anyway, so the dev studio and the Research Gallery's
  Experimental shelf showed a plugin the built tree deliberately hides.
  The dev model now applies the same gate: 21 bundles, 33 profiles, as
  in the built manifest. readBuildConfig() does not carry gatedProfiles,
  so the gate is read from the config file, as generate-tree does.
- golden-path-check takes its tree base from a tree-base attribute, not
  from profile-config. The studio only passed the latter, so inside the
  studio the check guessed the tree from the page URL, fetched
  /manifest.json, got a 404 and showed an empty self-test. The studio
  now sets tree-base on every element it mounts; elements that do not
  read it ignore it.

Dev sweep after: all 31 listed plugins mount with content, no page
errors, no failed requests. Rebuilt the plugin-studio bundle and
re-baked its SRI.
This commit is contained in:
doxa-maps-88655c70 2026-09-25 03:43:33 +00:00
parent 0907e6ade3
commit 580dff6369
6 changed files with 28 additions and 12 deletions

View file

@ -86,7 +86,18 @@ export function galleryModel(reg) {
// and nothing else — the dev equivalent of the built tree's <bundle>/<profile>/index.html, which
// is what this URL means in production. Same contract, so the studio behaves identically in both.
const link = (...parts) => '/__leaf/' + parts.map(encodeURIComponent).join('/')
const bundles = [...reg].sort((a, b) => a.bundle.localeCompare(b.bundle)).map((b) => {
// GATED bundles (vite.doxa-maps-build-config.json `gatedProfiles`, e.g. key-cities) are withheld
// from every public surface the BUILD emits. The dev model listed them anyway, so the studio and the
// Research Gallery's Experimental shelf showed under the dev server — which is what DX runs first
// after cloning — a plugin the built tree deliberately hides. Same rule here, so dev == built.
let gated = new Set()
// Read from the config file itself, as generate-tree does: readBuildConfig() returns a projection
// that does not carry gatedProfiles.
try {
const cfg = JSON.parse(readFileSync(resolve(REPO_ROOT, 'vite.doxa-maps-build-config.json'), 'utf8'))
if (Array.isArray(cfg.gatedProfiles)) gated = new Set(cfg.gatedProfiles.map(String))
} catch { /* no config: gate nothing */ }
const bundles = [...reg].filter((b) => !gated.has(b.bundle)).sort((a, b) => a.bundle.localeCompare(b.bundle)).map((b) => {
const scriptUrl = `/plugin-designs/${b.bundle}/index.js`
const presets = new Map() // profile → its preset instances (empty for every other kind)
const typeOf = new Map() // profile → composition tier machine key (single … nested-mfe-spa)

View file

@ -767,6 +767,11 @@ export default defineComponent({
// own guess, so this lands through the existing config path with no new prop.
if (this.base) pc.treeBase = this.base
el.setAttribute('profile-config', JSON.stringify(pc))
// …and as a plain `tree-base` ATTRIBUTE, for elements that take the base that way instead of
// through profile-config (golden-path-check does, deliberately — it has no ProfileLoader).
// Without it that check guessed the tree from the PAGE URL, which in the studio is the page
// root, and read /manifest.json: a 404 and an empty self-test. Unused attributes are inert.
if (this.base) el.setAttribute('tree-base', this.base.replace(/\/+$/, ''))
el.style.cssText = 'display:block;position:absolute;inset:0;width:100%;height:100%;'
slot.appendChild(el)
row.state = 'ready'

View file

@ -799,7 +799,7 @@
"bundle": "plugin-studio",
"scriptUrl": "./plugin-studio/plugin-studio.js",
"output": "doxa-maps/plugin-studio/plugin-studio.js",
"integrity": "sha384-N70Sfwq4XTc7BHosJDT1r9/qUrzr1NZ5DiLb3QUYST8vY7+quBQzytqcpOs4Rp1E",
"integrity": "sha384-PWsWQsPshQsOrFOoSZ3rPg6231BJmKV/pvopXruEZgKovSfp8P2MEjfEEEuBWqMl",
"elements": [
"plugin-studio"
],
@ -827,7 +827,7 @@
"scriptUrl": "./plugin-studio/plugin-studio.js",
"embed": {
"iframe": "<iframe src=\"./plugin-studio/plugin-studio/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-N70Sfwq4XTc7BHosJDT1r9/qUrzr1NZ5DiLb3QUYST8vY7+quBQzytqcpOs4Rp1E\" crossorigin=\"anonymous\"></script>\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-PWsWQsPshQsOrFOoSZ3rPg6231BJmKV/pvopXruEZgKovSfp8P2MEjfEEEuBWqMl\" crossorigin=\"anonymous\"></script>\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
},
"instances": [
{

File diff suppressed because one or more lines are too long

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <plugin-studio> custom element. -->
<script src="../plugin-studio.js" integrity="sha384-N70Sfwq4XTc7BHosJDT1r9/qUrzr1NZ5DiLb3QUYST8vY7+quBQzytqcpOs4Rp1E" crossorigin="anonymous"></script>
<script src="../plugin-studio.js" integrity="sha384-PWsWQsPshQsOrFOoSZ3rPg6231BJmKV/pvopXruEZgKovSfp8P2MEjfEEEuBWqMl" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <plugin-studio> custom element. -->
<script src="../../plugin-studio.js" integrity="sha384-N70Sfwq4XTc7BHosJDT1r9/qUrzr1NZ5DiLb3QUYST8vY7+quBQzytqcpOs4Rp1E" crossorigin="anonymous"></script>
<script src="../../plugin-studio.js" integrity="sha384-PWsWQsPshQsOrFOoSZ3rPg6231BJmKV/pvopXruEZgKovSfp8P2MEjfEEEuBWqMl" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order: