@descix/frqtl-node 0.0.0-stage → 0.6.0-p0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/CLAUDE.md +87 -0
  2. package/README.md +84 -2
  3. package/dist/dist-manifest.json +218 -0
  4. package/dist/eyes/index.js +109 -0
  5. package/dist/fat/pkg-node/egpt_wasm.js +1277 -0
  6. package/dist/fat/pkg-node/egpt_wasm_bg.wasm +0 -0
  7. package/dist/fat/pkg-node/package.json +12 -0
  8. package/dist/frqtl/assets/vendor/chroma.mjs +64 -0
  9. package/dist/frqtl/compat/boot-node.js +34 -0
  10. package/dist/frqtl/compat/engine.js +127 -0
  11. package/dist/frqtl/compat/package-root.js +24 -0
  12. package/dist/frqtl/compat/providers/wasm-engine.js +2501 -0
  13. package/dist/frqtl/compat/providers/wasm-load-browser.js +134 -0
  14. package/dist/frqtl/compat/providers/wasm-load-node.js +59 -0
  15. package/dist/frqtl/compat/renderer/FieldBuilder.js +145 -0
  16. package/dist/frqtl/compat/renderer/Filters.js +163 -0
  17. package/dist/frqtl/compat/renderer/RenderFamily.js +85 -0
  18. package/dist/frqtl/compat/renderer/RenderMesh.js +100 -0
  19. package/dist/frqtl/compat/renderer/RenderShape.js +154 -0
  20. package/dist/frqtl/compat/renderer/camera2d-geometry.js +183 -0
  21. package/dist/frqtl/compat/renderer/captureStill-common.js +259 -0
  22. package/dist/frqtl/compat/renderer/display-slot.js +96 -0
  23. package/dist/frqtl/compat/renderer/lo-drawn-center.js +231 -0
  24. package/dist/frqtl/compat/renderer/orbit-bag.js +216 -0
  25. package/dist/frqtl/compat/renderer/providers/godrays-layer.js +213 -0
  26. package/dist/frqtl/compat/renderer/providers/index.js +22 -0
  27. package/dist/frqtl/compat/renderer/providers/p5-provider.js +861 -0
  28. package/dist/frqtl/compat/renderer/providers/three-camera-contract.js +160 -0
  29. package/dist/frqtl/compat/renderer/providers/three-camera-geometry.js +571 -0
  30. package/dist/frqtl/compat/renderer/providers/three-provider.js +2474 -0
  31. package/dist/frqtl/compat/renderer/renderCapabilities-common.js +186 -0
  32. package/dist/frqtl/compat/renderer/renderer-provider-contract.js +238 -0
  33. package/dist/frqtl/compat/renderer/unprojectStill.js +172 -0
  34. package/dist/frqtl/compat/vendor.js +196 -0
  35. package/dist/frqtl/node-entry.js +17 -0
  36. package/dist/frqtl/objects/FrqtlApp.js +2922 -0
  37. package/dist/frqtl/objects/ObjectFactory.js +297 -0
  38. package/dist/frqtl/objects/RecipeContext.js +322 -0
  39. package/dist/frqtl/objects/collectors/DataCollector.js +116 -0
  40. package/dist/frqtl/objects/constants/WallBehaviors.js +178 -0
  41. package/dist/frqtl/objects/geometry/SlabFace.js +258 -0
  42. package/dist/frqtl/objects/instruments/capture-host.js +453 -0
  43. package/dist/frqtl/objects/instruments/capture.js +711 -0
  44. package/dist/frqtl/objects/instruments/hosted-eyes.js +985 -0
  45. package/dist/frqtl/objects/kinds-entry.js +14 -0
  46. package/dist/frqtl/objects/kinds.js +190 -0
  47. package/dist/frqtl/objects/objects/Box.js +273 -0
  48. package/dist/frqtl/objects/objects/Bullet.js +155 -0
  49. package/dist/frqtl/objects/objects/CircuitGate.js +380 -0
  50. package/dist/frqtl/objects/objects/CircuitProbe.js +214 -0
  51. package/dist/frqtl/objects/objects/DirectedTunnel.js +412 -0
  52. package/dist/frqtl/objects/objects/EgptFractal.js +164 -0
  53. package/dist/frqtl/objects/objects/LightSource.js +354 -0
  54. package/dist/frqtl/objects/objects/QuantumEmitter.js +760 -0
  55. package/dist/frqtl/objects/objects/Tube.js +471 -0
  56. package/dist/frqtl/objects/objects/absorbRadiation.js +310 -0
  57. package/dist/frqtl/objects/objects/actionCompiler.js +1747 -0
  58. package/dist/frqtl/objects/objects/controlAction.js +89 -0
  59. package/dist/frqtl/objects/objects/controlBind.js +278 -0
  60. package/dist/frqtl/objects/objects/directedRedirectProgram.js +120 -0
  61. package/dist/frqtl/objects/objects/emitterProgram.js +209 -0
  62. package/dist/frqtl/objects/objects/frqtl-control-slider.js +197 -0
  63. package/dist/frqtl/objects/objects/frqtl-control-sync.js +272 -0
  64. package/dist/frqtl/objects/objects/frqtl-control-widgets.js +219 -0
  65. package/dist/frqtl/objects/objects/frqtl-control-write-queue.js +174 -0
  66. package/dist/frqtl/objects/objects/makeControlsForObject.js +824 -0
  67. package/dist/frqtl/objects/objects/makeControlsForRenderSurface.js +161 -0
  68. package/dist/frqtl/objects/objects/slitLinerScatter.js +263 -0
  69. package/dist/frqtl/objects/objects/sustainedSource.js +299 -0
  70. package/dist/frqtl/objects/objects/tagger.js +228 -0
  71. package/dist/frqtl/objects/schema/engine-scopes.js +469 -0
  72. package/dist/frqtl/objects/schema/index.js +256 -0
  73. package/dist/frqtl/objects/schema/scopes.js +457 -0
  74. package/dist/frqtl/objects/schema/validate-descriptor.js +49 -0
  75. package/dist/frqtl/objects/schema/valueNormalizer.js +366 -0
  76. package/dist/frqtl/objects/setup/_collisionMatrixLanes.js +66 -0
  77. package/dist/frqtl/objects/setup/_setupOptions.js +118 -0
  78. package/dist/frqtl/objects/setup/_worldInit.js +162 -0
  79. package/dist/frqtl/objects/setup/setupBlackbodySubstrate.js +242 -0
  80. package/dist/frqtl/objects/setup/setupCircuitBasic.js +447 -0
  81. package/dist/frqtl/objects/setup/setupCollisionMatrix.js +188 -0
  82. package/dist/frqtl/objects/setup/setupConeEmitter3D.js +251 -0
  83. package/dist/frqtl/objects/setup/setupDoubleSlit.js +327 -0
  84. package/dist/frqtl/objects/setup/setupDoubleSlit_Laser.js +229 -0
  85. package/dist/frqtl/objects/setup/setupEmpty.js +59 -0
  86. package/dist/frqtl/objects/setup/setupFxSmoke.js +209 -0
  87. package/dist/frqtl/objects/setup/setupG1Race.js +80 -0
  88. package/dist/frqtl/objects/setup/setupG2Sweep.js +89 -0
  89. package/dist/frqtl/objects/setup/setupG3Collide.js +177 -0
  90. package/dist/frqtl/objects/setup/setupLightSourceLab.js +280 -0
  91. package/dist/frqtl/objects/setup/setupOscillator.js +68 -0
  92. package/dist/frqtl/objects/setup/setupParticleWalk.js +93 -0
  93. package/dist/frqtl/objects/setup/setupParticleWalk3D.js +133 -0
  94. package/dist/frqtl/objects/setup/setupSphereEmitter3D.js +1259 -0
  95. package/dist/frqtl/objects/setup/setupTraceCircuit.js +239 -0
  96. package/dist/frqtl/objects/setup/setupTunnelLab.js +242 -0
  97. package/dist/frqtl/objects/setup/setupTunnelPointExit.js +306 -0
  98. package/dist/frqtl/objects/setup/setupWaveInterference.js +178 -0
  99. package/dist/frqtl/objects/v1-replacements.js +30 -0
  100. package/dist/frqtl/package-core.js +23 -0
  101. package/dist/frqtl/parts/CameraControls.js +643 -0
  102. package/dist/frqtl/parts/CameraPath.js +575 -0
  103. package/dist/frqtl/parts/CollisionActions.js +35 -0
  104. package/dist/frqtl/parts/CollisionTypes.js +31 -0
  105. package/dist/frqtl/parts/DetectorWall.js +496 -0
  106. package/dist/frqtl/parts/FrqtlControlOverlay.js +227 -0
  107. package/dist/frqtl/parts/FrqtlControlsPanel.js +415 -0
  108. package/dist/frqtl/parts/FrqtlVision.js +818 -0
  109. package/dist/frqtl/parts/GraphingDetectorWall.js +490 -0
  110. package/dist/frqtl/parts/LargeObject.js +406 -0
  111. package/dist/frqtl/parts/LightColor.js +255 -0
  112. package/dist/frqtl/parts/LiveChart.js +285 -0
  113. package/dist/frqtl/parts/LogicGate.js +720 -0
  114. package/dist/frqtl/parts/OvenBox.js +612 -0
  115. package/dist/frqtl/parts/PointSource.js +763 -0
  116. package/dist/frqtl/parts/Rectangle.js +200 -0
  117. package/dist/frqtl/parts/SlitLightSource.js +234 -0
  118. package/dist/frqtl/parts/SlitScreen.js +628 -0
  119. package/dist/frqtl/parts/SphereEmitter.js +946 -0
  120. package/dist/frqtl/parts/Trace.js +508 -0
  121. package/dist/frqtl/parts/Tunnel.js +1057 -0
  122. package/dist/frqtl/parts/Wall.js +1211 -0
  123. package/dist/frqtl/parts/index.js +33 -0
  124. package/dist/frqtl/scenes/absorbing-wall-3d.js +33 -0
  125. package/dist/frqtl/scenes/absorbing-wall.js +32 -0
  126. package/dist/frqtl/scenes/atomic-model.js +88 -0
  127. package/dist/frqtl/scenes/big-bang.js +46 -0
  128. package/dist/frqtl/scenes/blackbody.js +81 -0
  129. package/dist/frqtl/scenes/circuit-sat.js +127 -0
  130. package/dist/frqtl/scenes/collision-matrix-3d.js +107 -0
  131. package/dist/frqtl/scenes/counting-wall-3d.js +36 -0
  132. package/dist/frqtl/scenes/counting-wall.js +38 -0
  133. package/dist/frqtl/scenes/double-slit.js +31 -0
  134. package/dist/frqtl/scenes/dse-one-emitter.js +196 -0
  135. package/dist/frqtl/scenes/dse-one-slit.js +114 -0
  136. package/dist/frqtl/scenes/dse-photoelectric.js +70 -0
  137. package/dist/frqtl/scenes/dse-tunnel-rebuild.js +244 -0
  138. package/dist/frqtl/scenes/dse-two-emitters.js +196 -0
  139. package/dist/frqtl/scenes/dse-two-slits.js +132 -0
  140. package/dist/frqtl/scenes/empty.js +14 -0
  141. package/dist/frqtl/scenes/laser-buildup.js +49 -0
  142. package/dist/frqtl/scenes/mirror-3d.js +56 -0
  143. package/dist/frqtl/scenes/mirror-route.js +140 -0
  144. package/dist/frqtl/scenes/mirror.js +38 -0
  145. package/dist/frqtl/scenes/omni-3d.js +27 -0
  146. package/dist/frqtl/scenes/omni-source.js +22 -0
  147. package/dist/frqtl/scenes/self-interference.js +39 -0
  148. package/dist/frqtl/scenes/smoking-gun.js +122 -0
  149. package/dist/frqtl/scenes/straight-walk.js +22 -0
  150. package/dist/frqtl/scenes/sun.js +39 -0
  151. package/dist/frqtl/scenes/two-source.js +37 -0
  152. package/dist/frqtl/scenes/wave.js +26 -0
  153. package/dist/shim/bundle/frqnb.js +112 -0
  154. package/dist/shim/bundle/index.js +121 -0
  155. package/dist/shim/bundle/indexHtml.js +107 -0
  156. package/dist/shim/bundle/manifest.js +95 -0
  157. package/dist/shim/bundle/zip.js +243 -0
  158. package/dist/shim/bus.js +67 -0
  159. package/dist/shim/controls/index.js +627 -0
  160. package/dist/shim/controls/registry.js +274 -0
  161. package/dist/shim/engine/artifact-shell.js +212 -0
  162. package/dist/shim/engine/boot-phases.js +44 -0
  163. package/dist/shim/engine/engine-stack-boot.js +59 -0
  164. package/dist/shim/engine/router.js +692 -0
  165. package/dist/shim/experiment-frame/index.js +296 -0
  166. package/dist/shim/expr/ast-schema.js +369 -0
  167. package/dist/shim/field-descriptor/index.js +326 -0
  168. package/dist/shim/frame-data/index.js +224 -0
  169. package/dist/shim/index.js +67 -0
  170. package/dist/shim/notebook/canvas-guard.js +82 -0
  171. package/dist/shim/notebook/catalog.js +35 -0
  172. package/dist/shim/notebook/format.js +736 -0
  173. package/dist/shim/notebook/frqtl-setups-importmap.js +81 -0
  174. package/dist/shim/notebook/kernel.js +672 -0
  175. package/dist/shim/notebook/knob.js +151 -0
  176. package/dist/shim/notebook/module-resolver.js +260 -0
  177. package/dist/shim/notebook/notebook-knobs.js +65 -0
  178. package/dist/shim/notebook/produced-bindings.js +67 -0
  179. package/dist/shim/notebook/realm-registry.js +121 -0
  180. package/dist/shim/notebook/realm-transport.js +73 -0
  181. package/dist/shim/notebook/setup-builder.js +510 -0
  182. package/dist/shim/notebook/store.js +159 -0
  183. package/dist/shim/notebook/vendor-importmap.js +134 -0
  184. package/dist/shim/notebook/view-builder.js +189 -0
  185. package/dist/shim/notebook/view-ctx.js +100 -0
  186. package/dist/shim/notebook/view-handle.js +202 -0
  187. package/dist/shim/notebook/warmup.js +102 -0
  188. package/dist/shim/package.json +4 -0
  189. package/dist/shim/page-params/index.js +214 -0
  190. package/dist/shim/project/identity.js +112 -0
  191. package/dist/shim/project/index.js +19 -0
  192. package/dist/shim/project/link.js +402 -0
  193. package/dist/shim/project/node-specifier-hook.mjs +35 -0
  194. package/dist/shim/project/register-node.mjs +17 -0
  195. package/dist/shim/project/specifiers.js +106 -0
  196. package/dist/shim/registry/copy-gate.js +110 -0
  197. package/dist/shim/registry/exhibits.js +455 -0
  198. package/dist/shim/registry/experiments.js +215 -0
  199. package/dist/shim/registry/index.js +19 -0
  200. package/dist/shim/registry/scene-source.js +157 -0
  201. package/dist/shim/registry/walkthrough.js +807 -0
  202. package/dist/shim/render/capture-envelope.js +279 -0
  203. package/dist/shim/render/heat-colormap.js +92 -0
  204. package/dist/shim/render/render-stages.js +855 -0
  205. package/dist/shim/render/sun-look.js +33 -0
  206. package/dist/shim/render-state/apply.js +262 -0
  207. package/dist/shim/render-state/index.js +74 -0
  208. package/dist/shim/rpc/index.js +207 -0
  209. package/dist/shim/runtime/index.js +1023 -0
  210. package/dist/shim/storage/boot.js +69 -0
  211. package/dist/shim/storage/index.js +169 -0
  212. package/dist/shim/storage/local-storage-provider.js +230 -0
  213. package/dist/shim/storage/make-namespace-store.js +132 -0
  214. package/dist/shim/storage/modules.js +249 -0
  215. package/dist/shim/storage/projects.js +150 -0
  216. package/llms.txt +12 -0
  217. package/package.json +62 -4
