Nelua → C → Wasm portable core
Status: SHIPPED JS compatibility oracle, parity-gated loader, frozen scheduler-packet fixtures, and CI execution of generated scalar/SIMD artifacts. EXPERIMENTAL pinned Nelua-to-C-to-Emscripten build path and portable scheduler core. PLANNED broader cursor operators, peer computation, and expanded vector/fuzz coverage.
The portable core accelerates calculation. It does not acquire authority merely because code was downloaded or a peer offered to run it.
formula / restricted Lua / scheduler task packet
↓ parse + validate / fixed portable ABI
versioned, capability-free calculation plan
↓
┌────────────────────────────────────────────────────────┐
│ SIMD Wasm ─ parity fail ─▶ scalar Wasm ─ fail ─▶ JS │
│ Nelua → generated C → Emscripten Wasm oracle │
└────────────────────────────────────────────────────────┘
↓
local Worker chunks (planned) → verified result/receipt
↓
SQLite transaction + outbox (separate body-layer work)
What is real in this milestone
src/portable-core.mjsis the readable normative implementation for checkedi64, fixed-scale decimals, canonicalf64bits, stable FNV-1a hashing, and validity bitmaps.src/portable-core-loader.mjstries SIMD, scalar, then JS.src/portable-core-wasm.mjsbinds the real linear-memory ABI, including checked batch addition. Every accelerated candidate must passportable/nelua/vectors.json; a mismatch disables that candidate for the session and produces a degradation record. CI executes both generated artifacts through that same adapter and parity gate before publishing them.portable/nelua/cursors_core.neluaexports ABI version/capabilities, allocation, checked addition, lease validation, batch addition, hashing, scheduler-packet execution, and errors through fixed C names.portable/nelua/Dockerfilepins Nelua by commit and Emscripten by image tag. Nelua emits C; Emscripten emits the two Wasm artifacts. Nelua does not directly emit Wasm.
The artifact directory is intentionally ignored. Build it with npm run build:nelua-core, then distribute it through the normal reviewed asset pipeline. The build requires Docker; ordinary JS-only development does not.
ABI discipline
The ABI is deliberately smaller than the eventual Cells language:
cursors_abi_version cursors_capabilities
cursors_alloc/free cursors_last_error
cursors_eval_batch cursors_hash_batch
cursors_checked_add_i64 cursors_lease_valid
cursors_execute_task fixed 32-byte task/result packets
Pointers are offsets into Wasm linear memory. Callers own inputs and outputs, enforce byte/cell budgets before allocation, and copy no host object, capability, SQL handle, secret, or network authority into the module.
Generated artifacts declare only Emscripten's memory-growth notification and three WASI file-descriptor functions. The browser loader supplies deterministic no-op/BADF shims, rejects any additional import in CI, and permits an embedding to override those shims explicitly; no network, storage, clock, or randomness capability is granted.
Strict builds do not enable fast-math. The optional build adds only -msimd128, and startup parity remains the admission gate.
Next focused PRs
- Cells IR and columnar planner: formula and restricted-Lua parsers, typed rectangular buffers, dependency levels, dirty propagation, deterministic Worker chunking, SQLite metadata/outbox boundaries.
- Cockpit grid and Array Lab: open-source Univer with its calculator replaced, engine/fallback inspection, array shape/stride/validity views, and reversible Blockly → restricted Lua → IR authoring.
- WebRTC exchange and attenuated compute: immutable chunk exchange first; later bounded
cells.computegrants, verification, sampling, Linda executor leases, retries, and local fallback.
JavaScript stays complete throughout. Wasm preference is a runtime optimization choice, never part of cursor identity or execution authority.
Reproducible proof
The Nelua Wasm workflow checks out the exact pull-request head, verifies the pinned Nelua revision, builds scalar and SIMD modules through generated C, rejects unexpected imports, and executes frozen arithmetic vectors plus scheduler packets through the browser-compatible adapter. A green artifact build proves the Wasm bytes ran; merely generating .wasm files is not sufficient.
Run npm run check:portable-core for the JS oracle and checked-in fixtures. Run npm run build:nelua-core with the pinned Docker toolchain, then npm run check:nelua-artifacts, for local generated-artifact proof. Rust issue #50 may implement the same packet contract independently; it is neither blocked by nor authoritative over this path.