Rescoped 2026-08-10 (operator decision): the specialized-JS executor must never require CSP unsafe-eval — now an architecture invariant (docs/architecture.md §3: nothing beyond wasm-unsafe-eval, ever; §8 v2 bullet).
contracts/descriptor-ir.md is designed for two executors over one IR; only the v1 generic interpreter ships today, and it has been fast enough for every consumer gate so far.
v2 design (emission-only):
- One generator: CABI descriptors → specialized JS modules. The generated-module contract is AOT-shaped from day one: explicit linking context, no closure capture of live runtime state — so every delivery mode shares one artifact.
- Two invocation times, one mechanism: a deploy-time AOT step (CLI emission), or — on server hosts (Deno/Node, no CSP) — first-load emission into a cache directory +
import(); pre-warming and freezing that cache is the AOT step. No eval/new Function anywhere; no CSP feature-detection or fallback-selection machinery.
- Browsers running dynamically-loaded components stay on the interpreter (correct, CSP-clean). Deployments that want browser speed AOT at build time.
- Differential testing: interpreter vs imported emitted modules over the full conformance corpus — the oracle exercises the production delivery mechanism itself, and stays a two-mode (not three-mode) test matrix.
- Benches vs jco's generated JS on the consumer workloads (docs/architecture.md §12 risk row): webcrypto (call-heavy), webrtc/websocket (stream-heavy).
Gate: a measured gap from #17, not the calendar. iroh's 5× polling-workaround removal dominates first-consumer numbers; measure before optimizing.
Moved out: the deploy-time unbundled layout (real URLs per module → engine code-cache hits) is a packaging concern independent of the executor choice — now tracked with the caching work (#7).
Rescoped 2026-08-10 (operator decision): the specialized-JS executor must never require CSP
unsafe-eval— now an architecture invariant (docs/architecture.md §3: nothing beyondwasm-unsafe-eval, ever; §8 v2 bullet).contracts/descriptor-ir.mdis designed for two executors over one IR; only the v1 generic interpreter ships today, and it has been fast enough for every consumer gate so far.v2 design (emission-only):
import(); pre-warming and freezing that cache is the AOT step. Noeval/new Functionanywhere; no CSP feature-detection or fallback-selection machinery.Gate: a measured gap from #17, not the calendar. iroh's 5× polling-workaround removal dominates first-consumer numbers; measure before optimizing.
Moved out: the deploy-time unbundled layout (real URLs per module → engine code-cache hits) is a packaging concern independent of the executor choice — now tracked with the caching work (#7).