check:studio-rail — a production profile must DECLARE its name
The rail showed tiles nobody had named while this gate stayed green. The obvious fix is a no-op, and writing it first is how that came out. THE NO-OP: testing the rail's label for null/empty can never fail, because rowsFromManifest falls back to humanize(id) (plugin-studio.vue:421,429). A profile that declares nothing still arrives as "Doxa Simple Map" -- not empty, and not equal to the bare id either, so the existing bare-id rule misses it too. humanize() defeats BOTH rules. That is why country-posters could ship a tile nobody had named. So the property is the DECLARATION, read from the manifest, not the rendered label: does this profile's <profile>.meta.json carry a "label"? A humanized id is a reasonable DEFAULT and a bad NAME -- "Doxa Simple Map" tells a reader nothing the folder did not already say. PRODUCTION-STAGE ONLY, deliberately: 15 profiles declare no label today and 14 are experimental -- work in progress nobody has named yet, which is not a defect. A gate that is red for a condition the repo accepts gets ignored. Also declares the two labels my own plugin was missing: upg-100-list becomes "UPG-100 — Zoned Map" and poster-wall "UPG-100 — Poster Wall". ⚠ THIS GATE IS RED ON MAIN TODAY, 8 violations across 4 plugins and 4 owners (cities-internet 2, doxa-simple-map 1, gospel-resources 3, my-upg-100-list 2). It must NOT land before those labels do, or it blocks every other agent's landing for a defect that is not theirs. The two meta files here fix my share; they reach the manifest only through the full build, which is the build owner's. internal/ is the build owner's under rule 5B -- source sha to studio, sequenced after the other three owners declare their labels.
This commit is contained in:
parent
a02458a171
commit
112f4cee77
3 changed files with 34 additions and 0 deletions
|
|
@ -66,6 +66,32 @@ try {
|
|||
for (const b of byBundle.keys()) if (!seen.has(b)) fail(`bundle ${b} is missing from the rail`)
|
||||
// A row is NAMED, never shown as a bare id (the Driver: Gospel x Internet read just "board").
|
||||
for (const r of ctx.rows) if (r.label === r.profile || r.label === r.bundle) fail(`${r.key} shows a bare id ("${r.label}") — give its <profile>.meta.json a "label"`)
|
||||
// ★ AND A PRODUCTION PROFILE MUST DECLARE ITS NAME, not inherit one.
|
||||
//
|
||||
// ⚠ THE OBVIOUS VERSION OF THIS RULE IS A NO-OP, and writing it first is how I found out. Testing
|
||||
// the RAIL's label for null/empty can never fail: rowsFromManifest falls back to humanize(id)
|
||||
// (plugin-studio.vue:421,429), so a profile that declares NOTHING still arrives here as
|
||||
// "Doxa Simple Map" — not empty, and not equal to the bare id either, so the bare-id rule above
|
||||
// misses it too. humanize() defeats BOTH rules, which is why country-posters could ship a tile
|
||||
// nobody had named while this gate stayed green.
|
||||
//
|
||||
// So the property is the DECLARATION, read from the manifest, not the rendered label: does this
|
||||
// profile's <profile>.meta.json carry a "label"? A humanized id is a reasonable DEFAULT and a bad
|
||||
// NAME — "Doxa Simple Map" tells a reader nothing the folder did not already say.
|
||||
//
|
||||
// ⚠ PRODUCTION-STAGE ONLY, deliberately. 15 profiles declare no label today and 14 are
|
||||
// experimental — work in progress nobody has named yet, which is not a defect. Failing those
|
||||
// would make this gate red for a condition the repo accepts, and a gate that is red for an
|
||||
// accepted condition gets ignored. A profile earns the obligation when it reaches production.
|
||||
for (const b of manifest.bundles) {
|
||||
if (b.stage !== 'production') continue
|
||||
for (const p of b.profiles || []) {
|
||||
const declared = p.label
|
||||
if (declared === null || declared === undefined || !String(declared).trim()) {
|
||||
fail(`${b.bundle}/${p.profile} is PRODUCTION but declares no "label" in its <profile>.meta.json — the rail falls back to a humanized id, which names nothing`)
|
||||
}
|
||||
}
|
||||
}
|
||||
const canon = secs.flatMap((s) => s.nodes.filter((n) => n.canonical))
|
||||
for (const r of ctx.rows) { const c = canon.filter((n) => n.target === r.key).length; if (c !== 1) fail(`${r.key} has ${c} canonical nodes (want 1)`) }
|
||||
const nProd = [...stageOf.values()].filter((v) => v === 'production').length
|
||||
|
|
|
|||
4
plugin-designs/my-upg-100-list/poster-wall.meta.json
Normal file
4
plugin-designs/my-upg-100-list/poster-wall.meta.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"_comment": "The printable half of UPG-100: a wall of prayer-card posters, one per 100-list entry, with the three print paths. Declared so the Studio rail names it rather than falling back to a humanized id (check:studio-rail).",
|
||||
"label": "UPG-100 — Poster Wall"
|
||||
}
|
||||
4
plugin-designs/my-upg-100-list/upg-100-list.meta.json
Normal file
4
plugin-designs/my-upg-100-list/upg-100-list.meta.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"_comment": "The map half of UPG-100: the zoned list of unengaged people groups, with the semantic-tree legend and the packet/poster exports. Declared so the Studio rail names it rather than falling back to a humanized id (check:studio-rail).",
|
||||
"label": "UPG-100 — Zoned Map"
|
||||
}
|
||||
Loading…
Reference in a new issue