Skip to main content

The Engine Package

The implementation lives in src/engine/ as a standalone npm package. This page covers working on it. What it must do is the specs' job — start with the core.

Layout

PathWhat
src/engine/src/core/determinism/Seeded PCG32 and stream derivation
src/engine/src/core/persistence/Canonical serialization
src/engine/package.jsonScripts and the Node floor
src/engine/eslint.config.jsThe determinism guard

Tests sit beside the code they cover as .test.ts, rather than in a parallel tree.

Commands

Run everything from src/engine/, not the repository root — the package is not at the root and npm will not find it from there.

cd src/engine
npm install
npm test # vitest
npm run lint # determinism guard + typescript-eslint
npm run typecheck

Node 24 is the floor. engines.node declares it and CI selects it explicitly, but npm treats engines as advisory unless engine-strict is set — which this repository does not set — so a local install on an older Node will warn rather than stop. The declaration states the floor; it does not enforce it.

Determinism is enforced, not hoped for

The eslint configuration fails the build on Math.random, on the Math.* functions that are not bit-stable across engines, and on Date.now anywhere under src/. Randomness comes from a seeded generator and nowhere else, so a session replays byte-for-byte from its seed and its inputs.

That constraint is the reason for the seeded PCG32 and the canonical serializer: given the same seed and the same actions, every run must produce the same bytes. See the core for how that surfaces in the engine API, and architecture for why the platform is built on it.

Where the work is going

TODO breaks the MVP into ordered units. The package currently holds the two verified primitives above; the next unit adds the core contract types and the module skeleton.