@@ -0,0 +1,326 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * lib/shim/field-descriptor — the shared FIELD-SHAPE vocabulary contract.
5
+ *
6
+ * WS Studio Controls Realignment §7 r2 CEO call C1 (ratified 2026-07-07): the architect's
7
+ * escalation was that a single FIELD shape — `{name, type, constraint, unit,
8
+ * description, engineVisible, widgetHint, widgetConfig, default}` — and its
9
+ * closed TYPE vocabulary were about to be re-derived THREE times (physics
10
+ * object schema, the new render-capability descriptors, and a future Rosetta
11
+ * `paramsSchema`) instead of owned once. This module is that ONE owner — the
12
+ * peer of `lib/shim/controls` (which owns the CONTROL-descriptor shape one
13
+ * layer up) and `lib/shim/frame-data` (which owns the data-bubble shape) —
14
+ * same layout convention (closed vocabulary + a throw-or-apply `normalize`,
15
+ * named ES-module exports).
16
+ *
17
+ * ── Why this exists ──────────────────────────────────────────────────────────
18
+ *
19
+ * `lib/frqtl/objects/schema/index.js` (`ObjectSchema`) already declares
20
+ * ~200 fields across 16 kinds using EXACTLY this shape, documented only as a
21
+ * comment block (`type:'rect' → …`, `type:'rgb' → …`, …). Separately,
22
+ * `lib/frqtl/objects/objects/makeControlsForObject.js`'s `TYPE_DISPATCH` map
23
+ * independently enumerates the SAME 12 field types as its object keys — two
24
+ * hand-written lists that happen to agree today but have no shared owner
25
+ * enforcing that they always will (the exact schema-mirror-drift class root
26
+ * `CLAUDE.md` §Engineering Culture calls out: "the same data breaks in one
27
+ * consumer but not another"). `renderCapabilities()` (S5a item 2,
28
+ * `lib/frqtl/compat/renderer/providers/{p5,three}-provider.js`) needed the
29
+ * SAME field shape for a THIRD surface — the trigger for this extraction.
30
+ *
31
+ * ── Scope ─────────────────────────────────────────────────────────────────
32
+ *
33
+ * This module owns:
34
+ * - `FIELD_TYPES` — the closed field-TYPE vocabulary (12 members,
35
+ * mechanically identical to `ObjectSchema`'s documented comment list AND
36
+ * `makeControlsForObject.js`'s `TYPE_DISPATCH` keys — see the drift test).
37
+ * - `FIELD_ENVELOPE_KEYS` — the field-SHAPE envelope key list (documentation/
38
+ * introspection use — NOT a required-keys gate; most fields omit most of
39
+ * these optional keys, only `name`/`type`/`description` are mandatory).
40
+ * - `normalizeFieldDescriptor(partial)` — throw-or-apply validation of ONE
41
+ * field descriptor's envelope (name/type/description required; constraint/
42
+ * unit/engineVisible/widgetHint/widgetConfig/default validated IF present).
43
+ *
44
+ * This module does NOT:
45
+ * - Re-list or replace `ObjectSchema`'s ~200 existing per-kind field arrays —
46
+ * those stay EXACTLY as authored (byte-identical); `ObjectSchema` merely
47
+ * IMPORTS `FIELD_TYPES` from here to assert (at load time) that every field
48
+ * it declares uses a member of the ONE vocabulary, instead of hand-copying
49
+ * the type list into its own comment block as the only enforcement.
50
+ * - Replace `lib/shim/controls`'s CONTROL-descriptor shape (`{kind, id, label,
51
+ * min, max, step, value, fmt, onChange, bind, channel}`) — that is a
52
+ * DIFFERENT, downstream shape (a UI/live-knob descriptor), consumed by a
53
+ * factory that READS field descriptors of THIS shape and EMITS control
54
+ * descriptors of THAT shape. The two are peers, not the same contract.
55
+ *
56
+ * Usage:
57
+ * import { FIELD_TYPES, normalizeFieldDescriptor } from 'lib/shim/field-descriptor/index.js';
58
+ * var f = normalizeFieldDescriptor({
59
+ * name: 'godrays', type: 'number', unit: 'intensity',
60
+ * constraint: { min: 0, max: 3 }, default: 0,
61
+ * description: 'God-rays post-process intensity (render-only).'
62
+ * });
63
+ */
64
+
65
+
66
+
67
+ // ── Field type vocabulary (closed, 12 members) ──────────────────────────────
68
+ //
69
+ // Mechanically identical to the set actually used across ObjectSchema's field
70
+ // declarations (lib/frqtl/objects/schema/index.js) and
71
+ // makeControlsForObject.js's TYPE_DISPATCH keys — verified exhaustively by
72
+ // lib/shim/field-descriptor/test/field-descriptor.test.mjs's drift assertion.
73
+ // Adding a 13th type is a THREE-PLACE change (here, TYPE_DISPATCH, and any
74
+ // descriptor that uses it) — the drift test makes forgetting one of the three
75
+ // a CI failure rather than a silent runtime gap.
76
+ //
77
+ // number — numeric scalar; constraint: { min?, max?, integer? }
78
+ // boolean — true | false
79
+ // string — free string
80
+ // enum — one value from constraint.values object
81
+ // enum-set — array of zero or more values from constraint.values object
82
+ // rgb — [r, g, b] (0-255 integers)
83
+ // rect — { left, top, w, h } (+ optional z, d — WASM-only)
84
+ // rect-array — array of rect-shaped tuples
85
+ // readonly — derived/computed: inspectable but not editable
86
+ // forbidden — engine-owned topology: any write attempt throws
87
+ // object — an arbitrary structured bag (e.g. an op-program)
88
+ // writable — Frame-kind-only ACCESS-LEVEL tag (the actual value type is
89
+ // inferred from the live read — number/boolean/string/object)
90
+ var FIELD_TYPES = Object.freeze([
91
+ 'number', 'boolean', 'string', 'enum', 'enum-set',
92
+ 'rgb', 'rect', 'rect-array', 'readonly', 'forbidden',
93
+ 'object', 'writable'
94
+ ]);
95
+
96
+ // ── Field envelope keys (documentation/introspection — NOT a required list) ─
97
+ //
98
+ // Every field descriptor MAY carry these keys; only name/type/description are
99
+ // mandatory (validated by normalizeFieldDescriptor below). `default` is the
100
+ // C1 addition renderCapabilities() descriptors need (a physics ObjectSchema
101
+ // field's live value comes from the constructed object instead — `default`
102
+ // was rarely populated there and stays optional here for that reason).
103
+ var FIELD_ENVELOPE_KEYS = Object.freeze([
104
+ 'name', 'type', 'constraint', 'unit', 'description',
105
+ 'engineVisible', 'widgetHint', 'widgetConfig', 'default'
106
+ ]);
107
+
108
+ function _isStr(v) { return typeof v === 'string' && v.length > 0; }
109
+ function _isPlainObject(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); }
110
+
111
+ function _fail(name, msg) {
112
+ throw new Error('[lib/shim/field-descriptor] normalizeFieldDescriptor(name="' + String(name) +
113
+ '"): ' + msg + ' (FAIL-LOUD — throw-or-apply, never silently dropped/defaulted-around.)');
114
+ }
115
+
116
+ /**
117
+ * normalizeFieldDescriptor(partial) → full bag.
118
+ *
119
+ * THROW-OR-APPLY: a malformed field descriptor throws here — never silently
120
+ * dropped or coerced. Mandatory: `name` (non-empty string), `type` (member of
121
+ * FIELD_TYPES), `description` (non-empty string — every ObjectSchema field
122
+ * already carries one; see schema.test.mjs assertion (a)). Optional, validated
123
+ * IF present: `unit` (string), `constraint`/`widgetConfig` (plain object),
124
+ * `engineVisible` (boolean), `widgetHint` (string). `default` accepts ANY
125
+ * value (its shape depends on `type` — a number, a string, an array for rgb/
126
+ * rect, …) so it is NOT type-checked here.
127
+ *
128
+ * @param {object} partial
129
+ * @returns {object} a NEW object (input never mutated) carrying every input
130
+ * key verbatim.
131
+ * @throws {Error} FAIL-LOUD on a missing/empty `name`, an unrecognized `type`,
132
+ * a missing/empty `description`, or a mistyped optional key.
133
+ */
134
+ function normalizeFieldDescriptor(partial) {
135
+ if (!partial || typeof partial !== 'object') {
136
+ throw new Error('[lib/shim/field-descriptor] normalizeFieldDescriptor requires a field ' +
137
+ 'descriptor object; got ' + (partial === null ? 'null' : typeof partial) +
138
+ '. (FAIL-LOUD.)');
139
+ }
140
+ var name = partial.name;
141
+ if (!_isStr(name)) {
142
+ _fail(name, '"name" must be a non-empty string.');
143
+ }
144
+ var type = partial.type;
145
+ if (FIELD_TYPES.indexOf(type) === -1) {
146
+ _fail(name, '"type" must be one of [' + FIELD_TYPES.join(', ') + ']; got "' + String(type) + '".');
147
+ }
148
+ if (!_isStr(partial.description)) {
149
+ _fail(name, '"description" must be a non-empty string.');
150
+ }
151
+ if (partial.unit !== undefined && !_isStr(partial.unit)) {
152
+ _fail(name, '"unit", when present, must be a non-empty string.');
153
+ }
154
+ if (partial.constraint !== undefined && !_isPlainObject(partial.constraint)) {
155
+ _fail(name, '"constraint", when present, must be a plain object.');
156
+ }
157
+ if (partial.engineVisible !== undefined && typeof partial.engineVisible !== 'boolean') {
158
+ _fail(name, '"engineVisible", when present, must be a boolean.');
159
+ }
160
+ if (partial.widgetHint !== undefined && !_isStr(partial.widgetHint)) {
161
+ _fail(name, '"widgetHint", when present, must be a non-empty string.');
162
+ }
163
+ if (partial.widgetConfig !== undefined && !_isPlainObject(partial.widgetConfig)) {
164
+ _fail(name, '"widgetConfig", when present, must be a plain object.');
165
+ }
166
+
167
+ // Fresh bag — never mutate the caller's object (mirrors frame-data's
168
+ // normalizeDataBubble / controls' normalizeControlDescriptor convention).
169
+ var bag = {};
170
+ for (var k in partial) {
171
+ if (Object.prototype.hasOwnProperty.call(partial, k)) { bag[k] = partial[k]; }
172
+ }
173
+ bag.name = name;
174
+ bag.type = type;
175
+ return bag;
176
+ }
177
+
178
+ // ── UX presentation vocabulary (ws-experiments-walkthrough Bite 5b A0) ──────
179
+ //
180
+ // A per-KIND `ux:{}` block rides ON the ObjectSchema descriptor (peer of `fields`
181
+ // — a presentation contract, NOT a parallel `UxSchema`; architect Q-A0). Its
182
+ // closed value vocabularies live HERE, the PEER of FIELD_TYPES, so STUDIO's
183
+ // overlay AND a headless game consume ONE list (the SAME hooks a game uses
184
+ // programmatically — CEO §9). The vocab is READ DOWNWARD ONLY (shim → objects/
185
+ // features); no lib/frqtl/objects file re-lists these strings, and
186
+ // author-bbox-overlay.js (lib/features) FERRIES `UX_HANDLE_ZONES` (asserting its
187
+ // own returned zone names are members) instead of being a second owner.
188
+ //
189
+ // R6 legacy tolerance: a descriptor with NO `ux` block ⇒ `normalizeUx(undefined)`
190
+ // ⇒ today's behavior (resizable everywhere, 2D-draggable, all handle zones live,
191
+ // marker shell design-only).
192
+ // normalizeUx NEVER throws on an absent block — only on an INVALID member.
193
+
194
+ // The bbox interaction zones hitBboxZone (author-bbox-overlay.js) can classify a
195
+ // pointer into. 'move' = interior drag; 'scale-*' = a corner/edge resize handle.
196
+ // This is the ONE owner; author-bbox-overlay.js ferries it (drift = load-time throw).
197
+ var UX_HANDLE_ZONES = Object.freeze([
198
+ 'move',
199
+ 'scale-tl', 'scale-tr', 'scale-bl', 'scale-br',
200
+ 'scale-t', 'scale-b', 'scale-l', 'scale-r'
201
+ ]);
202
+
203
+ // The render modes a part may be cursor-dragged in. Only 2D: a 3D scene never cursor-drags
204
+ // (reposition is the aim + SPACE carry), so there is no per-object 3D knob to declare.
205
+ var UX_DRAGGABLE_MODES = Object.freeze(['2d']);
206
+
207
+ // When a manipulable object's visual shell renders (generalizes the Bite-4b
208
+ // `_designMarker` boolean at the ONE _visibleLargeObjects authority):
209
+ // design — only while authoring (Design mode). The Bite-4b marker default.
210
+ // run — always visible (the CEO's "red light bulb" opt-in).
211
+ // never — never drawn.
212
+ var UX_SHELL_RENDER = Object.freeze(['design', 'run', 'never']);
213
+
214
+ // The `ux` envelope keys (documentation/introspection — NOT a required list; a
215
+ // partial ux block fills the rest from the legacy defaults below).
216
+ var UX_ENVELOPE_KEYS = Object.freeze([
217
+ 'resizable', 'draggable', 'handles', 'shellRender'
218
+ ]);
219
+
220
+ // Keys a ux block may NOT carry any more, each with what replaced it (FAIL-LOUD on use).
221
+ var UX_DELETED_KEYS = Object.freeze({
222
+ inspectorSections: 'the Inspector shows a DECLARED object through its own descriptor (no per-role section list)'
223
+ });
224
+
225
+ function _uxFail(msg) {
226
+ throw new Error('[lib/shim/field-descriptor] normalizeUx: ' + msg +
227
+ ' (FAIL-LOUD — throw-or-apply, never silently dropped/defaulted-around.)');
228
+ }
229
+
230
+ /**
231
+ * normalizeUx(partial) → full ux bag.
232
+ *
233
+ * THROW-OR-APPLY: an INVALID member throws here; an ABSENT block (undefined/null)
234
+ * yields the legacy defaults (today's behavior, R6). Every field is optional; a
235
+ * partial block fills the rest from the defaults.
236
+ *
237
+ * resizable — boolean (default true). false ⇒ scale handles are never
238
+ * offered even for the SELECTED object (its corners never
239
+ * resize; the first-and-every interaction is select/move).
240
+ * draggable — { '2d':boolean } (default true). false disables the 2D
241
+ * cursor-drag. (A 3D scene never cursor-drags; '3d' is not a key.)
242
+ * handles — string[] ⊆ UX_HANDLE_ZONES (default = ALL zones). The
243
+ * live interaction zones; a zone NOT listed is downgraded
244
+ * to 'move' by the overlay (never a resize on the selecting
245
+ * click). `resizable:false` is the ergonomic shorthand for
246
+ * handles:['move'].
247
+ * shellRender — one of UX_SHELL_RENDER (default 'design'). When the
248
+ * object's visual shell/marker paints.
249
+ *
250
+ * @param {object|null|undefined} partial
251
+ * @returns {{resizable:boolean, draggable:{'2d':boolean}, handles:string[], shellRender:string}}
252
+ */
253
+ function normalizeUx(partial) {
254
+ var bag = {
255
+ resizable: true,
256
+ draggable: { '2d': true },
257
+ handles: UX_HANDLE_ZONES.slice(),
258
+ shellRender: 'design'
259
+ };
260
+ if (partial === null || partial === undefined) { return bag; }
261
+ if (typeof partial !== 'object' || Array.isArray(partial)) {
262
+ _uxFail('a ux block must be a plain object; got ' +
263
+ (Array.isArray(partial) ? 'array' : typeof partial) + '.');
264
+ }
265
+ Object.keys(UX_DELETED_KEYS).forEach(function (k) {
266
+ if (partial[k] !== undefined) { _uxFail('"' + k + '" is DELETED — ' + UX_DELETED_KEYS[k] + '.'); }
267
+ });
268
+ if (partial.resizable !== undefined) {
269
+ if (typeof partial.resizable !== 'boolean') { _uxFail('"resizable" must be a boolean.'); }
270
+ bag.resizable = partial.resizable;
271
+ }
272
+ if (partial.draggable !== undefined) {
273
+ if (!_isPlainObject(partial.draggable)) { _uxFail('"draggable" must be a { "2d" } object.'); }
274
+ Object.keys(partial.draggable).forEach(function (k) {
275
+ if (UX_DRAGGABLE_MODES.indexOf(k) === -1) {
276
+ _uxFail('"draggable.' + k + '" is not a draggable mode ([' + UX_DRAGGABLE_MODES.join(', ') +
277
+ ']) — a 3D scene never cursor-drags.');
278
+ }
279
+ });
280
+ var dr = { '2d': true };
281
+ for (var m = 0; m < UX_DRAGGABLE_MODES.length; m++) {
282
+ var mode = UX_DRAGGABLE_MODES[m];
283
+ if (partial.draggable[mode] !== undefined) {
284
+ if (typeof partial.draggable[mode] !== 'boolean') {
285
+ _uxFail('"draggable.' + mode + '" must be a boolean.');
286
+ }
287
+ dr[mode] = partial.draggable[mode];
288
+ }
289
+ }
290
+ bag.draggable = dr;
291
+ }
292
+ if (partial.handles !== undefined) {
293
+ if (!Array.isArray(partial.handles)) { _uxFail('"handles" must be an array of zone names.'); }
294
+ for (var h = 0; h < partial.handles.length; h++) {
295
+ if (UX_HANDLE_ZONES.indexOf(partial.handles[h]) === -1) {
296
+ _uxFail('"handles" entry "' + String(partial.handles[h]) + '" is not a member of ' +
297
+ 'UX_HANDLE_ZONES ([' + UX_HANDLE_ZONES.join(', ') + ']).');
298
+ }
299
+ }
300
+ bag.handles = partial.handles.slice();
301
+ } else if (partial.resizable === false) {
302
+ // Ergonomic shorthand: an explicitly non-resizable object offers ONLY move.
303
+ bag.handles = ['move'];
304
+ }
305
+ if (partial.shellRender !== undefined) {
306
+ if (UX_SHELL_RENDER.indexOf(partial.shellRender) === -1) {
307
+ _uxFail('"shellRender" must be one of [' + UX_SHELL_RENDER.join(', ') + ']; got "' +
308
+ String(partial.shellRender) + '".');
309
+ }
310
+ bag.shellRender = partial.shellRender;
311
+ }
312
+ return bag;
313
+ }
314
+
315
+ // ── Export ────────────────────────────────────────────────────────────────────
316
+
317
+ export {
318
+ FIELD_TYPES,
319
+ FIELD_ENVELOPE_KEYS,
320
+ normalizeFieldDescriptor,
321
+ UX_HANDLE_ZONES,
322
+ UX_DRAGGABLE_MODES,
323
+ UX_SHELL_RENDER,
324
+ UX_ENVELOPE_KEYS,
325
+ normalizeUx
326
+ };
@@ -0,0 +1,224 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * lib/shim/frame-data — The data-bubble schema contract.
5
+ *
6
+ * Single authority for the FrameData.data bag shape (§6 of
7
+ * docs/internal/engine/ENGINE_CONTRACT.md). The bubble is GENERIC and engine-opaque:
8
+ * SECTION_KEYS = ['detection', 'string_map']. The engine interprets NOTHING in
9
+ * string_map — it ferries every key verbatim across the JS↔WASM boundary.
10
+ *
11
+ * The data bubble has two cross-engine reserved namespaces (+ a JS-only ext):
12
+ * detection — written by the engine (MARK/DETECT primitives). Contains
13
+ * detector_name and any future detection tags.
14
+ * string_map — op-program-writable via `set 0.data.<key> = StrLit(value)`;
15
+ * a flat { key: string, ... } the engine carries opaque. ALL
16
+ * render data rides here as opaque keys: color is
17
+ * string_map['render.color'] (CSV 'r,g,b,a'); outline is
18
+ * string_map['render.outline'] === 'true'. Sugar/renderer code
19
+ * serializes on write and deserializes on read — there is NO
20
+ * typed `render` section (RETIRED: FrameDataRender,
21
+ * FrameMetaData.render, render_color SoA field, normalizeRender).
22
+ * ext — developer-extensible; engine carries opaque, never reads.
23
+ * NOTE (D2 decision): ext is JS-only. The Rust side has no ext
24
+ * field — serde_wasm_bindgen v0.6 cannot round-trip a free-form
25
+ * map through JsValue without serde_json::Value (which drops its
26
+ * contents). ext writes are carried through JS-only paths and are
27
+ * not asserted in cross-engine conformance. If ext survives a
28
+ * JS→WASM→JS round-trip, treat it as undefined behavior.
29
+ *
30
+ * The canonical section key list drives conformance (see §5 — the data-bubble
31
+ * round-trip oracle iterates over SECTION_KEYS to assert completeness).
32
+ *
33
+ * Usage:
34
+ * import { SECTION_KEYS, normalizeDataBubble, RENDER_INTENT_KEYS,
35
+ * normalizeRenderIntent } from 'lib/shim/frame-data/index.js';
36
+ */
37
+
38
+
39
+
40
+ /**
41
+ * Canonical section key table.
42
+ * Conformance iterates this list — adding a section here MUST be accompanied
43
+ * by a conformance assertion (cross-engine oracle, §5 item 2).
44
+ *
45
+ * Sections:
46
+ * detection — engine-writable (MARK/DETECT); { detector_name: string|null }
47
+ * string_map — op-program-writable via `set 0.data.<key> = StrLit(value)`;
48
+ * flat object { key: string, ... }. Absent → null in normalized form.
49
+ * Cross-engine (JS + WASM). Owner: this file + FrameMetaData (tick_data.rs).
50
+ * ALL render hints ride here as opaque keys (render.color, render.outline);
51
+ * there is no typed `render` section.
52
+ */
53
+ // 'render' section RETIRED — color (and all render hints) are opaque user-space data on
54
+ // string_map; the engine never carries a typed render section. Owner: this file + FrameMetaData.
55
+ const SECTION_KEYS = ['detection', 'string_map'];
56
+ // NOTE: 'ext' is deliberately excluded because it is not cross-engine assertable.
57
+
58
+ /**
59
+ * Normalize a partial data bag to the full canonical shape.
60
+ *
61
+ * Rules:
62
+ * - Each reserved section (detection, string_map) is present as an object or null.
63
+ * - Absent → null (mirrors the JS toFrameData() :2872 and Rust skip_serializing_if).
64
+ * - Extra keys inside a section are preserved (pass-through).
65
+ * - The ext key is passed through as-is (JS-only, not normalized).
66
+ *
67
+ * @param {object|null|undefined} partial — partial data bag from a frame or FrameData
68
+ * @returns {{ detection: object|null, string_map: object|null, ext: any }}
69
+ */
70
+ function normalizeDataBubble(partial) {
71
+ if (partial === null || partial === undefined) {
72
+ return { detection: null, string_map: null };
73
+ }
74
+ return {
75
+ detection: (partial.detection !== null && partial.detection !== undefined)
76
+ ? partial.detection
77
+ : null,
78
+ string_map: (partial.string_map !== null && partial.string_map !== undefined &&
79
+ typeof partial.string_map === 'object')
80
+ ? partial.string_map
81
+ : null,
82
+ ext: partial.ext !== undefined ? partial.ext : undefined,
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Normalize the detection sub-section.
88
+ * detector_name: string|null
89
+ */
90
+ function normalizeDetection(partial) {
91
+ if (!partial) return { detector_name: null };
92
+ return {
93
+ detector_name: (partial.detector_name !== null && partial.detector_name !== undefined)
94
+ ? String(partial.detector_name)
95
+ : null,
96
+ };
97
+ }
98
+
99
+ // ── Render-intent vocabulary (Part C) ────────────────────────────────────────
100
+ //
101
+ // Render-intent keys are opaque string_map keys that sugar objects and experiment
102
+ // setups write to describe per-frame render intent. Providers deserialize them on
103
+ // read — the engine carries them verbatim and interprets nothing (I1 preserved).
104
+ //
105
+ // Key list owned HERE (single source). Conformance assertions MUST be driven off
106
+ // this list so that adding a key automatically extends the test surface.
107
+ //
108
+ // Priority in any provider:
109
+ // render.color (exact CSV r,g,b,a) > render.colorScheme ramp via LightColor > renderer default
110
+
111
+ /**
112
+ * RENDER_INTENT_KEYS — the canonical set of render-intent string_map keys.
113
+ *
114
+ * Conformance tests iterate this list. To add a new render-intent key:
115
+ * 1. Add the key string here.
116
+ * 2. Add its allowed values to RENDER_INTENT_VALUES.
117
+ * 3. Update normalizeRenderIntent to pass it through.
118
+ * 4. Add a conformance assertion (cross-engine oracle).
119
+ * 5. Update both providers to consume it.
120
+ *
121
+ * Current keys:
122
+ * render.color — CSV 'r,g,b,a' exact RGBA override (highest priority); existing. OPEN-ID (no value set).
123
+ * render.outline — 'true' | 'false' (or absent); existing. ENUM.
124
+ * render.shape — 'ball' | 'box' | 'circle' | 'cube' | 'sphere' (per-frame shape; absent → renderer default). ENUM.
125
+ * 'sphere' = a TRUE 3D instanced-sphere mesh (three, _is3D), symmetric with 'cube';
126
+ * in 2D / p5 it degrades to the filled 'ball' disc (no per-provider map — RenderShape
127
+ * is the one authority; the three sphere path is gated on _is3D like the cube path).
128
+ * render.colorScheme — 'roygbiv' | 'warmcool' (named LightColor ramp; absent → default). ENUM.
129
+ * render.mesh — external-geometry asset id (e.g. an Objaverse glTF id); absent → sprite/cube path.
130
+ * OPEN-ID: no RENDER_INTENT_VALUES entry (accept-any-string); the renderer's RenderMesh
131
+ * resolver FAILS LOUD at the output boundary if the asset cannot load — never silent.
132
+ * render.meshScale — per-frame scale MULTIPLIER for the frame's render.mesh clone (a number as a string;
133
+ * local override of the experiment-wide setRenderOption('meshScale',…)). OPEN-ID.
134
+ * render.meshRotation— per-frame euler rotation for the frame's render.mesh clone, a CSV of THREE radians
135
+ * 'rx,ry,rz' (same unit as a LargeObject's lo.meshRotation → clone.rotation.set). OPEN-ID.
136
+ * (Bite 5b R3-3: previously written ad-hoc but undeclared + unread; declared
137
+ * here at the owner and read per-clone in three-provider's _layoutMeshClones.)
138
+ *
139
+ * Two contract shapes (architect ruling 2026-06-30):
140
+ * ENUM key — has a RENDER_INTENT_VALUES[] array; decoders ferry the array (no re-listing); conformance-validated.
141
+ * OPEN-ID key — has NO RENDER_INTENT_VALUES entry → assertRenderIntentConformance accepts any string; the
142
+ * decoder/resolver owns load-time validation and fails loud. Covers render.color and render.mesh.
143
+ */
144
+ const RENDER_INTENT_KEYS = [
145
+ 'render.color',
146
+ 'render.outline',
147
+ 'render.shape',
148
+ 'render.colorScheme',
149
+ 'render.mesh',
150
+ 'render.meshScale', // OPEN-ID — per-frame mesh scale multiplier (R3-3)
151
+ 'render.meshRotation' // OPEN-ID — per-frame mesh euler radians CSV (R3-3)
152
+ ];
153
+
154
+ /**
155
+ * RENDER_INTENT_VALUES — allowed values for each key (for validation).
156
+ * Keys without an entry accept any string (e.g. render.color is a CSV).
157
+ */
158
+ const RENDER_INTENT_VALUES = {
159
+ 'render.shape': ['ball', 'box', 'circle', 'cube', 'sphere'],
160
+ 'render.colorScheme': ['roygbiv', 'warmcool'],
161
+ 'render.outline': ['true', 'false']
162
+ // NOTE: render.color, render.mesh, render.meshScale, render.meshRotation are OPEN-ID keys —
163
+ // deliberately NO entry here (accept-any-string: a CSV / an asset id / a number / an euler CSV).
164
+ // Their decoders/resolvers own validation and fail loud at the boundary.
165
+ };
166
+
167
+ /**
168
+ * normalizeRenderIntent — ferry a partial render-intent bag to the full canonical shape.
169
+ *
170
+ * Reads only the keys declared in RENDER_INTENT_KEYS; copies them into the normalized
171
+ * bag if present; absent keys are omitted (not defaulted — the renderer defaults apply).
172
+ * This is the "ferry the bag" pattern: the caller never re-enumerates the key list.
173
+ *
174
+ * @param {object|null|undefined} partial — partial string_map or explicit intent object
175
+ * @returns {{ 'render.color'?: string, 'render.outline'?: string,
176
+ * 'render.shape'?: string, 'render.colorScheme'?: string }}
177
+ */
178
+ function normalizeRenderIntent(partial) {
179
+ var bag = {};
180
+ if (!partial || typeof partial !== 'object') return bag;
181
+ for (var i = 0; i < RENDER_INTENT_KEYS.length; i++) {
182
+ var k = RENDER_INTENT_KEYS[i];
183
+ if (partial[k] !== undefined && partial[k] !== null) {
184
+ bag[k] = String(partial[k]);
185
+ }
186
+ }
187
+ return bag;
188
+ }
189
+
190
+ /**
191
+ * assertRenderIntentConformance — throw if any key in a string_map bag violates the contract.
192
+ *
193
+ * Validates values for keys whose allowed set is enumerated in RENDER_INTENT_VALUES.
194
+ * Keys with unconstrained values (render.color, render.outline) are passed through.
195
+ * Unknown keys outside RENDER_INTENT_KEYS are ignored (the engine carries all keys opaque).
196
+ *
197
+ * @param {object} bag — string_map object to validate
198
+ * @throws {Error} if a constrained key holds an unknown value
199
+ */
200
+ function assertRenderIntentConformance(bag) {
201
+ if (!bag) return;
202
+ for (var i = 0; i < RENDER_INTENT_KEYS.length; i++) {
203
+ var k = RENDER_INTENT_KEYS[i];
204
+ var allowed = RENDER_INTENT_VALUES[k];
205
+ if (allowed && bag[k] !== undefined && allowed.indexOf(bag[k]) === -1) {
206
+ throw new Error(
207
+ 'render-intent conformance: key "' + k + '" has invalid value "' + bag[k] +
208
+ '"; allowed: ' + allowed.join('|')
209
+ );
210
+ }
211
+ }
212
+ }
213
+
214
+ // ── Export ────────────────────────────────────────────────────────────────────
215
+
216
+ export {
217
+ SECTION_KEYS,
218
+ normalizeDataBubble,
219
+ normalizeDetection,
220
+ RENDER_INTENT_KEYS,
221
+ RENDER_INTENT_VALUES,
222
+ normalizeRenderIntent,
223
+ assertRenderIntentConformance
224
+ };
@@ -0,0 +1,67 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * lib/shim — the unified shim router (was lib/common).
5
+ *
6
+ * ESM barrel: re-exports all named exports. A missing import is a hard
7
+ * FAIL-LOUD load error — no window.Common* ambient globals.
8
+ *
9
+ * Usage (under vite with alias 'lib' → repo-root/lib):
10
+ * import { Bus, Runtime, EXPERIMENTS, engineRouter } from 'lib/shim';
11
+ *
12
+ * Usage (direct relative path):
13
+ * import { Bus } from '../../lib/shim/index.js';
14
+ */
15
+
16
+ export { Bus } from './bus.js';
17
+ export { Runtime } from './runtime/index.js';
18
+ export { EXPERIMENTS, EXPERIMENT_TIERS, experimentById, experimentIs3D,
19
+ isPublicExperiment, publicExperiments,
20
+ internalExperiments } from './registry/experiments.js';
21
+ export { WALKTHROUGH, walkthroughIs3D, walkthroughModes, walkthroughGroup,
22
+ walkthroughById,
23
+ FIRST_CONTACT_WALKTHROUGH_ID,
24
+ defaultWalkthroughModeId, effectiveRenderState } from './registry/walkthrough.js';
25
+ export { loadSceneSource, scenePath, EMPTY_SCENE } from './registry/scene-source.js';
26
+ // The host-side experiment-iframe guard (the false-200 trap). Exported from the
27
+ // barrel so every host that frames an experiment page (lib/features/ide's GYM)
28
+ // asserts against the SAME contract.
29
+ export { EXPERIMENT_PAGE_MARKERS, HOST_SHELL_ROOT_SELECTOR, FRAME_VERDICTS,
30
+ DEFAULT_FRAME_TIMEOUT_MS, classifyFrameProbe, probeExperimentFrame,
31
+ paintFrameGuardOverlay, watchExperimentFrame } from './experiment-frame/index.js';
32
+ export { engineRouter, DEV_CORE_PROFILE, DIST_PROFILE } from './engine/router.js';
33
+ // Math backend registry — re-exported so lib/features can import from the shim
34
+ // barrel (the sanctioned route) without reaching past the shim into lib/egpt directly.
35
+ // Module identity is preserved: both the barrel re-export and any direct import of
36
+ // MathBackendRegistry.js resolve to the SAME singleton because ESM caches by
37
+ // canonical URL — there is only one MathBackendRegistry instance. The registry
38
+ // module has zero imports; the JS reference core never enters this graph.
39
+ export { MathBackendRegistry, MathBackendNotAvailableError } from '../egpt/js/model/backend/MathBackendRegistry.js';
40
+ // Notebook spine (WS-NOTEBOOK-A1): the native format parser/serializer and the
41
+ // per-notebook kernel. The kernel calls Runtime.runCell directly (no Bus
42
+ // executor). Consumers (the A2 notebook pane) import these from the barrel.
43
+ export { parse, serialize, normalize } from './notebook/format.js';
44
+ export { NotebookKernel, NOTEBOOK_CELL_STATUS } from './notebook/kernel.js';
45
+ // Cell-as-module resolver (WS-NOTEBOOK-IMPORT B2) — the host-neutral in-memory
46
+ // blob closure logic. Re-exported so tests + any host can build the closure
47
+ // (Runtime injects the browser blob minter; the resolver itself is DOM-free and
48
+ // must NOT assume a pane exists — model-gate ruling 6).
49
+ export {
50
+ canonKey, resolveRelativeKey, hasImport, splitImportsAndBody,
51
+ rewriteRelativeToSiblingBlobs, buildModuleClosure, compileEntryModuleSource
52
+ } from './notebook/module-resolver.js';
53
+ // Notebook webview-realm model (WS-NOTEBOOK-REALM): the FOURTH BYO pluggable
54
+ // surface. ONE registry authority + the frozen view-handle contract + the in-app
55
+ // transport (same-origin direct fast path). A realm pre-load
56
+ // is an above-the-shim renderer env; the frqtl pre-load co-locates the engine.
57
+ export * as RealmRegistry from './notebook/realm-registry.js';
58
+ export { makeViewHandle, isViewHandle, assertSerializable } from './notebook/view-handle.js';
59
+ export { inAppTransport } from './notebook/realm-transport.js';
60
+ // Realm import map — buildImportMap (vendor manifest → `{ imports }`), buildRealmImportMap
61
+ // (vendor + @frqtl/setups, through ONE router) and spliceRealmImportMap (the ONE splice the
62
+ // served hosts, lib/server/realm-html.js, and the static bake, apps/ide/vite.config.js, both
63
+ // call). PURE, DOM-free.
64
+ export { buildImportMap, buildRealmImportMap, spliceRealmImportMap } from './notebook/vendor-importmap.js';
65
+ // Canonical setup-factory bare-specifier surface — the manifest and its import-map fragment
66
+ // (merged by buildRealmImportMap above). PURE, DOM-free.
67
+ export { buildFrqtlSetupsImportMap, FRQTL_SETUPS_MANIFEST } from './notebook/frqtl-setups-importmap.js';