Wave-6 decomposition (mem engine): eleven tasks per the pg-wave rhythm — foundations (crate scaffold, MemStore::new isolation, guarded state core, wake routing, wasm32 gate from birth), seam-tx (the load-bearing tx overlay: eleven staged _tx methods, commit-merge + wake-at-commit — pg-fix-tx-wake's discipline structural from the start, drop = discard trivial, with_tx panic posture), mechanisms mutually parallel (notify-listen close-at-engine-drop/no-replay/never-coalesced; queues = ADR-010 machine driver-free with the equal-jitter curve and opts resolution as ADR-012 §2's third owner; streams log+offsets+trim; locks TTL registry, no busy-path analog), scheduler-outbox (tick/catch-up-64/leadership through the __alkstore_scheduler lock, engine-uniform per ADR-009 §4; outbox over queues with the 60/5/5 seam stamp), integration (suite third StoreFactory column green on host under a current-thread flavor, wasm32 acceptance items, engine-mem.md to implementation-complete), and the review-wave-6 gate (born-pinned audit: conformance read, discharge-map wiring, wasm items, three-way equivalence green, class-1 window discipline). Window riders: suite-harness-current-thread — the wave's one suite-side pre-task, past_stamp_sleep's blocking sleep goes async per review 003's properties.rs:1683 posture note, enabling the current-thread flavor; pg-fix-scheduler-tick-seam — review 003 Finding 1, the cfg(test) transient-fault seam driving the real tick_with_retries through retry-then-success and exhaustion arms (the last uncovered wave-4 hardening arm, sqlite-commit-error-arm pattern). Task hygiene: pg-fix-open-path frontmatter fixed (unquoted 'max_size: 0' colon-space inside the name scalar broke YAML parsing — taskgraph validate had been red one-error since the wave-4 fix-batch decomposition; also restores review-wave-4-fixes' dependency resolution). implementation.md: wave-6 table row → decomposed, task-set listing with the parallelism note (rider + pre-task independent of the mem chain; rider closes before the gate), wave-6 decomposition bullet in the review-rounds record. Docs-only change; verified taskgraph validate (60 tasks, no cycles), cargo fmt --check, cross-reference read
This commit is contained in:
1 parent
060f262e62
commit
5abd351c86
13 files changed
+939
-5
No files matched your search
@@ -1,8 +1,9 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-10-10 (ADR-024 — the mem engine adopted as wave 6
|
||||
and decomposed-in-place documentation; release readiness renumbered
|
||||
to wave 7. Waves 1–5 implemented and reviewed; engine specs stable.)
|
||||
last_updated: 2026-10-10 (ADR-024 — the mem engine adopted as wave 6,
|
||||
release readiness renumbered to wave 7; wave 6 decomposed — eleven
|
||||
tasks per the pg-wave rhythm with the tx overlay load-bearing. Waves
|
||||
1–5 implemented and reviewed; engine specs stable.)
|
||||
---
|
||||
|
||||
# alkstore — Implementation plan
|
||||
@@ -41,7 +42,7 @@ core crate plus the finished suite (wave 5) — born pinned, per
|
||||
| [3](#wave-3--sqlite-engine) | SQLite engine: connection architecture, re-derived queue ops on contract v1, scheduler/outbox, tx seam, SQLite backlog column | waves 1 + 2 | implemented + reviewed (2026-10-08) |
|
||||
| 4 | [Postgres engine](#wave-4--postgres-engine): schema bootstrap, pool/open, listener/forwarder, all mechanisms, tx seam, pg backlog column | wave 1 | implemented + reviewed (2026-10-08) |
|
||||
| 5 | [Contract suite](#wave-5--contract-suite): the cross-engine equivalence properties (core-contract.md §Verification backlog), version-stamped per ADR-017 | waves 3 + 4 | implemented + reviewed (2026-10-10) |
|
||||
| 6 | [Mem engine](#wave-6--mem-engine): separate `alkstore-mem` crate, full contract v1 over in-memory mechanisms (tx overlay, queue/scheduler/streams/locks/wakes), the suite's third factory column (born pinned), wasm32 compile-clean acceptance | waves 1 + 5 | not yet decomposed |
|
||||
| 6 | [Mem engine](#wave-6--mem-engine): separate `alkstore-mem` crate, full contract v1 over in-memory mechanisms (tx overlay, queue/scheduler/streams/locks/wakes), the suite's third factory column (born pinned), wasm32 compile-clean acceptance | waves 1 + 5 | decomposed (2026-10-10) |
|
||||
| 7 | [Release readiness](#wave-7--release-readiness): crate docs, deployment matrix final pass, README (written last, honestly), publish prep; fuzzing decision | wave 6 | not yet decomposed |
|
||||
|
||||
## Wave 1 — Foundations
|
||||
@@ -311,6 +312,49 @@ transient-error retry loop, MEDIUM — engine-side, small,
|
||||
mem-independent); Findings 2–3 follow their park recommendation into
|
||||
wave 7's pre-release pass.
|
||||
|
||||
**Wave 6's task set** (the decomposition, 2026-10-10 — the pg wave's
|
||||
rhythm: foundations → seam → mechanisms in parallel → scheduler/outbox
|
||||
→ integration → review gate):
|
||||
|
||||
- `mem-engine-foundations` — crate scaffold (core + tokio sync+time
|
||||
only), `MemStore::new()` isolation, guarded state core, wake-routing
|
||||
substrate, clock accessor; the wasm32 compile gate starts here and
|
||||
stays green onward.
|
||||
- `mem-engine-seam-tx` — the load-bearing task: the tx overlay (all
|
||||
eleven `*_tx` staged, commit-merge + wake-at-commit, drop =
|
||||
discard, `with_tx` panic posture) + the `Store` trait surface +
|
||||
entry-point numeric-domain guards (`suite-tx-commit-atomicity-rows`
|
||||
is what consumes it once integrated).
|
||||
- `mem-engine-notify-listen` — channels wake substrate surface,
|
||||
three recv forms, close-at-engine-drop, no-replay, never coalesced;
|
||||
depends on the seam (tx-staged notify).
|
||||
- `mem-engine-queues` — the ADR-010 state machine driver-free;
|
||||
equal-jitter curve and opts resolution as the third owner.
|
||||
- `mem-engine-streams` — in-memory log, per-consumer offsets,
|
||||
`trim_to`, receiver arms.
|
||||
- `mem-engine-locks` — TTL registry; the SQLite busy-path question
|
||||
has no mem analog (loser is a clean `None`).
|
||||
- `mem-engine-scheduler-outbox` — tick/boundary/catch-up/leadership
|
||||
through the reserved scheduler lock; outbox over queues.
|
||||
- `suite-harness-current-thread` — the wave's one suite-side pre-task
|
||||
(async `past_stamp_sleep`); engine-independent, required before the
|
||||
mem column's current-thread flavor.
|
||||
- `mem-engine-integration` — full-surface wiring, the suite's third
|
||||
`StoreFactory` column green on host under the current-thread
|
||||
flavor, the wasm32 acceptance items, `engine-mem.md` to
|
||||
implementation-complete.
|
||||
- `pg-fix-scheduler-tick-seam` — review 003 Finding 1, riding the
|
||||
window (engine-side, mem-independent; the last uncovered wave-4
|
||||
hardening arm).
|
||||
- `review-wave-6` — the born-pinned gate: conformance read, third-
|
||||
column discharge audit, wasm acceptance audit, spec disposition;
|
||||
depends on integration + the rider so the window closes everything.
|
||||
|
||||
Parallelism note: the foundation task blocks the seam; the seam blocks
|
||||
the mechanisms; the mechanisms are mutually parallel. The suite pre-task
|
||||
and the Findings-1 rider are independent of the mem chain entirely and
|
||||
can run any time in the window (the rider must close before the gate).
|
||||
|
||||
## Wave 7 — Release readiness
|
||||
|
||||
The original wave 6, renumbered when the mem engine inserted at wave
|
||||
@@ -446,6 +490,12 @@ decomposes. Specific gates:
|
||||
structural twin; wave-3 outcomes absorbed (constructors exist;
|
||||
arithmetic re-owned per engine; per-engine `@every` parser;
|
||||
SQLite-scoped deferred notes stay put). See the Wave 4 section.
|
||||
- **Wave 6 decomposition** (2026-10-10) — ADR-024 adopted the mem
|
||||
engine the same day the wave-5 gate closed; the task set follows the
|
||||
pg wave's rhythm with the tx overlay as the load-bearing task, the
|
||||
suite's third column as the born-pinned deliverable, the harness's
|
||||
async-sleep pre-task, and review 003 Finding 1 riding the window.
|
||||
See the Wave 6 section.
|
||||
- **Wave-4 fix-batch decomposition** (2026-10-09) — the general
|
||||
review's findings decomposed into seven `pg-fix-*` tasks + a
|
||||
`review-wave-4-fixes` gate: Finding 1 → `pg-fix-forwarder-reconnect`
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
---
|
||||
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
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
id: mem-engine-integration
|
||||
name: Mem engine — integration (full-surface wiring, suite third column, wasm32 acceptance)
|
||||
status: pending
|
||||
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
|
||||
|
||||
- [ ] `StoreFactory` implemented for the mem engine; the third suite
|
||||
column wired and **green on the host** (same row set per the
|
||||
wiring table above)
|
||||
- [ ] The column runs under the current-thread flavor; no blocking
|
||||
calls in mem internals (grep-verified)
|
||||
- [ ] `cargo check --target wasm32-unknown-unknown -p alkstore-mem`
|
||||
clean
|
||||
- [ ] `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
|
||||
- [ ] Workspace gates green; clippy `-D warnings`; fmt clean
|
||||
- [ ] 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
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
id: mem-engine-locks
|
||||
name: Mem engine — named locks (in-memory TTL registry)
|
||||
status: pending
|
||||
depends_on: [mem-engine-seam-tx]
|
||||
scope: narrow
|
||||
risk: low
|
||||
impact: component
|
||||
level: implementation
|
||||
tags: [wave-6, mem-engine, locks]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
The named-locks mechanism over an in-memory TTL registry
|
||||
(engine-mem.md §Mapping the contract, locks row):
|
||||
|
||||
- `store.try_lock(name, owner, ttl)` — acquire or fail (`Option<Lock>
|
||||
`; no-work is a value); validation at entry (empty → `InvalidName`,
|
||||
reserved → `ReservedName`); **duration guard at entry** —
|
||||
`ttl <= 0` rejects with opaque `Err`
|
||||
([ADR-023](../architecture/decisions/023-fourth-review-round.md) §2,
|
||||
durations kind), never a silent immediately-expired lease.
|
||||
- **`Lock` handle** ([ADR-019](../architecture/decisions/019-mechanism-handle-surfaces.md)):
|
||||
`renew(ttl)` (absolute reset; renews past expiry refused) and
|
||||
`release`. Registry entries carry owner + deadline; expiry is a
|
||||
clock check at try/renew boundaries (tokio time; no ambient
|
||||
revoker) — after TTL expiry exclusion lapses *silently* (the
|
||||
ADR-008 §7 row), re-acquirable; the holder may still release.
|
||||
- **Single-instance contention semantics**: two `try_lock`s on the
|
||||
same name within the registry are serialized by the guarded-state
|
||||
discipline — first wins, second gets `None` cleanly (the SQLite
|
||||
busy-path question has no mem analog; loser is a value, never an
|
||||
error). Not part of the tx seam (no `lock_tx` — contract-verbatim:
|
||||
a lock held across a business tx is held by explicit acquisition;
|
||||
the overlay neither sees nor stages locks).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `try_lock`/`renew`/`release` over the TTL registry; entry
|
||||
validation (names + duration guard) — pinned
|
||||
- [ ] TTL expiry: silent lapse, re-acquisition, renew-past-expiry
|
||||
refused — pinned (clock-controlled tests via the state core's
|
||||
clock accessor)
|
||||
- [ ] Concurrent-contention shape: loser is `None`, winner's lease
|
||||
intact — pinned
|
||||
- [ ] `cargo check --target wasm32-unknown-unknown -p alkstore-mem`
|
||||
clean; workspace gates green
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/core-contract.md §named locks
|
||||
- docs/architecture/decisions/008-contract-v1-pinning.md §7;
|
||||
019-mechanism-handle-surfaces.md; 023 §2
|
||||
- docs/architecture/engine-mem.md §Mapping the contract (locks row)
|
||||
- tasks/pg-engine-locks.md (the structural twin's task of record —
|
||||
the duration guards land identically)
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
id: mem-engine-notify-listen
|
||||
name: Mem engine — notify/listen surface (`WakeReceiver`, close-at-engine-drop)
|
||||
status: pending
|
||||
depends_on: [mem-engine-seam-tx]
|
||||
scope: narrow
|
||||
risk: medium
|
||||
impact: component
|
||||
level: implementation
|
||||
tags: [wave-6, mem-engine, notify]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
The notify/listen mechanism over the state core's wake-routing
|
||||
substrate (engine-mem.md §Architecture):
|
||||
|
||||
- `store.notify(channel, payload)` — validation like every engine
|
||||
(empty → `InvalidName`, reserved → `ReservedName`); encode via
|
||||
core's `encode_payload` (`Codec` on failure, ADR-023 §1); delivers
|
||||
committed-notify wakes to each open receiver on that channel at the
|
||||
commit boundary, per-subscriber FIFO by commit order, never
|
||||
coalesced (no batching boundary exists). No size limit at any size —
|
||||
`PayloadTooLarge` is never produced (engine asymmetry classification,
|
||||
[ADR-024](../architecture/decisions/024-mem-engine.md) §3).
|
||||
- `store.listen(channel) -> Box<dyn WakeReceiver>` — starts from
|
||||
"now" (attaches at the current commit watermark; a listener attached
|
||||
after a commit never sees it). Delivers opaque
|
||||
`Wake { channel }` signals — `recv`/`try_recv`/`recv_timeout` forms
|
||||
per the pinned shapes ([ADR-008](../architecture/decisions/008-contract-v1-pinning.md)
|
||||
§3).
|
||||
- `notify_tx` — staged in the tx overlay by `mem-engine-seam-tx`; this
|
||||
task's contract obligation is the close arms: **one close path —
|
||||
engine drop closes open receivers** (process exit/shutdown;
|
||||
terminal `recv() -> None`, cause = the documented engine asymmetry
|
||||
realized as drop). No reconnection concept exists; the
|
||||
reconnect-wake channel is never emitted (the reserved string stays
|
||||
reserved but unused — and still rejected as a consumer name).
|
||||
|
||||
Unit tests pin: channel-scoped delivery + foreign-channel silence
|
||||
(with the field carried, per the suite row's scoping observable),
|
||||
burst floor (≥1 wake), attach-after-commit no-replay, close-at-drop
|
||||
terminal `None`, commit-boundary delivery timing through
|
||||
`notify_tx` (nothing pre-merge).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] listen/notify surface trait-complete with entry validation and
|
||||
core payload encoding
|
||||
- [ ] Wake delivery: commit-ordered, channel-scoped, no-replay,
|
||||
never coalesced — unit-pinned
|
||||
- [ ] Engine drop closes open receivers (terminal `None`) — pinned
|
||||
- [ ] `notify_tx` delivers wakes only after the overlay merge —
|
||||
pinned with the seam task's commit-atomicity tests
|
||||
- [ ] `cargo check --target wasm32-unknown-unknown -p alkstore-mem`
|
||||
clean; workspace gates green
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/core-contract.md §notify / listen
|
||||
- docs/architecture/decisions/006-wake-and-delivery-contract.md;
|
||||
008-contract-v1-pinning.md §3; 021-tx-reads-and-value-shape-fixes.md §5
|
||||
- docs/architecture/engine-mem.md §Architecture, §Asymmetry classification
|
||||
- tasks/suite-wake-rows.md (the suite row the mem column will run —
|
||||
the observable shapes it pins)
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
id: mem-engine-queues
|
||||
name: Mem engine — queues (in-memory job table, ADR-010 state machine, engine-owned backoff curve)
|
||||
status: pending
|
||||
depends_on: [mem-engine-seam-tx, mem-engine-notify-listen]
|
||||
scope: moderate
|
||||
risk: medium
|
||||
impact: component
|
||||
level: implementation
|
||||
tags: [wave-6, mem-engine, queues]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
The queue mechanism: the
|
||||
[ADR-010](../architecture/decisions/010-queue-semantics-depth.md) state
|
||||
machine realized over an in-memory job table — all driver-free.
|
||||
|
||||
- **`Queue` handle surface** ([ADR-019](../architecture/decisions/019-mechanism-handle-surfaces.md)
|
||||
§1): `enqueue` (auto-commit, resolving over the handle's opts),
|
||||
`claim_one`/`claim_batch` (extents: `n <= 0` claims nothing),
|
||||
`ack_batch` (per-id uniform predicate, lapsed/non-claimed silently
|
||||
not counted), `cancel` (unconditional delete), `get_job`, and the
|
||||
queue-scoped `sweep_expired` (no-stranded-rows: *every* past-expiry
|
||||
row in any state moves to dead + retention enforcement).
|
||||
- **Claim discipline**: exactly-once handout, `worker_id` claimant
|
||||
identity (non-empty), claim ordering priority DESC → ready-time →
|
||||
enqueue FIFO. Visibility expiry and reclaim — **reclaim consumes an
|
||||
attempt**; the dual-execution window is contract-honest (a worker
|
||||
past its deadline may complete its work but its ack will not land).
|
||||
Under a single engine instance the claim race is in-process — the
|
||||
guarded merge discipline must still make claim-vs-claim atomic and
|
||||
claim-vs-expiry deterministic at the row level.
|
||||
- **JobHandle ops** ([ADR-019](../architecture/decisions/019-mechanism-handle-surfaces.md)
|
||||
§3): `ack`/`retry`/`fail` one-shot terminal, `heartbeat(&self)`
|
||||
repeatable absolute-reset renewal; the uniform validity predicate
|
||||
(processing + unexpired deadline); deadline lapse refuses all ops,
|
||||
false not error. `retry(err, None)` computes the queue's
|
||||
**equal-jitter exponential delay — mem's own implementation**
|
||||
([ADR-012](../architecture/decisions/012-forked-substrate-design.md)
|
||||
§2's one-owner rule, third owner; the SQLite engine's `resolution.rs`
|
||||
is reference, not a dependency); `retry(err, Some(d))` overrides
|
||||
verbatim; `fail` = immediate dead-letter with the engine-default
|
||||
strings (`"failed"` / `"max attempts exceeded"`).
|
||||
- **Opts stamping** ([ADR-020](../architecture/decisions/020-enqueue-opt-semantics-and-bridges.md)):
|
||||
resolution rules (delay-over-`run_at`, relative `expires`) are
|
||||
mem-owned (third copy); handle-enqueue stamps the handle's opts;
|
||||
the tx/no-handle shapes stamped plain 300/3/5/none in
|
||||
`mem-engine-seam-tx`. `get_job` shows resolved values.
|
||||
- **Dead letters**: move-to-dead storage, `get_job` sees dead rows
|
||||
(`last_error`/`died_at`), `dead_letter_retention_s` (None = forever)
|
||||
enforced by `sweep_expired`. No redrive API.
|
||||
- Timestamps and expiry checks are tokio-time/clock reads against the
|
||||
state core's clock accessor; expiry is *checked* at claim/renew
|
||||
boundaries (no ambient sweeper — `sweep_expired` is caller-driven,
|
||||
cadence recipe unchanged).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Full `Queue`/`JobHandle` surfaces over the in-memory job table
|
||||
- [ ] The ADR-010 state machine properties unit-pinned: visibility
|
||||
reclaim consumes an attempt, dead-letter moves, no-stranded-rows
|
||||
sweep, handle-op validity predicate, late-heartbeat boundary
|
||||
- [ ] Equal-jitter curve + opts resolution pinned to the identical
|
||||
numeric behavior the suite's equivalence rows assert (per the
|
||||
engine-side pin posture used for the cap legs)
|
||||
- [ ] Numeric-domain guards (extents) at entry — pinned
|
||||
- [ ] `cargo check --target wasm32-unknown-unknown -p alkstore-mem`
|
||||
clean; workspace gates green
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/queues.md; core-contract.md §queues
|
||||
- docs/architecture/decisions/010-queue-semantics-depth.md;
|
||||
019-mechanism-handle-surfaces.md §1/§3; 020 §1–§3; 023 §2
|
||||
- docs/architecture/engine-mem.md §Mapping the contract (queues row)
|
||||
- tasks/pg-engine-queues.md (the structural twin's task of record —
|
||||
the wave-4 rhythm and the resolution rule set)
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
id: mem-engine-scheduler-outbox
|
||||
name: Mem engine — scheduler (`schedule`/`unschedule`/`run_schedules`) and outbox helper
|
||||
status: pending
|
||||
depends_on: [mem-engine-queues, mem-engine-locks]
|
||||
scope: moderate
|
||||
risk: medium
|
||||
impact: component
|
||||
level: implementation
|
||||
tags: [wave-6, mem-engine, scheduler, outbox]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
The collapsed scheduler and the outbox helper
|
||||
([ADR-009](../architecture/decisions/009-scheduler-collapse.md),
|
||||
[ADR-014](../architecture/decisions/014-outbox-tx-enqueue.md)):
|
||||
|
||||
- **Scheduler surface**: `schedule(name, spec, queue, payload, opts)`
|
||||
(upsert by name; *both* name-bearing arguments validated — schedule
|
||||
name and queue argument identically, `InvalidName`/`ReservedName`),
|
||||
`unschedule(name) -> bool`, and the opt-in
|
||||
`run_schedules(stop: StopToken)` runner over a mem-owned tick task.
|
||||
- **Tick machinery — engine-uniform** ([ADR-009](../architecture/decisions/009-scheduler-collapse.md)
|
||||
§4's rule; single-instance leadership is trivially owned but the
|
||||
machinery still runs): each boundary fire enqueues ordinary work
|
||||
stamped with the schedule's `ScheduleOpts` resolved over the target
|
||||
queue's derived engine defaults; fire+advance is atomic under the
|
||||
guarded state (the no-double-fire floor); **bounded catch-up with
|
||||
the fixed 64-boundary cap and skip-forward past the cap**
|
||||
(mem-owned tick implementation — third owner per
|
||||
[ADR-012](../architecture/decisions/012-forked-substrate-design.md)
|
||||
§2); leadership rides the reserved `__alkstore_scheduler` lock
|
||||
through the lock mechanism (so two runners on one instance contend
|
||||
through the same machinery the other engines use; loss →
|
||||
`Err(LeadershipLost)`, clean stop → `Ok(())`).
|
||||
- **Spec grammar v1**: `@every <n><unit>` (`s|m|h|d`) only — mem owns
|
||||
its parser (third copy, the grammar is small and pinned); cron
|
||||
strings rejected (`InvalidSpec`). Boundary waits ride tokio time.
|
||||
- **Outbox helper**: `Outbox { enqueue, run_once }` per
|
||||
[ADR-019](../architecture/decisions/019-mechanism-handle-surfaces.md)
|
||||
§5 — `run_once(worker_id, delivery) -> bool` is pull: claim one,
|
||||
ack on `Ok`, `retry(err, None)` on `Err`; **no engine-issued
|
||||
heartbeat inside delivery** (inherited posture);
|
||||
`outbox_enqueue_tx` staged in the overlay by `mem-engine-seam-tx`
|
||||
(the 60/5/5 stamp set); the derived backing queue
|
||||
`__alkstore_outbox:{outbox}` unreachable by `enqueue_tx`
|
||||
(validation already pins the reserved prefix), name format pinned
|
||||
identical to the other engines (the suite's derived-queue-naming
|
||||
row composes it).
|
||||
|
||||
Unit tests pin: boundary fires (deterministic, tokio-time driven),
|
||||
bounded catch-up + skip-forward, leadership lock contention/loss
|
||||
through two `run_schedules` calls, outbox run_once ack/retry shapes,
|
||||
derived-name format.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Scheduler surface + tick: boundary fire, catch-up (≤64),
|
||||
skip-forward — unit-pinned with tokio-time determinism
|
||||
- [ ] Leadership contention through the `__alkstore_scheduler` lock;
|
||||
`LeadershipLost` on loss, `Ok(())` on clean stop — pinned
|
||||
- [ ] Schedule name + queue argument validation; `@every`-only parser
|
||||
(cron → `InvalidSpec`) — pinned
|
||||
- [ ] Outbox: `enqueue`/`run_once` semantics (no engine heartbeat);
|
||||
derived backing-queue name format identical to both engines —
|
||||
pinned
|
||||
- [ ] `cargo check --target wasm32-unknown-unknown -p alkstore-mem`
|
||||
clean; workspace gates green
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/queues.md; core-contract.md §scheduler, §outbox
|
||||
- docs/architecture/decisions/009-scheduler-collapse.md §1/§3/§4/§6;
|
||||
014-outbox-tx-enqueue.md; 019 §4/§5; 020 §3
|
||||
- docs/architecture/engine-mem.md §Mapping the contract
|
||||
(scheduler/outbox row)
|
||||
- tasks/pg-engine-scheduler-outbox.md (the structural twin's task of
|
||||
record — tick/catch-up/leadership shapes)
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
id: mem-engine-seam-tx
|
||||
name: Mem engine — tx overlay, `Store` surface, `TxHandle` (staged `*_tx`, commit-merge + wake-at-commit, drop = discard)
|
||||
status: pending
|
||||
depends_on: [mem-engine-foundations]
|
||||
scope: moderate
|
||||
risk: high
|
||||
impact: component
|
||||
level: implementation
|
||||
tags: [wave-6, mem-engine, seam]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
The seam task, and the wave's load-bearing artifact
|
||||
(engine-mem.md §The tx overlay): the `Store` trait impl plus the tx
|
||||
overlay's full discipline.
|
||||
|
||||
- **`Store` surface**: the trait methods (`notify`, `stream`,
|
||||
`queue`, `outbox`, `try_lock`, `listen`, `schedule`, `unschedule`,
|
||||
`run_schedules`, `begin_tx`, `with_tx`) implemented over the
|
||||
state core. `queue(name, opts)`/`outbox(name)` create/return
|
||||
handles whose opts ride the handle (queues are names, not config
|
||||
owners — the §3a stamp rules apply identically). Mechanism handles
|
||||
are core-owned trait objects; engine types never appear in
|
||||
signatures.
|
||||
- **The tx overlay**: `begin_tx()` allocates a handle-private overlay.
|
||||
All eleven `*_tx` methods stage effects in it — `enqueue_tx`,
|
||||
`publish_tx`, `publish_with_key_tx`, `notify_tx`,
|
||||
`save_offset_tx`, `get_job_tx`, `get_offset_tx`, `read_since_tx`,
|
||||
`read_from_consumer_tx`, `outbox_enqueue_tx`, `commit`. Reads *inside* the tx merge the overlay over committed state (read-
|
||||
your-own-writes, no round-trips: the tx-read rows'
|
||||
`get_job_tx`/`read_since_tx` behaviors come free, but pin them).
|
||||
Opt-stamping of staged effects runs at *enqueue* time on the
|
||||
overlay (resolution identical to the no-handle paths, per
|
||||
[ADR-020](../architecture/decisions/020-enqueue-opt-semantics-and-bridges.md)
|
||||
§3: `enqueue_tx` stamps plain derived defaults 300/3/5/none;
|
||||
`outbox_enqueue_tx` the 60/5/5 set).
|
||||
- **Commit-merge + wake-at-commit**: commit merges the overlay
|
||||
atomically (single guarded merge) and fires the overlay's pending
|
||||
wakes *in the same operation* — a tx-staged notify delivers nothing
|
||||
until the merge (the discipline pg got wrong and fixed via
|
||||
`pg-fix-tx-wake`; here structural, and pinned from birth by the
|
||||
suite's tx-commit-atomicity rows once integration wires them).
|
||||
- **Drop = discard**: dropping the handle without commit/rollback
|
||||
discards the overlay (rollback explicit form too) — no-ghosts
|
||||
trivially, uncommitted state never touched committed state.
|
||||
`with_tx` composition: `Ok` ⇒ commit, `Err`/drop/panic ⇒ rollback
|
||||
(the N-5 panic posture applies; overlay discard must be panic-safe
|
||||
through the unwind's drop).
|
||||
- **Numeric domains** ([ADR-023](../architecture/decisions/023-fourth-review-round.md)
|
||||
§2): validation at the trait-impl entry, before any storage-layer
|
||||
effect — extents clamp empty, durations reject, boundaries total.
|
||||
Same entry-point rule as the other engines, realized engine-side.
|
||||
|
||||
Engine-internal unit tests pin the overlay discipline directly
|
||||
(merge atomicity, wake-after-not-before, drop-discard, panic-through-
|
||||
unwind) in the family's mechanism-test posture; the suite column's
|
||||
cross-engine rows land in `mem-engine-integration`.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] The full `Store`/`TxHandle` trait surfaces implemented over
|
||||
guarded state; no engine types in consumer signatures
|
||||
- [ ] Overlay staging → commit-merge → wake-at-commit pinned by unit
|
||||
tests (a tx-staged notify delivers nothing pre-commit, one wake
|
||||
post-commit; enqueue/publish commit-atomicity shapes)
|
||||
- [ ] Drop-without-commit and explicit rollback leave zero residue;
|
||||
`with_tx` panic rolls back through the unwind's drop
|
||||
- [ ] Tx reads see staged effects; other views see none pre-commit;
|
||||
post-rollback reads' subjects gone (no-ghosts for reads)
|
||||
- [ ] Numeric-domain guards at entry (extents/durations/boundaries)
|
||||
pinned per [ADR-023](../architecture/decisions/023-fourth-review-round.md) §2
|
||||
- [ ] `cargo check --target wasm32-unknown-unknown -p alkstore-mem`
|
||||
clean; workspace gates green
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/core-contract.md §The seam; §Cross-cutting contracts
|
||||
- docs/architecture/decisions/007-transactional-seam.md;
|
||||
014-outbox-tx-enqueue.md; 020-enqueue-opt-semantics-and-bridges.md
|
||||
§3; 021-tx-reads-and-value-shape-fixes.md; 023-fourth-review-round.md §2
|
||||
- docs/architecture/engine-mem.md §The tx overlay (the spec of record)
|
||||
- tasks/pg-fix-tx-wake.md (the failure shape the overlay makes
|
||||
structurally impossible)
|
||||
- tasks/review-wave-5.md appendix (the suite rows whose mem wiring
|
||||
consumes this task)
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
id: mem-engine-streams
|
||||
name: Mem engine — streams (in-memory log, per-consumer offsets, trim)
|
||||
status: pending
|
||||
depends_on: [mem-engine-seam-tx, mem-engine-notify-listen]
|
||||
scope: moderate
|
||||
risk: medium
|
||||
impact: component
|
||||
level: implementation
|
||||
tags: [wave-6, mem-engine, streams]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
The streams mechanism over an in-memory event log + per-consumer
|
||||
offset table (engine-mem.md §Mapping the contract, streams row):
|
||||
|
||||
- **`StreamHandle` surface** ([ADR-019](../architecture/decisions/019-mechanism-handle-surfaces.md)
|
||||
§2): `publish` / `publish_with_key` (present key must be non-empty
|
||||
→ `InvalidName`), `read_since` / `read_from_consumer` (cursor reads,
|
||||
`offset ASC`, extents clamp empty per
|
||||
[ADR-023](../architecture/decisions/023-fourth-review-round.md) §2),
|
||||
`save_offset` / `get_offset` (monotone saves — below-checkpoint
|
||||
saves are silent no-ops, `Err` arm carries `Database` only),
|
||||
`trim_to` (delete `offset <= horizon`, exact-boundary, returns
|
||||
deleted count, negative horizon deletes nothing idempotently,
|
||||
**wakes nothing**, surviving rows keep offsets, never renumbered),
|
||||
and `subscribe` (durable consumption: attach, read to tail, resume
|
||||
from saved offset; wake-driven with re-read — the wake substrate
|
||||
delivers at commit; explicit saves only, no auto-checkpoint).
|
||||
- **Ordering**: engine-assigned monotonically increasing per-stream
|
||||
offsets, global FIFO by offset — the ADR-015 ordering row, mem's own
|
||||
counter (per-stream; absolute values need not equal the SQL engines'
|
||||
— the equivalence rows pin relative order).
|
||||
- **`StreamEvent` shape** exactly as pinned
|
||||
([ADR-015](../architecture/decisions/015-streams-depth.md) §3):
|
||||
`{ offset, stream, key, payload, created_at }` — `created_at` is
|
||||
unix-seconds at publish, informational, from the clock accessor.
|
||||
Reads from a trimmed-away region resume at the horizon's first
|
||||
remaining row.
|
||||
- **Keyed publish rides the tx overlay** (staged `publish_with_key_tx`
|
||||
landed in `mem-engine-seam-tx`); this task's non-tx forms, receiver,
|
||||
and trim live here.
|
||||
- **Receiver close arms** ([ADR-021](../architecture/decisions/021-tx-reads-and-value-shape-fixes.md)
|
||||
§5): `recv()`'s `Err` carries `Database` only (payloads cross raw;
|
||||
`Codec` at `payload_as<T>`); close is terminal — the one close path
|
||||
is engine drop (the notify-listen task's close arm, realized
|
||||
identically); no reconnection concept (the pg stays-open-across-
|
||||
reconnect row is absent from mem's column).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Full `StreamHandle` surface over the in-memory log +
|
||||
per-consumer offsets
|
||||
- [ ] The ADR-015 properties unit-pinned: global FIFO, immutable
|
||||
never-renumbered offsets (gaps legal post-trim), exact-boundary
|
||||
trim semantics (reads resume at horizon; saved sub-horizon
|
||||
offsets stay valid; trim wakes nothing), monotone save
|
||||
composition (direct + receiver forms interleave)
|
||||
- [ ] Key round-trips exactly (`None` vs `Some`); empty-`Some`-key
|
||||
rejected at every entry point
|
||||
- [ ] Extent/offset numeric-domain guards at entry — pinned
|
||||
- [ ] `cargo check --target wasm32-unknown-unknown -p alkstore-mem`
|
||||
clean; workspace gates green
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/core-contract.md §streams
|
||||
- docs/architecture/decisions/015-streams-depth.md;
|
||||
019-mechanism-handle-surfaces.md §2/§6; 021 §5; 023 §2
|
||||
- docs/architecture/engine-mem.md §Mapping the contract (streams row)
|
||||
- tasks/pg-engine-streams.md (the structural twin's task of record)
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
id: pg-fix-open-path
|
||||
name: Fix `max_size: 0` open hang + DSN options override (review 002 Finding 3 + options note)
|
||||
name: "Fix `max_size: 0` open hang + DSN options override (review 002 Finding 3 + options note)"
|
||||
status: completed
|
||||
depends_on: []
|
||||
scope: single
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
id: pg-fix-scheduler-tick-seam
|
||||
name: "pg scheduler — transient-fault tick seam: retry/exhaustion arms tested (review 003 Finding 1)"
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: narrow
|
||||
risk: low
|
||||
impact: component
|
||||
level: implementation
|
||||
tags: [wave-6, postgres-engine, scheduler, test-hardening]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Review 003 Finding 1 (MEDIUM — `docs/reviews/003-wave-5-general-review.md`):
|
||||
the pg scheduler's transient-error retry loop
|
||||
(`alkstore-postgres/src/scheduler.rs:680-704`, `tick_with_retries`)
|
||||
has never executed under any test — `pg-fix-scheduler-resilience`
|
||||
pinned its *constants* (`the_tick_retry_policy_is_pinned`) but the
|
||||
loop that uses them (retry, backoff sleeps, exhaustion error, the
|
||||
`eprintln` diagnostic — lcov 171-184, 237-260) is dead code under
|
||||
test, with no fault seam anywhere in the pg scheduler for `tick_once`.
|
||||
This is the last uncovered hardening arm from the wave-4 fix batch,
|
||||
and the exact class that produced review 002's live bugs.
|
||||
|
||||
Fix shape (the review's recommendation): a `cfg(test)` transient-
|
||||
fault seam on the pg tick path, following the `sqlite-commit-error-arm
|
||||
` precedent — a one-shot armed flag feeding a fabricated
|
||||
transient error into the *real* retry loop (never a replica):
|
||||
|
||||
- (a) one retried tick then success: the seam faults once, the next
|
||||
`tick_once` succeeds, the job processes — the retry + backoff-sleep
|
||||
arms execute for real;
|
||||
- (b) exhaustion: the seam faults the max retry count, the loop
|
||||
exhausts to the typed error shape and the `eprintln` diagnostic
|
||||
fires, the runner survives (the resilience property the fix
|
||||
promised).
|
||||
|
||||
Cross-test safety is per-store scoping (the commit-fault seam's
|
||||
pattern); no production-path changes — the seam is cfg-gated, born
|
||||
disarmed, consumed-on-use.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] The seam lands cfg(test)-gated; the real `tick_with_retries`
|
||||
executes under test (no loop replication)
|
||||
- [ ] Arms (a) and (b) pinned as above; the runner survives
|
||||
exhaustion
|
||||
- [ ] `cargo test -p alkstore-postgres` green against the harness
|
||||
server; skips clean server-less
|
||||
- [ ] Clippy `-D warnings`, fmt clean; workspace gates green
|
||||
|
||||
## References
|
||||
|
||||
- docs/reviews/003-wave-5-general-review.md §Finding 1 (sites, lcov
|
||||
inventory, recommendation)
|
||||
- docs/architecture/decisions/024-mem-engine.md (the wave-6 window
|
||||
this rider rides — the plan's wave-6 section, "Riding the window")
|
||||
- tasks/sqlite-commit-error-arm.md (the seam pattern of record)
|
||||
- tasks/pg-fix-scheduler-resilience.md (the constants the loop uses)
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
id: review-wave-6
|
||||
name: Review gate — wave 6 (mem engine)
|
||||
status: pending
|
||||
depends_on: [mem-engine-integration, pg-fix-scheduler-tick-seam]
|
||||
scope: moderate
|
||||
risk: low
|
||||
impact: phase
|
||||
level: review
|
||||
tags: [wave-6, review]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
The wave-6 review gate (the plan's §Review gates, wave 6; the
|
||||
born-pinned gate). Code-read the `alkstore-mem` engine against the
|
||||
contract and the pinned ADR-024 text, and audit:
|
||||
|
||||
1. **Conformance read**: engine-vs-contract line by line, mirroring
|
||||
the wave-3/4 gate pattern — every trait surface against
|
||||
core-contract.md and the pinning ADRs (007/008/009/010/015/019/
|
||||
020/021/023), the tx overlay against ADR-024 + engine-mem.md §The
|
||||
tx overlay (commit-merge atomicity, wake-at-commit, drop = discard,
|
||||
panic-through-unwind).
|
||||
2. **The third column as the compatibility instrument born pinned**:
|
||||
the mem column's wiring read row-by-row against the discharge map
|
||||
(which rows carry, which engine-shaped rows omit and why — the
|
||||
asymmetry classification, ADR-024 §3); `PayloadTooLarge`
|
||||
non-occurrence arm present; three-way arithmetic equivalence
|
||||
actually asserted green (backoff curve, opts resolution — the
|
||||
ADR-012 §2 one-owner rule's third owner), plus the derived-queue
|
||||
naming row composing identically.
|
||||
3. **wasm32 acceptance audit** (ADR-024 §5): the compile gate clean,
|
||||
tokio feature subset verified on the manifest, no blocking calls
|
||||
in mem internals, the current-thread flavor actually enforced by
|
||||
the column's tests.
|
||||
4. **engine-mem.md read against the implemented engine**; the
|
||||
deployment matrix's mem rows (`deployment.md`, landed with ADR-024)
|
||||
still true as implemented (honesty carriers: identity + docs +
|
||||
matrix — nothing runtime invented). Gate may flip `engine-mem.md`
|
||||
to `stable` if the read is clean.
|
||||
5. **The rider closed**: `pg-fix-scheduler-tick-seam`'s arms verified
|
||||
(review 003 Finding 1 discharged into this window; Findings 2–3
|
||||
confirmed still parked for wave 7).
|
||||
6. **Contract-window discipline**: the class-1 amend-in-place window
|
||||
is still open — any wobble the third implementation surfaced must
|
||||
appear as resolved ADR text (or be recorded as a finding with its
|
||||
disposition), not as a silent divergence between suite row and
|
||||
engine behavior.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Full conformance code-read recorded (findings + dispositions
|
||||
inline in this task's Notes, mirroring review-wave-3/4 style)
|
||||
- [ ] Suite mem column green on host, 25-row set wired per the
|
||||
classification; three-way equivalence rows green
|
||||
- [ ] wasm32 compile gate + feature-subset + current-thread flavor
|
||||
verified, recorded
|
||||
- [ ] The rider's arms verified; Finding 1 disposition recorded
|
||||
- [ ] Workspace gates re-run green this session (`cargo build`,
|
||||
`cargo test`, clippy `-D warnings`, fmt)
|
||||
- [ ] `engine-mem.md` disposition decided (stable flip or follow-up)
|
||||
and `implementation.md`'s wave-6 row updated
|
||||
|
||||
## References
|
||||
|
||||
- docs/plans/implementation.md §Wave 6, §Review gates (wave 6 entry)
|
||||
- docs/architecture/decisions/024-mem-engine.md (the charter this
|
||||
gate audits code against)
|
||||
- docs/architecture/engine-mem.md
|
||||
- tasks/review-wave-3.md / tasks/review-wave-4.md (the gate pattern)
|
||||
- docs/reviews/003-wave-5-general-review.md (Finding 1's disposition
|
||||
trail; Findings 2–3's wave-7 park)
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
id: suite-harness-current-thread
|
||||
name: Contract-suite harness — async sleep in `past_stamp_sleep`, current-thread flavor readiness
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: narrow
|
||||
risk: low
|
||||
impact: component
|
||||
level: implementation
|
||||
tags: [wave-6, contract-suite]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
The one suite-side change wave 6 carries
|
||||
([ADR-024](../architecture/decisions/024-mem-engine.md) §5 item 4; the
|
||||
review-003 posture note at `properties.rs:1683`): the suite's
|
||||
`past_stamp_sleep` helper uses a blocking `std::thread::sleep` inside
|
||||
async rows — safe under the multi-thread test flavors both existing
|
||||
engines' targets use, but it would stall a current-thread runtime. The
|
||||
mem engine's suite column **must** run under a current-thread flavor
|
||||
(`#[tokio::test(flavor = "current_thread")]`) to keep the mem
|
||||
engine's internals honestly current-thread-clean — which is what
|
||||
wasm32 needs.
|
||||
|
||||
- Replace `past_stamp_sleep`'s blocking sleep with `tokio::time::sleep`
|
||||
(async). The helper's semantics are unchanged (a bounded
|
||||
pre-`run_at` settle before reads); the existing rows' determinism
|
||||
posture is untouched — verify the two legs using it re-run green on
|
||||
both engines with no timing drift (tolerances unchanged).
|
||||
- Document (one line in the helper's doc comment or the factory
|
||||
contract notes) the harness posture: **no blocking calls inside
|
||||
suite rows** — the mem column enforces the flavor that catches
|
||||
violations.
|
||||
|
||||
This task is engine-independent and can run any time before
|
||||
`mem-engine-integration` wires the third column.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `past_stamp_sleep` is async (`tokio::time::sleep`)
|
||||
- [ ] Both engines' existing suites re-run green with identical
|
||||
assertions and tolerances (determinism posture intact)
|
||||
- [ ] The no-blocking-calls posture noted where the harness's
|
||||
determinism posture is documented
|
||||
- [ ] Clippy `-D warnings`, fmt clean; workspace gates green
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/decisions/024-mem-engine.md §5
|
||||
- docs/reviews/003-wave-5-general-review.md §Finding 5 (the
|
||||
`properties.rs:1683` posture note)
|
||||
- docs/architecture/decisions/022-contract-suite-layout.md (the
|
||||
factory contract the flavor rides)
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
Reference in new issue
Block a user