Files
alkstore/docs/plans/implementation.md
T

8.3 KiB
Raw Blame History

status, last_updated
status last_updated
draft 2026-10-08 (waves 1–2 implemented + reviewed; ADR-023 follow-through folded into wave 3; wave 3 decomposed)

alkstore — Implementation plan

Wave-based decomposition of the architecture (docs/architecture/) into units of implementable work. This is a deliberate deviation from the SDD process's decompose-everything-upfront step: the architecture is large, early waves change the shape of later ones (the fork's outcomes feed the SQLite engine tasks; the contract suite's harness shape feeds both engines' verification work), and decomposing only the next wave or two at a time keeps each session's task set reviewable and lets later decompositions absorb earlier waves' course corrections.

Rhythm: decompose a wave → implement it → review gate → decompose the next wave. Task files live in tasks/ (taskgraph-managed; frontmatter carries the categorical estimates). Wave boundaries are also review boundaries.

The waves

Dependency logic in one line: core → (substrate fork ∥ postgres engine) → sqlite engine → contract suite → release readiness. The substrate fork is contract-blind (ADR-012 §2), so it needs only the workspace scaffold from wave 1; the Postgres engine needs only the core crate. Waves 2 and 4 are therefore independent of each other and could run in either order (or in parallel, if agents are ever available in parallel).

Wave Contents Depends on Status
1 Workspace scaffold; core crate (errors, value types, full trait surface); contract-suite scaffold — implemented + reviewed (2026-10-08)
2 honker-core fork into alkstore-sqlite/src/substrate/: port, deltas, provenance, test floor wave 1 (workspace scaffold only) implemented + reviewed (2026-10-08)
3 SQLite engine: connection architecture, re-derived queue ops on contract v1, scheduler/outbox, tx seam, SQLite backlog column waves 1 + 2 decomposed (tasks/)
4 Postgres engine: schema bootstrap, pool/open, listener/forwarder, all mechanisms, tx seam, pg backlog column wave 1 not yet decomposed
5 Contract suite: the cross-engine equivalence properties (core-contract.md §Verification backlog), version-stamped per ADR-017 waves 3 + 4 not yet decomposed
6 Release readiness: crate docs, deployment matrix final pass, README (written last, honestly), publish prep; mem-engine and fuzzing decisions wave 5 not yet decomposed

Wave 1 — Foundations

The core crate is contract v1 in code: the error taxonomy (ADR-008 §5), the value types (ADR-019 §3, ADR-020), the full trait surface (ADR-008 §1–§3/§8, ADR-014, ADR-019, ADR-021), and the payload encoding posture (ADR-020 §4). Nothing engine-specific lives here — no resolution arithmetic, no SQL. The equal-jitter curve, opts-stamping resolution, and boundary math are deliberately not core: ADR-012 §2 pins each engine as the owner of one implementation, with equivalence pinned by the contract suite (wave 5).

The contract suite gets scaffolded now (not in wave 5) because its harness shape — a Store-factory-parameterized property crate — is easier to grow row by row as engines land than to retrofit onto two finished engines. Wave 5 fills it with the cross-engine equivalence rows; waves 3 and 4 adopt the harness for their own backlog columns.

Wave 2 — SQLite substrate fork

The fork per ADR-011/012/013: port honker-core at f4e53c6 into alkstore-sqlite/src/substrate/, apply the three watcher port deltas and the bootstrap re-keying, drop cron/experimental/cut-flag machinery, re-own the table family as __alkstore_*, carry PROVENANCE.md and the dual-license notice in-tree (ADR-018), and stand up the inherited test suites as the floor. The substrate stays sync and contract-blind; the engine layer that maps it onto the core contract is wave 3, not here. Reviewability against the lineage (ADR-012 §3) is a property the wave-2 review gate checks explicitly.

Wave 3 — SQLite engine

