The gallery's published section order: Prayer Progress before the UPG-100 List
The Deep Research page publishes the rail as Dashboards (Big Picture, Simple Research, Regions), Prayer Mobilization (Prayer Progress, UPG-100 List), Gospel Research (Cities with Internet, Gospel Resources), then the Experimental folder. Only the Prayer Mobilization pair moves. Big Picture now says "desktop only" on every width, not only once a phone has disabled it. check:spa-tab-order asserted the old four-name order with UPG-100 first; it now asserts all seven published rows in order (still relative, with tab 1 positional). It needs a browser: rega runs it.
This commit is contained in:
parent
a569868fef
commit
fa69209035
3 changed files with 16 additions and 7 deletions
|
|
@ -2,8 +2,9 @@
|
|||
/**
|
||||
* check-spa-tab-order.mjs — the cap-5 product SPA must open on the Big Picture, in the specified order.
|
||||
*
|
||||
* WHAT THIS PROTECTS. The rail was specified explicitly: cap-5 tab order (Big Picture, UPG-100,
|
||||
* Prayer Progress, Gospel Resources). Tab 1 is not a preference — it is the LANDING
|
||||
* WHAT THIS PROTECTS. The rail's order is PUBLISHED (the Deep Research page, 2026-09-29) and must not
|
||||
* change: Big Picture, Simple Research, Regions · Prayer Progress, UPG-100 List · Cities with Internet,
|
||||
* Gospel Resources, then the Experimental folder. Tab 1 is not a preference — it is the LANDING
|
||||
* SURFACE, the first thing anyone opening doxa-maps-spa sees, and the opening step of the
|
||||
* onboarding ramp. Today that ordering is held only by the order of entries in a source array and
|
||||
* by comments explaining why; nothing fails if someone reorders them.
|
||||
|
|
@ -59,7 +60,11 @@ await __treeGuard(BASE, __ROOT, 'SPA-TAB-ORDER')
|
|||
//
|
||||
// So: assert what was actually specified. Tab 1 must still be Big Picture — that IS positional,
|
||||
// it is the landing surface — and the other three must appear after it, in order.
|
||||
const EXPECTED = ['Big Picture', 'UPG-100', 'Prayer Progress', 'Gospel Resources']
|
||||
// ★ ALL SEVEN SINCE 2026-09-29. The published Deep Research order names every production row, so the
|
||||
// gate asserts every one of them, in order; the earlier four-name list had UPG-100 before Prayer
|
||||
// Progress, which the published order reverses. As before, the order is relative: a row between two
|
||||
// named ones is allowed, a named row out of order is not; tab 1 is positional.
|
||||
const EXPECTED = ['Big Picture', 'Simple Research', 'Regions', 'Prayer Progress', 'UPG-100', 'Cities with Internet', 'Gospel Resources']
|
||||
|
||||
const WALK = `(sel)=>{const o=[],s=new Set();const w=(r)=>{if(!r||s.has(r))return;s.add(r);try{o.push(...r.querySelectorAll(sel))}catch(e){};for(const e of r.querySelectorAll('*'))if(e.shadowRoot)w(e.shadowRoot)};w(document);return o}`
|
||||
|
||||
|
|
|
|||
|
|
@ -604,7 +604,7 @@
|
|||
"check:engine-contract": "the map must use the engine it was ASKED for or fail VISIBLY — never a substitute. resources-map read `engineGlobal(provider) || window.mapboxgl`; engineGlobal already defaults to mapbox, so that could only fire for provider 'maplibre' and then returned MAPBOX — a keyless page silently handed the engine that needs a token, which the profile then does not give it, so its tiles 401. Invisible to every other gate: the leaf mounts, renders and logs nothing. Six runtime measurements (2 providers x engine present / blocked / both blocked, CDN blocked by request routing the way a proxy or an offline kiosk does) The static arm was DELETED once check:no-silent-engine went into gates:post (main 23976fb0): two gates owning one source rule meant this leaf was checked twice and every other leaf once, and the narrower copy is the one that drifts. Mapbox arms inject a dummy MAP_TOKEN, because without one the element never mounts on a static tree and that is the environment, not the product. Engine attribution is read off the canvas class, not a debug handle. Browser gate. --poison names where the falsifiable source arm went rather than pretending to have one; the tree-wide gate self-tests with --self-test, not --poison.",
|
||||
"check:link-coverage": "rule 4 of the brief — 'verify a URL resolves before shipping it' — as a gate instead of a habit. verify-gospel-links.mjs does the verifying; nothing asserted the record COVERS what is shipped, so the honest state of the corpus was a number someone had to go and measure. DISCOVERS the URLs by recursing the pin index for any http string rather than naming fields: every field list in this bundle has gone stale (ga and se shipped unscreened, the SUN block and the access table were each added after the fact), and the recursion found 16 links my own hand-rolled measurement had missed. Resolves each against THREE records — the verification table, translator-org-links.json (contacts, fetched by their own script) and sun-deaf-index.json (proved by content against a catch-all control, which is stronger than a status code) — and fails on any unrecorded link, any shipped link recorded BROKEN, and any 'unknown' on a target a status code CAN prove. The status-blind list holds one URL SHAPE, not a host: jesusfilm.org/watch/jesus/<slug> discriminates and 2,049 links depend on that, while /watch/?languageId= does not. Static, sub-second. Self-test: `bun run check:link-coverage:poison`.",
|
||||
"check:snapshot-guard": "every gospel-resources catalogue fetcher must write through scripts/_snapshot-guard.mjs, which refuses a write that loses more than a tenth of the previous snapshot. Written after a rate-limited FCBH run silently replaced 1,666 video scopes with 1,103. Static, sub-second. Self-test: `bun run check:snapshot-guard:poison` injects a raw write and the check must fail on it.",
|
||||
"check:spa-tab-order": "the cap-5 SPA must open on Big Picture and keep the specified order (Big Picture, UPG-100, Prayer Progress, Gospel Resources) — asserted as PRESENCE + tab-1 + RELATIVE order on the RENDERED rail, because the rail gained three sections and now renders 12 rows with others between them. ⚠ NOT WAVE-WIRED: it FAILS rather than skips when the SPA is unreachable, deliberately (\"a gate that cannot reach its subject has not passed, it has not run\") — correct standalone, but gates:post runs on checkouts with no server. Needs `bun run serve` on 4173.",
|
||||
"check:spa-tab-order": "the cap-5 SPA must open on Big Picture and keep the published Deep Research order (Big Picture, Simple Research, Regions, Prayer Progress, UPG-100 List, Cities with Internet, Gospel Resources) — asserted as PRESENCE + tab-1 + RELATIVE order on the RENDERED rail, because the rail gained three sections and now renders 12 rows with others between them. ⚠ NOT WAVE-WIRED: it FAILS rather than skips when the SPA is unreachable, deliberately (\"a gate that cannot reach its subject has not passed, it has not run\") — correct standalone, but gates:post runs on checkouts with no server. Needs `bun run serve` on 4173.",
|
||||
"check:square-map-controls": "MapToolbar controls=\"square\" must be the ENGINE'S grouped card, not a square of ours. Reads node_modules/maplibre-gl/dist/maplibre-gl.css and compares our ported values against THAT FILE -- 4px corners, 0 0 0 2px rgba(0,0,0,.1) ring, 1px solid #ddd dividers -- because the look asked for is the engine default (DX-life adds NavigationControl and overrides nothing), so the target is published rather than a matter of taste. Asserts the three deliberate deviations: the engine's 29px is NOT adopted (touch target over pixel parity), there is NO overflow:hidden (it clips a focus ring; outer corners come from first/last child rounding, the engine's own mechanism), and a forced-colors block ships. Also asserts the BLAST RADIUS: round is the default and none of the nine MapToolbar consumers passes controls=, so no map changes -- opting one in turns it red. CSS assertions read the text passed to useShadowStyles, not the file, because the prop's doc comment quotes the engine's 29px and a checker that cannot tell a comment from a declaration finds the documentation it stands on.",
|
||||
"check:stale-sweep-claim": "a caveat that has stopped being true is a wrong number. The gospel surfaces carry a paragraph saying which pools were searched; while the GRN sweep ran they truthfully said part of it was unread, the sweep finished, and the sentence stayed for four more commits. The DATA decides here: undecided gap codes mean the claim is allowed, all-decided means it must go, so it re-arms itself for the next slow pool. Does NOT flag a claim rendered under a v-if on the pending count — that form expires on its own. Self-test: `--poison`. Static, sub-second.",
|
||||
"check:surfaces-read-the-tier": "a surface may READ the tier the pin index computed, never re-derive 'this group has nothing' from the raw resource fields. That hand-rolled field list went stale every time a source was added: 7 codes drawn as having nothing while the map showed them a link, then 28 when Scripture Earth landed. Static, sub-second. Self-test: `bun run check:surfaces-read-the-tier:poison` re-injects the old formula into every surface and each must be caught.",
|
||||
|
|
|
|||
|
|
@ -278,8 +278,9 @@ const NAV_MODEL = [
|
|||
// newcomer the concrete new artifact, THEN ask them to pray it.
|
||||
{ key: 'prayer-mobilization', label: 'Prayer Mobilization', i18n: 'sec.prayer', icon: 'heart',
|
||||
tabs: [
|
||||
{ id: 'upg-100', icon: 'list' }, // 1. UPG-100 List — the NEW thing, introduced first
|
||||
{ id: 'prayer-map', icon: 'embed' }, // 2. Prayer Progress — now pray the list
|
||||
// Prayer Progress, then the UPG-100 List: the published order of this section, fixed.
|
||||
{ id: 'prayer-map', icon: 'embed' },
|
||||
{ id: 'upg-100', icon: 'list' },
|
||||
] },
|
||||
// Gospel Research — RENAMED section (was "Research"). Cities with Internet then Gospel Resources,
|
||||
// per the spec's table (rows 5-6). The plain, uncomposited "Research Map" tab (doxa-research-map)
|
||||
|
|
@ -962,9 +963,12 @@ export default defineComponent({
|
|||
// at the layout level and this shell is what turns that click into a message instead
|
||||
// of a mount.
|
||||
const disabled = this.isDesktopOnly(t.id)
|
||||
// A desktop-only map says so on EVERY width, not only once a phone has disabled it:
|
||||
// a desktop reader should know before sharing the link to a phone.
|
||||
const desktopOnly = disabled || this.mobileFlagOf(t.id) === 'desktop-only'
|
||||
return {
|
||||
key: t.id, label: this.tabLabel(t), sub: this.tabSub(t), icon: r.icon,
|
||||
badge: disabled ? this.tr('desktopOnly') : r.badge, disabled
|
||||
badge: desktopOnly ? this.tr('desktopOnly') : r.badge, disabled
|
||||
}
|
||||
}),
|
||||
seen)
|
||||
|
|
|
|||
Loading…
Reference in a new issue