@descix/frqtl-node 0.6.0-p0.1 → 0.6.0-p0.2
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 +1 -1
- package/LICENSE.md +664 -0
- package/README.md +1 -1
- package/dist/dist-manifest.json +125 -125
- package/dist/fat/pkg-node/egpt_wasm.js +7 -7
- package/dist/fat/pkg-node/egpt_wasm_bg.wasm +0 -0
- package/dist/fat/pkg-node/package.json +1 -1
- package/dist/frqtl/compat/providers/wasm-engine.js +29 -31
- package/dist/frqtl/compat/providers/wasm-load-browser.js +2 -2
- package/dist/frqtl/compat/renderer/RenderFamily.js +1 -2
- package/dist/frqtl/compat/renderer/RenderMesh.js +2 -3
- package/dist/frqtl/compat/renderer/RenderShape.js +1 -1
- package/dist/frqtl/compat/renderer/captureStill-common.js +1 -2
- package/dist/frqtl/compat/renderer/display-slot.js +1 -1
- package/dist/frqtl/compat/renderer/providers/p5-provider.js +5 -5
- package/dist/frqtl/compat/renderer/providers/three-camera-contract.js +1 -1
- package/dist/frqtl/compat/renderer/providers/three-camera-geometry.js +4 -4
- package/dist/frqtl/compat/renderer/providers/three-provider.js +23 -27
- package/dist/frqtl/compat/renderer/renderCapabilities-common.js +2 -2
- package/dist/frqtl/compat/renderer/renderer-provider-contract.js +1 -1
- package/dist/frqtl/compat/vendor.js +2 -2
- package/dist/frqtl/objects/FrqtlApp.js +22 -24
- package/dist/frqtl/objects/ObjectFactory.js +1 -2
- package/dist/frqtl/objects/constants/WallBehaviors.js +5 -5
- package/dist/frqtl/objects/geometry/SlabFace.js +6 -6
- package/dist/frqtl/objects/instruments/capture-host.js +2 -2
- package/dist/frqtl/objects/instruments/capture.js +4 -5
- package/dist/frqtl/objects/instruments/hosted-eyes.js +3 -4
- package/dist/frqtl/objects/objects/DirectedTunnel.js +10 -11
- package/dist/frqtl/objects/objects/LightSource.js +22 -25
- package/dist/frqtl/objects/objects/QuantumEmitter.js +14 -14
- package/dist/frqtl/objects/objects/Tube.js +14 -14
- package/dist/frqtl/objects/objects/absorbRadiation.js +12 -13
- package/dist/frqtl/objects/objects/actionCompiler.js +52 -52
- package/dist/frqtl/objects/objects/controlAction.js +2 -2
- package/dist/frqtl/objects/objects/controlBind.js +2 -2
- package/dist/frqtl/objects/objects/directedRedirectProgram.js +3 -3
- package/dist/frqtl/objects/objects/emitterProgram.js +9 -9
- package/dist/frqtl/objects/objects/frqtl-control-slider.js +3 -3
- package/dist/frqtl/objects/objects/frqtl-control-sync.js +9 -9
- package/dist/frqtl/objects/objects/frqtl-control-widgets.js +2 -2
- package/dist/frqtl/objects/objects/frqtl-control-write-queue.js +2 -2
- package/dist/frqtl/objects/objects/makeControlsForObject.js +25 -29
- package/dist/frqtl/objects/objects/makeControlsForRenderSurface.js +2 -2
- package/dist/frqtl/objects/objects/slitLinerScatter.js +8 -10
- package/dist/frqtl/objects/objects/sustainedSource.js +15 -16
- package/dist/frqtl/objects/objects/tagger.js +2 -2
- package/dist/frqtl/objects/schema/engine-scopes.js +11 -12
- package/dist/frqtl/objects/schema/index.js +6 -6
- package/dist/frqtl/objects/schema/scopes.js +10 -10
- package/dist/frqtl/objects/setup/_collisionMatrixLanes.js +1 -1
- package/dist/frqtl/objects/setup/setupBlackbodySubstrate.js +1 -1
- package/dist/frqtl/objects/setup/setupCollisionMatrix.js +3 -3
- package/dist/frqtl/objects/setup/setupConeEmitter3D.js +7 -8
- package/dist/frqtl/objects/setup/setupDoubleSlit.js +20 -21
- package/dist/frqtl/objects/setup/setupFxSmoke.js +1 -1
- package/dist/frqtl/objects/setup/setupLightSourceLab.js +23 -26
- package/dist/frqtl/objects/setup/setupSphereEmitter3D.js +39 -40
- package/dist/frqtl/objects/setup/setupTunnelLab.js +17 -19
- package/dist/frqtl/objects/setup/setupTunnelPointExit.js +1 -1
- package/dist/frqtl/objects/setup/setupWaveInterference.js +4 -5
- package/dist/frqtl/objects/v1-replacements.js +0 -1
- package/dist/frqtl/parts/CameraControls.js +5 -5
- package/dist/frqtl/parts/CameraPath.js +1 -1
- package/dist/frqtl/parts/CollisionActions.js +2 -3
- package/dist/frqtl/parts/CollisionTypes.js +1 -2
- package/dist/frqtl/parts/DetectorWall.js +10 -10
- package/dist/frqtl/parts/FrqtlControlsPanel.js +11 -11
- package/dist/frqtl/parts/FrqtlVision.js +1 -1
- package/dist/frqtl/parts/GraphingDetectorWall.js +3 -4
- package/dist/frqtl/parts/LargeObject.js +7 -8
- package/dist/frqtl/parts/LightColor.js +2 -2
- package/dist/frqtl/parts/LiveChart.js +1 -1
- package/dist/frqtl/parts/LogicGate.js +4 -7
- package/dist/frqtl/parts/OvenBox.js +1 -2
- package/dist/frqtl/parts/PointSource.js +10 -11
- package/dist/frqtl/parts/SlitLightSource.js +6 -6
- package/dist/frqtl/parts/SlitScreen.js +14 -14
- package/dist/frqtl/parts/SphereEmitter.js +24 -24
- package/dist/frqtl/parts/Tunnel.js +17 -17
- package/dist/frqtl/parts/Wall.js +17 -17
- package/dist/frqtl/scenes/dse-one-emitter.js +1 -1
- package/dist/frqtl/scenes/dse-one-slit.js +2 -2
- package/dist/frqtl/scenes/dse-photoelectric.js +3 -3
- package/dist/frqtl/scenes/dse-tunnel-rebuild.js +5 -6
- package/dist/frqtl/scenes/dse-two-emitters.js +1 -1
- package/dist/frqtl/scenes/dse-two-slits.js +2 -2
- package/dist/frqtl/scenes/laser-buildup.js +1 -1
- package/dist/frqtl/scenes/mirror-3d.js +4 -4
- package/dist/frqtl/scenes/mirror-route.js +9 -9
- package/dist/frqtl/scenes/mirror.js +1 -1
- package/dist/frqtl/scenes/self-interference.js +1 -1
- package/dist/frqtl/scenes/smoking-gun.js +1 -1
- package/dist/frqtl/scenes/sun.js +2 -2
- package/dist/shim/bundle/frqnb.js +3 -3
- package/dist/shim/bundle/index.js +1 -1
- package/dist/shim/bundle/manifest.js +2 -2
- package/dist/shim/bundle/zip.js +1 -1
- package/dist/shim/controls/index.js +14 -14
- package/dist/shim/controls/registry.js +3 -3
- package/dist/shim/engine/artifact-shell.js +1 -2
- package/dist/shim/engine/router.js +15 -17
- package/dist/shim/expr/ast-schema.js +5 -5
- package/dist/shim/field-descriptor/index.js +7 -8
- package/dist/shim/frame-data/index.js +3 -3
- package/dist/shim/index.js +4 -4
- package/dist/shim/notebook/canvas-guard.js +1 -1
- package/dist/shim/notebook/catalog.js +2 -2
- package/dist/shim/notebook/format.js +26 -26
- package/dist/shim/notebook/kernel.js +3 -4
- package/dist/shim/notebook/knob.js +0 -1
- package/dist/shim/notebook/module-resolver.js +6 -6
- package/dist/shim/notebook/produced-bindings.js +1 -1
- package/dist/shim/notebook/setup-builder.js +9 -12
- package/dist/shim/notebook/vendor-importmap.js +1 -1
- package/dist/shim/notebook/view-builder.js +1 -1
- package/dist/shim/notebook/view-ctx.js +1 -1
- package/dist/shim/notebook/warmup.js +2 -2
- package/dist/shim/page-params/index.js +8 -9
- package/dist/shim/registry/copy-gate.js +1 -1
- package/dist/shim/registry/exhibits.js +4 -4
- package/dist/shim/registry/experiments.js +3 -3
- package/dist/shim/registry/walkthrough.js +21 -24
- package/dist/shim/render/render-stages.js +2 -2
- package/dist/shim/render/sun-look.js +2 -2
- package/dist/shim/rpc/index.js +2 -2
- package/dist/shim/runtime/index.js +12 -12
- package/dist/shim/storage/modules.js +8 -8
- package/llms.txt +2 -2
- package/package.json +4 -3
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
*
|
|
28
28
|
* three loads through the classic path because the vendored r128 is the UMD build only; moving it to
|
|
29
29
|
* three.module.js + the jsm loaders is a change inside this file, owned by the p5 instance-mode / renderer
|
|
30
|
-
*
|
|
30
|
+
* change (unscheduled).
|
|
31
31
|
*
|
|
32
32
|
* Zero physics: vendors draw; nothing here reads or writes a frame.
|
|
33
33
|
*/
|
|
@@ -39,7 +39,7 @@ const VENDOR_DIR = new URL('../assets/vendor/', import.meta.url);
|
|
|
39
39
|
* hook (called every frame). They are p5's contract, not FRQTL surfaces, so the page door's retired-
|
|
40
40
|
* name refusal (experiments/_shared/page-door.js) installs no throwing accessor on them — it subtracts
|
|
41
41
|
* this table from the census. This file is their one writer.
|
|
42
|
-
* Deleter: the
|
|
42
|
+
* Deleter: the change that moves p5 to instance mode (not yet scheduled; not P0c).
|
|
43
43
|
*/
|
|
44
44
|
export const P5_GLOBAL_MODE_HOOKS = Object.freeze(['setup', 'draw']);
|
|
45
45
|
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* NO LONGER used. window.draw is no longer set.
|
|
25
25
|
* - The renderer is obtained from THE DISPLAY SLOT (compat/renderer/display-slot.js, set by
|
|
26
26
|
* the boot module, experiments/_shared/boot.js). If the slot is empty when the draw loop first fires, the app
|
|
27
|
-
* FAILS LOUD (paintBootFailure) — no silent P5Renderer fallback (Phase 1
|
|
27
|
+
* FAILS LOUD (paintBootFailure) — no silent P5Renderer fallback (Phase 1).
|
|
28
28
|
* - Fixed-timestep accumulator decouples physics ticks from draw frames:
|
|
29
29
|
* tickHz: physics ticks per second (default: lock to drawHz → 1:1 as today)
|
|
30
30
|
* drawHz: draw frames per second cap (default: display refresh)
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* - stepsPerFrame is kept as a back-compat alias: sets tickHz = drawHz * stepsPerFrame.
|
|
34
34
|
* - Spiral-of-death guard: accumulated time clamped + ticks-per-frame capped.
|
|
35
35
|
* - Determinism preserved: physics only ever advances in whole doTick() steps;
|
|
36
|
-
* the headless run.js
|
|
36
|
+
* the headless run.js drivers (no RAF, no rendering) are unaffected.
|
|
37
37
|
*
|
|
38
38
|
* Usage (unchanged from before):
|
|
39
39
|
*
|
|
@@ -242,7 +242,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
242
242
|
this._declaredTicks = new Map();
|
|
243
243
|
this._setupResult = null;
|
|
244
244
|
this._sceneReplay = null; // retainSceneReplay(fn) — what restart() replays
|
|
245
|
-
// Design-mode signal
|
|
245
|
+
// Design-mode signal — DEFAULT false (Run / standalone bundles /
|
|
246
246
|
// experiment pages). When true (STUDIO authoring), the renderer DRAWS the
|
|
247
247
|
// Design-only markers (a manipulable emitter's visual circle, `lo._designMarker`).
|
|
248
248
|
// A render toggle at the output boundary (zero physics): it filters ONLY the
|
|
@@ -339,9 +339,9 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
339
339
|
});
|
|
340
340
|
|
|
341
341
|
/**
|
|
342
|
-
* runner.controlHost — THE door a scene's on-canvas chrome mounts through (
|
|
343
|
-
*
|
|
344
|
-
* ids
|
|
342
|
+
* runner.controlHost — THE door a scene's on-canvas chrome mounts through (host-owned
|
|
343
|
+
* control mount through the runner's one door; scenes do not name DOM
|
|
344
|
+
* ids). Read: the element a HOSTING PANE set, else the element the scene canvas is mounted
|
|
345
345
|
* in (its wrapper), else null (no canvas yet — a notebook pane before its mount: the chrome
|
|
346
346
|
* stays in the exposed registry only). Write: a hosting pane (STUDIO) hands an element it
|
|
347
347
|
* owns ABOVE its own overlays; every chrome already mounted through the door (a knob overlay
|
|
@@ -380,7 +380,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
380
380
|
};
|
|
381
381
|
|
|
382
382
|
/**
|
|
383
|
-
* Toggle Design mode
|
|
383
|
+
* Toggle Design mode. STUDIO calls setDesignMode(true) while authoring
|
|
384
384
|
* (MODE_DESIGN) so the manipulable emitter markers (`lo._designMarker`) render as
|
|
385
385
|
* visible circles, and false during Run / Pause so they are suppressed (you see
|
|
386
386
|
* the emission, not the source marker). Standalone bundles + experiment pages
|
|
@@ -393,13 +393,13 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
393
393
|
};
|
|
394
394
|
|
|
395
395
|
/**
|
|
396
|
-
* Effective shellRender mode for a LargeObject
|
|
396
|
+
* Effective shellRender mode for a LargeObject — the SINGLE
|
|
397
397
|
* suppression authority. Precedence:
|
|
398
398
|
* 1. per-instance `lo.shellRender` (a valid 'design'|'run'|'never' string) —
|
|
399
399
|
* the live override the Inspector / a game sets via updateObjectProperty
|
|
400
400
|
* (the "red light bulb" flips a marker to 'run').
|
|
401
401
|
* 2. kind default: a manipulable marker (`lo._designMarker === true`) defaults
|
|
402
|
-
* 'design' (
|
|
402
|
+
* 'design' (invisible during Run); every ordinary LO defaults
|
|
403
403
|
* 'run' (always visible). This keeps every pre-existing scene byte-identical.
|
|
404
404
|
* @returns {'design'|'run'|'never'}
|
|
405
405
|
*/
|
|
@@ -410,7 +410,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
410
410
|
};
|
|
411
411
|
|
|
412
412
|
/**
|
|
413
|
-
* The largeObjects VIEW passed to the renderer each frame
|
|
413
|
+
* The largeObjects VIEW passed to the renderer each frame: each LO
|
|
414
414
|
* is shown per its effective `shellRender` (see _shellRenderOf) — 'run' always,
|
|
415
415
|
* 'design' only while `_designMode` is on, 'never' hidden.
|
|
416
416
|
*
|
|
@@ -433,7 +433,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
433
433
|
return los.filter(function (lo) { return self._isShellVisible(lo); });
|
|
434
434
|
};
|
|
435
435
|
|
|
436
|
-
/** Whether a LO's shell paints in the CURRENT mode
|
|
436
|
+
/** Whether a LO's shell paints in the CURRENT mode. */
|
|
437
437
|
FrqtlApp.prototype._isShellVisible = function (lo) {
|
|
438
438
|
var sr = this._shellRenderOf(lo);
|
|
439
439
|
if (sr === 'run') { return true; }
|
|
@@ -669,7 +669,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
669
669
|
//
|
|
670
670
|
// The stage vocabulary stays with its owner, `lib/shim/render/render-stages` (the shim
|
|
671
671
|
// owns cross-layer vocabularies — peer of frame-data's RENDER_INTENT_KEYS); the
|
|
672
|
-
// instrument ferries it.
|
|
672
|
+
// instrument ferries it.
|
|
673
673
|
|
|
674
674
|
/**
|
|
675
675
|
* runner.setSourceRef(ref) — register the experiment/rung identity for the SceneRecord.
|
|
@@ -762,7 +762,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
762
762
|
};
|
|
763
763
|
|
|
764
764
|
/**
|
|
765
|
-
* Add a background-image under-layer (shared backdrop helper — Phase 2
|
|
765
|
+
* Add a background-image under-layer (shared backdrop helper — Phase 2).
|
|
766
766
|
*
|
|
767
767
|
* Creates and registers a NON-COLLIDING LargeObject that the renderer draws as the
|
|
768
768
|
* bottom-most layer via _layerBackdrop (under particles and large objects).
|
|
@@ -808,9 +808,8 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
808
808
|
|
|
809
809
|
// ── THE DECLARED-OBJECT REGISTRY ─────────────────────────────────────────────────────────
|
|
810
810
|
//
|
|
811
|
-
//
|
|
812
|
-
//
|
|
813
|
-
// should be registered."
|
|
811
|
+
// From STUDIO's point of view only the declared sugar object in code (not its sub objects)
|
|
812
|
+
// is manipulable, so only what the user proactively declares is registered.
|
|
814
813
|
//
|
|
815
814
|
// `declared` is the ordered list of the handles the user's DECLARING calls produced
|
|
816
815
|
// (`exp.addObject`, a palette drop, a codegen replay — all three funnel through
|
|
@@ -1139,7 +1138,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
1139
1138
|
// far away. Throw-or-apply, one call, every caller.
|
|
1140
1139
|
value = schema.normalizeValue(fieldDef, value, kind);
|
|
1141
1140
|
|
|
1142
|
-
// ── SphereEmitter
|
|
1141
|
+
// ── SphereEmitter — sugar; no engine handle ───────────────────────
|
|
1143
1142
|
// A SphereEmitter's real state lives in the setupSphereEmitter3D control
|
|
1144
1143
|
// closure (a host emit tick-fn), not on any engine object. Route EVERY
|
|
1145
1144
|
// editable/adapter prop to the matching control setter via the facade's
|
|
@@ -1231,7 +1230,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
1231
1230
|
// Mutate the JS-side wrapper object directly. The renderer reads from it
|
|
1232
1231
|
// on the next draw frame. No engine ABI — physics is not affected.
|
|
1233
1232
|
if (!fieldDef.engineVisible) {
|
|
1234
|
-
//
|
|
1233
|
+
// Studio Controls Realignment S4:
|
|
1235
1234
|
// collision_type/actions are SUGAR-INPUT fields compiled to an
|
|
1236
1235
|
// op-program at REGISTRATION (actionCompiler.js) — a bare mirror-write
|
|
1237
1236
|
// (what every OTHER engineVisible:false prop gets) would only update
|
|
@@ -1537,7 +1536,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
1537
1536
|
};
|
|
1538
1537
|
|
|
1539
1538
|
// ── THE AIM: a stationary reticle, a center-ray hover, a SPACEBAR grab ──────────────────
|
|
1540
|
-
//
|
|
1539
|
+
// The reticle sits at screen centre
|
|
1541
1540
|
// and the sticks fly the CAMERA in every state. The first visible object on the camera's
|
|
1542
1541
|
// centre ray is GRAB-READY; SPACE grabs it; a grabbed object HOLDS its camera-relative pose
|
|
1543
1542
|
// (position + heading) under every camera motion, so it is placed by moving the world and
|
|
@@ -1972,7 +1971,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
1972
1971
|
|
|
1973
1972
|
/**
|
|
1974
1973
|
* Uniform schema-driven mutation entry point for the live UNIVERSE singleton
|
|
1975
|
-
* (
|
|
1974
|
+
* (Studio Controls Realignment S1, design §2.3.2 / gap-census #10).
|
|
1976
1975
|
*
|
|
1977
1976
|
* Mirrors `updateObjectProperty`'s throw-or-apply discipline for the ONE other
|
|
1978
1977
|
* object every experiment page has exactly one of: the universe itself. Unlike
|
|
@@ -2126,7 +2125,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
2126
2125
|
* A factory carrying the deleted `RATE_LIMITS` static THROWS here; pacing is
|
|
2127
2126
|
* `runner.setRateLimits(...)` (a scene: `exp.runner.setRateLimits(...)`).
|
|
2128
2127
|
*
|
|
2129
|
-
* CANONICAL TEARDOWN (
|
|
2128
|
+
* CANONICAL TEARDOWN (the S4 dispose discipline,
|
|
2130
2129
|
* generalized to setup-level reinit): `universe.init()` (called by the world step
|
|
2131
2130
|
* below) resets the WASM instance's physics state but does NOT
|
|
2132
2131
|
* clear the JS-side `universe.experimentTickFunctions` array — a fact
|
|
@@ -2197,7 +2196,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
2197
2196
|
|
|
2198
2197
|
/**
|
|
2199
2198
|
* restart() — the PAGE-LEVEL restart primitive (presentation pass Item 2,
|
|
2200
|
-
*
|
|
2199
|
+
* E-P2b): stop → replay the RETAINED scene (`retainSceneReplay` — a setup
|
|
2201
2200
|
* factory's world + part steps with its ORIGINAL opts, or a sketch's `exp.build(sketch)`
|
|
2202
2201
|
* on the same runner and canvas) → start. The scene returns to tick 0 IN-PAGE: no reload,
|
|
2203
2202
|
* so the camera orbit, render options and any host wiring survive. The declared `restart`
|
|
@@ -2240,8 +2239,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
2240
2239
|
* "which provider owns the display", written by whichever boot ran the selection.
|
|
2241
2240
|
*
|
|
2242
2241
|
* The bare `window._egptActiveRenderer` global this used to read is DELETED: a slot
|
|
2243
|
-
* plus a global would be two truths about one fact (RENDERER_CONTRACT §9
|
|
2244
|
-
* finding d.1).
|
|
2242
|
+
* plus a global would be two truths about one fact (RENDERER_CONTRACT §9).
|
|
2245
2243
|
*
|
|
2246
2244
|
* FAIL-LOUD: if neither is set when rendering is requested, this is a boot
|
|
2247
2245
|
* configuration error — the boot must select a renderer before the draw loop starts
|
|
@@ -220,8 +220,7 @@ import { V1_REPLACEMENTS } from './v1-replacements.js';
|
|
|
220
220
|
var msg = '[ObjectFactory] create: unknown kind "' + kind + '". Registered kinds: ' +
|
|
221
221
|
ObjectFactory.kinds().slice().sort().join(', ') + '. The ' + unregisteredKindMessage(kind) + '.';
|
|
222
222
|
if (Object.prototype.hasOwnProperty.call(V1_REPLACEMENTS, kind)) {
|
|
223
|
-
msg += ' "' + kind + '" is a retired V1 part, not a published part — compose ' + V1_REPLACEMENTS[kind] + ' instead
|
|
224
|
-
'(docs/internal/engine/V2_PARTS_CLASSIFICATION.md).';
|
|
223
|
+
msg += ' "' + kind + '" is a retired V1 part, not a published part — compose ' + V1_REPLACEMENTS[kind] + ' instead.';
|
|
225
224
|
}
|
|
226
225
|
throw new Error(msg + ' (FAIL-LOUD.)');
|
|
227
226
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* vocabulary (`collisionBehavior` × `bounceDirection` × composable hooks × presets)
|
|
6
6
|
* and the structured resolver that turns a wall spec into a compiled op-program.
|
|
7
7
|
*
|
|
8
|
-
* ── Schema-mirror discipline (
|
|
8
|
+
* ── Schema-mirror discipline (W1(ii)/(iv) guard) ─────────────────────────────
|
|
9
9
|
* The hook table FERRIES the frozen `CollisionActions` constant set BY REFERENCE —
|
|
10
10
|
* it NEVER re-types a SCREAMING_SNAKE string. The vocabulary keys ARE the enum: the
|
|
11
11
|
* `Wall` descriptor's enum fields read these maps (never a hand-listed enum),
|
|
@@ -33,7 +33,7 @@ import { compileWallV2 } from '../objects/actionCompiler.js';
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
// ═══════════════════════════════════════════════════════════════════════
|
|
36
|
-
// Collision LEXICON v2
|
|
36
|
+
// Collision LEXICON v2 — the STUDIO/palette surface and the ONLY
|
|
37
37
|
// wall vocabulary. Three ferried vocab tables + a structured resolver that
|
|
38
38
|
// delegates to the ONE compiler authority (compileWallV2 in actionCompiler.js).
|
|
39
39
|
// ═══════════════════════════════════════════════════════════════════════
|
|
@@ -112,12 +112,12 @@ import { compileWallV2 } from '../objects/actionCompiler.js';
|
|
|
112
112
|
// + closest3d eject). Derived from the caller (Wall.js reads it off the rect);
|
|
113
113
|
// omitted/false ⇒ the 2D path (byte-identical, SU1).
|
|
114
114
|
is3D: props.is3D === true,
|
|
115
|
-
// MIRROR
|
|
115
|
+
// MIRROR rule — the TRUE slab dims (Wall reads them off the rect) so a tilted 2D
|
|
116
116
|
// reflect wall can bake the OBB-NORMAL eject (perpendicular to the drawn face) instead
|
|
117
117
|
// of the beam-scattering AABB 'closest'. Omitted ⇒ the AABB eject (byte-identical, SU1).
|
|
118
118
|
slabW: props.slabW,
|
|
119
119
|
slabH: props.slabH,
|
|
120
|
-
// R2AX (
|
|
120
|
+
// R2AX (two-axis mirror) — the plate's up/down tilt + z-depth,
|
|
121
121
|
// ferried so a pitched plate compiles the 3-space reflection about SlabFace's
|
|
122
122
|
// plate3.n. Omitted ⇒ byte-identical un-pitched programs (SU1).
|
|
123
123
|
pitchDeg: props.pitchDeg,
|
|
@@ -130,7 +130,7 @@ import { compileWallV2 } from '../objects/actionCompiler.js';
|
|
|
130
130
|
// ── Presets (B6) — pure CONSTRUCTION sugar expanding to the v2 descriptor fields.
|
|
131
131
|
// The recipe/codegen round-trips the EXPANDED fields (never the preset name).
|
|
132
132
|
//
|
|
133
|
-
// THE NAMING RULE
|
|
133
|
+
// THE NAMING RULE: a preset's NAME MUST ASSERT ITS BEHAVIOR.
|
|
134
134
|
// `collisionBehavior:'nothing'` (pass-through) belongs ONLY on a preset whose name SAYS
|
|
135
135
|
// it passes through — `transparent-probe` is the one that earns it. A palette entry
|
|
136
136
|
// labelled "Wall" that particles walk through is the same defect class as mistaking
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* SlabFace.js — the SOLE face / OBB / convention authority for a rotated Wall slab.
|
|
5
5
|
*
|
|
6
|
-
* ## Why this file exists (the DRY crux —
|
|
6
|
+
* ## Why this file exists (the DRY crux — Gate-2, circulation §1)
|
|
7
7
|
*
|
|
8
8
|
* A Wall mirror's reflecting FACE is derived from its `orientationDeg` in what USED to be
|
|
9
9
|
* three independent, hand-authored places, each re-writing the SAME "tall slab, y-DOWN
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* (the drawn-tall-face reflection line);
|
|
14
14
|
* 3. the engine swept-OBB narrow-phase needs the slab's rotated collision region.
|
|
15
15
|
*
|
|
16
|
-
* A hand-mirrored sign in ANY of the three re-creates the off-face deflection bug
|
|
17
|
-
*
|
|
16
|
+
* A hand-mirrored sign in ANY of the three re-creates the off-face deflection bug seen
|
|
17
|
+
* when rotating a mirror (the "1A/1D" class). This module is the ONE place the
|
|
18
18
|
* convention is written: `orientationDeg (+ slab aspect, z-slab) → canonical face geometry`.
|
|
19
19
|
* `_buildReflectOps` reads `reflectBaseDeg` from here; `Wall.compileWallV2` reads `obb` from
|
|
20
20
|
* here for the engine `region` field. The renderer consumes the RAW `orientationDeg` (the
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
* [-90,90]; 3D wall REQUIRED). ≠0 ⇒ the PITCHED result shape: `{ pitched:true, obb:null,
|
|
73
73
|
* plate3:{ n,u,v, hw,hh,hz, aabb } }` — the true 3-space plate basis; NO engine region
|
|
74
74
|
* (z-theta-only contract; the in-op guard is the narrow phase). 0/absent ⇒ byte-identical
|
|
75
|
-
* un-pitched behavior (this whole block is opt-in
|
|
75
|
+
* un-pitched behavior (this whole block is opt-in).
|
|
76
76
|
*
|
|
77
77
|
* ## Layer 2 — physics behavior
|
|
78
78
|
* ZERO physics of its own (SU1). This is a pure geometry derivation consumed by the reflect
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
var h = +spec.h;
|
|
101
101
|
var o = (typeof spec.orientationDeg === 'number' && isFinite(spec.orientationDeg))
|
|
102
102
|
? spec.orientationDeg : 0;
|
|
103
|
-
// ── PITCH (two-axis mirror
|
|
103
|
+
// ── PITCH (two-axis mirror) ────────────────────────────────────────────────
|
|
104
104
|
// `pitchDeg` rotates the plate about its OWN in-plane LONG axis (the drawn face
|
|
105
105
|
// line), tipping the face normal out of the xy-plane: positive pitch tips the
|
|
106
106
|
// normal toward +z. The TRUE 3-space plate basis:
|
|
@@ -224,7 +224,7 @@
|
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
/**
|
|
227
|
-
* BROAD-PHASE SUPERSET (
|
|
227
|
+
* BROAD-PHASE SUPERSET (the MIRROR rule — the sugar-half
|
|
228
228
|
* broad-phase-rect flag closed here). The engine's spatial index is an AABB broad
|
|
229
229
|
* phase over the LO's registered rect (`octree.rs`); a tilted TALL slab's raw
|
|
230
230
|
* un-rotated rect is NARROWER in x than the rotated slab, so a beam aimed at the
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
* the ONE boundary codec, and the verification that proves the two processes are
|
|
12
12
|
* talking about the SAME scene.
|
|
13
13
|
*
|
|
14
|
-
* Contract
|
|
14
|
+
* Contract: RENDERER_CONTRACT §9 (the capture-host KIND) and
|
|
15
15
|
* §10.3 (the normalized format this ferries).
|
|
16
16
|
*
|
|
17
|
-
* ── Why a distinct KIND and not a provider-shaped adapter (
|
|
17
|
+
* ── Why a distinct KIND and not a provider-shaped adapter (V3) ──────────────────
|
|
18
18
|
*
|
|
19
19
|
* A `RendererProvider` adapter would have been the tempting shape: implement
|
|
20
20
|
* `captureStill()` in node, forward to the browser, let the local dispatcher stamp the
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* capture.js — THE render-pipeline tap MECHANISM, as an INSTRUMENT on the primitive
|
|
5
|
-
* surface (THE_MINIMAL_SIM.md §4;
|
|
5
|
+
* surface (THE_MINIMAL_SIM.md §4; home = the primitive surface).
|
|
6
6
|
*
|
|
7
7
|
* `capture(stage)` is the ONE generic read-at-a-named-stage mechanism; `captureStill()` is
|
|
8
8
|
* its last-stage CONVENIENCE; `sceneRecord()` is the run-invariant half of the normalized
|
|
9
9
|
* format. All dispatch, all throw rules and ALL provenance stamping live HERE and nowhere
|
|
10
|
-
* else. Contract text: docs/internal/engine/RENDERER_CONTRACT.md §1a.4 + §10.
|
|
11
10
|
*
|
|
12
11
|
* ── Why this is not on the host ──────────────────────────────────────────────
|
|
13
12
|
*
|
|
@@ -42,7 +41,7 @@
|
|
|
42
41
|
* `tick` and `field` are backend-independent, so a bare node process taps them with no
|
|
43
42
|
* renderer at all. `composite` is different in kind: it IS the render stack's output, and
|
|
44
43
|
* re-drawing it with a node raster library would show the agent a different picture than
|
|
45
|
-
* the user sees (
|
|
44
|
+
* the user sees (V3 — a god-rays shader turns particles into A SUN, and the
|
|
46
45
|
* shader is part of the experiment, not decoration). So `composite` is executed by a
|
|
47
46
|
* CAPTURE HOST — a remote stage executor running the real stack in a managed headless
|
|
48
47
|
* browser — attached via `attachCaptureHost()`. The KIND, its boundary codec and its
|
|
@@ -98,7 +97,7 @@ import * as FrqtlDisplay from '../../compat/renderer/display-slot.js';
|
|
|
98
97
|
/**
|
|
99
98
|
* The RASTER PATH pin — which GL backend this browser actually rasters with.
|
|
100
99
|
*
|
|
101
|
-
* Measured, not assumed
|
|
100
|
+
* Measured, not assumed: a
|
|
102
101
|
* `composite` still is bit-reproducible run-to-run WITHIN a pinned (machine, driver,
|
|
103
102
|
* browser build) — under software SwiftShader AND under hardware ANGLE/Metal alike —
|
|
104
103
|
* but the software and hardware pictures differ (0.42% of pixels raw, 1.75% with a
|
|
@@ -672,7 +671,7 @@ import * as FrqtlDisplay from '../../compat/renderer/display-slot.js';
|
|
|
672
671
|
|
|
673
672
|
/**
|
|
674
673
|
* captureStill() — the LAST-STAGE CONVENIENCE. Capturing the canvas is capturing the
|
|
675
|
-
* fully composed stack of transforms
|
|
674
|
+
* fully composed stack of transforms.
|
|
676
675
|
*
|
|
677
676
|
* PURE DELEGATION: it contains no capture logic, no provider call and no provenance
|
|
678
677
|
* stamping of its own — it resolves the final stage name and calls the mechanism. The
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* **The browser is the ENGINE ROOM, never the interface.** Nothing above this file mentions
|
|
19
19
|
* a page, a selector or a screenshot: a consumer opens a handle, drives it, and reads the
|
|
20
20
|
* same normalized still bags `FrqtlVision` hands out everywhere else. That is the whole
|
|
21
|
-
* point of
|
|
21
|
+
* point of this file — a raster backend that RE-DREW the scene in
|
|
22
22
|
* node would have shown the agent a different picture than the end user sees, which defeats
|
|
23
23
|
* the purpose (a god-rays shader turns a bunch of particles into A SUN, and the shader is
|
|
24
24
|
* part of the experiment, not decoration).
|
|
@@ -78,8 +78,7 @@
|
|
|
78
78
|
*
|
|
79
79
|
* ── The raster path is RECORDED, never assumed ───────────────────────────────
|
|
80
80
|
*
|
|
81
|
-
* The default launch flags select HARDWARE GL, per the measured policy
|
|
82
|
-
* (`docs/internal/physics-lab/composite-determinism/`): hardware is bit-reproducible on a
|
|
81
|
+
* The default launch flags select HARDWARE GL, per the measured policy: hardware is bit-reproducible on a
|
|
83
82
|
* pinned machine/driver/build, so a software default would trade V3's premise for a
|
|
84
83
|
* property we measured we already have. But the flags are a REQUEST — headless chromium
|
|
85
84
|
* silently falls back to SwiftShader, which is how a naive rig measures the software path
|
|
@@ -287,7 +286,7 @@ import { projectIdentity, projectBytes } from '../../../shim/project/identity.js
|
|
|
287
286
|
* The caller's `build`/`projection` are an EXPECTATION, never a request.
|
|
288
287
|
*
|
|
289
288
|
* They are boot RESULTS, so a caller who states them is asserting what the source will
|
|
290
|
-
* resolve to. Agreement is silent; a disagreement THROWS naming BOTH sides — the
|
|
289
|
+
* resolve to. Agreement is silent; a disagreement THROWS naming BOTH sides — the
|
|
291
290
|
* "caller forces 2D onto a 3D source" case. The one thing never allowed is the third
|
|
292
291
|
* outcome: quietly running the caller's display over the source's world.
|
|
293
292
|
* @private
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
* false) is the SAME orthogonal axis `slitLinerScatter.js` already defines.
|
|
50
50
|
* - Unknown string — throws (FAIL-LOUD, never a silent no-op).
|
|
51
51
|
*
|
|
52
|
-
* ── `options.orientation` — v1 semantics (
|
|
52
|
+
* ── `options.orientation` — v1 semantics (open; DOCUMENT LOUDLY) ──────────────────────
|
|
53
53
|
*
|
|
54
54
|
* `orientation` (degrees) is the direction the tunnel DIRECTS TOWARDS — it drives
|
|
55
55
|
* the DIRECTION machinery EXACTLY, at ANY angle, NEVER snapped:
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
* nearest axis-aligned orientation" trivially resolves to X (the only axis Tube
|
|
66
66
|
* can cap) for EVERY input angle. A genuine Y/Z-long BODY (a real closed breech
|
|
67
67
|
* positioned at a Y or Z extreme) is NOT achievable without new Tube geometry
|
|
68
|
-
* (adding `capNegY`/`capPosY`) and is explicitly OUT OF SCOPE
|
|
68
|
+
* (adding `capNegY`/`capPosY`) and is explicitly OUT OF SCOPE here — it
|
|
69
69
|
* is sugar-layer work, not engine work, but it is a materially larger addition
|
|
70
70
|
* than "opt-in default-off params," so it is deliberately deferred, not silently
|
|
71
71
|
* claimed. The DIRECTION (redirect angle / exit vector / emitter velocity) is the
|
|
@@ -107,8 +107,7 @@
|
|
|
107
107
|
* @property {Object} tube - the underlying `Tube` instance (walls/sinks/innerRect).
|
|
108
108
|
* @property {Array<LargeObject>} walls - alias for `this.tube.walls`.
|
|
109
109
|
* @property {Object|null} emitter - alias for `this.tube.emitter`.
|
|
110
|
-
* @property {Function} applyRedirect - ALWAYS present (C1 fix,
|
|
111
|
-
* ruling_directed_tunnel_lightsource.md), regardless of the current `behavior`
|
|
110
|
+
* @property {Function} applyRedirect - ALWAYS present (C1 fix), regardless of the current `behavior`
|
|
112
111
|
* — a redirect applier is cheap to build and this lets a LIVE `updateBehavior`
|
|
113
112
|
* switch INTO 'option1' work without reconstruction. Prefer
|
|
114
113
|
* `applyRedirectIfActive(tickData)` (below) over calling this directly — it
|
|
@@ -157,7 +156,7 @@ import { CollisionTypes } from '../../parts/CollisionTypes.js';
|
|
|
157
156
|
var hasDepth = (options.depth !== undefined && options.depth !== null);
|
|
158
157
|
var depth = hasDepth ? options.depth : width; // placeholder — Tube requires interiorDepth > 0 even when zContain:false
|
|
159
158
|
var zContain = hasDepth;
|
|
160
|
-
//
|
|
159
|
+
// The SAME N1-fix-precedent
|
|
161
160
|
// gate `hasRealDepth` uses elsewhere in this file (polarSpreadRad) — stored
|
|
162
161
|
// for `_applyBehaviorToWalls`'s composable-behavior branch below, which
|
|
163
162
|
// threads it into `SlitLinerScatter.applyLinerScatter`'s new `hasRealDepth`
|
|
@@ -234,7 +233,7 @@ import { CollisionTypes } from '../../parts/CollisionTypes.js';
|
|
|
234
233
|
this._topWall = this.walls.filter(function (w) { return w.name === 'TOP'; })[0];
|
|
235
234
|
this._bottomWall = this.walls.filter(function (w) { return w.name === 'BOTTOM'; })[0];
|
|
236
235
|
|
|
237
|
-
// C1 FIX
|
|
236
|
+
// C1 FIX: the host redirect applier is ALWAYS
|
|
238
237
|
// built (regardless of the INITIAL behavior) — mirrors the DSE-lab tunnels'
|
|
239
238
|
// OWN "always collectCollided:true + always an applyRedirect fallback" design
|
|
240
239
|
// (needed so a LIVE switch INTO option1 works with no reconstruction). Kept
|
|
@@ -248,7 +247,7 @@ import { CollisionTypes } from '../../parts/CollisionTypes.js';
|
|
|
248
247
|
angleRad: orientationRad,
|
|
249
248
|
spreadRad: redirectSpreadDeg * Math.PI / 180,
|
|
250
249
|
speed: redirectSpeed,
|
|
251
|
-
// 3D EXTENSION (
|
|
250
|
+
// 3D EXTENSION (§4 option (c)): when this tunnel
|
|
252
251
|
// has REAL z-containment armed (zContain, the SAME N1-fix-precedent
|
|
253
252
|
// gate `hasRealDepth` uses elsewhere — never innerRect.d, always a
|
|
254
253
|
// positive placeholder), mirror the azimuth spread's own magnitude
|
|
@@ -299,7 +298,7 @@ import { CollisionTypes } from '../../parts/CollisionTypes.js';
|
|
|
299
298
|
if (topWall) { topWall.recompileActions({ collisionType: 'BOUNCE', actions: [] }); }
|
|
300
299
|
if (bottomWall) { bottomWall.recompileActions({ collisionType: 'BOUNCE', actions: [] }); }
|
|
301
300
|
} else if (SlitLinerScatter.BEHAVIORS.indexOf(behavior) !== -1) {
|
|
302
|
-
//
|
|
301
|
+
// hasRealDepth threads THIS tunnel's own zContain (set
|
|
303
302
|
// at construction, never re-derived) into the composable scatter
|
|
304
303
|
// behaviors — a randomXY/symmetric switch on a real-depth tunnel now
|
|
305
304
|
// scatters all 3 axes, matching option2's (native BOUNCE) own
|
|
@@ -334,7 +333,7 @@ import { CollisionTypes } from '../../parts/CollisionTypes.js';
|
|
|
334
333
|
};
|
|
335
334
|
|
|
336
335
|
/**
|
|
337
|
-
* C1 FIX
|
|
336
|
+
* C1 FIX — the redirect applier is a plain
|
|
338
337
|
* function the CALLER invokes once per tick with that tick's `tickData`
|
|
339
338
|
* (directedRedirectProgram.js's own docstring explains why this can never be
|
|
340
339
|
* a self-registering `experimentTickFunctions` push: it needs THIS tick's
|
|
@@ -363,8 +362,8 @@ import { CollisionTypes } from '../../parts/CollisionTypes.js';
|
|
|
363
362
|
// that needs to enumerate the full set — never hand-typed (T3, 2026-07-13).
|
|
364
363
|
DirectedTunnel.BEHAVIORS = [OPTION1, OPTION2].concat(SlitLinerScatter.BEHAVIORS);
|
|
365
364
|
|
|
366
|
-
// BEHAVIOR_META (
|
|
367
|
-
//
|
|
365
|
+
// BEHAVIOR_META (option1/option2 are non-descript names): a DISPLAY-ONLY
|
|
366
|
+
// label/description per canonical
|
|
368
367
|
// `options.behavior` VALUE — the wire value ('option1'/'option2'/composable
|
|
369
368
|
// name) is UNCHANGED (every existing caller — the tunnel/lightsource labs and
|
|
370
369
|
// every test — keeps passing/reading the
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
* side-by-side `this.bulletHandle` (hand-placed) / `this.emitter` (auto-wired)
|
|
14
14
|
* duality:
|
|
15
15
|
*
|
|
16
|
-
* - `options.source = 'particleWalk'` (DEFAULT, I2 — the
|
|
16
|
+
* - `options.source = 'particleWalk'` (DEFAULT, I2 — the PRIMARY
|
|
17
17
|
* REFERENCE source) — one or more HAND-PLACED leaf frames in the bore (the
|
|
18
18
|
* hand-placed-projectile pattern, generalized to
|
|
19
19
|
* `options.particleCount` quanta — I1's own scale-sweep validated technique
|
|
20
20
|
* for building a stochastic ensemble from IDENTICAL start conditions:
|
|
21
|
-
*
|
|
21
|
+
* the scale sweep places its whole
|
|
22
22
|
* N-quantum population at ONE shared entrance pixel per seed and still
|
|
23
23
|
* measures genuine per-quantum variance at exit — each frame's OWN
|
|
24
24
|
* move-gate/wavelength-oscillator RNG draws diverge it from its siblings
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
* `orientation`-derived `vx/vy`). Requires `capNegX` (defaults to `true` for
|
|
35
35
|
* THIS source type — a LightSource with no wall to emit from is meaningless).
|
|
36
36
|
*
|
|
37
|
-
* **I2 default flip (
|
|
37
|
+
* **I2 default flip (directed-tunnel composition model §3 row 2):
|
|
38
38
|
* `options.source` now DEFAULTS to `'particleWalk'`** (was `'emitter'` in T2) —
|
|
39
39
|
* "the PRIMARY reference source." The one production caller
|
|
40
40
|
* (the DSE-lab tunnels) always passes `source:'emitter'` explicitly, so this
|
|
41
41
|
* default flip is byte-identical for every existing caller in the tree; it only
|
|
42
42
|
* changes behavior for a hypothetical caller that OMITTED `source` entirely (none
|
|
43
|
-
* exist yet).
|
|
43
|
+
* exist yet). The scale sweep's companion
|
|
44
44
|
* source-invariance harness (I2) quantifies particleWalk vs emitter exit-ensemble
|
|
45
45
|
* equivalence — the empirical justification for treating them as interchangeable
|
|
46
46
|
* defaults at all.
|
|
@@ -50,20 +50,20 @@
|
|
|
50
50
|
* ~16px length"):** `options.tunnel.width`/`options.tunnel.length` now default to
|
|
51
51
|
* `8`/`16` when the caller omits them (previously REQUIRED — `DirectedTunnel`
|
|
52
52
|
* itself still throws on non-positive values, so a caller could not omit them
|
|
53
|
-
* before
|
|
53
|
+
* before). `left`/`top`/`z` remain caller-required (position is always
|
|
54
54
|
* scene-specific) — DIRECTLY passed through, byte-identical.
|
|
55
55
|
*
|
|
56
56
|
* `options.polarization` ('random'|'positive'|'negative', default 'random') —
|
|
57
|
-
*
|
|
58
|
-
*
|
|
57
|
+
* lasers are light sources which are polarized and have smaller widths.
|
|
58
|
+
* Maps DIRECTLY onto the SAME charge vocabulary `PointSource`/
|
|
59
59
|
* `QuantumEmitter`'s own `chargeMode` already use — no new charge concept:
|
|
60
60
|
* 'random' -> null (charge draw per particle — the DEFAULT, matches every
|
|
61
61
|
* existing DSE/WI emitter's un-polarized behavior)
|
|
62
62
|
* 'positive' -> 0 ('POSITIVE'), 'negative' -> 1 ('NEGATIVE') (a FIXED charge —
|
|
63
63
|
* every emitted/placed quantum gets the SAME charge: a polarized beam).
|
|
64
64
|
*
|
|
65
|
-
* **`LightSource.laser(universe, options)`** — the Laser preset/factory (
|
|
66
|
-
*
|
|
65
|
+
* **`LightSource.laser(universe, options)`** — the Laser preset/factory (a Laser
|
|
66
|
+
* is a LightSource preset, not a separate class — report §4.4 point
|
|
67
67
|
* 3: "A thin Laser wrapper is legitimately separate... mirroring
|
|
68
68
|
* the fx-* factories layering thin convenience over
|
|
69
69
|
* Tube.js"). A STATIC FACTORY, not a subclass: pre-fills `polarization` (default
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
* @property {number|null} particleQid - DEPRECATED alias for `particleQids[0]`
|
|
113
113
|
* (see above).
|
|
114
114
|
* @property {Function} applyRedirect - alias for `this.tunnel.applyRedirect`,
|
|
115
|
-
* ALWAYS present (C1 fix
|
|
115
|
+
* ALWAYS present (C1 fix)
|
|
116
116
|
* — prefer `this.tunnel.applyRedirectIfActive(tickData)` over calling this
|
|
117
117
|
* directly (self-gates on the tunnel's current `behavior`).
|
|
118
118
|
*
|
|
@@ -125,11 +125,9 @@
|
|
|
125
125
|
* every particle-walk/Gun-bullet experiment already uses, looped). The laser's
|
|
126
126
|
* "collimated, phase-locked beam" IS free (report §4.3): skipping the
|
|
127
127
|
* random-direction draw means every quantum gets IDENTICAL `vx,vy`, and a fresh
|
|
128
|
-
* emission is already phase-locked at `local_time=0` (
|
|
129
|
-
* new mechanism. Source-invariance (I2
|
|
130
|
-
*
|
|
131
|
-
* tunnel params produce statistically comparable exit-face ensembles (see that
|
|
132
|
-
* script's README section for the measured numbers and the metric used).
|
|
128
|
+
* emission is already phase-locked at `local_time=0` (established) — no
|
|
129
|
+
* new mechanism. Source-invariance (I2): particleWalk and emitter sourcing at IDENTICAL
|
|
130
|
+
* tunnel params produce statistically comparable exit-face ensembles.
|
|
133
131
|
*/
|
|
134
132
|
|
|
135
133
|
import { DirectedTunnel } from './DirectedTunnel.js';
|
|
@@ -156,9 +154,9 @@ import * as SustainedSource from './sustainedSource.js';
|
|
|
156
154
|
this.universe = universe;
|
|
157
155
|
this._schemaKind = 'LightSource';
|
|
158
156
|
|
|
159
|
-
// I2 default flip (directed-tunnel composition model §3 row 2
|
|
160
|
-
//
|
|
161
|
-
// source
|
|
157
|
+
// I2 default flip (directed-tunnel composition model §3 row 2):
|
|
158
|
+
// 'particleWalk' is now the DEFAULT (the PRIMARY reference
|
|
159
|
+
// source) — was 'emitter' in T2. The one production caller
|
|
162
160
|
// (the DSE-lab tunnels) always passes source:'emitter' explicitly, so
|
|
163
161
|
// this is byte-identical for every existing caller in the tree.
|
|
164
162
|
var source = options.source !== undefined ? options.source : 'particleWalk';
|
|
@@ -234,14 +232,13 @@ import * as SustainedSource from './sustainedSource.js';
|
|
|
234
232
|
// the emitter's own aperture placement), or at the bore's geometric
|
|
235
233
|
// X-centre when open on both ends (no breech to anchor to). ALL
|
|
236
234
|
// `particleCount` quanta share the SAME entrance pixel — the I1
|
|
237
|
-
// scale-sweep's own validated ensemble-building technique
|
|
238
|
-
// (docs/internal/physics-lab/directed-tunnel-scale-sweep/sweep.cjs): a shared
|
|
235
|
+
// scale-sweep's own validated ensemble-building technique: a shared
|
|
239
236
|
// injection-time position does not merge same-tick frames, and each
|
|
240
237
|
// leaf's OWN move-gate/wavelength-oscillator RNG draws diverge it
|
|
241
238
|
// from its siblings over subsequent ticks — a genuine stochastic
|
|
242
239
|
// ensemble from an identical start, not degenerate.
|
|
243
240
|
//
|
|
244
|
-
//
|
|
241
|
+
// One source surface: this burst
|
|
245
242
|
// now routes through `sustainedSource.js`'s ONE `placeSourceQuanta`
|
|
246
243
|
// primitive — the SAME entrance-formula/velocity-draw/z-centring code
|
|
247
244
|
// `setupTunnelLab.js`'s and `setupLightSourceLab.js`'s own independently
|
|
@@ -273,8 +270,8 @@ import * as SustainedSource from './sustainedSource.js';
|
|
|
273
270
|
this.particleHandle = this.particleHandles.length ? this.particleHandles[0] : null;
|
|
274
271
|
this.particleQid = this.particleQids.length ? this.particleQids[0] : null;
|
|
275
272
|
|
|
276
|
-
//
|
|
277
|
-
//
|
|
273
|
+
// LightSource itself has the sustain capability through the SAME
|
|
274
|
+
// single authority: OPT-IN —
|
|
278
275
|
// `options.sustain` omitted (default) is byte-identical to every
|
|
279
276
|
// pre-existing caller (a genuine one-shot construction, DSE Lab's own
|
|
280
277
|
// usage untouched). When supplied (truthy — `true` for "use the SAME
|
|
@@ -311,8 +308,8 @@ import * as SustainedSource from './sustainedSource.js';
|
|
|
311
308
|
};
|
|
312
309
|
|
|
313
310
|
/**
|
|
314
|
-
* The Laser preset/factory (
|
|
315
|
-
* separate class
|
|
311
|
+
* The Laser preset/factory (a Laser is a LightSource preset, not a
|
|
312
|
+
* separate class). Pre-fills a FIXED polarization (default 'positive' — a
|
|
316
313
|
* polarized beam, matching "lasers are ... polarized"), a NARROWER default
|
|
317
314
|
* width (report §4.3 — collimation/geometry convenience, zero new physics),
|
|
318
315
|
* and `source:'emitter'` (I2: a laser is "a collimated, phase-locked BEAM" —
|