Decouple the library's prose: no host-platform names in the QA widget, StackLayout or script notes

The QA widget comments (QaCorner, ProfileLoader, app-wrapper-material) say our own surfaces and the host's
session instead of naming one host; StackLayout describes a normal host page's flow; the live-cors script
note says it was measured on the live test host. Comments and notes only; no behaviour changes.
This commit is contained in:
Doxa Maps 2026-09-26 16:45:32 +00:00
parent 44a1afba04
commit dec7059e87
5 changed files with 7 additions and 7 deletions

View file

@ -141,7 +141,7 @@ watch(() => config.value?.tokenUrl, (url) => {
// host override via profile-config.dataSource. (doxa-csv stays the final offline fallback.)
const dataSource = computed(() => config.value?.dataSource || sourcesConfig.activeSource || 'doxa-csv')
const colorSet = computed(() => config.value?.colorSet || 'default')
// QA corner widget: OPT-IN via profile-config.qa (default OFF). On for the DOXA go-base
// QA corner widget: OPT-IN via profile-config.qa (default OFF). On for our own
// surfaces (SPA + plugins); OFF for partner embeds so no QA button appears on their sites.
const showQa = computed(() => !!QaCorner && config.value?.qa === true)
// Conversion coach-mark: DEFAULT ON (opt-out via profile-config pinHint:false).

View file

@ -5,7 +5,7 @@
* Visible shell of the QA-agent bridge (see _qa-cycle/01-ideation-research/
* qa-loops/qa-embeddable-qa-agent-bridge.md). OIDC-gated onboarding — NEVER a key.
*
* AUTH: the widget detects the go-base session via a same-origin GET /api/auth/me.
* AUTH: the widget detects the host's session via a same-origin GET /api/auth/me.
* That only succeeds when the plugin iframe is SAME-ORIGIN (allow-same-origin). When
* the app-shell runs with NUXT_PUBLIC_PLUGIN_SANDBOX_ISOLATE_ORIGIN=true the frame is
* origin-'null' and the call is blocked — login is then impossible from inside the

View file

@ -4,7 +4,7 @@
★ WHY THIS EXISTS (the second shared layout, alongside VerticalTabsLayout). VerticalTabsLayout shows
ONE element at a time (tabs, fixed-viewport panes). StackLayout does the OPPOSITE: it renders ALL of
its elements STACKED VERTICALLY, each at its NATURAL height, so the whole thing grows the page and the
HOST page scrolls through them — exactly how a normal document / a doxa-life / nuxtinator page flows.
HOST page scrolls through them — exactly how a normal host page flows.
Use it to GROUP two (or more) elements on top of each other and embed the group on a page you scroll.
★ SAME NESTED-ELEMENT CONTRACT as VerticalTabsLayout (so a shell composes other element-plugins). Pass
@ -32,7 +32,7 @@
self-sizing element that still can't measure its own height in flow, pass :min-section-height (or a
section's own `minHeight`) to reserve room. Optionally cap a section with :max-section-height to give
a genuinely tall element an inner scroll instead of an endless page (default: no cap = pure page
scroll — the doxa-life / nuxtinator page-flow model).
scroll — a normal host page's flow).
★ EMBEDDING A LAYOUT INSIDE A LAYOUT (scroll-page in the cap-5 main). The cap-5 SPA's shell is
VerticalTabsLayout (sidebar + a FIXED-VIEWPORT content frame whose pane is `position:absolute;
@ -210,7 +210,7 @@ export default defineComponent({
// Optional top-bar title (omit for a bare stack with no header).
title: { type: String, default: '' },
// Optional per-section max height (e.g. '70vh') → that section gets an inner scroll instead of an
// unbounded page. Default '' = no cap, pure page scroll (the doxa-life/nuxtinator page-flow model).
// unbounded page. Default '' = no cap, pure page scroll (a normal host page's flow).
maxSectionHeight: { type: String, default: '' },
// Optional default MIN height for every section (e.g. '60vh') → reserves room for a self-sizing
// element that ships its own fixed layout and can't measure its natural height in flow. A section

View file

@ -1060,7 +1060,7 @@ async function mount(id){
// a subpath (e.g. /plugin-assets/doxa-maps-spa/), a bare '/assets' or './assets' misresolves,
// so hand each bundle an ABSOLUTE base derived from THIS shell's own document — correct at any depth.
if (!cfg.assetsBase) cfg.assetsBase = new URL('assets', document.baseURI).href.replace(/\/+$/, '')
// QA corner widget ON for the go-base SPA surface (opt-in flag; off for partner embeds).
// QA corner widget ON for our own SPA surface (opt-in flag; off for partner embeds).
cfg.qa = (new URLSearchParams(location.search).get('qa') === '1') /* QA opt-in via ?qa=1; widget exists only in DOXA_QA=1 builds */; cfg.qaLabel = spec.label || cfg.profile
el.setAttribute('profile-config', JSON.stringify(cfg))

View file

@ -311,7 +311,7 @@
"check:fits-screen:self-test:d": "★ A DEDICATED ENTRY, not a mode appended at the call site. The parent script value ends in an inline # comment, so a mode appended by the caller lands INSIDE that comment and the shell drops it — the run then exits 0 in DEFAULT mode, indistinguishable from the mode being selected. A self-test is the proof a gate can fail, so a self-test whose mode cannot be chosen is a gate certifying itself. This entry hardcodes its mode, so nothing has to be appended. (Flag names are deliberately not spelled here: check:script-flags scans script VALUES, and naming one in prose reads as advertising it.)",
"check:fits-screen:self-test:e": "★ A DEDICATED ENTRY, not a mode appended at the call site. The parent script value ends in an inline # comment, so a mode appended by the caller lands INSIDE that comment and the shell drops it — the run then exits 0 in DEFAULT mode, indistinguishable from the mode being selected. A self-test is the proof a gate can fail, so a self-test whose mode cannot be chosen is a gate certifying itself. This entry hardcodes its mode, so nothing has to be appended. (Flag names are deliberately not spelled here: check:script-flags scans script VALUES, and naming one in prose reads as advertising it.)",
"check:gallery-embed": "the cap-5 Research Gallery must embed on a FOREIGN ORIGIN (a stand-in host page on localhost, the built tree on 127.0.0.1) in BOTH modes, bare <script>+<doxa-maps-spa> and <iframe>, with the layout inside the host box and every curated tab painting a map. The summary line prints the tab count PER MODE, and a mode that checked zero tabs is a FAIL. One mode only: check:gallery-embed:js or check:gallery-embed:iframe. Starts its own servers on OS-assigned ports; needs only a built tree. Exit 2 = SKIP (no built tree / no playwright).",
"check:gallery-embed:live-cors": "the Research Gallery on a foreign page under the LIVE static layer's CORS rule (Access-Control-Allow-Origin on files inside the tree's folders, NOT on the root manifest.json, measured on nuxtbase): it must still boot every tab, by reading the CORS-readable manifest copy generate-tree writes beside its bundle.",
"check:gallery-embed:live-cors": "the Research Gallery on a foreign page under the LIVE static layer's CORS rule (Access-Control-Allow-Origin on files inside the tree's folders, NOT on the root manifest.json, measured on the live test host): it must still boot every tab, by reading the CORS-readable manifest copy generate-tree writes beside its bundle.",
"check:gospel-all": "EVERYTHING gospel-resources owns, in one command. Its ten gates were all hand-run, which is how a dead bundle shipped: a duplicate module killed all five leaves and the one gate run that day was pointed at the map. check:no-orphan-gates was right that they were reachable — reachable is not run. Deliberately NOT in gates:pre/post: three need a browser, the shared wave holds browser gates under load, and a bundle owner should not be able to slow everyone else's build by adding to a list they do not own. Static gates run first and stop the run on failure, so a scarce browser slot is never spent confirming a table is inconsistent. Exit 75 = NOT MEASURED, never folded into a pass.",
"check:heartbeat": "the HEARTBEAT ZONE threshold (the choropleth's top bin) must come from config AND the shipped config must still render today's ramp. Two sides: (B) a configured threshold must MOVE the edge — catches re-hard-coding; (A2) dashboard.config.js's own map.* must still resolve to 5/20/60/150/Infinity — catches the shipped default silently changing. A2 was MISSING at first and heartbeatThreshold:999 shipped past this gate printing 'default ramp unchanged'. A grep for '150' cannot do either job: it false-positives on the legitimate default and false-negatives on a re-hard-coding at 200. run check:heartbeat:self-test for the NEGATIVE tests (3 cases).",
"check:heartbeat:self-test": "THREE regression cases, each required to fire ITS OWN assertion: [literal] resolver replaced by the old hard-coded array -> B; [shipped-default] dashboard.config.js heartbeatThreshold changed -> A2; [shipped-mode] heartbeatMode flipped to quantile -> A2. Poisons IN MEMORY, never the file. Testing that the FEATURE works is not testing that the REGRESSION is caught — this gate shipped with only the first and missed the second.",