--- id: review-wave-6 name: Wave 6 review gate — the fleet gate status: completed depends_on: [suite-column-fleet] scope: narrow risk: low impact: phase level: review tags: [wave-6, review] --- ## Description The wave-6 review gate — **the fleet gate** (docs/plans/implementation.md §Review gates: "exact-count sweep outcomes under concurrency vs live postgres, the joint entry+pin tx atomicity, the sweep lease semantics vs ADR-013 §2, the composite fleet-validity predicate enforced at the constructor, kv-only put-time rejection"), before wave 7 decomposes. The gate reads the implementation against the pinned ADR text line by line (the wave-1..5 gates' method) — the documents, not memory. Gate checks: - **Exact-count fleet sweep outcomes under concurrency vs live postgres**: the fleet column green against the harness server (server-less runs skip cleanly — a skip never substitutes for acceptance); the two-instance survival shape, the lease-contention abort, the cross-instance arbitration refusal, the race across the window delay, and the maintenance-step reaping all exact-count asserted (INV-4's engine-gated fleet form). - **The joint entry+pin tx atomicity**: through the public `put` (not only engine-level) — an independent connection never observes an entry without its pin row or the reverse; the A1 drop discipline audited as implemented (every path from `begin_joint_tx` onward terminates the tx — the wave-4 gate's amendment closed, its owner discharged); the pg-lo consolidation one-tx form (LO writes + companion row + pin row + commit in one tx; zero residue on failure); the large=local pin-first/publish-second ordering (the reverse ordering nowhere coded). - **The sweep lease semantics vs ADR-013 §2**: one sweeper per pool across instances; atomic test-and-set; holdership ends at release/owner death/session loss; contention is the `GcAbortCause::SweeperLock` report abort (`Ok(SweepReport)`, nothing deleted — ADR-012 §1), never an error. - **The composite fleet-validity predicate enforced at the constructor**: every fleet-valid configuration constructs; every non-fleet-valid configuration is a constructor error (kv ≠ postgres, `mem` anywhere, `local` without the shared-media declaration, pg-lo cross-instance); the declaration is explicit, never inferred (ADR-012 §3); the same-instance probe's design audited (a failed probe errors closed). - **kv-only put-time rejection** under the re-routing posture (ADR-012 §6.2's machinery, fleet edition). - **The TTL/3 renewal on the guard**: the renewal lifecycle audited (no leaked tasks; drop/conversion/batch-contribution stops renewal; a failed renewal never resurrects an expired row — ADR-012 §2's expiry semantics verbatim); the TTL is a fleet constructor parameter (default 60 s), never API. - **The fleet liveness verb vs ADR-012 §6.6 / ADR-008 §2**: the named table reference form; the schema-ownership rule (the store reads the embedder's table, never owns it); the protect callback's single-node-only posture recorded; the two-domain arbitration composition (in-process + SQL) decided and recorded. - **The one-window-host rule under fleet**: every fleet-valid configuration's window hosts on the kv engine; the pg-lo window clauses dormant; the form branch keys off the engine representation, never a flag. - **The non-fleet postures unchanged**: the in-process protocol verbatim under `fleet: false` regardless of engine — the wave-2/3/4/5 suites green untouched. - **Code-smell / hygiene sweep** (the gate's standing hygiene block — the twice-bitten lesson is now an explicit check, not a hope): - **`cargo doc --no-deps` zero warnings** — the PGLO-1 class (public-module doc links resolving to crate-internal items) has bitten waves 4 and 5; the gate runs rustdoc and asserts clean, and de-links rather than exports. - **The `#![allow(dead_code)]` scope notes match their remaining scope** — the fleet family's note in `src/gc.rs` (its consumers land this wave) must shrink to its true remainder or vanish; the postgres/pg-lo notes likewise audited. - **Stale forward references updated** — every "wave 6" note in the module docs (`store.rs`'s fleet-declaration paragraph, the constructors' "slots in without reshaping" recordings, `pg_lo.rs`'s scope boundary, `postgres.rs`'s scope note, the batch-delete helper's consumer note) reads the landed state. - **Family conventions**: no inline comments in code (doc comments on public API fine), thiserror, tokio-only async, no `unwrap`/`expect` outside tests, naming, one-module-per-file re-export shape, no blocking I/O on the async path. - **Task-description correctness**: each wave-6 task's Summary matches what actually landed (the gate reads the diffs against the task texts, not the Notes' claims alone). - **Gates green**: `cargo test` (default), `cargo test --features postgres` (server-less: skipping), `cargo test --features "postgres,pg-lo"`, `cargo test --all-features` (against the server), the pure builds (`cargo check --no-default-features --features postgres` and `--features "postgres,pg-lo"`), `cargo clippy --all-targets -- -D warnings` (default + the postgres/pg-lo variants + `--all-features`), `cargo fmt --check`, `cargo doc --no-deps`. Findings are fixed inline where cheap, or recorded as wave-7 amendments where they shape the next decomposition (the ops wave's pin-token contract rides the fleet machinery — a renewal-surface finding lands beside it). The gate's completion is what unblocks wave 7's decomposition. ## Acceptance Criteria - [x] Every gate check above read and verified against the cited ADR text (not from memory of it) - [x] Named design points each decided, recorded, and consistent with the specs - [x] Findings fixed inline or recorded as wave-7 amendments with owners - [x] All gates re-run green after any fixes — including `cargo doc --no-deps` explicitly (the PGLO-1 class) - [x] Wave 7 decomposition unblocked (recorded in this task's Summary) ## References - docs/plans/implementation.md (§Wave 6, §Review gates — the fleet gate) - docs/architecture/decisions/008-trait-size-probe-fleet-gc-and-large-engines.md §2/§3 - docs/architecture/decisions/010-backend-io-seams-and-fleet-state-home.md §2/§4 - docs/architecture/decisions/012-pre-decomposition-consistency-rulings.md §1–§6 - docs/architecture/decisions/013-family-composition-reactive-boundary-and-feature-graph.md §2 - docs/architecture/store-api.md (§Invariants 4 — the fleet form) - docs/architecture/backends-and-dispatch.md (the composite fleet-validity rule) - tasks/review-wave-4.md, tasks/review-wave-5.md (the gate method; the amendments A1/A2 this gate audits closed) - tasks/store-fleet-construction.md, tasks/store-fleet-put.md, tasks/store-fleet-sweep.md, tasks/engine-pg-lo-joint.md, tasks/suite-column-fleet.md (the wave's tasks) ## Notes > Gate completed 2026-10-12, the wave-1..5 method: every gate check read > against the pinned text (ADR-008 §2/§3, ADR-010 §2, ADR-012 §1–§6, > ADR-013 §2, store-api.md §Invariants 4's engine-gated fleet form, > backends-and-dispatch.md's composite fleet-validity rule, and the > engine-state seam trait in src/gc.rs), then verified against the > landed diffs (b6b3532 → 53b85dd; the operator's hash log matched > `git log` exactly) and re-run gates. The task hashes were confirmed: > store-fleet-construction b6b3532, engine-pg-lo-joint 76be7b0, > store-fleet-put 950af9a, store-fleet-sweep 3a51bb4, > suite-column-fleet 53b85dd. > > **Gate checks, each verdict:** > > - **Exact-count fleet sweep outcomes vs live postgres** — conformant. > The fleet column green against the harness server (pglo-poc, :15432; > a skip never substituted — the suite ran live): the two-instance > exact-count shape (b marks all three, stages exactly 3, deletes > exactly the two unpinned twins, cancels exactly the pinned entry > via A's un-expired row; the byte-identical survivor read back from > the other instance), the lease-contention abort as report data with > nothing staged/deleted, the cross-instance arbitration refusal > until expiry, the race across the window delay, the maintenance > step's exact reap, the embedder-table liveness row with the > schema-ownership rule, and the kv-only re-routing row — every row > ADR-stamped; 16 stamps counted in the column file. > - **Joint entry+pin tx atomicity** — conformant through the public > `put` (the both-or-neither row asserts over an independent > connection), with two A1 termination-path findings fixed inline > (below). The pg-lo consolidation one-tx form verified > structurally (`put_joint_staged` borrows the held `PgJointTx` > checkout it never owns; no Drop, no COMMIT/ROLLBACK on any path — > transactional LO creation makes the pages die with the driver's > termination) and live (the byte-exact consolidation round-trip > row). The `large = local` ordering is pin-first/publish-second in > code (`fleet_staged_commit`: row-only joint tx, then > commit-rename), with the reverse ordering nowhere coded. > - **Sweep lease vs ADR-013 §2** — conformant: atomic test-and-set > (`pg_try_advisory_lock`, session-scoped), one sweeper per pool > across instances (the in-process flag composes — both domains, > either domain's contention aborting as `SweeperLock` report data > with nothing deleted), holdership ends at release / owner death / > session loss (in-instance reaping of dead checkouts — the wave-4 > PG-1 fix present), and the pool-sizing composition enforced at > every `_fleet` constructor's entry (`max_size >= 2`). > - **Composite fleet-validity predicate at the constructor** — > conformant: the one-sentence predicate as code (`fleet_validity_error` > over engine-representation-derived shapes, never a flag), the > structural clauses enforced by the constructor set's shape with > the predicate's rejection arms unit-tested per clause, the pg-lo > same-instance probe design recorded and implemented > (`pg_control_system().system_identifier` compared across one > connection per engine; a mismatch **or any probe failure** errors > closed), the declaration explicit and never inferred (a sealed > `FleetSharedMedia` named type plus the `_fleet` twin constructors; > the pre-existing constructors byte-unchanged, implicitly > `fleet: false`), the TTL a fleet constructor parameter (zero > rejected at entry before any I/O). > - **kv-only put-time rejection** — conformant: ADR-012 §6.2's > machinery unchanged under fleet (known-length rejects at entry, > unknown-length at mid-stream threshold overflow; the fleet column's > re-routing row green). > - **The TTL/3 renewal on the guard** — conformant: per-guard tokio > task on the TTL/3 cadence (the 1 ms floor named), spawned at the > row's durability, aborted at every guard-life boundary (drop, > `Batch::add` moving the duty into the batch, the ordered-step > conversion's pre-stop), silent on `Err`, ended by the never- > resurrect `Ok(false)` (`pin_renew`'s `expiry > now` predicate — > live-tested); no leaked tasks; the TTL never API. > - **Fleet liveness verb vs ADR-012 §6.6 / ADR-008 §2** — conformant: > the same verb with the fleet-shaped `LivenessRegistration` argument > (the named table reference form; the verb fallible with the > error surface decided and recorded; in-process sources > allow-and-document — instance-local protection); the > schema-ownership rule holds (the engine is handed a reference, > never creates the table — live-asserted); the protect callback's > single-node-only posture recorded in the verb docs; the two-domain > arbitration composition decided and recorded (in-process first, > SQL second, implemented once at `arbitrated_delete`, shared by the > direct path and window execution). > - **One-window-host rule under fleet** — conformant: every > fleet-valid configuration ensures both GC tables on the kv host; > the pg-lo window clauses dormant (no `gc_window` in the pg-lo > schema — constructor-tested); the form branch keys off the engine > representation (the `sweep_window` match), never a flag. > - **Non-fleet postures unchanged** — conformant: the in-process > protocol verbatim under `fleet: false`; the wave-2/3/4/5 suites > green untouched alongside the fleet additions. > - **Hygiene sweep** — findings fixed inline (below); `cargo doc > --no-deps` zero warnings (the new allow-scope notes initially > linked private items — PGLO-1's shape — and were de-linked); the > `#![allow(dead_code)]` scope notes audited against a measured > remainder (allow-stripped `cargo check` across the default, > postgres, sqlite-only, mem, postgres+pg-lo, and all-features > shapes) and corrected where stale. > - **Task-description correctness** — the diffs read against the five > task texts; the Summaries match what landed, with the one finding > (the A1 coverage gap, below) fixed inline rather than amending the > task texts. > > **Findings fixed inline:** > > - **W6-1 — two A1 termination paths were uncovered (fixed).** A1's > discipline (catch-propagate-terminate: every path from > `begin_joint_tx` onward terminates the held tx before > propagating) was not complete: `fleet_put_kv`'s pin-row expiry > mint propagated with `?` between `begin_joint_tx` and `pin_commit` > without terminating (the exact PG-2 dirty-session hazard A1 > exists for), and `fleet_joint_publish` — invoked with an already- > begun tx — propagated on its host-None and row-mint paths without > termination. Fixed: the kv driver terminates the tx on the > row-mint error; the pg-lo drivers resolve the pin row inside > their caught drives and hand the precomputed host + row to > `fleet_joint_publish`, whose only fallible step left is the > terminal `pin_commit` (clause-owned rollback). The A1 design-point > doc records the row-mint path; `fleet_joint_publish`'s doc > ordering corrected (the code mints the in-process refcount after > `pin_commit` — the row is the publish-time protection, the > refcount the instance-local bookkeeping; the invariant is row- > carried, so the ordering is safe as written). > - **W6-2 — the pg-pure test builds failed `clippy --all-targets`** > (fixed). `--no-default-features --features postgres[,pg-lo]` with > tests: the wave-6 test instruments' `_ => panic!` match arms went > unreachable-pattern (single-variant KvEngine) and a let-else was > irrefutable — a wave-6 regression invisible to the gate lists > (those run only `cargo check` for the pure builds, and the clippy > variants that are listed are default/postgres/all-features, which > passed). Fixed: the test helpers ride `Store::fleet_host()`'s > expect instead of matching the engine enum (in-crate private > access, cfg-exact). All seven clippy feature variants now green, > the four pure shapes among them. > - **W6-3 — stale/missing allow(dead_code) scope notes** (fixed). > store.rs's module-doc paragraph still said the fleet sweep was > "not yet driven" (landed 3a51bb4) — rewritten to the landed state > plus the allow's true remainder; local.rs's note still pointed at > wave 3 ("until wave 3's facade constructors... name them") — > corrected to its true remainder (the cfg(test) commit-failure > injection knob behind feature `mem`; an allow-stripped check > confirmed the lib bodies live); sqlite.rs's note misclaimed the > remainder (its real residue is the test-instrument nanos decode) > — corrected; backend.rs's "the reporting and fleet waves consume" > forward reference → the landed reading (`Backend::name`, > test-consumed today); gc.rs's note sharpened to name the true > remainder (`pin_check` deliberately unconsumed — wave 7's ops > renewal probe; `convert`/`pin_count` test-consumed today); the > postgres.rs and pg_lo.rs notes gained their missing allow-scope > sentences (the batch-delete helper, `system_identifier`, > `reap_orphans`, the feature-subset shapes). No allow was removed: > every file still carries real dead scope. > - **W6-4 — harness schema residue from a stale parallel run** (not a > code finding). Three `alkblobs_fleet_*` schemas belonged to > earlier battery pids (their teardown raced a parallel run), not to > the suite as landed: a fresh full conformance run left zero new > schemas (A2's janitor discipline holds); the stale three were > dropped manually — residue 0. > > **Verification (post-fixes; tests live against pglo-poc :15432 unless > noted):** `cargo test` 73/19/3 ok (default); `cargo test --features > postgres` 131/52/3 ok; `cargo test --features postgres,pg-lo` > 167/73/3 ok; `cargo test --all-features` 226/125/4 ok; pg-pure > test-builds green (`--no-default-features --features postgres` / > `postgres,pg-lo`; the suite skips cleanly server-less); > `cargo check --no-default-features --features postgres` and > `--features postgres,pg-lo` green (the pure builds); clippy > `--all-targets -D warnings` green on all seven feature variants > (default, mem, postgres, postgres+pg-lo(+mem), all-features, and the > pg-pure builds); `cargo fmt --check` green; `cargo doc --no-deps` > zero warnings (the gated doc build's pre-existing count 32 → 31 — > nothing added; verified against the wave-5 base 93f9a93's > identical-pre-existing class); shared-db schema residue 0. ## Summary > Completed 2026-10-12 (wave 6). The fleet gate read the landed > wave-6 implementation against the pinned ADR text line by line and > found it conformant on every check: the exact-count fleet sweep > outcomes green against live postgres (two-instance survival with > exact counts, lease contention as report data, cross-instance > arbitration, the race across the delay, the exact-set reap, the > embedder-table liveness verb with its schema-ownership rule, the > kv-only re-routing row), the joint entry+pin tx atomicity through > the public put (both-or-neither over an independent connection; the > pg-lo consolidation one-tx form; the local pin-first ordering), the > sweep lease's ADR-013 §2 semantics with the pool-sizing guard, the > composite fleet-validity predicate enforced at the constructor with > the errors-closed same-instance probe, kv-only put-time rejection, > the TTL/3 renewal lifecycle on the guard, the fleet liveness verb's > named-table form, the one-window-host rule, and the non-fleet > postures byte-unchanged. Four findings fixed inline: two uncovered > A1 termination paths (the pin-row expiry mint's `?` in the kv > driver; `fleet_joint_publish`'s host/row propagation now resolved > pre- or terminal), a wave-6 pg-pure test-build clippy regression > (unreachable patterns — helpers now ride `fleet_host()`), and the > stale/missing allow-scope notes (five files' notes corrected against > a measured remainder; a stale "fleet sweep not yet driven" paragraph > rewritten to landed state). All gates re-run green after the fixes — > test suites live, the seven clippy variants, fmt, and > `cargo doc --no-deps` zero warnings. The operator's task-hash log > matched `git log`. Wave 7 (the ops surface) decomposition is > unblocked; its review gate is the ops-vs-alkcall conformance shape.