The engine layer that maps the forked substrate onto the core contract: the open constructor (connection architecture — writer slot, reader pool, watcher spawn — per engine-sqlite.md), the spawn_blocking seam, the full Store/TxHandle/mechanism-handle trait impls over the substrate's ops, the scheduler leader loop and outbox helper, and the engine's backlog column in the contract suite (the ADR-023 rows among them, factory-parameterized so wave 5 runs them against both engines).

The waves-1–2 general review (docs/reviews/2026-10-08-waves-1-2-general-review.md) and its resolution (ADR-023) shaped this wave's task set:

  • Already landed pre-decomposition (commit 44637ee, not wave-3 tasks): encode_payload is fallible (Result<Vec<u8>, Error::Codec>, ADR-023 §1); open_conn drops SQLITE_OPEN_URI (§3, register D-29); the numeric-argument domain table is pinned in core-contract.md (§2); the 1 ms watcher default stands with the cadence documented in deployment.md (§4).
  • Folded into wave 3's tasks (the review's §7 wiring items): the trait-impl extent/duration guards (the contract-side domain rule, enforced at the engine's trait-impl entry — the sqlite-engine-* tasks carry it per mechanism), the two #![allow] lint removals in substrate/mod.rs (the integration task — they can only lift once every substrate surface is wired), and SqliteOpts::poll_interval wiring (the constructor task).
  • Staying put as ordered: M-1's retention-failure test and N-5's panic probe → wave 5's contract-suite rows; N-1's growth-posture review → wave 6.

Decided points

  • Contract-suite layout — option (a): a small internal alkstore-contract-suite crate (not published) exposing property tests parameterized over a Store factory; each engine crate takes it as a dev-dependency. One normative owner per property, mirroring ADR-012 §2's one-owner rule. This discharges ADR-017 §4.2's "decided at implementation" deferral; recorded as ADR-022 by the scaffold task.
  • Engine tests vs. contract suite: each engine wave carries its own mechanism tests (does the engine work); wave 5 carries the cross-engine equivalence properties (do the engines agree). The verification-backlog rows are mostly equivalence-shaped, so this split keeps wave 5 from re-testing engine internals.
  • CI: none, deliberately. CI and publishing are run manually (self-hosted Gitea; supply-chain posture). No CI-wiring task exists; the merge gates (cargo test, cargo clippy --all-targets -- -D warnings, cargo fmt --check) are run coordinator-side.
  • Mem engine (ADR-001 §4) and fuzzing adoption (the alksocks/alktty/alktunnels pattern): both are "decided at implementation" deferrals, recorded here so they surface as explicit decision points in wave 6 (or earlier if the test story demands the mem engine sooner) rather than ambushing a later session.

Review gates

Each wave ends in a review task (review-wave-N) before the next wave decomposes. Specific gates:

  • Wave 1 review — the trait surface is versioned contract surface from the first release (ADR-017); a shape error found here is cheap, found in wave 5 it is a migration. Review checks the code against the pinned ADR text line by line.
  • Wave 2 review — diff reviewability against the honker lineage (ADR-012 §3's fidelity posture), provenance register completeness (ADR-018), floor tests green.
  • Wave 3/4 reviews — engine-vs-contract conformance; the backlog columns each engine owns.
  • Wave 5 review — the suite as compatibility instrument: every backlog row present, version-stamped, green on both engines; this is the gate that flips the engine specs to stable.

Review rounds so far

  • Wave 1 review gate (review-wave-1) — trait surface vs pinned ADR text; validation coverage fixes landed.
  • Wave 2 review gate (review-wave-2) — lineage diff clean, one re-derivation defect found and fixed (D-27).
  • General review, waves 1–2 (2026-10-08, docs/reviews/2026-10-08-waves-1-2-general-review.md) — M-1 fixed inline (sweep savepoint scope); M-2/N-2/N-4/N-6 resolved as ADR-023 pre-decomposition; lint removal + suite adds folded into waves 3/5; N-1 recorded for wave 6.