method-ASK_seed-mediated-generated-interface.figure.js
This view shows one file as text; the diagram front door links it. It is generated at build time, static and bounded: nothing here runs the code, and there is no browsing beyond this file.
/* method-ASK_seed-mediated-generated-interface.figure.js — instantiation path + the loading-boundary seam (source-v1, ASK 2026-07-18) Subject: the instantiation path and where it fails — NOT the classification taxonomy (that is the sibling ontology figure). The fork appears AT the loading boundary, before the grammar grants the aperture. Colour discipline: neutral throughout, with ONE licensed exception — the grammar box carries the design-system-ASK legislative function, because the doctrine states the grammar grants the aperture (docs/bounded-generativity.md spine, restated in SMGI §Relation to bounded generativity). No colour is invented for integrity: fork-at-load is rendered as structural branching + broken continuity (.held = dashed, muted), not as alarm chrome. Integrity is a conformance condition, not a fourth function. Repo prose is source of truth: docs/seed-mediated-generated-interface.md. */ (function () { /* FAIL CLOSED BEFORE ANY LAYOUT. diagrams-fit.js is a DS-owned support file that must be vendored alongside this figure and loaded immediately BEFORE it. Checked at the top of the builder so a missing helper stops this file before the SVG is constructed, rather than leaving a half-built, unpositioned artifact. Message names the figure builder. */ if (!window.DIAGRAM_FIT || typeof window.DIAGRAM_FIT.compute !== 'function') { throw new Error('Diagram fit support is missing. Load diagrams-fit.js before the figure builder.'); } /* The Fit's v3 placement options (balance, compactClearance) are not read by an older diagrams-fit.js, which would silently keep the old geometry. FAIL CLOSED instead. */ if (!(window.DIAGRAM_FIT.VERSION >= 3)) { throw new Error('diagrams-fit.js is older than v3. Re-vendor it from design-system-ASK with this figure builder.'); } /* FAIL-CLOSED on the design-system gesture carrier, on the same terms: diagrams-pointer.js (v2) is vendored alongside this figure and loaded BEFORE it. */ if (!window.DIAGRAM_POINTER || typeof window.DIAGRAM_POINTER.attach !== 'function' || !(window.DIAGRAM_POINTER.VERSION >= 2)) { throw new Error('Diagram gesture support is missing. Load diagrams-pointer.js (v2) before the figure builder.'); } const M = { seed: { label: 'authored seed', n1: 'grammar · behavior', n2: 'loading path · return contract' }, bound: { tag: 'loading boundary', q: 'does the authored seed remain governing?' }, // conforming branch grammar: { label: 'grammar', note: 'grants the aperture' }, runtime: { label: 'runtime', note: 'opaque to the author — the hard case' }, interact:{ label: 'generated interaction', note: 'realizes inside the aperture' }, ret: { label: 'return', note: 'application-specific' }, outside: { tag: 'authority + governance remain outside the thread', claim: 'a generated thread cannot self-authorize' }, // fork branch demote: { label: 'seed demoted', n1: 'to source material', n2: 'reconcile · retarget · rewrite' }, deriv: { label: 'derivative grammar', note: 'authored in the runtime' }, borrow: { label: 'borrowed shape', n1: '+ causal provenance', n2: 'governing role not carried' }, noncon: { label: 'nonconforming derivative', n1: 'not an instance of the', n2: 'authored interface' }, forkTag: 'fork-at-load', conformTag: 'conforming instance', claimA: 'seed provenance ≠ seed conformance', claimB: 'morphology ≠ behavioral conformance', // overlays elicit: { h: 'example // governed elicitation', l1: 'stop + capture >> status-bearing record', l2: 'recipient governance >> classification · validation · selection · closure · durable handling' }, pcs: { h: 'negative pressure case // PCS · 2026-07-09', l1: 'setup prompt + prior exports >> runtime reconciliation', l2: 'borrowed _BOOTSTRAP / _INDEX morphology', l3: 'not a conforming PCS instance' }, }; const svgNS = 'http://www.w3.org/2000/svg'; const W = 1900, H = 880; const svg = document.getElementById('svg'); svg.setAttribute('width', W); svg.setAttribute('height', H); svg.setAttribute('viewBox', `0 0 ${W} ${H}`); while (svg.firstChild) svg.removeChild(svg.firstChild); function el(name, attrs = {}, kids = []) { const e = document.createElementNS(svgNS, name); for (const [k, v] of Object.entries(attrs)) if (v != null) e.setAttribute(k, v); for (const c of kids) e.appendChild(typeof c === 'string' ? document.createTextNode(c) : c); return e; } const edges = el('g', { class: 'edges' }), nodes = el('g', { class: 'nodes' }); svg.append(edges, nodes); const AH = 9; const headR = (x, y, cls='edge-arrowhead') => el('path', { class: cls, d: `M ${x-AH} ${y-AH/1.6} L ${x-AH} ${y+AH/1.6} L ${x} ${y} Z` }); const box = (x, y, w, h, cls='node-box') => el('rect', { x, y, width:w, height:h, rx:4, ry:4, class:cls }); const line = (d, cls='edge', dash=null) => el('path', { class:cls, fill:'none', d, 'stroke-dasharray':dash }); const lbl = (x, y, t, cls='node-label', a='start') => el('text', { x, y, class:cls, 'text-anchor':a }, [t]); const note = (x, y, t, a='start', cls='node-note') => el('text', { x, y, class:cls, 'text-anchor':a }, [t]); const tag = (x, y, t, a='middle') => el('text', { x, y, class:'flow-tag', 'text-anchor':a }, [t]); /* ===== grid ===== */ const SPINE = 430; // single origin axis (seed → boundary) const YM = 276, YF = 604; // conforming branch / fork branch const BX = 486; // loading boundary const COL = [612, 928, 1244, 1560]; const NW = 252; // node width const H2 = 58, H3 = 78; // two-line / three-line node heights const BRK_Y = YM - 74; // authority/governance bracket level — shared by the conforming-path header /* ===== authored seed — single origin, NEUTRAL ===== */ nodes.append(box(126, SPINE - H3/2, 254, H3)); nodes.append(lbl(146, SPINE - 16, M.seed.label)); nodes.append(note(146, SPINE + 4, M.seed.n1)); nodes.append(note(146, SPINE + 23, M.seed.n2)); edges.append(line(`M 380 ${SPINE} L ${BX-16} ${SPINE}`)); edges.append(headR(BX - 12, SPINE)); /* ===== the loading boundary — the seam this figure exists to show ===== */ /* The dashed seam starts BELOW its question caption so no text crosses the rule. */ edges.append(el('path', { class:'section-rule', d:`M ${BX} ${YM - 84} L ${BX} ${YF + 112}`, 'stroke-dasharray':'3 4' })); nodes.append(tag(BX, YM - 122, M.bound.tag)); nodes.append(note(BX, YM - 104, M.bound.q, 'middle')); /* Branch out of the boundary: up = conforming, down = fork (broken continuity). Orthogonal (cartesian) split — a straight stub out of the seam, then a right-angle riser to each branch line — rather than a curve. */ edges.append(line(`M ${BX} ${SPINE} L ${BX+52} ${SPINE} L ${BX+52} ${YM} L ${COL[0]-16} ${YM}`)); edges.append(headR(COL[0] - 12, YM)); edges.append(line(`M ${BX} ${SPINE} L ${BX+52} ${SPINE} L ${BX+52} ${YF} L ${COL[0]-16} ${YF}`, 'edge held')); edges.append(headR(COL[0] - 12, YF, 'edge-arrowhead held')); /* Branch tags read as path HEADERS, centred over the first node box of each branch: "conforming instance" rises to the authority/governance bracket level (BRK_Y), so it reads as the conforming path's header — parallel to that bracket — and breathes clear of the grammar box; "fork-at-load" sits centred below the seed-demoted box. */ nodes.append(tag(COL[0] + NW/2, BRK_Y, M.conformTag, 'middle')); nodes.append(el('text', { x: COL[0] + NW/2, y: YF + 58, class:'flow-tag node-label-held', 'text-anchor':'middle' }, [M.forkTag])); /* ===== conforming branch — NEUTRAL, except the licensed legislative grammar box ===== */ // 1 · grammar (LEGISLATIVE — doctrine: the grammar grants the aperture) nodes.append(box(COL[0], YM - H2/2, NW, H2, 'node-box fn-leg')); nodes.append(lbl(COL[0] + 20, YM - 6, M.grammar.label)); nodes.append(note(COL[0] + 20, YM + 14, M.grammar.note)); // 2 · runtime nodes.append(box(COL[1], YM - H2/2, NW, H2)); nodes.append(lbl(COL[1] + 20, YM - 6, M.runtime.label)); nodes.append(note(COL[1] + 20, YM + 14, M.runtime.note)); // 3 · generated interaction nodes.append(box(COL[2], YM - H2/2, NW, H2)); nodes.append(lbl(COL[2] + 20, YM - 6, M.interact.label)); nodes.append(note(COL[2] + 20, YM + 14, M.interact.note)); // 4 · return nodes.append(box(COL[3], YM - H2/2, NW, H2)); nodes.append(lbl(COL[3] + 20, YM - 6, M.ret.label)); nodes.append(note(COL[3] + 20, YM + 14, M.ret.note)); for (let i = 0; i < 3; i++) { edges.append(line(`M ${COL[i]+NW} ${YM} L ${COL[i+1]-16} ${YM}`)); edges.append(headR(COL[i+1] - 12, YM)); } /* authority + governance sit OUTSIDE the generated thread — dashed bracket above. BRK_Y is defined with the grid; the conforming-path header shares that level. */ edges.append(line(`M ${COL[1]} ${BRK_Y+14} L ${COL[1]} ${BRK_Y} L ${COL[3]+NW} ${BRK_Y} L ${COL[3]+NW} ${BRK_Y+14}`, 'edge held')); /* Both labels sit CLEAR ABOVE the bracket rule. .node-note is dominant-baseline:middle, so a note at BRK_Y-4 centres 4px above the rule and its body crosses it — which rendered as a strikethrough through "a generated thread cannot self-authorize". Caught in the exported raster, not by any bbox check. */ nodes.append(tag((COL[1] + COL[3] + NW) / 2, BRK_Y - 36, M.outside.tag)); nodes.append(note((COL[1] + COL[3] + NW) / 2, BRK_Y - 17, M.outside.claim, 'middle')); /* governed-elicitation overlay — ONE application, not the universal return shape */ const EY = YM + 74; nodes.append(el('text', { x: COL[2], y: EY, class:'flow-tag', 'text-anchor':'start' }, [M.elicit.h])); nodes.append(note(COL[2], EY + 19, M.elicit.l1)); nodes.append(note(COL[2], EY + 37, M.elicit.l2)); /* ===== fork branch — dashed / muted throughout (.held); no colour, no alarm chrome ===== */ const HB = 'node-box held', HL = 'node-label held'; nodes.append(box(COL[0], YF - H3/2, NW, H3, HB)); nodes.append(lbl(COL[0] + 20, YF - 16, M.demote.label, HL)); nodes.append(note(COL[0] + 20, YF + 4, M.demote.n1)); nodes.append(note(COL[0] + 20, YF + 23, M.demote.n2)); nodes.append(box(COL[1], YF - H2/2, NW, H2, HB)); nodes.append(lbl(COL[1] + 20, YF - 6, M.deriv.label, HL)); nodes.append(note(COL[1] + 20, YF + 14, M.deriv.note)); nodes.append(box(COL[2], YF - H3/2, NW, H3, HB)); nodes.append(lbl(COL[2] + 20, YF - 16, M.borrow.label, HL)); nodes.append(note(COL[2] + 20, YF + 4, M.borrow.n1)); nodes.append(note(COL[2] + 20, YF + 23, M.borrow.n2)); nodes.append(box(COL[3], YF - H3/2, NW, H3, HB)); nodes.append(lbl(COL[3] + 20, YF - 16, M.noncon.label, HL)); nodes.append(note(COL[3] + 20, YF + 4, M.noncon.n1)); nodes.append(note(COL[3] + 20, YF + 23, M.noncon.n2)); for (let i = 0; i < 3; i++) { edges.append(line(`M ${COL[i]+NW} ${YF} L ${COL[i+1]-16} ${YF}`, 'edge held')); edges.append(headR(COL[i+1] - 12, YF, 'edge-arrowhead held')); } /* the two load-bearing non-identities, on the branch they govern */ nodes.append(tag((COL[1] + NW + COL[2]) / 2, YF - 58, M.claimA)); nodes.append(tag((COL[2] + NW + COL[3]) / 2, YF - 58, M.claimB)); /* PCS negative pressure case — evidence note beside the fork branch */ const PY = YF + 82; nodes.append(el('text', { x: COL[0], y: PY, class:'flow-tag', 'text-anchor':'start' }, [M.pcs.h])); nodes.append(note(COL[0], PY + 19, M.pcs.l1)); nodes.append(note(COL[0], PY + 37, M.pcs.l2)); nodes.append(note(COL[0], PY + 55, M.pcs.l3)); /* ===== tighten the viewBox to drawn content (+ uniform margin), as the sibling figure ===== */ const VB_PAD = 30; const bb = svg.getBBox(); const vbX = Math.floor(bb.x - VB_PAD), vbY = Math.floor(bb.y - VB_PAD); const vbW = Math.ceil(bb.width + 2*VB_PAD), vbH = Math.ceil(bb.height + 2*VB_PAD); svg.setAttribute('viewBox', `${vbX} ${vbY} ${vbW} ${vbH}`); svg.setAttribute('width', vbW); svg.setAttribute('height', vbH); /* ---- pan / zoom / fit + drag + wheel (the camera is local; FIT and gestures are DS-owned) ---- */ const wrap = document.getElementById('canvasWrap'), stage = document.getElementById('stage'), pct = document.getElementById('zoomPct'); if (wrap && stage) { let tx=0, ty=0, sc=1; /* Interaction floor. Ordinary zoom-out floor is this figure's historical 0.2 base, but the DS panel-aware fit can land BELOW it on a constrained viewport; a fixed floor above the fitted scale would make zoom-out ENLARGE the figure (direction reversal). So the live floor is the lower of the base and the most recent Fit. Every fit applied sets it from its result — the reader's Fit, and the automatic refits of a view at Fit. */ const BASE_MIN_SCALE = 0.2; let fittedMinScale = BASE_MIN_SCALE; /* FIT MODE (design-system-ASK responsive chrome). The view is at Fit after fit() and until the reader zooms, drags or wheels. Only a view at Fit follows a resize, the webfonts landing, or `diagram-chrome-change` from diagrams-chrome.js (a caption or legend opening or closing, the compact layout switching, its control band changing). A reader's own pan and zoom is not reset by a browser-toolbar resize or a disclosure. */ let atFit = true; const apply = () => { stage.style.transform = `translate(${tx}px,${ty}px) scale(${sc})`; if (pct) pct.textContent = Math.round(sc*100)+'%'; }; /* Fit is DS-owned (diagrams-fit.js; presence checked at the top of this file). This figure's interim local realization — the one routed as `2026-07-18_method-ASK_to_design-system-ASK_diagram-fit-reserves-panel-band` — has been RETIRED: design-system-ASK adopted the panel-band default (PR #77), and method-ASK vendored it (PR #122). What landed upstream is stronger than the proposal: reservation is overlap-gated (a placement that already clears the chrome is returned untouched) and edge-aware (four edges, so chrome is reserved along the edge it actually occupies). CALLER-OWNED, not DS defaults, carried over from the interim implementation: clearanceX 90 (DS default 80), clearanceY 20 — this figure is width-limited and deliberately spends less vertical clearance than its sibling — and maxScale 1.3 (DS default 1.2). Bounds start at ZERO although the tightened viewBox origin above is negative: the transform target is the stage div, whose box starts at 0 in CSS space, so the viewBox origin never enters the transform. */ const fitResult = () => window.DIAGRAM_FIT.compute({ wrap, bounds: { minX: 0, minY: 0, maxX: vbW, maxY: vbH }, clearanceX: 90, clearanceY: 20, maxScale: 1.3, gutter: 26, /* v3 (diagrams-fit.js): centre vertically between the chrome above and below the figure, and cap the clearance while the responsive chrome is compact. */ balance: true, compactClearance: 32 }); const applyFit = (f) => { fittedMinScale = Math.min(BASE_MIN_SCALE, f.scale); sc = f.scale; tx = f.tx; ty = f.ty; atFit = true; apply(); }; /* The page's responsive chrome (diagrams-chrome.js): its open compact panel, the Fit the reader returns to when that panel closes, and its one truthful way to close it. An open panel moves the drawing only where the drawing keeps its closed-panel size; otherwise the drawing keeps that closed-panel Fit and the panel overlays it until it closes. */ const chrome = window.DIAGRAM_CHROME || null; /* FAIL-CLOSED with the chrome: its edge declaration needs diagrams-fit.js v2. */ if (chrome && !(window.DIAGRAM_FIT.VERSION >= 2)) throw new Error('The responsive chrome needs the current diagrams-fit.js. Re-vendor it with diagrams-chrome.js.'); const panelOpen = () => !!(chrome && chrome.openPanel(wrap)); const closedFit = () => (chrome ? chrome.withoutOpenPanel(wrap, fitResult) : fitResult()); const keepsSize = (f, c) => f.clear && f.scale >= c.scale * (1 - 1e-6); const fitAround = () => { const f = fitResult(); if (!panelOpen()) return f; const c = closedFit(); return keepsSize(f, c) ? f : c; }; /* FIT, the reader's request, always ends at a usable fitted view: when the open compact panel would cover the drawing, Fit closes it through the chrome's state controller and fits against the chrome that remains. */ const fit = () => { if (panelOpen()) { const f = fitResult(); if (keepsSize(f, closedFit())) { applyFit(f); return; } chrome.close(wrap); } applyFit(fitResult()); }; /* A resize, the webfonts landing or a chrome change refits only a view at Fit, by the same open-panel rule. */ const refitAtFit = () => { if (atFit) applyFit(fitAround()); }; /* Refit once the webfonts land — the helper measures the live caption / legend / HUD rectangles and the vendored faces use `font-display: swap`. Same treatment as the sibling figure. */ fit(); const fonts = document.fonts; if (fonts && fonts.ready && typeof fonts.ready.then === 'function') { fonts.ready.then(refitAtFit).catch(() => {}); } window.addEventListener('resize', refitAtFit); wrap.addEventListener('diagram-chrome-change', refitAtFit); const zi=document.getElementById('zoomIn'), zo=document.getElementById('zoomOut'), zf=document.getElementById('zoomFit'); /* The view leaves Fit only when the reader moves it: a zoom at its limit changes nothing, and a press that stays inside the pointer controller's tap slop is a tap. */ const zoomTo = (s) => { if (s === sc) return; sc = s; atFit = false; apply(); }; if (zi) zi.onclick=()=>zoomTo(Math.min(sc*1.2,4)); if (zo) zo.onclick=()=>zoomTo(Math.max(sc/1.2,fittedMinScale)); if (zf) zf.onclick=fit; /* GESTURES through the design-system pointer controller (diagrams-pointer.js, checked at the top of this file): one pointer pans from anywhere on the drawing, two pinch about their centroid, a wheel zooms about the pointer. The canvas carries `touch-action: none` (diagrams.css), so a touch gesture there moves the drawing, never the page. A press on the HUD or the chrome block stays native, and a wheel over the chrome block scrolls an open panel unless it is a trackpad pinch (ctrlKey). A moved gesture swallows its own click. */ const clampK = (k) => Math.max(fittedMinScale, Math.min(4, k)); window.DIAGRAM_POINTER.attach({ stage: wrap, exclude: '.hud, .legend, .caption, .diagram-info', wheelStep: 1.1, clampK, getView: () => ({ k: sc, x: tx, y: ty }), setView: (v) => { /* A gesture that moves the view takes it off Fit; float noise from a still pinch does not. */ if (Math.abs(v.k - sc) > 1e-9 * sc || Math.abs(v.x - tx) > 1e-6 || Math.abs(v.y - ty) > 1e-6) atFit = false; sc = v.k; tx = v.x; ty = v.y; apply(); }, zoomAt: (f, mx, my) => { const ns = clampK(sc*f); if (ns === sc) return; const k = ns/sc; tx = mx-(mx-tx)*k; ty = my-(my-ty)*k; sc = ns; atFit = false; apply(); } }); } })();