--- id: sqlite-engine-integration name: SQLite engine — integration (lint removal, full-surface wiring, suite adoption) status: completed depends_on: [sqlite-engine-notify-listen, sqlite-engine-streams, sqlite-engine-queues, sqlite-engine-locks, sqlite-engine-scheduler-outbox] scope: moderate risk: medium impact: phase level: implementation tags: [wave-3, sqlite-engine, integration] --- ## Description Close the wave's integration gaps once every mechanism is wired: - **Remove the two lint suppressions** in `alkstore-sqlite/src/substrate/mod.rs` (`#![allow(dead_code)]`, `#![allow(unused_imports)]`) — the waves-1–2 review's explicit wave-3 obligation. With the engine layer wired, every substrate surface should be reachable; genuinely dead ported code must be **cut, not suppressed** (and the cut registered in PROVENANCE.md if it diverges from the lineage's kept set — ADR-018's delta discipline). Fix whatever the lints surface; do not re-add allows. - **Full-surface sweep**: every `Store`/`TxHandle`/mechanism trait method implemented (no `todo!`/`unimplemented!` anywhere); the engine crate's lib re-exports its public surface (`open`, `SqliteOpts`, the concrete store type) per the module-per-file convention. - **Contract-suite adoption** (the plan's "waves 3 and 4 adopt the harness"): implement `StoreFactory` for the SQLite engine (fresh temp-file store per `open`, idempotent teardown) and wire the engine's backlog column — the rows this engine owns now, per ADR-023's verification-backlog additions and the engine-scoped backlog rows: - Extent-clamp semantics (`claim_batch(n <= 0)`, stream reads `limit <= 0`) — stamped `ADR-023 §2` - Duration-refusal (`try_lock`/`renew` with `ttl <= 0`) — stamped `ADR-023 §2` - `encode_payload` typed-failure round-trip (enqueue/publish store + decode the exact serialization) — stamped `ADR-023 §1` - Plain-path open (`?name=value` suffix = literal filename) — stamped `ADR-023 §3` - Poll-cadence default + knob (config-surface accounting, not wall-clock) — stamped `ADR-023 §4` - The engine-scoped rows core-contract.md assigns this engine: `PayloadTooLarge` never produced (ADR-016 §5), drop = rollback no-ghosts (ADR-021 §4), in-tx read-your-own-writes (ADR-021 §1), enqueue-opts resolution (ADR-020 §1–§3), receiver close arms (ADR-021 §5) — each stamped per the suite's convention. Rows run against the SQLite factory now; wave 5 runs the same rows against pg (the factory-parameterized point). - **Crate docs**: the engine crate's lib-level doc comments state the single-host posture and the writer-parking honesty note (ADR-016, ADR-007's negative consequence) — the identity statements this crate owns. - **Gates**: full workspace build/test/clippy/fmt; coverage spot-check on the engine crate (no large uncovered regions outside error arms). ## Acceptance Criteria - [x] Both `#![allow]` lints removed from `substrate/mod.rs`; any code the removal surfaces is cut (and registered) or wired — clippy `-D warnings` green without them - [x] No `todo!`/`unimplemented!` in the engine crate; full trait surface implemented - [x] `StoreFactory` implemented for SQLite; the backlog-column rows listed above exist, version-stamped, and run green against the SQLite factory - [x] Engine crate lib docs carry the single-host + writer-parking posture statements - [x] Workspace gates green: `cargo build`, `cargo test`, clippy `-D warnings`, fmt clean ## References - docs/reviews/001-waves-1-2-general-review.md (§2 smells, §7) - docs/architecture/decisions/023-fourth-review-round.md (Verification backlog additions) - docs/architecture/core-contract.md (§Verification backlog) - docs/architecture/decisions/022-contract-suite-layout.md - docs/architecture/decisions/016-deployment-honesty.md - alkstore-contract-suite/src/factory.rs ## Notes > Decisions of record the description didn't pin: - **Lint removal cut six substrate items, registered D-32..D-36** — lifting the two `#![allow]`s surfaced six genuinely dead surfaces, all cut rather than wired, each an ADR-018 register entry with its reason: `arg_opt_i64` (upstream consumed it at the optional-arg SQL entry points whose queue functions D-04 dropped — the re-derivation resolves opts engine-side), `ops::now_unix` (the fold D-17 gave each module region its own clock read; `resolution.rs` owns the engine layer's single clock), `queue_next_claim_at` (upstream's external-poll-driver function; the v1 scheduler surface has no next-wake query — the engine's leader loop derives the boundary from `scheduler_tick` + `scheduler_soonest`), `Writer::try_acquire` (a try-shaped begin doesn't exist on the contract — `begin_tx` *parks* on the lease by design, ADR-007; a try-acquire would contradict the posture), and `UpdateWatcher::spawn` / `SharedUpdateWatcher::new` (the config-less convenience twins — this engine's single open posture always constructs `WatcherConfig` from `SqliteOpts`, ADR-023 §4; a second config-less path would recreate the mixed-posture shape D-29 resolved). None changed kept-fidelity posture — all six are `drop`-category entries against the *kept* set, with the affected substrate tests re-expressing their properties through the reachable surface (no assertion strength lost: the probe tests test the same coercion/lease behavior through the surviving forms). - **Two substrate items kept under `#[cfg(test)]`** rather than cut: `SharedUpdateWatcher::subscriber_count` and the `DEFAULT_WATCHER_POLL_INTERVAL` re-export — engine-side tests reach them (the leak/no-leak pins, the 1 ms default pin); they are test-observation surface, honestly gated `#[cfg(test)]`, not suppressed. `open_store` was likewise promoted `pub(crate)` (the store tests construct the concrete handle; `open` stays the consumer surface). - **The exemplar row had a real-engine sequencing defect — fixed suite-side** (a suite-text change, ADR-017 §2 class 4): the name-validation row held its `tx` handle alive across the whole battery including the final `with_tx` leg. The mock harness never saw this; a real engine's `begin_tx` parks a concurrent begin on the writer slot (ADR-007's honest model), so the row deadlocked a real factory. The tx battery is now scoped so the handle drops before the `with_tx` leg. The row's *assertions* are unchanged — only the sequencing fix — but the incident is the wave-5 lesson the factory exists to surface: rows are mock-blind until an executes them against a real single-writer engine. - **Row set** (nine total — the exemplar + eight new, all in `alkstore-contract-suite/src/properties.rs`, one owner, version-stamped per the convention, each a public `pub async fn(&dyn StoreFactory)`): the ADR-023-stamped rows (extent-clamp including the boundary-totality legs, duration-refusal, `encode_payload` round-trip), and the engine-scoped rows the task names (PayloadTooLarge-never-produced — the SQLite arm, the pg rejection arm rides wave 4's adoption of the same row text; the drop=rollback no-ghosts; in-tx read-your-own-writes; enqueue-opts resolution — ADR-020 §1–§3; receiver close/save arms — ADR-021 §5). **Plain-path open (§3) and poll cadence (§4) pin engine-side, not as suite rows**: both are constructor-level SQLite-native facts not expressible over `StoreFactory::open()` — `uri_shaped_open_path_is_a_literal_filename` and `poll_interval_flows_to_the_watcher_config` (stamped, `open_tests.rs`) are this engine's rows for them; wave 4's pg column simply doesn't carry them (they're SQLite-scoped backlog rows per core-contract.md). - **The factory** (`alkstore-sqlite/tests/contract_suite.rs`): a fresh never-before-used temp file per `open` under a per-instance directory; teardown = directory delete, idempotent (already-deleted ⇒ `Ok`). Its isolation/idempotence contract has its own pin in the test target (`opens_are_isolated_and_teardown_is_idempotent`); receiver-close rows drive the terminal-close arm by dropping the store handle (the dispose carrier every engine has), not teardown — deleting files under a live store is not a close mechanism. - **Coverage spot-check** (cargo-llvm-cov, engine crate): 93.59% lines / ~89% regions, every file ≥85% lines; the misses are error arms and Windows-only `file_id` variants (`watcher.rs`'s HighRes/LowRes halves) — no large uncovered regions outside error arms, the gate the task pinned. ## Summary > Landed: the two `#![allow]` lints removed from > `substrate/mod.rs` (its module docs re-stated to the wave-3 wired > posture); the removal surfaced six dead surfaces — cut, each > registered D-32..D-36 in `PROVENANCE.md` (queue-side: `arg_opt_i64`, > `now_unix`, `queue_next_claim_at`; writer/watcher-side: > `Writer::try_acquire`, `UpdateWatcher::spawn`, > `SharedUpdateWatcher::new`), their probe tests re-expressed through > the reachable surface; two test-observation items honestly > `#[cfg(test)]`-gated (`subscriber_count`, the > `DEFAULT_WATCHER_POLL_INTERVAL` re-export); no allows re-added — > clippy `-D warnings` green without them. > > Contract-suite adoption: eight new rows in > `alkstore-contract-suite/src/properties.rs` (extent-clamp + > boundary-totality, duration-refusal, payload round-trip, > `PayloadTooLarge`-never-produced SQLite arm, drop=rollback > no-ghosts, in-tx read-your-own-writes, enqueue-opts resolution, > receiver close/save arms) — all version-stamped, all re-exported > from the suite lib. `store::SqliteFactory` implemented in the > engine's new integration test target > (`alkstore-sqlite/tests/contract_suite.rs`), running all nine rows > (the exemplar + the eight) against the SQLite factory — 10 tests, > green; the factory's isolation/idempotence contract pinned > alongside. Found and fixed suite-side: the exemplar row's > hold-the-tx-across-`with_tx` sequencing deadlocked any real > single-writer factory (the mock never saw it). > > Engine crate lib docs: the posture statements surfaced under a > `# Posture` heading — single-host (ADR-016) and writer-parking > (ADR-007's negative consequence) spelled as the crate's identity > statements. > > Verified: workspace `cargo build`/`cargo test` green (25 + 186 + > 10 + 3 + harness), clippy `--workspace --all-targets -D warnings` > clean, `cargo fmt --check` clean; engine-crate coverage 93.59% > lines (cargo-llvm-cov), misses confined to error arms and > Windows-only watcher variants.