# 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.

```text
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.mjs` is the readable normative implementation for checked `i64`, fixed-scale decimals, canonical `f64` bits, stable FNV-1a hashing, and validity bitmaps.
- `src/portable-core-loader.mjs` tries SIMD, scalar, then JS. `src/portable-core-wasm.mjs` binds the real linear-memory ABI, including checked batch addition. Every accelerated candidate must pass `portable/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.nelua` exports ABI version/capabilities, allocation, checked addition, lease validation, batch addition, hashing, scheduler-packet execution, and errors through fixed C names.
- `portable/nelua/Dockerfile` pins 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:

```text
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

1. **Cells IR and columnar planner:** formula and restricted-Lua parsers, typed rectangular buffers, dependency levels, dirty propagation, deterministic Worker chunking, SQLite metadata/outbox boundaries.
2. **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.
3. **WebRTC exchange and attenuated compute:** immutable chunk exchange first; later bounded `cells.compute` grants, 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.
