betterwithage Claude Opus 4.7 commited on
Commit
6a3fdca
·
verified ·
1 Parent(s): 8cce9cd

deploy(hf): sync szl-holdings/a11oy@main derived COPY set

Browse files

Reusable Dockerfile-COPY-derived deploy from szl-holdings/a11oy main.
Files: 930 Pruned: 0
Derived from Dockerfile COPY sources (NO hand-maintained allowlist).

Signed-off-by: SZL Holdings <noreply@szlholdings.ai>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

static/3d/holographic.html CHANGED
@@ -173,6 +173,7 @@ const SURFACES = [
173
  { id: "aigov", title: "AI Governance Conformance · Λ-Advisory Readiness (crosswalk)", mod: "/static/3d/surfaces/aigov.js" },
174
  { id: "fmverif", title: "Proof-Carrying Inference (Machine-Checkable Certificates)", mod: "/static/3d/surfaces/fmverif.js" },
175
  { id: "supplychain", title: "Model-Artifact Provenance (SLSA / in-toto / Rekor / C2PA)", mod: "/static/3d/surfaces/supplychain.js" },
 
176
  ];
177
 
178
  const stageEl = document.getElementById("stage");
 
173
  { id: "aigov", title: "AI Governance Conformance · Λ-Advisory Readiness (crosswalk)", mod: "/static/3d/surfaces/aigov.js" },
174
  { id: "fmverif", title: "Proof-Carrying Inference (Machine-Checkable Certificates)", mod: "/static/3d/surfaces/fmverif.js" },
175
  { id: "supplychain", title: "Model-Artifact Provenance (SLSA / in-toto / Rekor / C2PA)", mod: "/static/3d/surfaces/supplychain.js" },
176
+ { id: "hybridssm", title: "HybridSSM · Attention vs State-Space vs Hybrid Frontier (synthesis)", mod: "/static/3d/surfaces/hybridssm.js" },
177
  ];
178
 
179
  const stageEl = document.getElementById("stage");
