@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.
- package/CLAUDE.md +87 -0
- package/README.md +84 -2
- package/dist/dist-manifest.json +218 -0
- package/dist/eyes/index.js +109 -0
- package/dist/fat/pkg-node/egpt_wasm.js +1277 -0
- package/dist/fat/pkg-node/egpt_wasm_bg.wasm +0 -0
- package/dist/fat/pkg-node/package.json +12 -0
- package/dist/frqtl/assets/vendor/chroma.mjs +64 -0
- package/dist/frqtl/compat/boot-node.js +34 -0
- package/dist/frqtl/compat/engine.js +127 -0
- package/dist/frqtl/compat/package-root.js +24 -0
- package/dist/frqtl/compat/providers/wasm-engine.js +2501 -0
- package/dist/frqtl/compat/providers/wasm-load-browser.js +134 -0
- package/dist/frqtl/compat/providers/wasm-load-node.js +59 -0
- package/dist/frqtl/compat/renderer/FieldBuilder.js +145 -0
- package/dist/frqtl/compat/renderer/Filters.js +163 -0
- package/dist/frqtl/compat/renderer/RenderFamily.js +85 -0
- package/dist/frqtl/compat/renderer/RenderMesh.js +100 -0
- package/dist/frqtl/compat/renderer/RenderShape.js +154 -0
- package/dist/frqtl/compat/renderer/camera2d-geometry.js +183 -0
- package/dist/frqtl/compat/renderer/captureStill-common.js +259 -0
- package/dist/frqtl/compat/renderer/display-slot.js +96 -0
- package/dist/frqtl/compat/renderer/lo-drawn-center.js +231 -0
- package/dist/frqtl/compat/renderer/orbit-bag.js +216 -0
- package/dist/frqtl/compat/renderer/providers/godrays-layer.js +213 -0
- package/dist/frqtl/compat/renderer/providers/index.js +22 -0
- package/dist/frqtl/compat/renderer/providers/p5-provider.js +861 -0
- package/dist/frqtl/compat/renderer/providers/three-camera-contract.js +160 -0
- package/dist/frqtl/compat/renderer/providers/three-camera-geometry.js +571 -0
- package/dist/frqtl/compat/renderer/providers/three-provider.js +2474 -0
- package/dist/frqtl/compat/renderer/renderCapabilities-common.js +186 -0
- package/dist/frqtl/compat/renderer/renderer-provider-contract.js +238 -0
- package/dist/frqtl/compat/renderer/unprojectStill.js +172 -0
- package/dist/frqtl/compat/vendor.js +196 -0
- package/dist/frqtl/node-entry.js +17 -0
- package/dist/frqtl/objects/FrqtlApp.js +2922 -0
- package/dist/frqtl/objects/ObjectFactory.js +297 -0
- package/dist/frqtl/objects/RecipeContext.js +322 -0
- package/dist/frqtl/objects/collectors/DataCollector.js +116 -0
- package/dist/frqtl/objects/constants/WallBehaviors.js +178 -0
- package/dist/frqtl/objects/geometry/SlabFace.js +258 -0
- package/dist/frqtl/objects/instruments/capture-host.js +453 -0
- package/dist/frqtl/objects/instruments/capture.js +711 -0
- package/dist/frqtl/objects/instruments/hosted-eyes.js +985 -0
- package/dist/frqtl/objects/kinds-entry.js +14 -0
- package/dist/frqtl/objects/kinds.js +190 -0
- package/dist/frqtl/objects/objects/Box.js +273 -0
- package/dist/frqtl/objects/objects/Bullet.js +155 -0
- package/dist/frqtl/objects/objects/CircuitGate.js +380 -0
- package/dist/frqtl/objects/objects/CircuitProbe.js +214 -0
- package/dist/frqtl/objects/objects/DirectedTunnel.js +412 -0
- package/dist/frqtl/objects/objects/EgptFractal.js +164 -0
- package/dist/frqtl/objects/objects/LightSource.js +354 -0
- package/dist/frqtl/objects/objects/QuantumEmitter.js +760 -0
- package/dist/frqtl/objects/objects/Tube.js +471 -0
- package/dist/frqtl/objects/objects/absorbRadiation.js +310 -0
- package/dist/frqtl/objects/objects/actionCompiler.js +1747 -0
- package/dist/frqtl/objects/objects/controlAction.js +89 -0
- package/dist/frqtl/objects/objects/controlBind.js +278 -0
- package/dist/frqtl/objects/objects/directedRedirectProgram.js +120 -0
- package/dist/frqtl/objects/objects/emitterProgram.js +209 -0
- package/dist/frqtl/objects/objects/frqtl-control-slider.js +197 -0
- package/dist/frqtl/objects/objects/frqtl-control-sync.js +272 -0
- package/dist/frqtl/objects/objects/frqtl-control-widgets.js +219 -0
- package/dist/frqtl/objects/objects/frqtl-control-write-queue.js +174 -0
- package/dist/frqtl/objects/objects/makeControlsForObject.js +824 -0
- package/dist/frqtl/objects/objects/makeControlsForRenderSurface.js +161 -0
- package/dist/frqtl/objects/objects/slitLinerScatter.js +263 -0
- package/dist/frqtl/objects/objects/sustainedSource.js +299 -0
- package/dist/frqtl/objects/objects/tagger.js +228 -0
- package/dist/frqtl/objects/schema/engine-scopes.js +469 -0
- package/dist/frqtl/objects/schema/index.js +256 -0
- package/dist/frqtl/objects/schema/scopes.js +457 -0
- package/dist/frqtl/objects/schema/validate-descriptor.js +49 -0
- package/dist/frqtl/objects/schema/valueNormalizer.js +366 -0
- package/dist/frqtl/objects/setup/_collisionMatrixLanes.js +66 -0
- package/dist/frqtl/objects/setup/_setupOptions.js +118 -0
- package/dist/frqtl/objects/setup/_worldInit.js +162 -0
- package/dist/frqtl/objects/setup/setupBlackbodySubstrate.js +242 -0
- package/dist/frqtl/objects/setup/setupCircuitBasic.js +447 -0
- package/dist/frqtl/objects/setup/setupCollisionMatrix.js +188 -0
- package/dist/frqtl/objects/setup/setupConeEmitter3D.js +251 -0
- package/dist/frqtl/objects/setup/setupDoubleSlit.js +327 -0
- package/dist/frqtl/objects/setup/setupDoubleSlit_Laser.js +229 -0
- package/dist/frqtl/objects/setup/setupEmpty.js +59 -0
- package/dist/frqtl/objects/setup/setupFxSmoke.js +209 -0
- package/dist/frqtl/objects/setup/setupG1Race.js +80 -0
- package/dist/frqtl/objects/setup/setupG2Sweep.js +89 -0
- package/dist/frqtl/objects/setup/setupG3Collide.js +177 -0
- package/dist/frqtl/objects/setup/setupLightSourceLab.js +280 -0
- package/dist/frqtl/objects/setup/setupOscillator.js +68 -0
- package/dist/frqtl/objects/setup/setupParticleWalk.js +93 -0
- package/dist/frqtl/objects/setup/setupParticleWalk3D.js +133 -0
- package/dist/frqtl/objects/setup/setupSphereEmitter3D.js +1259 -0
- package/dist/frqtl/objects/setup/setupTraceCircuit.js +239 -0
- package/dist/frqtl/objects/setup/setupTunnelLab.js +242 -0
- package/dist/frqtl/objects/setup/setupTunnelPointExit.js +306 -0
- package/dist/frqtl/objects/setup/setupWaveInterference.js +178 -0
- package/dist/frqtl/objects/v1-replacements.js +30 -0
- package/dist/frqtl/package-core.js +23 -0
- package/dist/frqtl/parts/CameraControls.js +643 -0
- package/dist/frqtl/parts/CameraPath.js +575 -0
- package/dist/frqtl/parts/CollisionActions.js +35 -0
- package/dist/frqtl/parts/CollisionTypes.js +31 -0
- package/dist/frqtl/parts/DetectorWall.js +496 -0
- package/dist/frqtl/parts/FrqtlControlOverlay.js +227 -0
- package/dist/frqtl/parts/FrqtlControlsPanel.js +415 -0
- package/dist/frqtl/parts/FrqtlVision.js +818 -0
- package/dist/frqtl/parts/GraphingDetectorWall.js +490 -0
- package/dist/frqtl/parts/LargeObject.js +406 -0
- package/dist/frqtl/parts/LightColor.js +255 -0
- package/dist/frqtl/parts/LiveChart.js +285 -0
- package/dist/frqtl/parts/LogicGate.js +720 -0
- package/dist/frqtl/parts/OvenBox.js +612 -0
- package/dist/frqtl/parts/PointSource.js +763 -0
- package/dist/frqtl/parts/Rectangle.js +200 -0
- package/dist/frqtl/parts/SlitLightSource.js +234 -0
- package/dist/frqtl/parts/SlitScreen.js +628 -0
- package/dist/frqtl/parts/SphereEmitter.js +946 -0
- package/dist/frqtl/parts/Trace.js +508 -0
- package/dist/frqtl/parts/Tunnel.js +1057 -0
- package/dist/frqtl/parts/Wall.js +1211 -0
- package/dist/frqtl/parts/index.js +33 -0
- package/dist/frqtl/scenes/absorbing-wall-3d.js +33 -0
- package/dist/frqtl/scenes/absorbing-wall.js +32 -0
- package/dist/frqtl/scenes/atomic-model.js +88 -0
- package/dist/frqtl/scenes/big-bang.js +46 -0
- package/dist/frqtl/scenes/blackbody.js +81 -0
- package/dist/frqtl/scenes/circuit-sat.js +127 -0
- package/dist/frqtl/scenes/collision-matrix-3d.js +107 -0
- package/dist/frqtl/scenes/counting-wall-3d.js +36 -0
- package/dist/frqtl/scenes/counting-wall.js +38 -0
- package/dist/frqtl/scenes/double-slit.js +31 -0
- package/dist/frqtl/scenes/dse-one-emitter.js +196 -0
- package/dist/frqtl/scenes/dse-one-slit.js +114 -0
- package/dist/frqtl/scenes/dse-photoelectric.js +70 -0
- package/dist/frqtl/scenes/dse-tunnel-rebuild.js +244 -0
- package/dist/frqtl/scenes/dse-two-emitters.js +196 -0
- package/dist/frqtl/scenes/dse-two-slits.js +132 -0
- package/dist/frqtl/scenes/empty.js +14 -0
- package/dist/frqtl/scenes/laser-buildup.js +49 -0
- package/dist/frqtl/scenes/mirror-3d.js +56 -0
- package/dist/frqtl/scenes/mirror-route.js +140 -0
- package/dist/frqtl/scenes/mirror.js +38 -0
- package/dist/frqtl/scenes/omni-3d.js +27 -0
- package/dist/frqtl/scenes/omni-source.js +22 -0
- package/dist/frqtl/scenes/self-interference.js +39 -0
- package/dist/frqtl/scenes/smoking-gun.js +122 -0
- package/dist/frqtl/scenes/straight-walk.js +22 -0
- package/dist/frqtl/scenes/sun.js +39 -0
- package/dist/frqtl/scenes/two-source.js +37 -0
- package/dist/frqtl/scenes/wave.js +26 -0
- package/dist/shim/bundle/frqnb.js +112 -0
- package/dist/shim/bundle/index.js +121 -0
- package/dist/shim/bundle/indexHtml.js +107 -0
- package/dist/shim/bundle/manifest.js +95 -0
- package/dist/shim/bundle/zip.js +243 -0
- package/dist/shim/bus.js +67 -0
- package/dist/shim/controls/index.js +627 -0
- package/dist/shim/controls/registry.js +274 -0
- package/dist/shim/engine/artifact-shell.js +212 -0
- package/dist/shim/engine/boot-phases.js +44 -0
- package/dist/shim/engine/engine-stack-boot.js +59 -0
- package/dist/shim/engine/router.js +692 -0
- package/dist/shim/experiment-frame/index.js +296 -0
- package/dist/shim/expr/ast-schema.js +369 -0
- package/dist/shim/field-descriptor/index.js +326 -0
- package/dist/shim/frame-data/index.js +224 -0
- package/dist/shim/index.js +67 -0
- package/dist/shim/notebook/canvas-guard.js +82 -0
- package/dist/shim/notebook/catalog.js +35 -0
- package/dist/shim/notebook/format.js +736 -0
- package/dist/shim/notebook/frqtl-setups-importmap.js +81 -0
- package/dist/shim/notebook/kernel.js +672 -0
- package/dist/shim/notebook/knob.js +151 -0
- package/dist/shim/notebook/module-resolver.js +260 -0
- package/dist/shim/notebook/notebook-knobs.js +65 -0
- package/dist/shim/notebook/produced-bindings.js +67 -0
- package/dist/shim/notebook/realm-registry.js +121 -0
- package/dist/shim/notebook/realm-transport.js +73 -0
- package/dist/shim/notebook/setup-builder.js +510 -0
- package/dist/shim/notebook/store.js +159 -0
- package/dist/shim/notebook/vendor-importmap.js +134 -0
- package/dist/shim/notebook/view-builder.js +189 -0
- package/dist/shim/notebook/view-ctx.js +100 -0
- package/dist/shim/notebook/view-handle.js +202 -0
- package/dist/shim/notebook/warmup.js +102 -0
- package/dist/shim/package.json +4 -0
- package/dist/shim/page-params/index.js +214 -0
- package/dist/shim/project/identity.js +112 -0
- package/dist/shim/project/index.js +19 -0
- package/dist/shim/project/link.js +402 -0
- package/dist/shim/project/node-specifier-hook.mjs +35 -0
- package/dist/shim/project/register-node.mjs +17 -0
- package/dist/shim/project/specifiers.js +106 -0
- package/dist/shim/registry/copy-gate.js +110 -0
- package/dist/shim/registry/exhibits.js +455 -0
- package/dist/shim/registry/experiments.js +215 -0
- package/dist/shim/registry/index.js +19 -0
- package/dist/shim/registry/scene-source.js +157 -0
- package/dist/shim/registry/walkthrough.js +807 -0
- package/dist/shim/render/capture-envelope.js +279 -0
- package/dist/shim/render/heat-colormap.js +92 -0
- package/dist/shim/render/render-stages.js +855 -0
- package/dist/shim/render/sun-look.js +33 -0
- package/dist/shim/render-state/apply.js +262 -0
- package/dist/shim/render-state/index.js +74 -0
- package/dist/shim/rpc/index.js +207 -0
- package/dist/shim/runtime/index.js +1023 -0
- package/dist/shim/storage/boot.js +69 -0
- package/dist/shim/storage/index.js +169 -0
- package/dist/shim/storage/local-storage-provider.js +230 -0
- package/dist/shim/storage/make-namespace-store.js +132 -0
- package/dist/shim/storage/modules.js +249 -0
- package/dist/shim/storage/projects.js +150 -0
- package/llms.txt +12 -0
- package/package.json +62 -4
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/* Copyright 2023-2026 by Essam Abadir */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* makeControlsForRenderSurface.js — the RENDER-side factory twin of
|
|
5
|
+
* `makeControlsForObject.js` (WS Studio Controls Realignment, Bite S5a).
|
|
6
|
+
*
|
|
7
|
+
* ── Layer 1: API contract ────────────────────────────────────────────────────
|
|
8
|
+
*
|
|
9
|
+
* `makeControlsForRenderSurface({runner})` → `{ controls }`.
|
|
10
|
+
*
|
|
11
|
+
* Walks the ACTIVE renderer provider's OPTIONAL `renderCapabilities()` method
|
|
12
|
+
* (`lib/frqtl/compat/renderer/providers/{p5,three}-provider.js` — the
|
|
13
|
+
* `getCameraControl()` optional-capability precedent: absent ⇒ no render
|
|
14
|
+
* controls, never an error) and mechanically emits ONE `channel:'render'`
|
|
15
|
+
* contract control descriptor per declared capability — never a hand-mirrored
|
|
16
|
+
* per-page control array (this is exactly what retires `_egptFx.controls`,
|
|
17
|
+
* `fx-experiment.js`'s bespoke `{key,label,min,max,step}` vocabulary — see
|
|
18
|
+
* that file's own updated docstring).
|
|
19
|
+
*
|
|
20
|
+
* Each renderCapabilities() entry is a `lib/shim/field-descriptor`-shaped
|
|
21
|
+
* field descriptor (`{name, type, constraint, unit, default, description}` —
|
|
22
|
+
* §7 r2 CEO call C1's shared vocabulary): `type:'number'` → a `scalar`
|
|
23
|
+
* control; `type:'enum'` → an `enum` control; a render-only `type:'boolean'`
|
|
24
|
+
* → a 0/1 `scalar`; `type:'string'` (an OPEN-ID asset id) → no control. The
|
|
25
|
+
* conversions REUSE `makeControlsForObject.js`'s OWN handlers (exposed as
|
|
26
|
+
* `RENDER_TYPE_HANDLERS`) rather than re-deriving bounds/label/format logic.
|
|
27
|
+
*
|
|
28
|
+
* Every generated control binds `{object:'render', prop:capability.name}`, and
|
|
29
|
+
* `controlBind.js`'s render branch ferries it to `runner.setRenderOption` /
|
|
30
|
+
* `runner.getRenderOption` — the ONE render-option gate (declared key, valid
|
|
31
|
+
* value, and the `filter.<name>` toggle routing all live there).
|
|
32
|
+
*
|
|
33
|
+
* @param {object} opts
|
|
34
|
+
* @param {object} opts.runner — the FrqtlApp (REQUIRED — the only way
|
|
35
|
+
* to reach the active provider's `renderCapabilities()`/read the runner's
|
|
36
|
+
* own universal render options).
|
|
37
|
+
* @returns {{controls: object[]}} `controls` are ALREADY normalized
|
|
38
|
+
* (`lib/shim/controls` `normalizeControlDescriptor` has already run —
|
|
39
|
+
* fail-fast: a factory bug throws HERE, at generation time).
|
|
40
|
+
* @throws {Error} FAIL-LOUD — missing `opts.runner`, a capability descriptor
|
|
41
|
+
* whose `type` is not `RENDER_TYPE_HANDLERS`-dispatchable (see
|
|
42
|
+
* `makeControlsForObject.js`'s own docstring for why the remaining
|
|
43
|
+
* ObjectSchema field types are NOT reused here), or a malformed capability
|
|
44
|
+
* descriptor (`lib/shim/field-descriptor`'s own `normalizeFieldDescriptor`
|
|
45
|
+
* validates the envelope before conversion).
|
|
46
|
+
*
|
|
47
|
+
* ── Arrow legality ────────────────────────────────────────────────────────
|
|
48
|
+
*
|
|
49
|
+
* Same precedent as `makeControlsForObject.js`'s own "Arrow legality" note:
|
|
50
|
+
* this file `require`s `lib/shim/controls/index.js` and
|
|
51
|
+
* `lib/shim/field-descriptor/index.js` directly (an `objects → shim` schema-
|
|
52
|
+
* contract edge, NOT an engine dependency) — `lib/frqtl/objects` is annotated
|
|
53
|
+
* in `scripts/verify-arrows.mjs` as "user-space sugar — NOT a violation."
|
|
54
|
+
*
|
|
55
|
+
* ── Layer 2: physics behavior ────────────────────────────────────────────────
|
|
56
|
+
*
|
|
57
|
+
* Zero physics — render is output-boundary only (root CLAUDE.md §Object
|
|
58
|
+
* architecture: "render never feeds physics"). Generating a control changes
|
|
59
|
+
* NOTHING about the rendered scene until a host actually calls the generated
|
|
60
|
+
* control's `bind` through `resolveBind`, which itself calls
|
|
61
|
+
* `setRenderOption`/`filter()` — the IDENTICAL effect as calling those
|
|
62
|
+
* directly by hand.
|
|
63
|
+
*
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
import * as ControlsSchema from '../../../shim/controls/index.js';
|
|
67
|
+
import * as FieldDescriptorSchema from '../../../shim/field-descriptor/index.js';
|
|
68
|
+
import { MakeControlsForObject as _MakeControlsForObjectNode } from './makeControlsForObject.js';
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
// ── Imports (lazy-guarded, mirrors makeControlsForObject.js's own precedent) ─
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Resolve a capability's CURRENT live value (to seed the generated control) through
|
|
82
|
+
* `runner.getRenderOption` — the one read path (it answers `filter.<name>` too). Falls back
|
|
83
|
+
* to `field.default` while the option has never been written.
|
|
84
|
+
*/
|
|
85
|
+
function _resolveCapabilityValue(runner, field) {
|
|
86
|
+
var live = runner.getRenderOption(field.name);
|
|
87
|
+
return (live !== undefined) ? live : field.default;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** A synthetic single-field wrapper — see file docstring: `_numberHandler`/
|
|
91
|
+
* `_enumHandler` fall through to their generic `wrapper[propName]` read for
|
|
92
|
+
* any `env.kind` outside {'Frame','Universe'}, so this is all `env.wrapper`
|
|
93
|
+
* needs to be for them to work UNMODIFIED. */
|
|
94
|
+
function _singleFieldWrapper(name, value) {
|
|
95
|
+
var w = {};
|
|
96
|
+
w[name] = value;
|
|
97
|
+
return w;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @see file docstring for the full contract.
|
|
102
|
+
*/
|
|
103
|
+
function makeControlsForRenderSurface(opts) {
|
|
104
|
+
opts = opts || {};
|
|
105
|
+
var runner = opts.runner;
|
|
106
|
+
if (!runner) {
|
|
107
|
+
throw new Error('[makeControlsForRenderSurface] requires opts.runner (an FrqtlApp). ' +
|
|
108
|
+
'(FAIL-LOUD.)');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
var normalizeControlDescriptor = ControlsSchema.normalizeControlDescriptor;
|
|
112
|
+
var normalizeFieldDescriptor = FieldDescriptorSchema.normalizeFieldDescriptor;
|
|
113
|
+
var RENDER_TYPE_HANDLERS = _MakeControlsForObjectNode.RENDER_TYPE_HANDLERS;
|
|
114
|
+
|
|
115
|
+
// Optional capability (the getCameraControl() precedent) — absent
|
|
116
|
+
// renderCapabilities() ⇒ empty output, never an error.
|
|
117
|
+
var rawCaps = (typeof runner.renderCapabilities === 'function') ? runner.renderCapabilities() : null;
|
|
118
|
+
if (!Array.isArray(rawCaps)) { rawCaps = []; }
|
|
119
|
+
|
|
120
|
+
var controls = [];
|
|
121
|
+
|
|
122
|
+
for (var i = 0; i < rawCaps.length; i++) {
|
|
123
|
+
// Fail-fast: a provider's malformed renderCapabilities() entry throws
|
|
124
|
+
// HERE, at generation time — never silently skipped.
|
|
125
|
+
var field = normalizeFieldDescriptor(rawCaps[i]);
|
|
126
|
+
|
|
127
|
+
var handler = RENDER_TYPE_HANDLERS[field.type];
|
|
128
|
+
if (!handler) {
|
|
129
|
+
throw new Error('[makeControlsForRenderSurface] capability "' + field.name + '" declares ' +
|
|
130
|
+
'type "' + field.type + '" — only ' + Object.keys(RENDER_TYPE_HANDLERS).join(', ') +
|
|
131
|
+
' are dispatchable render-capability types today (the ones real render capabilities ' +
|
|
132
|
+
'use). (FAIL-LOUD — never a silent drop.)');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
var value = _resolveCapabilityValue(runner, field);
|
|
136
|
+
var env = {
|
|
137
|
+
kind: 'RenderSurface',
|
|
138
|
+
wrapper: _singleFieldWrapper(field.name, value),
|
|
139
|
+
ctx: {},
|
|
140
|
+
opts: {},
|
|
141
|
+
objectName: 'render'
|
|
142
|
+
};
|
|
143
|
+
var result = handler(field, env);
|
|
144
|
+
if (!result || result.kind !== 'control') { continue; } // defined skip — no live value to seed a control
|
|
145
|
+
|
|
146
|
+
var descriptor = result.descriptor;
|
|
147
|
+
descriptor.channel = 'render'; // override the physics default — this IS a render-channel control
|
|
148
|
+
controls.push(normalizeControlDescriptor(descriptor));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return { controls: controls };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ── Export ────────────────────────────────────────────────────────────────────
|
|
155
|
+
|
|
156
|
+
var MakeControlsForRenderSurface = {
|
|
157
|
+
makeControlsForRenderSurface: makeControlsForRenderSurface
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export { MakeControlsForRenderSurface };
|
|
161
|
+
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/* Copyright 2023-2026 by Essam Abadir */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* slitLinerScatter.js — the ONE authority for the double-slit edge-diffraction
|
|
5
|
+
* liner's collision op-program (behavior × resetLocalTime, ORTHOGONAL).
|
|
6
|
+
*
|
|
7
|
+
* DSE LAB (2026-07-13, CEO-chartered systematic controls): "behavior × reset are
|
|
8
|
+
* ORTHOGONAL controls" — this file composes the velocity-tail (`behavior`) and the
|
|
9
|
+
* `local_time=0` reset independently, so every (behavior, resetLocalTime) combo is
|
|
10
|
+
* reachable, INCLUDING combos that had no name before (`bounce`+reset,
|
|
11
|
+
* `ejectY`+reset, `ejectYReflect`+reset). The pre-existing compound `slitScatter`
|
|
12
|
+
* variants (EXPERIMENT LOOP 2026-07-12 + MATRIX EXTENSION) map onto specific combos
|
|
13
|
+
* — see `LEGACY_VARIANT_MAP` — proven byte-identical by
|
|
14
|
+
* `slit-liner-scatter.test.mjs`'s composed-vs-legacy equality tests.
|
|
15
|
+
*
|
|
16
|
+
* ONE AUTHORITY, NO FORK: both `SlitScreen.js` (construction-time, via the legacy
|
|
17
|
+
* `linerScatter` string) and the `dse-lab` experiment page (LIVE, via explicit
|
|
18
|
+
* `{behavior, resetLocalTime}`) call `buildLinerProgram`/`applyLinerScatter` here —
|
|
19
|
+
* neither re-derives the op shapes.
|
|
20
|
+
*
|
|
21
|
+
* ## Ground-truth (pkg-node instrumentation, EXPERIMENT LOOP delivery report)
|
|
22
|
+
* The liner's compiled `RANDOM_XY` op DOES fire; its OWN writes are `vx=random()`
|
|
23
|
+
* (ALWAYS non-negative) and `vy=random()*2-1` (already symmetric) — the sign bias
|
|
24
|
+
* the CEO's original hypothesis named (vy) was actually in `vx`, which the engine's
|
|
25
|
+
* 2D diagonal wave-kick (`frame.rs` `axy` branch, `dy_perp=(vx>0?+1:-1)*is_heads`)
|
|
26
|
+
* keys its transverse-Y sign off; `is_heads` is coherently biased by the SAME
|
|
27
|
+
* `local_time=0` phase-lock mechanism (`compute_spin`) the theorist found driving
|
|
28
|
+
* the separately-escalated 3D z-asymmetry. `local_time=0` is deliberate — it is
|
|
29
|
+
* what CREATES the y-interference fringes for the un-amended collision — hence
|
|
30
|
+
* this file's variants for visual/statistical A/B comparison, not a "fix."
|
|
31
|
+
*
|
|
32
|
+
* ## The FIVE composable BEHAVIORS (velocity-tail + eject-prefix + charge-draw?)
|
|
33
|
+
* - `randomXY` — generic BLOCK eject prefix + `vx=random()` (always +), `vy` symmetric; charge redrawn.
|
|
34
|
+
* - `symmetric` — generic BLOCK eject prefix + `vx` ALSO symmetric (fixes the actual bias found); charge redrawn.
|
|
35
|
+
* - `bounce` — generic BLOCK eject prefix + `vy=-vy` only (elastic reflection); no charge redraw.
|
|
36
|
+
* - `ejectY` — EXPLICIT Y-into-cavity eject prefix (not generic 'closest' — see
|
|
37
|
+
* `buildLinerProgram`'s docstring for why); NO velocity writes at all; no charge redraw.
|
|
38
|
+
* - `ejectYReflect` — `ejectY`'s prefix PLUS `vy=-vy`; no charge redraw.
|
|
39
|
+
*
|
|
40
|
+
* `resetLocalTime` (boolean, independent axis): when true, appends `set frame.local_time = 0`
|
|
41
|
+
* AFTER the velocity-tail and BEFORE any charge-draw (matching the ORIGINAL native
|
|
42
|
+
* RANDOM_XY/RANDOM_Y op order this file's `randomXY`+reset=true combo reproduces
|
|
43
|
+
* byte-for-byte).
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
import { compileActions as _compileActions, buildEjectOps as _buildEjectOpsFn, buildTriggerExpr as _buildTriggerExprFn, applyProgramTrigger as _applyProgramTriggerFn } from './actionCompiler.js';
|
|
47
|
+
import * as _astSchema from '../../../shim/expr/ast-schema.js';
|
|
48
|
+
import { CollisionTypes } from '../../parts/CollisionTypes.js';
|
|
49
|
+
|
|
50
|
+
// ── Imports (Node.js) or globals (browser) ──────────────────────────
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
/** The five composable behaviors (see module docstring). */
|
|
54
|
+
var BEHAVIORS = ['randomXY', 'symmetric', 'bounce', 'ejectY', 'ejectYReflect'];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* LEGACY_VARIANT_MAP — the pre-existing compound `slitScatter` string ->
|
|
58
|
+
* {behavior, resetLocalTime} this composable builder reproduces byte-for-byte.
|
|
59
|
+
* `'current'` maps to `null` — the SPECIAL no-op sentinel (construction leaves
|
|
60
|
+
* the LO's own naturally-compiled `RANDOM_XY` program untouched, ZERO
|
|
61
|
+
* `updateObjectProperty` calls — verified by test). `'current'` the STRING is
|
|
62
|
+
* therefore NOT the same as calling this builder with `{behavior:'randomXY',
|
|
63
|
+
* resetLocalTime:true}` (which WOULD produce an identical-shaped program, but
|
|
64
|
+
* via an explicit push — the two are proven ops-equal by test, but only the
|
|
65
|
+
* string sentinel gets the "untouched, zero side effects" default-path contract).
|
|
66
|
+
*/
|
|
67
|
+
var LEGACY_VARIANT_MAP = {
|
|
68
|
+
current: null,
|
|
69
|
+
noreset: { behavior: 'randomXY', resetLocalTime: false },
|
|
70
|
+
symmetric: { behavior: 'symmetric', resetLocalTime: true },
|
|
71
|
+
combined: { behavior: 'symmetric', resetLocalTime: false },
|
|
72
|
+
bounce: { behavior: 'bounce', resetLocalTime: false },
|
|
73
|
+
ejectY: { behavior: 'ejectY', resetLocalTime: false },
|
|
74
|
+
ejectYReflect: { behavior: 'ejectYReflect', resetLocalTime: false },
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Resolve a legacy `slitScatter` string to `{behavior, resetLocalTime}`, or
|
|
79
|
+
* `null` for `'current'`/omitted (the no-op sentinel). Throws on an unknown
|
|
80
|
+
* string (fail-loud, never silent).
|
|
81
|
+
* @param {string|undefined|null} slitScatterString
|
|
82
|
+
* @returns {{behavior:string, resetLocalTime:boolean}|null}
|
|
83
|
+
*/
|
|
84
|
+
function resolveLegacyVariant(slitScatterString) {
|
|
85
|
+
if (slitScatterString === undefined || slitScatterString === null) return null;
|
|
86
|
+
if (!Object.prototype.hasOwnProperty.call(LEGACY_VARIANT_MAP, slitScatterString)) {
|
|
87
|
+
throw new Error('[slitLinerScatter] unknown slitScatter legacy variant: ' + slitScatterString);
|
|
88
|
+
}
|
|
89
|
+
return LEGACY_VARIANT_MAP[slitScatterString];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* THE composable builder: `behavior` (velocity-tail + its own eject-prefix
|
|
94
|
+
* choice + whether it redraws charge) × `resetLocalTime` (an independent
|
|
95
|
+
* boolean — appends `local_time=0` after the tail, before any charge-draw).
|
|
96
|
+
*
|
|
97
|
+
* WHY `ejectY`/`ejectYReflect` use an EXPLICIT `intoCavityDir` instead of the
|
|
98
|
+
* generic `'closest'` nearest-face eject every other behavior reuses: the
|
|
99
|
+
* liner is a WIDE, THIN strip (much wider in x than tall in y) sitting at one
|
|
100
|
+
* edge of a slit's cavity — `'closest'` could pick a side (L/R) face for some
|
|
101
|
+
* approach angles/positions, ejecting the particle OUT of the cavity or back
|
|
102
|
+
* the way it came, the opposite of "lands between the slits" (ground-truthed,
|
|
103
|
+
* MATRIX EXTENSION delivery report). A `_top`-positioned liner always ejects
|
|
104
|
+
* `'bottom'` (deeper into the cavity below it); a `_bottom`-positioned liner
|
|
105
|
+
* always ejects `'top'` — the caller supplies which via `intoCavityDir`.
|
|
106
|
+
*
|
|
107
|
+
* @param {'randomXY'|'symmetric'|'bounce'|'ejectY'|'ejectYReflect'} behavior
|
|
108
|
+
* @param {boolean} resetLocalTime - independent reset axis (see module docstring).
|
|
109
|
+
* @param {Object} ast - the ast-schema module (Lit/Bin/Cond/Cmp/Fn/Ref/HANDLE_FRAME/HANDLE_SELF).
|
|
110
|
+
* @param {Function} buildEjectOpsFn - `actionCompiler.js`'s exported `buildEjectOps`.
|
|
111
|
+
* @param {Function} compileActionsFn - `actionCompiler.js`'s exported `compileActions`
|
|
112
|
+
* (used ONLY by randomXY/symmetric/bounce to derive the generic BLOCK/'closest'
|
|
113
|
+
* eject prefix — the SAME helper the liner's own constructor uses).
|
|
114
|
+
* @param {string} loName - the liner LO's name (passed to compileActionsFn for the
|
|
115
|
+
* generic-eject-prefix behaviors; irrelevant to ejectY/ejectYReflect).
|
|
116
|
+
* @param {string} reposition - the liner LO's `.reposition` (normally 'closest');
|
|
117
|
+
* passed through to compileActionsFn for the generic-eject-prefix behaviors.
|
|
118
|
+
* @param {'top'|'bottom'|'left'|'right'|'near'|'far'} [intoCavityDir] - REQUIRED for
|
|
119
|
+
* ejectY/ejectYReflect only. It is forwarded VERBATIM to `_buildEjectOps`, whose named-
|
|
120
|
+
* direction domain is all six faces — so this is the eject NORMAL, not a Y-only knob.
|
|
121
|
+
* The `ejectY` NAME is historical (the DSE liner is a horizontal strip that always ejects
|
|
122
|
+
* on Y); a vertical corridor (`Tunnel` axis 'y') passes 'left'/'right' through the SAME
|
|
123
|
+
* builder. Documenting the true domain, not widening it — no code change.
|
|
124
|
+
* @param {boolean} [hasRealDepth=false] - ws-dse-3d AC2 (CEO drive #2 round-2
|
|
125
|
+
* ruling: "It is immediately obvious that the reflections on one of the
|
|
126
|
+
* axes is missing... immediately obvious that we are not using the same
|
|
127
|
+
* objects with the same contracts"): when true, `randomXY`/`symmetric`
|
|
128
|
+
* (the two SCATTER behaviors — a wall-normal-agnostic velocity redraw, not
|
|
129
|
+
* a physical y-wall reflection) ALSO append `set frame.vz = random()*2-1`
|
|
130
|
+
* — the SAME `randomSigned()` term already used for `vy` — so a scatter
|
|
131
|
+
* event on a real-depth-armed tunnel redraws all 3 axes, not just 2.
|
|
132
|
+
* `bounce` (a genuine y-NORMAL wall reflection) and `ejectY`/`ejectYReflect`
|
|
133
|
+
* (Y-specific by design, the DSE liner's own cavity-eject convention) are
|
|
134
|
+
* UNCHANGED regardless of this flag — reflecting vz off a Y-normal wall
|
|
135
|
+
* would be physically wrong (this is a TOP/BOTTOM face; NEAR/FAR is
|
|
136
|
+
* handled correctly already by native BOUNCE, see the round-1 deliverable).
|
|
137
|
+
* Default `false` — byte-identical for every existing caller (`SlitScreen.js`'s
|
|
138
|
+
* own 2D liner construction, which never passes this).
|
|
139
|
+
* @returns {Array<Object>} the FULL composed ops array (eject-prefix + tail +
|
|
140
|
+
* [reset] + [charge-draw]) — ready to wrap as `{on:'collision', ops}`.
|
|
141
|
+
*/
|
|
142
|
+
function buildLinerProgram(behavior, resetLocalTime, ast, buildEjectOpsFn, compileActionsFn, loName, reposition, intoCavityDir, hasRealDepth) {
|
|
143
|
+
var Lit = ast.Lit, Bin = ast.Bin, Cond = ast.Cond, Cmp = ast.Cmp, Fn = ast.Fn, Ref = ast.Ref;
|
|
144
|
+
var HF = ast.HANDLE_FRAME, HS = ast.HANDLE_SELF;
|
|
145
|
+
var randomSigned = function () { return Bin('-', Bin('*', Fn('random', []), Lit(2)), Lit(1)); }; // random()*2-1
|
|
146
|
+
var chargeDraw = function () { return Cond(Cmp('<', Fn('random', []), Lit(0.5)), Lit(0), Lit(1)); };
|
|
147
|
+
|
|
148
|
+
var ejectPrefix, velocityTail, includesCharge;
|
|
149
|
+
|
|
150
|
+
if (behavior === 'ejectY' || behavior === 'ejectYReflect') {
|
|
151
|
+
ejectPrefix = buildEjectOpsFn(intoCavityDir, HF, HS, Lit, Ref, Bin, Cmp, Cond, Fn) || [];
|
|
152
|
+
velocityTail = (behavior === 'ejectYReflect')
|
|
153
|
+
? [{ set: HF + '.vy', to: Bin('*', Ref(HF, 'vy'), Lit(-1)) }]
|
|
154
|
+
: [];
|
|
155
|
+
includesCharge = false;
|
|
156
|
+
} else if (behavior === 'randomXY') {
|
|
157
|
+
var ejectOnlyRX = compileActionsFn(['BLOCK'], loName, reposition, CollisionTypes.NONE);
|
|
158
|
+
ejectPrefix = ejectOnlyRX.program ? ejectOnlyRX.program.ops : [];
|
|
159
|
+
velocityTail = [
|
|
160
|
+
{ set: HF + '.vx', to: Fn('random', []) },
|
|
161
|
+
{ set: HF + '.vy', to: randomSigned() },
|
|
162
|
+
];
|
|
163
|
+
if (hasRealDepth) { velocityTail.push({ set: HF + '.vz', to: randomSigned() }); }
|
|
164
|
+
includesCharge = true;
|
|
165
|
+
} else if (behavior === 'symmetric') {
|
|
166
|
+
var ejectOnlySym = compileActionsFn(['BLOCK'], loName, reposition, CollisionTypes.NONE);
|
|
167
|
+
ejectPrefix = ejectOnlySym.program ? ejectOnlySym.program.ops : [];
|
|
168
|
+
velocityTail = [
|
|
169
|
+
{ set: HF + '.vx', to: randomSigned() },
|
|
170
|
+
{ set: HF + '.vy', to: randomSigned() },
|
|
171
|
+
];
|
|
172
|
+
if (hasRealDepth) { velocityTail.push({ set: HF + '.vz', to: randomSigned() }); }
|
|
173
|
+
includesCharge = true;
|
|
174
|
+
} else if (behavior === 'bounce') {
|
|
175
|
+
var ejectOnlyBounce = compileActionsFn(['BLOCK'], loName, reposition, CollisionTypes.NONE);
|
|
176
|
+
ejectPrefix = ejectOnlyBounce.program ? ejectOnlyBounce.program.ops : [];
|
|
177
|
+
velocityTail = [{ set: HF + '.vy', to: Bin('*', Ref(HF, 'vy'), Lit(-1)) }];
|
|
178
|
+
includesCharge = false;
|
|
179
|
+
} else {
|
|
180
|
+
throw new Error('[slitLinerScatter] unknown behavior: ' + behavior);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
var ops = ejectPrefix.concat(velocityTail);
|
|
184
|
+
if (resetLocalTime) { ops = ops.concat([{ set: HF + '.local_time', to: Lit(0) }]); }
|
|
185
|
+
if (includesCharge) { ops = ops.concat([{ set: HF + '.charge', to: chargeDraw() }]); }
|
|
186
|
+
return ops;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Apply a scatter/behavior combo to an already-constructed liner LO — pushes
|
|
191
|
+
* the composed op-program LIVE via `universe.updateObjectProperty` (the SAME
|
|
192
|
+
* mechanism `LargeObject.prototype.recompileActions` uses for its own live
|
|
193
|
+
* collision-type edits). Accepts EITHER a legacy `slitScatter` string (used by
|
|
194
|
+
* `SlitScreen`'s constructor) OR an explicit `{behavior, resetLocalTime}` pair
|
|
195
|
+
* (used LIVE by the `dse-lab` page's controls) — ONE authority, no fork.
|
|
196
|
+
*
|
|
197
|
+
* `'current'`/omitted (legacy string) is the SPECIAL no-op sentinel: the LO
|
|
198
|
+
* keeps its own naturally-compiled program, ZERO `updateObjectProperty` calls.
|
|
199
|
+
*
|
|
200
|
+
* @param {Object} linerLO - the liner LargeObject instance (has `.handle`,
|
|
201
|
+
* `.name`, `.reposition`, `.program`).
|
|
202
|
+
* @param {Object} universe
|
|
203
|
+
* @param {'top'|'bottom'} intoCavityDir - REQUIRED for ejectY/ejectYReflect only.
|
|
204
|
+
* @param {Object} [opts]
|
|
205
|
+
* @param {string} [opts.slitScatter] - legacy compound variant string (mutually
|
|
206
|
+
* exclusive with opts.behavior/opts.resetLocalTime).
|
|
207
|
+
* @param {string} [opts.behavior] - explicit composable behavior (LIVE controls).
|
|
208
|
+
* @param {boolean} [opts.resetLocalTime] - explicit composable reset (LIVE controls).
|
|
209
|
+
* @param {boolean} [opts.hasRealDepth=false] - ws-dse-3d AC2 — see
|
|
210
|
+
* `buildLinerProgram`'s own param doc. Default false — byte-identical for
|
|
211
|
+
* every existing caller.
|
|
212
|
+
*/
|
|
213
|
+
function applyLinerScatter(linerLO, universe, intoCavityDir, opts) {
|
|
214
|
+
opts = opts || {};
|
|
215
|
+
var resolved;
|
|
216
|
+
if (opts.behavior !== undefined) {
|
|
217
|
+
resolved = { behavior: opts.behavior, resetLocalTime: !!opts.resetLocalTime };
|
|
218
|
+
} else {
|
|
219
|
+
resolved = resolveLegacyVariant(opts.slitScatter);
|
|
220
|
+
}
|
|
221
|
+
if (resolved === null) return; // 'current'/omitted — no-op sentinel, LO untouched.
|
|
222
|
+
|
|
223
|
+
var ast = _astSchema;
|
|
224
|
+
var ops = buildLinerProgram(
|
|
225
|
+
resolved.behavior, resolved.resetLocalTime, ast,
|
|
226
|
+
_buildEjectOpsFn, _compileActions,
|
|
227
|
+
linerLO.name, linerLO.reposition, intoCavityDir, !!opts.hasRealDepth
|
|
228
|
+
);
|
|
229
|
+
var newProgram = { on: 'collision', ops: ops };
|
|
230
|
+
|
|
231
|
+
// O4b FIX (tester Rule-0 finding, 2026-07-13): every liner is FIRST
|
|
232
|
+
// constructed via `new LargeObject(..., CollisionTypes.RANDOM_XY,
|
|
233
|
+
// [CollisionActions.BLOCK], ...)`, whose NATIVE `compileActions` compilation
|
|
234
|
+
// attaches a program-level `trigger` (`Fn('intersects',[HANDLE_FRAME,
|
|
235
|
+
// HANDLE_SELF])` — see actionCompiler.js's G2b design: "if trigger==0, ALL
|
|
236
|
+
// ops are skipped atomically"). This function's REPLACEMENT program was
|
|
237
|
+
// missing that `trigger` entirely — pkg-node isolation proved this ALONE
|
|
238
|
+
// (re-pushing an AST-IDENTICAL ops array onto an already-'current'-
|
|
239
|
+
// constructed liner, with no other change) regressed detector total
|
|
240
|
+
// 103->10, i.e. every push-based variant (every non-'current' legacy
|
|
241
|
+
// string, AND every LIVE composable combo) has been running with a
|
|
242
|
+
// missing/no-op trigger since this mechanism existed — not a behavior- or
|
|
243
|
+
// reset-specific effect. All liner collision types here are BLOCK-style
|
|
244
|
+
// overlap-only (never WALL), so `withPastEdge=false` always; reuse the
|
|
245
|
+
// SAME builder+attacher `compileActions` itself uses (one authority).
|
|
246
|
+
var trigger = _buildTriggerExprFn(
|
|
247
|
+
linerLO.reposition || null, false,
|
|
248
|
+
ast.HANDLE_FRAME, ast.HANDLE_SELF,
|
|
249
|
+
ast.Lit, ast.Ref, ast.Cmp, ast.Cond, ast.Fn
|
|
250
|
+
);
|
|
251
|
+
_applyProgramTriggerFn(newProgram, trigger);
|
|
252
|
+
|
|
253
|
+
linerLO.program = newProgram; // mirror on the JS wrapper (inspector/serialize source of truth)
|
|
254
|
+
if (universe && typeof universe.updateObjectProperty === 'function') {
|
|
255
|
+
universe.updateObjectProperty(linerLO.handle, 'LargeObject', 'program', newProgram);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// ── Export ───────────────────────────────────────────────────────────
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
export { BEHAVIORS, LEGACY_VARIANT_MAP, resolveLegacyVariant, buildLinerProgram, applyLinerScatter };
|
|
263
|
+
|