--- id: mem-engine-foundations name: Mem engine — crate scaffold, `MemStore::new()`, guarded state core, wake routing status: pending depends_on: [] scope: moderate risk: medium impact: component level: implementation tags: [wave-6, mem-engine] --- ## Description The mem engine's foundations (wave 6 — [ADR-024](../architecture/decisions/024-mem-engine.md)): a new workspace member `alkstore-mem` and the state core every later task builds on. - **Crate + manifest**: workspace member per [ADR-024](../architecture/decisions/024-mem-engine.md) §1 — dependencies are `alkstore` (versioned path pin per [ADR-017](../architecture/decisions/017-contract-versioning.md) §4.1, matching the other engines' manifests) plus tokio restricted to the **wasm-supported subset (sync + time only)**. No driver dependencies. `thiserror` via core; no other crates.io surface. - **Constructor**: `MemStore::new()` — engine-native, no connection string, no file path (the one documented exception to the core-contract open prose, amended by [ADR-024](../architecture/decisions/024-mem-engine.md) §4). Each `new()` yields a fully isolated instance sharing nothing (the suite factory's isolation contract); teardown is drop. No `PgOpts`-equivalent opts struct exists — nothing to configure (if a knob surfaces during the wave, `MemOpts` with `..Default::default()` follows the family opts pattern; not assumed now). - **Guarded per-mechanism state core**: the store instance is the state — per-mechanism structures (queues+jobs, dead letters, streams+offsets, locks, schedules) behind the family's locking discipline (parking_lot short-held internal locks per AGENTS convention 3; tokio primitives for cross-await coordination). Layout is module-per-file under `src/`, mirroring the other engines. Subsequent mechanism tasks own their tables' shapes; this task owns the shared scaffolding: the guarded-state container idiom, name validation at entry (same `InvalidName`/`ReservedName` rules as every other engine — reserved prefix `__alkstore_`, the one reserved string `__alkstore_listener_reconnected__` unused here but still rejected), and the wake-routing substrate (in-process channels; a mechanism registers its commit-ordered wake source, receivers attach per channel). - **Wake substrate shape**: no batching boundary exists — wakes deliver at the commit boundary directly to each open receiver, per-subscriber FIFO by commit order (engine-mem.md §Architecture; coalescing not applicable). The routing core lives here; the `listen()`/`WakeReceiver` surface lives in `mem-engine-notify-listen`. - **Clock posture**: every timestamp (unix-seconds stamps, visibility deadlines, TTLs, scheduler boundaries) reads the process clock — there is no server clock to defer to. Keep the clock behind one internal accessor so tests can observe timestamps deterministically the same way the SQL engines' row shapes do. The `Store` trait impl itself is ADR-007-shaped and lands in `mem-engine-seam-tx` (the tx overlay is the load-bearing half); this task lands everything up to the trait boundary. ## Acceptance Criteria - [ ] `alkstore-mem` is a workspace member compiling clean; manifest dependency surface is core + tokio (sync + time) only - [ ] `MemStore::new()` constructs; two instances share nothing (pinned by a unit test) - [ ] The guarded state core, validation rules, wake-routing substrate, and clock accessor exist with unit pins - [ ] `cargo check --target wasm32-unknown-unknown -p alkstore-mem` clean from this task onward (tokio subset discipline enforced here, not retro-fitted) - [ ] Workspace gates green (`cargo build`, `cargo test`, clippy `-D warnings`, fmt) ## References - docs/architecture/decisions/024-mem-engine.md §1/§4 - docs/architecture/engine-mem.md §Identity and posture, §Architecture - docs/architecture/core-contract.md §Naming / reserved namespace - tasks/pg-engine-schema.md (the wave-4 rhythm this wave mirrors — its "foundations first" slot) ## Notes > To be filled by implementation agent ## Summary > To be filled on completion