@descix/frqtl-node 0.6.1-p3.4 → 0.7.0-p0
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 +3 -3
- package/README.md +4 -3
- package/dist/dist-manifest.json +26 -56
- package/dist/frqtl/experiments/_shared/empty-sketch.js +17 -0
- package/dist/frqtl/objects/setup/setupBlackbodySubstrate.js +6 -6
- package/dist/frqtl/objects/setup/setupFxSmoke.js +2 -2
- package/dist/frqtl/objects/setup/setupG3Collide.js +1 -1
- package/dist/frqtl/objects/setup/setupSphereEmitter3D.js +2 -2
- package/dist/frqtl/objects/v1-replacements.js +1 -1
- package/dist/frqtl/parts/OvenBox.js +2 -2
- package/dist/frqtl/parts/SphereEmitter.js +1 -1
- package/dist/shim/engine/router.js +18 -6
- package/dist/shim/engine/site-assemble.mjs +268 -0
- package/dist/shim/engine/site-graph.js +42 -14
- package/dist/shim/host/device.js +1 -1
- package/dist/shim/index.js +3 -7
- package/dist/shim/notebook/catalog.js +2 -2
- package/dist/shim/notebook/format.js +1 -1
- package/dist/shim/notebook/knob.js +1 -1
- package/dist/shim/notebook/notebook-knobs.js +1 -1
- package/dist/shim/project/specifiers.js +8 -8
- package/dist/shim/registry/copy-gate.js +3 -3
- package/dist/shim/registry/index.js +9 -12
- package/dist/shim/registry/roster-link.js +142 -0
- package/dist/shim/registry/roster.js +595 -0
- package/dist/shim/registry/scene-source.js +80 -105
- package/dist/shim/registry/studio-landing.js +15 -7
- package/dist/shim/render/sun-look.js +1 -2
- package/llms.txt +4 -2
- package/package.json +1 -1
- package/dist/frqtl/scenes/absorbing-wall-3d.js +0 -37
- package/dist/frqtl/scenes/absorbing-wall.js +0 -36
- package/dist/frqtl/scenes/atomic-model.js +0 -91
- package/dist/frqtl/scenes/big-bang.js +0 -49
- package/dist/frqtl/scenes/blackbody.js +0 -84
- package/dist/frqtl/scenes/circuit-sat.js +0 -131
- package/dist/frqtl/scenes/collision-matrix-3d.js +0 -110
- package/dist/frqtl/scenes/counting-wall-3d.js +0 -40
- package/dist/frqtl/scenes/counting-wall.js +0 -42
- package/dist/frqtl/scenes/double-slit.js +0 -34
- package/dist/frqtl/scenes/dse-one-emitter.js +0 -200
- package/dist/frqtl/scenes/dse-one-slit.js +0 -118
- package/dist/frqtl/scenes/dse-photoelectric.js +0 -74
- package/dist/frqtl/scenes/dse-tunnel-rebuild.js +0 -279
- package/dist/frqtl/scenes/dse-two-emitters.js +0 -201
- package/dist/frqtl/scenes/dse-two-slits.js +0 -136
- package/dist/frqtl/scenes/empty.js +0 -17
- package/dist/frqtl/scenes/laser-buildup.js +0 -56
- package/dist/frqtl/scenes/mirror-3d.js +0 -60
- package/dist/frqtl/scenes/mirror-route.js +0 -164
- package/dist/frqtl/scenes/mirror.js +0 -42
- package/dist/frqtl/scenes/omni-3d.js +0 -30
- package/dist/frqtl/scenes/omni-source.js +0 -25
- package/dist/frqtl/scenes/self-interference.js +0 -42
- package/dist/frqtl/scenes/smoking-gun.js +0 -126
- package/dist/frqtl/scenes/straight-walk.js +0 -25
- package/dist/frqtl/scenes/sun.js +0 -42
- package/dist/frqtl/scenes/two-source.js +0 -42
- package/dist/frqtl/scenes/wave.js +0 -29
- package/dist/shim/engine/artifact-shell.js +0 -211
- package/dist/shim/registry/exhibits.js +0 -436
- package/dist/shim/registry/scene-roster.js +0 -35
- package/dist/shim/registry/showcase-link.js +0 -61
- package/dist/shim/registry/walkthrough.js +0 -752
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
/* Copyright 2023-2026 by Essam Abadir */
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* artifact-shell.js — pure generator for the claude.ai Artifact host shell.
|
|
5
|
-
*
|
|
6
|
-
* The "artifact host shell" is a SINGLE self-contained HTML file a user pastes
|
|
7
|
-
* into a claude.ai chat as an Artifact. It has no server, no build step, no
|
|
8
|
-
* relative-file dependencies of its own — every asset it needs is fetched from
|
|
9
|
-
* `cdn.jsdelivr.net/npm/` (the ONLY non-`self` script-src origin this shell
|
|
10
|
-
* needs; see §1 of the design doc for the full captured CSP).
|
|
11
|
-
*
|
|
12
|
-
* This module is PURE (no DOM, no browser globals) and node-testable. It has
|
|
13
|
-
* exactly two responsibilities, kept separate so the "never hand-drifted"
|
|
14
|
-
* requirement is mechanically enforced rather than asserted in prose:
|
|
15
|
-
*
|
|
16
|
-
* buildArtifactImportMap() — the ONE import-map entry the shell embeds,
|
|
17
|
-
* derived from router.js's CDN_BASE (the single
|
|
18
|
-
* CDN path authority — never a second hand-typed
|
|
19
|
-
* jsdelivr URL literal).
|
|
20
|
-
* renderArtifactShellHtml() — the full HTML document text, calling
|
|
21
|
-
* buildArtifactImportMap() internally (so the
|
|
22
|
-
* embedded `<script type="importmap">` can never
|
|
23
|
-
* drift from the generator — a conformance test
|
|
24
|
-
* asserts this by construction, see
|
|
25
|
-
* lib/shim/engine/test/artifact-shell.test.mjs).
|
|
26
|
-
*
|
|
27
|
-
* WHAT the import map holds (and why it never lists engine/renderer files): the shell's inline
|
|
28
|
-
* `<script type="module">` imports `bootScene` from `'@descix/frqtl-web/boot'` (the package's scene doors,
|
|
29
|
-
* lib/frqtl/experiments/_shared/doors.js) — everything the boot loads (engine, renderer, game layer)
|
|
30
|
-
* resolves relative to that module's own URL — and the embedded scene imports its parts by the
|
|
31
|
-
* published self-reference. Both come from the ONE specifier table (`pageImportMapFor`). Growing this
|
|
32
|
-
* map by hand per script would re-enumerate the module graph by hand — the schema-mirror-drift
|
|
33
|
-
* anti-pattern.
|
|
34
|
-
*
|
|
35
|
-
* CSP notes baked into the generated HTML (never re-derive elsewhere):
|
|
36
|
-
* - NO `blob:` module imports (forbidden by the captured CSP's script-src).
|
|
37
|
-
* - NO script/style/font origin outside the allowlist in the design doc §1
|
|
38
|
-
* (jsdelivr/npm, cdnjs, claudeusercontent, tailwindcss CDN, jquery CDN) —
|
|
39
|
-
* this shell in fact uses ONLY jsdelivr/npm plus inline scripts/styles
|
|
40
|
-
* ('unsafe-inline' is granted), so it is a strict subset of the allowlist.
|
|
41
|
-
* - The inline `<script type="module">` and the `<script type="importmap">`
|
|
42
|
-
* are both confirmed-PASS under this exact CSP (Step 0, design doc §1).
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
|
-
'use strict';
|
|
46
|
-
|
|
47
|
-
import { CDN_BASE } from './router.js';
|
|
48
|
-
import { pageImportMapFor, FRQTL_WEB_BOOT } from '../project/specifiers.js';
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* The bare-specifier import map the artifact shell embeds: the ONE table, `pageImportMapFor(<the dist
|
|
52
|
-
* root>/)` (lib/shim/project/specifiers.js) — the scene doors (`@descix/frqtl-web/boot`) and the sketch's
|
|
53
|
-
* self-reference rows, at their lib-identity paths under the dist root, so the embedded scene's imports
|
|
54
|
-
* resolve to the SAME module URLs the boot loads.
|
|
55
|
-
*
|
|
56
|
-
* @param {object} [opts]
|
|
57
|
-
* @param {string} [opts.base] - The dist base (default `CDN_BASE` from router.js): the absolute URL
|
|
58
|
-
* (no trailing slash) of an unmodified copy of the package's dist/ tree. The PUBLISHED shell
|
|
59
|
-
* (`sdk/frqtl-web/build.js`) never passes it; the local mirror
|
|
60
|
-
* (`sdk/frqtl-web/scripts/serve-local-cdn-mirror.mjs`) does.
|
|
61
|
-
* @returns {{imports: Object<string,string>}}
|
|
62
|
-
*/
|
|
63
|
-
export function buildArtifactImportMap(opts) {
|
|
64
|
-
opts = opts || {};
|
|
65
|
-
var base = opts.base !== undefined ? opts.base : CDN_BASE;
|
|
66
|
-
return pageImportMapFor(base + '/');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* The scene the artifact shell boots — a frqtl-relative scene file (lib/frqtl/<ARTIFACT_SCENE>).
|
|
71
|
-
* The generator is pure: its caller reads this file and hands the TEXT in (`opts.sceneSource`),
|
|
72
|
-
* and the page embeds it verbatim. The scene is its one home; its constants are its knobs.
|
|
73
|
-
*/
|
|
74
|
-
export var ARTIFACT_SCENE = 'scenes/double-slit.js';
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* The bounded wait an artifact page gives its boot before it FAILS LOUD. An SDK entry that never
|
|
78
|
-
* loads (a 404, an unreachable CDN, an unpublished pin) runs NO code, so nothing inside the module
|
|
79
|
-
* can report it — without this deadline the page sits on "booting FRQTL…" forever. The authored
|
|
80
|
-
* sdk/frqtl-web/src/artifact/sun.html carries BOOT_DEADLINE_MARKER, where the build splices
|
|
81
|
-
* bootDeadlineScript() — one script, one number.
|
|
82
|
-
*/
|
|
83
|
-
export var ARTIFACT_BOOT_DEADLINE_MS = 30000;
|
|
84
|
-
|
|
85
|
-
/** Where an AUTHORED artifact page (sun.html) takes the deadline script: the build splices it here. */
|
|
86
|
-
export var BOOT_DEADLINE_MARKER = '<!-- FRQTL:BOOT-DEADLINE -->';
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* The classic deadline script (runs whether or not the module ever loads). On expiry with no live
|
|
90
|
-
* boot it stamps `data-egpt-boot-timeout="1"` on #frqtl-status, names the entry the page boots from
|
|
91
|
-
* (the import map's `@descix/frqtl-web/boot` row, else the frqtl-web.min.js <script>), and logs it. The module sets `window.__frqtlLive = true` once the boot resolves.
|
|
92
|
-
* @returns {string} a `<script>…</script>` element
|
|
93
|
-
*/
|
|
94
|
-
export function bootDeadlineScript() {
|
|
95
|
-
return (
|
|
96
|
-
'<script>\n' +
|
|
97
|
-
' /* BOOT DEADLINE — lib/shim/engine/artifact-shell.js ARTIFACT_BOOT_DEADLINE_MS. */\n' +
|
|
98
|
-
' setTimeout(function () {\n' +
|
|
99
|
-
' if (window.__frqtlLive) { return; }\n' +
|
|
100
|
-
' var map = document.querySelector(\'script[type="importmap"]\');\n' +
|
|
101
|
-
' var min = document.querySelector(\'script[src$="frqtl-web.min.js"]\');\n' +
|
|
102
|
-
' var entry = min ? min.src : \'(no import map)\';\n' +
|
|
103
|
-
' try { if (map) { entry = new URL(JSON.parse(map.textContent).imports[\'' + FRQTL_WEB_BOOT.specifier + '\'], document.baseURI).href; } } catch (e) { /* the message names the absence */ }\n' +
|
|
104
|
-
' var msg = \'FRQTL BOOT TIMEOUT — not live after \' + (' + ARTIFACT_BOOT_DEADLINE_MS + ' / 1000) + \' s: the SDK entry \' + entry +\n' +
|
|
105
|
-
' \' did not load, or its boot never reached a first tick.\';\n' +
|
|
106
|
-
' var el = document.getElementById(\'frqtl-status\');\n' +
|
|
107
|
-
' if (el) { el.textContent = msg; el.setAttribute(\'data-egpt-boot-timeout\', \'1\'); }\n' +
|
|
108
|
-
' if (window.console && console.error) { console.error(\'[frqtl-artifact]\', msg); }\n' +
|
|
109
|
-
' }, ' + ARTIFACT_BOOT_DEADLINE_MS + ');\n' +
|
|
110
|
-
'</script>\n'
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Render the complete, self-contained artifact host shell HTML.
|
|
116
|
-
*
|
|
117
|
-
* The document boots the scene file's sketch (ARTIFACT_SCENE, embedded VERBATIM) via
|
|
118
|
-
* `bootScene()` — the scene doors (lib/frqtl/experiments/_shared/doors.js) — into a mount div.
|
|
119
|
-
* FAIL-LOUD: `bootScene`'s own promise rejection is caught here and surfaced in the status
|
|
120
|
-
* line; `bootScene` itself paints a detailed error overlay inside the mount div on any
|
|
121
|
-
* load/compile/engine failure (never a silent blank canvas).
|
|
122
|
-
*
|
|
123
|
-
* The shell writes NO size: the mount is `width:fit-content`, sized by the canvas the scene's
|
|
124
|
-
* co-init call creates.
|
|
125
|
-
*
|
|
126
|
-
* WHERE THE PACKAGE COMES FROM (`opts.host`):
|
|
127
|
-
* 'cdn' (default) — the import map is the jsdelivr pin (buildArtifactImportMap; `opts.base`
|
|
128
|
-
* re-anchors it): the self-contained page a user pastes into a claude.ai Artifact.
|
|
129
|
-
* 'dist' — the import map is page-relative, `pageImportMapFor('../')` (placed by the build like
|
|
130
|
-
* sun.html's): the page the package ships boots against WHATEVER dist serves it.
|
|
131
|
-
* Either way the doors locate every file they load relative to their own URL, and the page carries a
|
|
132
|
-
* bounded boot DEADLINE (bootDeadlineScript): a silent hang fails loud.
|
|
133
|
-
*
|
|
134
|
-
* @param {object} opts
|
|
135
|
-
* @param {string} opts.sceneSource - REQUIRED: the text of lib/frqtl/<ARTIFACT_SCENE>, a sketch
|
|
136
|
-
* module (`export default function buildExperiment(exp)`), inlined into the page's module script —
|
|
137
|
-
* its imports resolve through the page's import map. Missing, or defining no buildExperiment, THROWS.
|
|
138
|
-
* @param {number} [opts.seed=42] - RNG seed.
|
|
139
|
-
* @param {string} [opts.base] - Forwarded to `buildArtifactImportMap` (a 'cdn' page re-anchored
|
|
140
|
-
* at a self-hosted dist root). Omitted by the published shell.
|
|
141
|
-
* @returns {string} the full `<!DOCTYPE html>...</html>` document text.
|
|
142
|
-
*/
|
|
143
|
-
export function renderArtifactShellHtml(opts) {
|
|
144
|
-
opts = opts || {};
|
|
145
|
-
var sceneSource = opts.sceneSource;
|
|
146
|
-
if (typeof sceneSource !== 'string' || !sceneSource.trim()) {
|
|
147
|
-
throw new Error('[artifact-shell] renderArtifactShellHtml needs opts.sceneSource — the text of lib/frqtl/' +
|
|
148
|
-
ARTIFACT_SCENE + ' (the caller reads the file; this generator is pure). (FAIL-LOUD.)');
|
|
149
|
-
}
|
|
150
|
-
if (!/function buildExperiment\s*\(/.test(sceneSource)) {
|
|
151
|
-
throw new Error('[artifact-shell] opts.sceneSource defines no `function buildExperiment(exp)` — it must be the ' +
|
|
152
|
-
'scene file ' + ARTIFACT_SCENE + '. (FAIL-LOUD.)');
|
|
153
|
-
}
|
|
154
|
-
var seed = opts.seed !== undefined ? opts.seed : 42;
|
|
155
|
-
var host = opts.host === undefined ? 'cdn' : opts.host;
|
|
156
|
-
if (host !== 'cdn' && host !== 'dist') {
|
|
157
|
-
throw new Error('[artifact-shell] opts.host must be "cdn" or "dist" (got ' + JSON.stringify(host) + '). (FAIL-LOUD.)');
|
|
158
|
-
}
|
|
159
|
-
if (host === 'dist' && opts.base) {
|
|
160
|
-
throw new Error('[artifact-shell] opts.base re-anchors the CDN pin; a "dist" page anchors at its own entry. (FAIL-LOUD.)');
|
|
161
|
-
}
|
|
162
|
-
var importMapJson = JSON.stringify(host === 'dist' ? pageImportMapFor('../') : buildArtifactImportMap(opts));
|
|
163
|
-
|
|
164
|
-
return (
|
|
165
|
-
'<!DOCTYPE html>\n' +
|
|
166
|
-
'<!-- Copyright 2023-2026 by Essam Abadir -->\n' +
|
|
167
|
-
'<!-- FRQTL — claude.ai Artifact host shell.\n' +
|
|
168
|
-
' Generated by lib/shim/engine/artifact-shell.js — DO NOT hand-edit.\n' +
|
|
169
|
-
' Paste this ENTIRE file into a claude.ai chat as an Artifact (type: HTML). -->\n' +
|
|
170
|
-
'<html lang="en">\n' +
|
|
171
|
-
'<head>\n' +
|
|
172
|
-
'<meta charset="UTF-8">\n' +
|
|
173
|
-
'<meta name="viewport" content="width=device-width, initial-scale=1">\n' +
|
|
174
|
-
'<title>FRQTL — Double-Slit (live)</title>\n' +
|
|
175
|
-
'<style>\n' +
|
|
176
|
-
' html,body{margin:0;padding:0;background:#0b0b0b;color:#c9c9c9;font-family:ui-monospace,Menlo,Consolas,monospace;}\n' +
|
|
177
|
-
' #frqtl-status{text-align:center;font-size:12px;color:#888;padding:10px 0 4px;}\n' +
|
|
178
|
-
' #frqtl-mount{width:fit-content;margin:0 auto 24px;position:relative;}\n' +
|
|
179
|
-
'</style>\n' +
|
|
180
|
-
'</head>\n' +
|
|
181
|
-
'<body>\n' +
|
|
182
|
-
'<div id="frqtl-status" data-role="frqtl-artifact-status">booting FRQTL…</div>\n' +
|
|
183
|
-
'<div id="frqtl-mount" data-role="frqtl-artifact-mount"></div>\n' +
|
|
184
|
-
'<script type="importmap">' + importMapJson + '</script>\n' +
|
|
185
|
-
bootDeadlineScript() +
|
|
186
|
-
'<script type="module">\n' +
|
|
187
|
-
' import { bootScene } from \'' + FRQTL_WEB_BOOT.specifier + '\';\n' +
|
|
188
|
-
' var statusEl = document.getElementById(\'frqtl-status\');\n' +
|
|
189
|
-
' var tickCount = 0;\n' +
|
|
190
|
-
sceneSource.replace(/\s*$/, '') + '\n' +
|
|
191
|
-
' bootScene(\'frqtl-mount\', buildExperiment, {\n' +
|
|
192
|
-
' seed: ' + seed + ',\n' +
|
|
193
|
-
' onTick: function () {\n' +
|
|
194
|
-
' tickCount++;\n' +
|
|
195
|
-
' if (tickCount % 20 === 0) {\n' +
|
|
196
|
-
' statusEl.textContent = \'FRQTL double-slit — live — tick \' + tickCount;\n' +
|
|
197
|
-
' }\n' +
|
|
198
|
-
' }\n' +
|
|
199
|
-
' }).then(function () {\n' +
|
|
200
|
-
' window.__frqtlLive = true;\n' +
|
|
201
|
-
' statusEl.textContent = \'FRQTL double-slit — live\';\n' +
|
|
202
|
-
' }).catch(function (err) {\n' +
|
|
203
|
-
' window.__frqtlLive = true; // failed LOUDLY already — the deadline has nothing to add\n' +
|
|
204
|
-
' statusEl.textContent = \'FRQTL boot FAILED — see overlay below.\';\n' +
|
|
205
|
-
' if (window.console && console.error) { console.error(\'[frqtl-artifact]\', err); }\n' +
|
|
206
|
-
' });\n' +
|
|
207
|
-
'</script>\n' +
|
|
208
|
-
'</body>\n' +
|
|
209
|
-
'</html>\n'
|
|
210
|
-
);
|
|
211
|
-
}
|