--- id: mem-engine-integration name: Mem engine — integration (full-surface wiring, suite third column, wasm32 acceptance) status: completed depends_on: [mem-engine-notify-listen, mem-engine-streams, mem-engine-queues, mem-engine-locks, mem-engine-scheduler-outbox, mem-engine-seam-tx, suite-harness-current-thread] scope: moderate risk: medium impact: phase level: implementation tags: [wave-6, mem-engine, integration] --- ## Description The integration task: wire the finished mechanisms into a complete `Store`, adopt the contract suite as the third column, and carry the wasm acceptance items through ([ADR-024](../architecture/decisions/024-mem-engine.md) §5; the born-pinned posture — engine-mem.md §Isolation and the suite factory): - **Full-surface wiring**: every handle constructible off one `MemStore`; trait-object plumbing; crate docs (module docs + a crate-level doc carrying the honest-ephemeral posture statement — no durability, single-process, ephemeral by design, never fleet-valid, per [ADR-024](../architecture/decisions/024-mem-engine.md) §2 — and the wasm identity line per engine-mem.md §Identity). - **Suite third column**: a `tests/contract_suite.rs` target implementing `StoreFactory` (fresh `MemStore::new()` per run, teardown = drop — the factory's isolation contract verbatim) and running the shared rows wired per engine: mem's column carries the mechanism rows that express on it and omits the engine-shaped rows that cannot (reconnect-wake, watcher-death close, watcher-cadence — the per-engine wiring the suite's rows already use; `PayloadTooLarge`'s non-occurrence arm *wires* — the arm is the pin). The column runs under a **current-thread runtime flavor** (the pre-task's async-sleep harness makes this clean). - **wasm32 acceptance**: `cargo check --target wasm32-unknown-unknown -p alkstore-mem` (and the workspace's other crates untouched) clean; the manifest's tokio features verified as the sync+time subset. On-target suite execution stays scoped out (the named collapse condition — a wasm-bindgen-test adapter crate — recorded in the task Notes at completion, not an OQ). - **No `spawn_blocking` anywhere**: grep-verified; internals current-thread-clean by construction, now proven by the flavor the column runs under. - Suite column green is the wave's center-of-mass: 25 rows' worth of contract v1 assertions against a third, independent implementation — any red row is either a mem defect or (if the row pins implementation detail a correct engine could fail) a found suite defect to raise with the reviewer *before* editing the row (rows pin ADR text; a wobble is amend-in-place material under the class-1 window). ## Acceptance Criteria - [x] `StoreFactory` implemented for the mem engine; the third suite column wired and **green on the host** (same row set per the wiring table above) - [x] The column runs under the current-thread flavor; no blocking calls in mem internals (grep-verified) - [x] `cargo check --target wasm32-unknown-unknown -p alkstore-mem` clean - [x] `engine-mem.md` updated from `draft`-initial to implementation-complete (the spec grows with the wave per its frontmatter note); crate docs carry the posture + wasm identity - [x] Workspace gates green; clippy `-D warnings`; fmt clean - [x] The class-1 window discipline respected: any suite-row change or contract wobble surfaced to the reviewer, not silently patched ## Dependencies note `mem-engine-seam-tx` is listed because the overlay's commit-merge and `*_tx` read shapes are what the suite's tx rows exercise on mem; the mechanism tasks consume it, but a late seam fix may be needed if the suite surfaces one — the task owns absorbing it. ## References - docs/architecture/decisions/024-mem-engine.md §5 (acceptance items); 022-contract-suite-layout.md (the factory both engines already implement — the shape to mirror) - docs/architecture/engine-mem.md (spec of record) - tasks/sqlite-engine-integration.md / tasks/pg-engine-integration.md (the structural twins' integration tasks of record) - tasks/review-wave-5.md appendix (the discharge map the third column rides) ## Notes > Decisions of record the description didn't pin: - **The full-surface wiring was already true by construction** — the `mem-engine-seam-tx` task's whole-engine scope realized the entire `Store`/`TxHandle`/mechanism-handle surfaces over guarded state (a Rust trait impl is all-or-nothing per method), and the lib crate docs already carried the ADR-016/ADR-024 posture statement and the wasm identity line from `mem-engine-foundations`. This task verified both rather than re-landed them: the sweep found no `todo!`/`unimplemented!`, no `spawn_blocking`/`block_on` anywhere in `alkstore-mem/src` (grep), and the posture/wasm-identity crate docs in place; zero production code changed. - **The `PayloadTooLarge` asymmetry row gained a third arm — a new suite row, not a row edit** (ADR-017 §2 class 4 suite-side non-event, recorded here for the review gate): the existing pair are engine-named (`payload_too_large_never_produced_on_sqlite` / `payload_too_large_produced_on_pg`) with "the engine-differing leg inside" their own functions, so mem's non-occurrence posture gets its same-shaped arm — `payload_too_large_never_produced_on_mem`, stamped ADR-016 §5 + ADR-024 §3, driving a payload just past the 2 MiB mark the tx seam's mem unit pins (2 MiB + 1) through notify and asserting success. The existing SQLite and pg rows are untouched; their columns still run 25 rows each. - **The mem column carries all 25 rows with no omissions**: the engine-shaped arms the description lists as omit-able (reconnect-wake, watcher-death close, watcher-cadence) never existed as suite rows — per review-wave-5's discharge map they were per-engine *engine-side* rows from birth (SQLite's `poll_interval_flows_to_the_watcher_config` and the pg reconnect-stays-open leg each pin in their own crate's tests; receiver-close arms pin through the store-handle drop that `receiver_close_and_save_arms` drives — the dispose carrier mem also implements). So the classification's "omits the rows that cannot" is trivially satisfied: there was nothing to leave out, and the mem arm substitution keeps the column at the full 25. - **Factory shape**: `MemFactory` is a unit struct — no per-tag backing directory (there is no external backing; the store instance is the state). `open` = `MemStore::new()` boxed; `teardown` = the documented no-op `Ok(())` (the holder's drop of the handle *is* the teardown — nothing outside the instance exists to dispose of), idempotent trivially, safe against abandoned stores (the abandoned box drops with the test's frame). The factory-shape pin proves isolation behaviorally (a publish under `a` invisible to `b`) and teardown idempotence (both calls `Ok`). - **Current-thread flavor enforced per-test**: every `#[tokio::test]` in the target names `flavor = "current_thread"` explicitly — a blocking call inside a row or inside the engine stalls the flavor into a hang, not a pass: the no-blocking posture is proven by the flavor running, not by a grep alone. - **The on-target wasm suite-execution scope-out's named collapse condition** (recorded per the task description, not an OQ): a **wasm-bindgen-test adapter crate** — the suite's rows await real time (`past_stamp_sleep`) and drive the store through `BoxedFuture`s; on-target execution needs a wasm-bindgen-test runner bridging those futures and the suite's `#[tokio::test]` executor posture, which no row demands today. Until a consumer needs it, the wasm acceptance stays at compile-clean (green). - **No red rows** — the center-of-mass landed green on the first full-column run: zero mem defects surfaced and zero suite-row wobbles found, so the class-1 amend-in-place path was never exercised and no reviewer escalation was owed. ## Summary > Landed: the contract suite's third column — > `alkstore-mem/tests/contract_suite.rs` — with `StoreFactory` > implemented for the mem engine (fresh `MemStore::new()` per open, > teardown = drop; a unit struct, no backing path), all 25 rows > wired (the 24 engine-shared mechanism rows + mem's new > `payload_too_large_never_produced_on_mem` arm) **under the > current-thread flavor**, every test explicitly > `flavor = "current_thread"` — green first run in 13 s. The suite > addition (the new mem-arm row in `properties.rs` + its export) is > the only suite-side change; no existing row changed. > > Full-surface wiring and crate docs verified as already landed by > the seam/foundations tasks (`no todo!/unimplemented!`, > `spawn_blocking`-free by grep, posture + wasm-identity crate docs > in place) — zero production code changed. `engine-mem.md` > frontmatter flipped `draft` → `implementation-complete` with the > last_updated line recording the wave's landing; the stable flip > stays with the review gate. > > Verified: workspace `cargo build` green; workspace `cargo test` > green (core 25, suite harness 3, mem 100 lib + 25 suite, SQLite 191 > lib + 25 suite, pg 124 lib + 25 suite + 9 schema); clippy > `--all-targets -D warnings` clean; `cargo fmt --check` clean; > `cargo check --target wasm32-unknown-unknown -p alkstore-mem` > clean; the manifest's tokio subset (sync + time; dev rt/macros) > verified — unchanged by this task beyond the > `alkstore-contract-suite` dev-dep (test-side, host-only).