@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,469 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * engine-scopes.js — the ENGINE-CORE ACCESSOR descriptors: `Frame`, `Universe`,
5
+ * `Dimension`.
6
+ *
7
+ * These three are a different family from every other descriptor in this
8
+ * directory. The rest describe AUTHORED PARTS — things a person places, wires and
9
+ * drags, whose fields are constructor parameters. These three describe the
10
+ * ENGINE'S OWN SCOPES: the objects an op-program addresses (`0.mass`,
11
+ * `universe.tick`, `dimension.layer`) and the uniform accessors
12
+ * `getFrameProperty`/`setFrameProperty` write through. They are never placed,
13
+ * never dragged, and never appear in the palette.
14
+ *
15
+ * That is the seam this file splits on. `schema/index.js` is the ONE registry and
16
+ * the ONE public surface — it requires this module, registers these three
17
+ * descriptors alongside the part descriptors, and re-exports them, so NO consumer
18
+ * changes and `ObjectSchema.get('Frame')` is exactly what it always was.
19
+ *
20
+ * An ES module like its sibling `valueNormalizer.js`; `schema/index.js` imports it.
21
+ *
22
+ * WHY IT WAS SPLIT OUT: `schema/index.js` reached the per-file size ceiling that
23
+ * `sdk/_build/verify-publish-surface.mjs` enforces on every
24
+ * authored/copied-from-source dist directory (the backstop against a renamed or
25
+ * minified core re-bundle landing in the package). That gate's own instruction is
26
+ * to SPLIT AT A NATURAL SEAM rather than raise the ceiling, which is what this
27
+ * file is. Adding a part descriptor should never require touching this one.
28
+ *
29
+ * DATA-BUBBLE DISCIPLINE: the `Frame.data` sub-shape is NOT re-listed here either.
30
+ * `lib/shim/frame-data` (SECTION_KEYS, normalizeDataBubble) is the one owner and is
31
+ * referenced BY REFERENCE through `FrameDataSchema`, exactly as index.js does.
32
+ */
33
+
34
+ import * as FrameDataSchema from '../../../shim/frame-data/index.js';
35
+
36
+
37
+
38
+ /**
39
+ * Frame — Writable engine-core descriptor for any frame in the simulation.
40
+ *
41
+ * Relationship to `particle` kind:
42
+ * `particle` is a READ-ONLY inspector view of a leaf frame (is_leaf=true).
43
+ * `Frame` is the WRITABLE engine-core accessor for ANY frame (leaf or composite).
44
+ * Keep them DISTINCT — do NOT merge them. `particle` drives the inspector palette;
45
+ * `Frame` drives the uniform accessor (getFrameProperty/setFrameProperty).
46
+ *
47
+ * Property access rules (docs/internal/engine/ENGINE_CONTRACT.md):
48
+ * type:'writable' → user-writable; reaches the engine.
49
+ * type:'readonly' → derived/computed; inspectable, write THROWS.
50
+ * type:'forbidden' → engine-owned topology; any write FAIL-LOUDs (TypeError).
51
+ *
52
+ * FAIL-LOUD discipline (Gate-2 architect binding, 2026-06-21):
53
+ * The Frame accessor is THROW-OR-APPLY, never silent-skip.
54
+ * Frames have NO JS-wrapper upstream (engine owns them).
55
+ * Every writable prop reaches the engine or throws.
56
+ * Every non-writable/forbidden prop throws on write, always.
57
+ *
58
+ * data bubble sub-shape:
59
+ * NOT re-listed here. The canonical authority is lib/shim/frame-data (SECTION_KEYS,
60
+ * normalizeDataBubble). Reference it via FrameDataSchema — never re-enumerate
61
+ * 'detection'/'render'/'ext' keys (schema-mirror trap; §Engineering Culture CEO mandate).
62
+ */
63
+ var FrameDescriptor = {
64
+ kind: 'Frame',
65
+ description: 'Any simulation frame (leaf or composite). ' +
66
+ 'Provides writable access to engine-core properties via getFrameProperty/setFrameProperty. ' +
67
+ 'Leaf frames (is_leaf=true) are the fundamental quanta; composite frames are parent nodes ' +
68
+ 'in the Frame hierarchy. The Frame Axiom: everything is a Frame — there is no separate ' +
69
+ 'particle class. Position/velocity/mass writes bypass move() by design (user override); ' +
70
+ 'the engine\'s CA rules reconcile topology and wavelength on the next tick. ' +
71
+ 'Topology (parent/children) is engine-owned and FORBIDDEN from user writes.',
72
+ fields: [
73
+ // ── Writable: position ──────────────────────────────────────────────
74
+ {
75
+ name: 'x',
76
+ type: 'writable',
77
+ engineVisible: true,
78
+ unit: 'px',
79
+ description: 'Frame center X position (physics pixels). ' +
80
+ 'Write repositions the frame directly, bypassing move() — user override. ' +
81
+ 'The engine does not clamp; caller is responsible for placing within bounds. ' +
82
+ 'Children that escape their parent rect are released next tick by releaseEscapedChildren.'
83
+ },
84
+ {
85
+ name: 'y',
86
+ type: 'writable',
87
+ engineVisible: true,
88
+ description: 'Frame center Y position (physics pixels). ' +
89
+ 'Write repositions the frame directly, bypassing move() — user override.'
90
+ },
91
+ {
92
+ name: 'z',
93
+ type: 'writable',
94
+ engineVisible: true,
95
+ description: 'Frame center Z position (depth, physics pixels). ' +
96
+ 'Default 0.0 when active_axes.z is false (2D mode). ' +
97
+ 'Bite 3 (ws-3d-discrete-walk): set by the 3D emitter; moved by the ' +
98
+ 'independent z yo-yo coin when active_axes.z is true. ' +
99
+ 'Cube edge = w (spec §11 — no separate d field; cubes only).'
100
+ },
101
+ {
102
+ name: 'left',
103
+ type: 'writable',
104
+ engineVisible: true,
105
+ description: 'Frame left edge (physics pixels). ' +
106
+ 'Write repositions the frame by its left edge (mirrors lo._eject otherRect.left = newLeft). ' +
107
+ 'Bit-identical to the native WALL eject — used in §10.3 eject-expression programs. ' +
108
+ 'Setting left also updates right; center x is derived.'
109
+ },
110
+ {
111
+ name: 'top',
112
+ type: 'writable',
113
+ engineVisible: true,
114
+ description: 'Frame top edge (physics pixels). ' +
115
+ 'Write repositions the frame by its top edge (mirrors lo._eject otherRect.top = newTop). ' +
116
+ 'Bit-identical to the native WALL eject — used in §10.3 eject-expression programs. ' +
117
+ 'Setting top also updates bottom; center y is derived.'
118
+ },
119
+ // ── Writable: momentum ─────────────────────────────────────────────
120
+ {
121
+ name: 'vx',
122
+ type: 'writable',
123
+ engineVisible: true,
124
+ unit: 'px/tick',
125
+ description: 'X velocity / momentum (pixels/tick). ' +
126
+ 'Positive = rightward, negative = leftward. ' +
127
+ 'The 1px/tick speed limit still applies on the next move() call; ' +
128
+ 'excess accumulates back into vx.'
129
+ },
130
+ {
131
+ name: 'vy',
132
+ type: 'writable',
133
+ engineVisible: true,
134
+ description: 'Y velocity / momentum (pixels/tick). ' +
135
+ 'Positive = downward (screen coords), negative = upward.'
136
+ },
137
+ {
138
+ name: 'vz',
139
+ type: 'writable',
140
+ engineVisible: true,
141
+ description: 'Z velocity / momentum (pixels/tick). ' +
142
+ 'Default 0.0 when active_axes.z is false (2D mode). ' +
143
+ 'When active_axes.z is true, the yo-yo z coin adds/subtracts to vz ' +
144
+ 'each tick for the transverse axes (spec §3 / D5/D10). ' +
145
+ 'The Euclidean L2 walk probs include vz: D = sqrt(vx²+vy²+vz²).'
146
+ },
147
+ // ── Writable: mass ─────────────────────────────────────────────────
148
+ {
149
+ name: 'mass',
150
+ type: 'writable',
151
+ engineVisible: true,
152
+ description: 'Pixel occupancy count. Feeds setWavelength() on the next tick ' +
153
+ '(EGPTfrqtl.js:1716 / FrameStore.set_wavelength). Higher mass → shorter ' +
154
+ 'wavelength → higher frequency (E=mc² analog, invariant 6).'
155
+ },
156
+ // ── Writable: charge ───────────────────────────────────────────────
157
+ {
158
+ name: 'charge',
159
+ type: 'writable',
160
+ engineVisible: true,
161
+ description: 'Charge polarity: "POSITIVE" or "NEGATIVE" (canonical SCREAMING_SNAKE). ' +
162
+ 'Determines wave phase (sine vs cosine random walk) and bonding attraction/repulsion. ' +
163
+ 'Wire format: provider translates to engine-native (JS: 0/1; Rust: Charge enum).'
164
+ },
165
+ // ── Writable: lifecycle ────────────────────────────────────────────
166
+ {
167
+ name: 'is_alive',
168
+ type: 'writable',
169
+ engineVisible: true,
170
+ description: 'Liveness flag. Setting false kills the frame: it is excluded from ' +
171
+ 'physics next tick and GC\'d at end-of-tick. Equivalent to killFrame(id) ' +
172
+ 'but accessed uniformly. Children of a killed composite are orphaned ' +
173
+ '(not recursively killed) — topology is reconciled by garbageCollectDeadParents.'
174
+ },
175
+ // ── Writable: motion control ───────────────────────────────────────
176
+ {
177
+ name: 'is_stationary',
178
+ type: 'writable',
179
+ engineVisible: true,
180
+ description: 'Pins the frame in place: move() is skipped when true. ' +
181
+ 'Existing per-frame flag (EGPTfrqtl.js:1681 / FrameStore.is_stationary). ' +
182
+ 'Used in bespoke experiments to freeze specific frames while others evolve.'
183
+ },
184
+ {
185
+ name: 'wrap',
186
+ type: 'writable',
187
+ engineVisible: true,
188
+ description: 'Toroidal boundary for this individual frame. When true the frame ' +
189
+ 'wraps at the canvas edges instead of escaping or bouncing. ' +
190
+ 'Overrides the universe-level wrap setting for this frame.'
191
+ },
192
+ {
193
+ name: 'speed_prob',
194
+ type: 'writable',
195
+ engineVisible: true,
196
+ description: 'Per-frame OVERRIDE of the leaf longitudinal "speed probability" — the ' +
197
+ 'probability the frame takes its along-momentum step this tick (frame.rs move_frame ' +
198
+ 'leaf gate). Sentinel -1.0 (default; any negative resets to it) = derive from ' +
199
+ 'fullness (mass/capacity). When >= 0.0 it overrides the gate so user space can set ' +
200
+ 'the move-probability independent of mass — e.g. red vs blue light sharing a speed ' +
201
+ 'while differing in momentum/wavelength. Does NOT change the orthogonal wavelength.'
202
+ },
203
+ // ── Writable: wave phase ───────────────────────────────────────────
204
+ {
205
+ name: 'local_time',
206
+ type: 'writable',
207
+ constraint: { integer: true },
208
+ engineVisible: true,
209
+ description: 'Per-frame wave-phase counter (integer ticks; EGPTfrqtl.js:2473 / ' +
210
+ 'frame.rs local_time). Drives the spin/coin-flip via local_time % wavelength. ' +
211
+ 'Incremented each tick; reset to 0 on collision/reset. Op-programs that ' +
212
+ 'reproduce the native reset() (e.g. compiled RANDOM_* collision behavior) ' +
213
+ 'write 0 here. CANONICAL home for the writable-prop contract — both engines ' +
214
+ 'mirror this descriptor; neither hand-lists it (schema-mirror-drift fix).'
215
+ },
216
+ // ── Writable: data bubble ──────────────────────────────────────────
217
+ {
218
+ name: 'data',
219
+ type: 'writable',
220
+ engineVisible: true,
221
+ // IMPORTANT: the sub-shape of this bag is OWNED by lib/shim/frame-data.
222
+ // We reference it here — we NEVER re-list 'detection'/'render'/'ext' keys.
223
+ // Callers must use FrameDataSchema (= lib/shim/frame-data) for the shape.
224
+ dataBubbleSchema: FrameDataSchema,
225
+ description: 'The per-frame data bubble: { detection, render, ext }. ' +
226
+ 'Sub-shape is owned by lib/shim/frame-data (SECTION_KEYS + normalizeDataBubble). ' +
227
+ 'detection — written by engine MARK/DETECT primitives (detector_name). ' +
228
+ 'render — written by sugar (emitter stamps data.render.color); renderer reads. ' +
229
+ 'ext — developer-extensible; JS-only (not cross-engine assertable). ' +
230
+ 'NEVER enumerate the section keys here — always resolve from FrameDataSchema.'
231
+ },
232
+ // ── Read-only: derived ─────────────────────────────────────────────
233
+ {
234
+ name: 'fullness',
235
+ type: 'readonly',
236
+ engineVisible: true,
237
+ description: 'Derived: mass / capacity (0.0–1.0). ' +
238
+ 'Used by the renderer for color mapping and by detectors for density measurement. ' +
239
+ 'Not directly writable — set mass to change fullness indirectly.'
240
+ },
241
+ {
242
+ name: 'capacity',
243
+ type: 'readonly',
244
+ engineVisible: true,
245
+ unit: 'px²',
246
+ description: 'Derived: rect.w * rect.h (physics pixels). ' +
247
+ 'Fixed at frame creation; determined by the frame\'s bounding rect size.'
248
+ },
249
+ {
250
+ name: 'child_count',
251
+ type: 'readonly',
252
+ engineVisible: true,
253
+ description: 'Number of direct children in this frame\'s hierarchy (0 for leaf frames). ' +
254
+ 'Per-tick result; changes as promote/merge/release rules run.'
255
+ },
256
+ {
257
+ name: 'collided_id',
258
+ type: 'readonly',
259
+ engineVisible: true,
260
+ description: 'ID of the other frame this frame collided with in the last tick, ' +
261
+ 'or -1/null if no collision occurred. Per-tick result from the Phase C collide pass.'
262
+ },
263
+ {
264
+ name: 'r',
265
+ type: 'readonly',
266
+ engineVisible: true,
267
+ description: 'Radius cache: max(rect.w, rect.h) / 2. ' +
268
+ 'Used in proximity checks and rendering. Derived from rect size.'
269
+ },
270
+ {
271
+ name: 'w',
272
+ type: 'readonly',
273
+ engineVisible: true,
274
+ description: 'Frame width in physics pixels (fixed at creation, derived from rect.w). ' +
275
+ 'Read in op-program scope for eject geometry: set frame.left = self.left - frame.w - 1. ' +
276
+ 'For leaf quanta this is 1.'
277
+ },
278
+ {
279
+ name: 'h',
280
+ type: 'readonly',
281
+ engineVisible: true,
282
+ description: 'Frame height in physics pixels (fixed at creation, derived from rect.h). ' +
283
+ 'Read in op-program scope for eject geometry: set frame.top = self.top - frame.h - 1. ' +
284
+ 'For leaf quanta this is 1.'
285
+ },
286
+ {
287
+ name: 'layer',
288
+ type: 'readonly',
289
+ engineVisible: true,
290
+ description: 'Dimension layer membership (u32). Assigned at frame creation; ' +
291
+ 'engine-managed — changes only when the frame is promoted to a higher dimension. ' +
292
+ 'User writes are REJECTED (use the promote/detach structural primitives).'
293
+ },
294
+ // ── Read-only: scope-read pre-move snapshot ────────────────────────
295
+ // prev_x/prev_y are the CENTER position before this tick's move() (saved by
296
+ // Frame::move, frame.rs:626). They are READABLE in op-program scope
297
+ // (frame_to_scope_bag, universe.rs) so the compiled MOMENTUM_BASED behavior can
298
+ // restore the pre-move position via `set 0.x = Ref(0,'prev_x')`. Promoted to
299
+ // canonical FrameDescriptor fields (PF1) so the one owner is mirrored by both
300
+ // interpreters + conformance — closes the scope-read schema-mirror gap
301
+ // (docs/internal/engine/ENGINE_LANGUAGE_SPEC.md §5-F3). Read-only — engine-owned per-tick snapshot.
302
+ {
303
+ name: 'prev_x',
304
+ type: 'readonly',
305
+ engineVisible: true,
306
+ description: 'Derived (scope-read): frame CENTER X before this tick\'s move() ' +
307
+ '(physics pixels). Readable in op-program scope as Ref(0,"prev_x") — the ' +
308
+ 'compiled MOMENTUM_BASED behavior restores pre-move position via set 0.x = prev_x. ' +
309
+ 'Read-only — write THROWS (engine-owned per-tick snapshot, saved by Frame::move).'
310
+ },
311
+ {
312
+ name: 'prev_y',
313
+ type: 'readonly',
314
+ engineVisible: true,
315
+ description: 'Derived (scope-read): frame CENTER Y before this tick\'s move() ' +
316
+ '(physics pixels). Readable in op-program scope as Ref(0,"prev_y"). ' +
317
+ 'Read-only — write THROWS (engine-owned per-tick snapshot, saved by Frame::move).'
318
+ },
319
+ {
320
+ name: 'prev_z',
321
+ type: 'readonly',
322
+ engineVisible: true,
323
+ description: 'Derived (scope-read): frame CENTER Z before this tick\'s move() ' +
324
+ '(physics pixels). Default 0.0 when active_axes.z is false. ' +
325
+ 'Bite 3 (ws-3d-discrete-walk): saved by Frame::move_frame alongside prev_x/prev_y. ' +
326
+ 'Read-only — write THROWS (engine-owned per-tick snapshot).'
327
+ },
328
+ // ── Forbidden: engine-owned topology ──────────────────────────────
329
+ {
330
+ name: 'parent',
331
+ type: 'forbidden',
332
+ engineVisible: false,
333
+ description: 'FORBIDDEN — engine-owned topology. ' +
334
+ 'The parent link is managed exclusively by the engine\'s promote/detach/GC rules. ' +
335
+ 'Any write attempt FAIL-LOUDs with a TypeError. ' +
336
+ 'To move a frame: write its x/y position and let the engine reconcile topology ' +
337
+ '(releaseEscapedChildren drops children outside their parent rect next tick).'
338
+ },
339
+ {
340
+ name: 'children',
341
+ type: 'forbidden',
342
+ engineVisible: false,
343
+ description: 'FORBIDDEN — engine-owned topology. ' +
344
+ 'The children list is managed exclusively by the engine\'s promote/attach/detach rules. ' +
345
+ 'Any write attempt FAIL-LOUDs with a TypeError.'
346
+ }
347
+ ]
348
+ };
349
+
350
+ /**
351
+ * Universe — property table for the top-level simulation container.
352
+ *
353
+ * Gate-2 architect binding (§10.8 B4, 2026-06-21):
354
+ * Same home/pattern as FrameDescriptor. Reads = readonly (activeQuanta, tick).
355
+ * Scratch slots = writable (no scratch slots defined in that slice).
356
+ * THROW-OR-APPLY FAIL-LOUD on writes to readonly fields (no silent-skip).
357
+ *
358
+ * WS Studio Controls Realignment S1 (design §2.3.2 / gap-census #10, 2026-07-05):
359
+ * Added the FIRST writable field, `wavelengthScale` — Wave Interference's
360
+ * primary physics knob was previously unbindable (no writable Universe field
361
+ * existed to validate a bind against; the page wrote `universe.wavelengthScale`
362
+ * directly, undeclared and unreachable by any control-contract mechanism). This
363
+ * does NOT retroactively make every Universe field writable — each new writable
364
+ * field is added deliberately, per field, exactly like every other kind's schema.
365
+ *
366
+ * Used by: op-program evaluator scope (HANDLE_UNIVERSE = 2) for the readonly
367
+ * fields; `FrqtlApp.prototype.setUniverseProperty`/`getUniverseProperty`
368
+ * (the validated JS-side accessor pair — mirrors `updateObjectProperty`'s
369
+ * throw-or-apply discipline) for `wavelengthScale`.
370
+ * NOT a placeable kind — not in PLACEABLE_KINDS.
371
+ */
372
+ var UniverseDescriptor = {
373
+ kind: 'Universe',
374
+ description: 'The top-level simulation universe. Most properties are read-only state accessible ' +
375
+ 'from op-programs via HANDLE_UNIVERSE (2) in the expression scope; a small number of ' +
376
+ 'universe-wide physics constants (currently: wavelengthScale) are writable through the ' +
377
+ 'validated setUniverseProperty accessor. THROW-OR-APPLY: any write to an unknown or readonly ' +
378
+ 'field FAIL-LOUDs with TypeError — there is no bind-local property list anywhere in the stack.',
379
+ fields: [
380
+ {
381
+ name: 'tick',
382
+ type: 'readonly',
383
+ engineVisible: true,
384
+ description: 'Current tick count (u64). Increments once per doTick() call. ' +
385
+ 'Available in op-program scope via Ref(HANDLE_UNIVERSE, "tick"). ' +
386
+ 'Write THROWS — tick is engine-owned and monotonically increasing.'
387
+ },
388
+ {
389
+ name: 'activeQuanta',
390
+ type: 'readonly',
391
+ engineVisible: true,
392
+ description: 'Number of currently alive leaf quanta (usize). ' +
393
+ 'Derived by counting is_alive=true frames in the fundamental dimension. ' +
394
+ 'Available in op-program scope via Ref(HANDLE_UNIVERSE, "activeQuanta"). ' +
395
+ 'Write THROWS — this is a derived aggregate, not a writable property.'
396
+ },
397
+ {
398
+ name: 'wavelengthScale',
399
+ type: 'number',
400
+ constraint: { min: 1, integer: true },
401
+ widgetHint: 'slider',
402
+ widgetConfig: { max: 32, step: 1 },
403
+ // engineVisible:true — this IS an engine-visible universe-wide physics
404
+ // constant (WASM-live: EGPTUniverse.prototype.wavelengthScale's setter
405
+ // calls `this._wasm.set_wavelength_scale(value)`, wasm-engine.js:268-274).
406
+ // Unlike a Frame/LargeObject field, there is no separate engine-ABI branch
407
+ // to add here — the JS-side property setter already dispatches to the WASM
408
+ // ABI, so `setUniverseProperty` validates then does `universe[prop] = value`
409
+ // (safe ONLY because the schema check ran first — never a bare, unvalidated
410
+ // universe[prop]=v anywhere else in the stack).
411
+ engineVisible: true,
412
+ description: 'Layer 1 — universe-wide oscillation-wavelength scale: ' +
413
+ '`wavelength = floor((capacity/mass) * wavelengthScale)`, minimum 4 ' +
414
+ '(Core Axioms §6B). Every Frame in the universe shares this one multiplier. ' +
415
+ 'Layer 2 — physics behavior: this is Wave Interference\'s and Double-Slit\'s ' +
416
+ 'primary knob — raising it stretches every Frame\'s transverse oscillation ' +
417
+ 'period, widening fringe/interference spacing without changing any Frame\'s ' +
418
+ 'mass or capacity (see docs/internal/records/physics-lab/2026-06-16-wave-interference-wavelengthScale.md, ' +
419
+ 'docs/internal/physics-lab/double-slit-wavelength.md for the observed sweep figures).'
420
+ }
421
+ ]
422
+ };
423
+
424
+ /**
425
+ * Dimension — read-only property table for a scale layer in the simulation.
426
+ *
427
+ * Gate-2 architect binding (§10.8 B4, 2026-06-21):
428
+ * Same home/pattern as FrameDescriptor and UniverseDescriptor.
429
+ * layer = readonly (engine-managed).
430
+ * THROW-OR-APPLY FAIL-LOUD on writes.
431
+ *
432
+ * Used by: op-program evaluator (not yet in scope; defined here as the descriptor
433
+ * home so conformance can iterate it and validate getObjectProperty / setObjectProperty).
434
+ * NOT a placeable kind — not in PLACEABLE_KINDS.
435
+ */
436
+ var DimensionDescriptor = {
437
+ kind: 'Dimension',
438
+ description: 'A scale layer in the simulation (a "dimension" in FRQTL terminology). ' +
439
+ 'Each dimension is a spatial index (QuadTree) that organises frames at one scale. ' +
440
+ 'Properties are readonly — the engine manages dimensional structure. ' +
441
+ 'THROW-OR-APPLY: any write attempt FAIL-LOUDs with TypeError.',
442
+ fields: [
443
+ {
444
+ name: 'layer',
445
+ type: 'readonly',
446
+ engineVisible: true,
447
+ description: 'Dimension layer index (u32). Assigned at creation (add_dimension / addDimension). ' +
448
+ '0 = fundamental (leaf-quanta layer). Higher values = higher scales. ' +
449
+ 'Engine-owned — write THROWS (topology is engine-derived).'
450
+ },
451
+ {
452
+ name: 'frame_count',
453
+ type: 'readonly',
454
+ engineVisible: true,
455
+ description: 'Number of frames currently in this dimension (usize). ' +
456
+ 'Changes each tick as frames are added, promoted, or GC\'d. ' +
457
+ 'Derived from the dimension\'s frame list length — not user-writable.'
458
+ }
459
+ ]
460
+ };
461
+
462
+ /**
463
+ * backdrop — A draw-only LargeObject (collision_type=NONE, actions=[]).
464
+ * Created via FrqtlApp.addBackdrop(). All fields are render-only.
465
+ * Phase 3 declares backdrop as a formal kind so Phase 4a can route edits uniformly
466
+ * instead of relying on the ad-hoc backdrop=true flag set inline.
467
+ */
468
+
469
+ export { FrameDescriptor, UniverseDescriptor, DimensionDescriptor };