static/3d/surfaces/hybridssm.js ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // © 2026 Lutar, Stephen P. — SZL Holdings · ORCID 0009-0001-0110-4173 · Doctrine v11
3
+ //
4
+ // surfaces/hybridssm.js — HYBRIDSSM: a MODELED comparison of attention vs
5
+ // state-space (SSM) vs hybrid (Jamba / Griffin / Samba / Zamba) architectures on
6
+ // the compute / memory frontier. Each architecture is a lane; a polyline traces
7
+ // its KV-cache memory (Y, log-scaled) across a sweep of context lengths (X). A
8
+ // dense-attention baseline climbs steeply (lattice-blue) as its KV cache grows
9
+ // linearly with context; a pure SSM stays flat on the floor (proof-teal — a
10
+ // constant recurrent state, no growing KV); the hybrids sit between (violet-blue),
11
+ // keeping a MINORITY of attention layers to recover long-context recall at a
12
+ // fraction of the memory. Node size = an ILLUSTRATIVE long-context recall proxy
13
+ // (NOT a benchmark). Live snapshot:
14
+ // /api/a11oy/v1/frontier/hybridssm
15
+ //
16
+ // This is a MODELED architecture-frontier picture, honestly labeled:
17
+ // ANALYTIC cost curves — KV-cache memory (2·d·L·bytes per global-attn layer,
18
+ // windowed for sliding attention, constant state for SSM) and per-token decode
19
+ // FLOPs (constant backbone + ~4·d·ctx per attention layer + constant SSM scan)
20
+ // — plus an illustrative recall proxy. NO measured benchmark numbers.
21
+ //
22
+ // LEADERS CITED (clean-room; NOT claimed as SZL's own):
23
+ // Mamba — Gu & Dao 2023, arXiv:2312.00752
24
+ // Jamba — Lieber et al. 2024, arXiv:2403.19887
25
+ // Griffin — De et al. 2024, arXiv:2402.19427
26
+ // Samba — Ren et al. 2024, arXiv:2406.07522
27
+ // Zamba — Glorioso et al. 2024, arXiv:2405.16712
28
+ //
29
+ // HONESTY LABELS: MODELED (analytic KV / FLOPs curves computed from documented
30
+ // architecture compositions + stated cost coefficients; read VERBATIM from
31
+ // JSON, never upgraded). The recall proxy is ILLUSTRATIVE, NOT a benchmark. The
32
+ // per-arch compositions and the Λ-advisory pick are CONJECTURE (Λ = Conjecture
33
+ // 1, gray, never green; advisory trust capped ≤0.97). Curves are MODELED, NOT
34
+ // MEASURED (no profiler / no hardware).
35
+ // COLOURS: lattice-blue 0x5b8dee (dense attention baseline), proof-teal 0x3af4c8
36
+ // (pure SSM / Mamba), violet-blue 0x8a6bff (hybrids), greys (degraded / no data).
37
+ // Purple BANNED.
38
+ // 0 RUNTIME CDN. three.js via ctx.THREE (vendored by the page importmap).
39
+ // DOCTRINE v11: degrades gracefully (grey) on 404/error; honesty label still shown.
40
+ // Nothing here is in the locked-8 (adds 0). Λ stays Conjecture 1. Trust never 100%.
41
+
42
+ import { createShowcase } from "./_showcase.js";
43
+
44
+ const ID = "hybridssm";
45
+ const TITLE = "HybridSSM · Attention vs State-Space vs Hybrid Frontier (live)";
46
+
47
+ // Served SAME-ORIGIN by szl_hybridssm.py — a deterministic MODELED cost model.
48
+ const EP = "/api/a11oy/v1/frontier/hybridssm?d_model=4096&n_layers=32";
49
+
50
+ // data-viz hues — purple BANNED
51
+ const C_ATTN = 0x5b8dee; // lattice-blue (dense attention baseline)
52
+ const C_SSM = 0x3af4c8; // proof-teal (pure SSM / Mamba)
53
+ const C_HYB = 0x8a6bff; // violet-blue (hybrid family)
54
+ const C_DIM = 0x42505d; // grey (degraded / no live data)
55
+ const C_GRID = 0x1b3a44; // floor / link colour
56
+
57
+ // layout geometry
58
+ const MAX_ARCH = 8; // pre-allocated architecture lanes
59
+ const MAX_PTS = 16; // pre-allocated points per lane (seq-length sweep)
60
+ const X_STEP = 1.7; // spacing between seq-length nodes along X
61
+ const Z_STEP = 2.3; // spacing between architecture lanes along Z
62
+ const Y_SCALE = 1.9; // log10(MB+1) -> world Y
63
+
64
+ let _stage = null, _THREE = null, _ctx = null, _group = null, _show = null;
65
+ let _frameReg = false, _polls = [], _badge = null, _f = {};
66
+
67
+ // geometry handles — pre-allocated lanes; each lane has a polyline + point meshes.
68
+ let _floor = null;
69
+ let _lanes = []; // Array<{ line, pts: THREE.Mesh[], endMesh }>
70
+
71
+ const S = {
72
+ label: null,
73
+ dModel: null, nLayers: null, bytesPerElem: null, stateDim: null,
74
+ seqLengths: null,
75
+ archs: null, // architectures[]
76
+ frontier: null,
77
+ advisory: null,
78
+ state: "init",
79
+ };
80
+
81
+ function _colorFor(name) {
82
+ if (name === "attention") return C_ATTN;
83
+ if (name === "mamba") return C_SSM;
84
+ return C_HYB; // jamba / griffin / samba / zamba (hybrid family)
85
+ }
86
+
87
+ // =============================================================================
88
+ // mount(ctx)
89
+ // =============================================================================
90
+ export function mount(ctx) {
91
+ _ctx = ctx; _stage = ctx.stage; _THREE = ctx.THREE;
92
+ _group = new _THREE.Group();
93
+ _stage.scene.add(_group);
94
+ _stage.camera.position.set(2, 11, 24);
95
+ try { if (_stage.controls && _stage.controls.target) { _stage.controls.target.set(0, 3.2, 0); _stage.controls.update(); } } catch (_) {}
96
+ try { _stage.setBloom(true); } catch (_) {}
97
+
98
+ _buildFloor();
99
+ _buildLanes();
100
+
101
+ if (!_frameReg && _stage.onFrame) { _stage.onFrame(_onFrame); _frameReg = true; }
102
+
103
+ _badge = ctx.live.createBadge();
104
+ _buildShowcase(ctx);
105
+
106
+ // top-N lane labels (billboarded) + hover tooltip via the shared helper.
107
+ // Label the endpoint node of each lane; weight by KV memory so the steep
108
+ // attention lane ranks first.
109
+ _show.attachSceneLabels({
110
+ objects: () => _lanes.map((l) => l.endMesh).filter((m) => m && m.visible),
111
+ text: (o) => (o && o.userData && o.userData.label) || "",
112
+ weight: (o) => (o && o.userData ? o.userData.weight : 0),
113
+ topN: MAX_ARCH,
114
+ hover: true,
115
+ });
116
+
117
+ _polls.push(ctx.live.poll(EP, 8000, _onData, {
118
+ badge: _badge, onState: (m) => { S.state = m.state; _paint(); },
119
+ }));
120
+ return { id: ID, started: true };
121
+ }
122
+
123
+ // =============================================================================
124
+ // builders
125
+ // =============================================================================
126
+ function _buildFloor() {
127
+ const THREE = _THREE;
128
+ const grid = new THREE.GridHelper(44, 44, C_GRID, 0x0f2027);
129
+ grid.material.opacity = 0.18; grid.material.transparent = true; grid.position.y = -0.01;
130
+ _group.add(grid);
131
+ _floor = grid;
132
+ }
133
+
134
+ // Pre-allocate MAX_ARCH lanes, each with a polyline (KV-memory curve) and
135
+ // MAX_PTS point meshes. Everything hidden until live data arrives.
136
+ function _buildLanes() {
137
+ const THREE = _THREE;
138
+ const ptGeo = new THREE.SphereGeometry(0.16, 10, 10);
139
+ for (let a = 0; a < MAX_ARCH; a++) {
140
+ const pts = [];
141
+ for (let i = 0; i < MAX_PTS; i++) {
142
+ const mesh = new THREE.Mesh(
143
+ ptGeo,
144
+ new THREE.MeshStandardMaterial({ color: C_DIM, emissive: C_DIM, emissiveIntensity: 0.2, transparent: true, opacity: 0.0 }),
145
+ );
146
+ mesh.visible = false;
147
+ mesh.userData = { label: "", weight: 0 };
148
+ _group.add(mesh);
149
+ pts.push(mesh);
150
+ }
151
+ const lgeo = new THREE.BufferGeometry();
152
+ lgeo.setAttribute("position", new THREE.BufferAttribute(new Float32Array(MAX_PTS * 3), 3));
153
+ lgeo.setDrawRange(0, 0);
154
+ const lmat = new THREE.LineBasicMaterial({ color: C_DIM, transparent: true, opacity: 0.0 });
155
+ const line = new THREE.Line(lgeo, lmat);
156
+ line.visible = false;
157
+ _group.add(line);
158
+ _lanes.push({ line, pts, endMesh: pts[0] });
159
+ }
160
+ }
161
+
162
+ // =============================================================================
163
+ // live data handler
164
+ // =============================================================================
165
+ function _onData(j) {
166
+ const p = (j && typeof j.payload === "object" && j.payload) ? j.payload : j;
167
+ const rawLabel = (j && j.label) || (p && p.label) || "MODELED";
168
+ S.label = String(rawLabel).toUpperCase();
169
+
170
+ S.dModel = typeof p.d_model === "number" ? p.d_model : null;
171
+ S.nLayers = typeof p.n_layers === "number" ? p.n_layers : null;
172
+ S.bytesPerElem = typeof p.bytes_per_elem === "number" ? p.bytes_per_elem : null;
173
+ S.stateDim = typeof p.state_dim === "number" ? p.state_dim : null;
174
+ S.seqLengths = Array.isArray(p.seq_lengths) ? p.seq_lengths : null;
175
+ S.archs = Array.isArray(p.architectures) ? p.architectures : null;
176
+ S.frontier = (p && typeof p.frontier === "object") ? p.frontier : null;
177
+ S.advisory = (p && typeof p.advisory === "object") ? p.advisory : null;
178
+
179
+ _updateScene();
180
+ _paint();
181
+ }
182
+
183
+ // =============================================================================
184
+ // geometry updater
185
+ // =============================================================================
186
+ function _updateScene() {
187
+ const live = S.state === "live";
188
+ const archs = live && S.archs ? S.archs.slice(0, MAX_ARCH) : [];
189
+ const nSeq = S.seqLengths ? Math.min(S.seqLengths.length, MAX_PTS) : 0;
190
+ const xMid = (nSeq - 1) / 2;
191
+ const zMid = (Math.max(1, archs.length) - 1) / 2;
192
+
193
+ for (let a = 0; a < MAX_ARCH; a++) {
194
+ const lane = _lanes[a];
195
+ const arch = a < archs.length ? archs[a] : null;
196
+ if (!arch || !arch.curve || nSeq === 0) {
197
+ lane.line.visible = false;
198
+ lane.pts.forEach((m) => { m.visible = false; });
199
+ continue;
200
+ }
201
+ const col = live ? _colorFor(arch.name) : C_DIM;
202
+ const z = (a - zMid) * Z_STEP;
203
+ const curve = arch.curve;
204
+ const posAttr = lane.line.geometry.getAttribute("position");
205
+ let drawn = 0;
206
+ let endIdx = 0;
207
+
208
+ for (let i = 0; i < MAX_PTS; i++) {
209
+ const mesh = lane.pts[i];
210
+ const pt = i < nSeq && i < curve.length ? curve[i] : null;
211
+ if (!pt) { mesh.visible = false; continue; }
212
+ const mb = typeof pt.kv_cache_mb === "number" ? pt.kv_cache_mb : 0;
213
+ const recall = typeof pt.recall_proxy === "number" ? pt.recall_proxy : 0.5;
214
+ const x = (i - xMid) * X_STEP;
215
+ const y = Math.log10(mb + 1) * Y_SCALE;
216
+ mesh.position.set(x, y, z);
217
+ mesh.visible = true;
218
+ mesh.material.color.setHex(col);
219
+ mesh.material.emissive.setHex(col);
220
+ mesh.material.emissiveIntensity = live ? 0.5 : 0.12;
221
+ mesh.material.opacity = live ? 0.95 : 0.3;
222
+ // node size encodes the illustrative recall proxy (bigger = better recall).
223
+ mesh.scale.setScalar(0.55 + recall * 1.4);
224
+ mesh.userData.label = "";
225
+ mesh.userData.weight = 0;
226
+ posAttr.array[drawn * 3] = x;
227
+ posAttr.array[drawn * 3 + 1] = y;
228
+ posAttr.array[drawn * 3 + 2] = z;
229
+ drawn++;
230
+ endIdx = i;
231
+ }
232
+
233
+ posAttr.needsUpdate = true;
234
+ lane.line.geometry.setDrawRange(0, drawn);
235
+ lane.line.geometry.computeBoundingSphere();
236
+ lane.line.visible = drawn > 1;
237
+ lane.line.material.color.setHex(col);
238
+ lane.line.material.opacity = live ? 0.55 : 0.12;
239
+
240
+ // endpoint node carries the lane label (arch name + KV at seq_max).
241
+ const endMesh = lane.pts[endIdx];
242
+ lane.endMesh = endMesh;
243
+ const summ = arch.summary || {};
244
+ const kvEnd = typeof summ.kv_cache_mb === "number" ? summ.kv_cache_mb : null;
245
+ endMesh.userData.label = arch.name + (kvEnd != null ? " · " + _mb(kvEnd) : "");
246
+ endMesh.userData.weight = kvEnd != null ? kvEnd : 0;
247
+ }
248
+ }
249
+
250
+ // =============================================================================
251
+ // per-frame animation
252
+ // =============================================================================
253
+ function _onFrame() {
254
+ const t = (typeof performance !== "undefined" ? performance.now() : Date.now());
255
+ if (_group) _group.rotation.y = Math.sin(t * 0.00006) * 0.10;
256
+ }
257
+
258
+ // =============================================================================
259
+ // showcase overlay (shared helper) — compact chrome + collapsible KPIs
260
+ // =============================================================================
261
+ function _buildShowcase(ctx) {
262
+ _show = createShowcase(ctx, {
263
+ id: ID,
264
+ title: TITLE,
265
+ accent: "#5b8dee",
266
+ badge: _badge,
267
+ chips: [
268
+ { label: "MODELED", text: "cost curves", name: "cost" },
269
+ { label: "STRUCTURAL-ONLY", text: "Λ=Conjecture 1 · recall proxy illustrative", name: "syn" },
270
+ ],
271
+ legend: ["MODELED", "STRUCTURAL-ONLY"],
272
+ description:
273
+ "<b>HybridSSM.</b> Each lane is an architecture; its polyline traces the " +
274
+ "<b>KV-cache memory</b> (log Y) across a sweep of context lengths (X). " +
275
+ "Dense <b>attention</b> (lattice-blue) climbs steeply — its KV cache grows " +
276
+ "linearly with context. A pure <b>SSM</b> (Mamba, proof-teal) stays on the " +
277
+ "floor: a constant recurrent state, no growing KV. The <b>hybrids</b> " +
278
+ "(Jamba / Griffin / Samba / Zamba, violet-blue) keep a minority of " +
279
+ "attention layers to recover long-context recall at a fraction of the " +
280
+ "memory. Node size = an <b>illustrative long-context recall proxy</b> — a " +
281
+ "coverage model, <b>NOT a benchmark</b>. The KV-memory and per-token " +
282
+ "decode-FLOPs curves are <b>MODELED (analytic), not MEASURED</b> — no " +
283
+ "profiler or hardware is involved.",
284
+ citations:
285
+ "Mamba arXiv:2312.00752 · Jamba arXiv:2403.19887 · Griffin arXiv:2402.19427 · " +
286
+ "Samba arXiv:2406.07522 · Zamba arXiv:2405.16712. " +
287
+ "MODELED/CONJECTURE · not claimed-as. Nothing here is in the locked-8.",
288
+ plain: {
289
+ html: () =>
290
+ "Big language models remember their context in a <b>KV cache</b> that grows " +
291
+ "with the length of the text — so very long prompts cost a lot of memory. " +
292
+ "<b>State-space models</b> (like Mamba) instead keep a small fixed summary, " +
293
+ "so they stay cheap, but a fixed summary can forget exact details far back. " +
294
+ "<b>Hybrids</b> mix a few attention layers into a state-space backbone to " +
295
+ "get the best of both: near-attention recall at a fraction of the memory. " +
296
+ "This view models that trade-off — the curves are calculated from each " +
297
+ "design, <b>not measured</b>, and the recall dots are illustrative, not a " +
298
+ "benchmark score.",
299
+ },
300
+ });
301
+
302
+ _f.ref = _show.addField("reference model (MODELED)", "ref");
303
+ _f.attnKv = _show.addField("attention KV @ seq_max", "attnKv");
304
+ _f.ssmKv = _show.addField("SSM (Mamba) KV @ seq_max", "ssmKv");
305
+ _f.hybKv = _show.addField("best hybrid KV @ seq_max", "hybKv");
306
+ _f.kvRed = _show.addField("KV reduction vs attention", "kvRed");
307
+ _f.flRed = _show.addField("decode-FLOPs reduction", "flRed");
308
+ _f.advise = _show.addField("Λ-advisory pick (gray)", "advise");
309
+ _f.trust = _show.addField("advisory trust (≤0.97)", "trust");
310
+ _f.recall = _show.addField("recall proxy (illustrative)", "recall");
311
+ _f.label = _show.addField("honesty label", "label");
312
+ _paint();
313
+ }
314
+
315
+ function _tok(s) {
316
+ if (s === "live") return null;
317
+ if (s === "missing") return "NO-LIVE-DATA";
318
+ if (s === "degraded") return "DEGRADED";
319
+ if (s === "error") return "OFFLINE";
320
+ return "…";
321
+ }
322
+
323
+ function _mb(v) {
324
+ if (typeof v !== "number") return "—";
325
+ if (v >= 1024) return (v / 1024).toFixed(2) + " GB";
326
+ if (v >= 1) return v.toFixed(1) + " MB";
327
+ return v.toFixed(3) + " MB";
328
+ }
329
+ function fx(v, d) { return typeof v === "number" ? v.toFixed(d) : "—"; }
330
+ function _archByName(n) { return (S.archs || []).find((a) => a.name === n) || null; }
331
+
332
+ function _paint() {
333
+ if (!_show) return;
334
+ const t = _tok(S.state);
335
+ if (_show.setChip) _show.setChip("cost", S.label || "MODELED", { text: "cost curves" });
336
+
337
+ _set("ref", t || (S.dModel != null
338
+ ? "d=" + S.dModel + " · L=" + (S.nLayers != null ? S.nLayers : "—") + " layers · bf" + (S.bytesPerElem != null ? S.bytesPerElem * 8 : "?")
339
+ : "—"));
340
+
341
+ const attn = _archByName("attention");
342
+ const ssm = _archByName("mamba");
343
+ const fr = S.frontier || {};
344
+
345
+ _set("attnKv", t || (attn && attn.summary ? _mb(attn.summary.kv_cache_mb) : "—"));
346
+ _set("ssmKv", t || (ssm && ssm.summary ? _mb(ssm.summary.kv_cache_mb) : "—"));
347
+ _set("hybKv", t || (fr.min_hybrid
348
+ ? _mb(fr.min_hybrid_kv_mb) + " (" + fr.min_hybrid + ")" : "—"));
349
+ _set("kvRed", t || (fr.best_kv_reduction_x != null ? fr.best_kv_reduction_x + "×" : "—"));
350
+ _set("flRed", t || (fr.best_flops_reduction_x != null ? fr.best_flops_reduction_x + "×" : "—"));
351
+
352
+ const adv = S.advisory || {};
353
+ _set("advise", t || (adv.recommended
354
+ ? adv.recommended + (adv.at_seq_len ? " @ " + _ctxLen(adv.at_seq_len) : "") : "—"));
355
+ _set("trust", t || (adv.trust != null
356
+ ? fx(adv.trust, 3) + (adv.trust_cap != null ? " (≤" + adv.trust_cap + ")" : "") : "—"));
357
+ _set("recall", t || (adv.recommended_recall_proxy != null
358
+ ? fx(adv.recommended_recall_proxy, 3) + " (illustrative)" : "—"));
359
+ _set("label", t || (S.label || "MODELED"));
360
+ }
361
+
362
+ function _ctxLen(n) {
363
+ if (typeof n !== "number") return "—";
364
+ if (n >= 1024) return (n / 1024) + "k";
365
+ return String(n);
366
+ }
367
+ function _set(k, v) { if (_f[k]) _f[k].textContent = v; }
368
+
369
+ // =============================================================================
370
+ // unmount — clean up everything; must not affect other organs
371
+ // =============================================================================
372
+ export function unmount() {
373
+ _polls.forEach((p) => { try { p.stop(); } catch (_) {} }); _polls = [];
374
+ try { if (_show) _show.destroy(); } catch (_) {}
375
+ try {
376
+ if (_group && _stage) {
377
+ _group.traverse((o) => {
378
+ if (o.geometry && o.geometry.dispose) o.geometry.dispose();
379
+ if (o.material) {
380
+ const ms = Array.isArray(o.material) ? o.material : [o.material];
381
+ ms.forEach((m) => { if (m.dispose) m.dispose(); });
382
+ }
383
+ });
384
+ _stage.scene.remove(_group);
385
+ }
386
+ } catch (_) {}
387
+ _group = _show = null;
388
+ _floor = null; _lanes = [];
389
+ _f = {}; _badge = null; _frameReg = false;
390
+ _stage = _THREE = _ctx = null;
391
+ S.label = S.dModel = S.nLayers = S.bytesPerElem = S.stateDim = null;
392
+ S.seqLengths = S.archs = S.frontier = S.advisory = null;
393
+ S.state = "init";
394
+ }
395
+
396
+ export default { id: ID, title: TITLE, endpoints: [EP], mount, unmount };