Six tasks against the wave-2 contract surface as reviewed (no
amendments from the gate):
- engine-sqlite: the default kv engine — WAL + synchronous=NORMAL,
prepared statements, the indexed size column probe (B5's row shape),
has-as-EXISTS, virgin-store no-tables-yet tolerance, spawn_blocking
discipline
- engine-sqlite-window: the engine-state seam's window family only
(ADR-012 §5's reduction — gc_window, stage/take; no pin rows, no
sweep-lock body)
- store-sqlite-construction: KvEngine::Sqlite slots in, the
dual-tier/kv-only constructors with the constructor-tunable window
delay (default 5 min), ensure_gc_schema at construction, the
one-window-host posture
- store-sweep-durable-window: the sweep's SQL-backed form — overdue
rows execute with re-arbitration before/alongside marking, candidates
stage at mark_end + window, counts exact relative to the schedule
(ADR-012 §6.7); the inline form preserved verbatim
- suite-column-sqlite: the first SQL-backed column, server-less —
form-independent reference rows mirror directly; the sweep rows are
schedule-relative (the recorded INV-4/5 mirror amendment)
- review-wave-3: the engine-wave gate (engine-vs-contract conformance)
Verification: dependency graph validated (all ids resolve, no cycles,
topological order clean); docs-only change.
Refs: docs/plans/implementation.md §Wave 3
Read the wave-2 implementation against the pinned ADR text line by
line (ADR-003/005/006/010/011/012/013 §2, store-api.md): the three
numbered unknown-length rules each test-backed, the delete-window
ordering invariants (arbitrate-at-delete-time, pin-before-publish on
both put paths and both tiers, raced conversion ordering,
delete-then-recover), abort-as-data with all three causes, dispatch
purity + fall-through + constructor modes + kv-only's two put-time
rejection points, stage-hygiene exact counts on both engines (incl.
the Drop-cancellation story), both suite columns green/ADR-stamped/
traceable with the factory binding recorded, the dispatch-coverage
shape exercised, all eight named design points recorded and
consistent, and the staged-put key-at-commit amendment audited
accepted. No wave-3 amendments arise.
Inline fixes applied by the gate:
- facade.rs: stale Batch::add dead-code allow + stale task-pointer
comment removed (put_in_batch's call sites landed)
- dispatch.rs: module-level allow(dead_code) removed (route/Tier now
driven; clippy clean without it), scope note updated
- backend.rs: the allow kept but its scope note corrected to what is
actually dead (trait name, kv put until wave 3)
- mem.rs: stale constructor doc line updated to the landed state
- tasks/gc-protocol.md: stray placeholder lines removed
Verification: cargo test (42 lib + 2 conformance + 3 git-interop),
cargo test --features mem and --all-features (97 lib + 37 conformance
+ 4 git-interop), clippy --all-targets and --all-features --all-targets
(-D warnings), fmt --check — all green post-fix. Wave 3 decomposition
unblocked.
- tests/conformance/local_column.rs: the first dual-tier column, run
against the kv = mem + large = local factory (ADR-012 §6.3) — fresh
temp-root store per open, per-instance tracked roots, idempotent
teardown safe against abandoned/panicking rows (structural tests
included); never skips (mem-gated — the dual-tier constructor rides
feature mem until wave 3 provides an ungated kv engine)
- the reference INV row set (rows.rs) mirrored against the dual-tier
factory at a column-declared tuned threshold (1024), so the shared
matrix and race fixtures exercise both tiers' bodies (INV-7)
- dispatch rows grown: pure-function routing across put paths and
re-puts with an on-disk placement oracle (tier residency is
facade-invisible; with kv = mem the medium is the oracle), threshold
boundary legs at the tuned and shipped-default thresholds with the
constructor-tuned re-route leg, and fall-through per op with
both-tier miss shapes (ADR-003/ADR-012 §6.1/§6.3/§6.5)
- local-specific rows: on-disk stage-hygiene exact counts over both
put paths (the real stage form, INV-3), pread windows over committed
files with slice digests verified independently (ADR-006/ADR-010),
virgin-store no-ops on a fresh root, and exact sweep counts over a
both-tiers pool (INV-4/INV-5's both-tiers form)
- rows.rs shared fixtures made pub(crate); README records the column's
row inventory (§Columns beyond the reference set), the declared-
threshold posture, and the new current state
- stat-as-stat rides the mirrored INV-6 row's over-threshold legs;
the Drop-cancellation hygiene form stays per-engine (recorded)
Verification: cargo test (default) green; cargo test --features mem
green (97 lib + 37 conformance + 4 git-interop); cargo test
--all-features green; clippy --all-targets -D warnings green in both
feature shapes (default + all-features); cargo fmt --check green;
cargo doc --no-deps shows only the pre-existing warning class
- rows.rs: the reference row set (INV-1…6 + two constructor-mode rows),
factory-generic and engine-uniform, every row ADR-stamped and traced
to the backlog: round-trips over the content matrix on both put
paths, dedup (same/cross-path), stage hygiene (both paths, both
injectable failure modes, kv-degenerate residue via sweep outcomes),
sweep safety (full-protection-set happy shape, all three
GcAbortCause abort shapes incl. the single-flight SweeperLock lease,
the sweep-vs-pinned-put race), list correctness through exact sweep
outcomes only, stat discipline, mem-only posture, and kv-only
put-time rejection (threshold discovered by free probes; immediate/
mid-stream rejections and at-threshold-lands legs)
- mem_column.rs: the column's factories — mem-only (reference host)
and kv-only(mem) at a declared threshold — fresh isolated opens,
no-op idempotent teardown; structural factory-contract tests cover
isolation and teardown against a panicking row
- README: the reference row set recorded (INV-7's basis — what other
columns mirror), the row-lifecycle convention, column plan and
current state updated
- task suite-column-mem: status completed, notes and summary filled
Verification: cargo test --features mem (97 lib + 18 conformance +
4 git-interop), cargo test (default), cargo test --all-features,
clippy --all-features --all-targets -D warnings, fmt --check, and
cargo doc --no-deps — all green
- `put(len: Option<u64>, stream: impl AsyncRead + Unpin + Send) -> (Key, Pin)`:
known-length one-pass flow; unknown-length buffer-to-threshold flow with
the mid-stream fresh-stage flush (ADR-003 option (d), three numbered rules:
flush-and-continue, derivation over the eventual stored artifact as a
whole via buffer form and StagingCursor read-back form, zero residue on
stream error)
- staged-put seam amended (operator sign-off): `put_staged()` keyless
handout, `StagingCursor::commit(self, key)` publishes under the
store-core-resolved key — the canonical key completes at stream end and
the wave-1 handout shape could not express the commit-rename flow
- pin-before-publish rides the arbitration lock on both paths and both
tiers; dedup re-puts refcount the existing entry
- Batch seam: `Store::batch()` + `put_in_batch()`, members publish pin-
before-publish, group pins drop together on `Batch::commit` (new public
verb) or drop
- kv-only rejection (ADR-012 §6.2): known-length over-threshold rejects
immediately (stream never read), unknown-length at mid-stream overflow;
zero residue; error carrier `Io(String)` (named design point)
- declared-len mismatch rejects `Verification` zero-residue (named design
point); stream shape generic-no-dyn (named design point)
- incremental BlobHasher (pinned byte-equal to Algorithm::derive);
AnyStaging cursor dispatch; git-interop put-path leg against
git hash-object; eleven put-path behavior tests
Verification: cargo test (default/--features mem/--all-features) green;
clippy --all-targets -D warnings green in all three feature shapes;
cargo fmt --check green; cargo doc --no-deps at the 24-warning baseline.
The gc-protocol task (ADR-005; abort-as-data per ADR-012 §1; non-SQL
inline window staging per ADR-012 §5) wired on the Store facade:
- src/gc.rs — GcHome + RegistryCore: one arbitration lock over per-key
pin refcounts, in-flight delete markers, and the registered source
lists; async pin minting (acquire) that blocks on in-flight deletes
(ADR-005's re-put case (a) delete-then-recover without engine I/O
under the lock); the ordered-step convert primitive (pin release +
registration in one section); batch one-step release; the
single-node sweep lease (the in-process analog of ADR-013 §2).
- src/facade.rs — Pin/Batch carry the registry back-reference and own
their drop release (batch drop decrements every member in one
ordered step); new public vocabulary LivenessSource, ProtectCallback,
Registration, re-exported from lib.rs.
- src/store.rs — sweep() (single-flight → zero-source safe default →
protect consult → mark over both tiers' list() union → arbitrate at
delete time → ~100/batch commit → exact-count report or
abort-as-data), direct delete() (existence probe → full protection
set per ADR-012 §6.4 → GcRefuse/Missing/delete through the
fall-through), and the registration/unregistration verbs.
- 16 new tests + the facade pin/batch shape test reworked on the wired
machinery: exact counts across both tiers, abort shapes, dedup
refcounts, batch drops, live-shared sources, the conversion ordered
step sequentially and raced, sweep-vs-pinned-put (64 rounds, every
schedule, byte-identical delete-then-recover), publish-after-mark,
no-torn reads under a window, single-flight contention, and
malformed-list sweeps as operational errors.
- tasks/gc-protocol.md — status completed; named design points recorded
in Notes.
Verification: cargo test (default) 46 passed; --features mem and
--all-features 89 passed each; cargo clippy --all-targets -- -D
warnings (default and --all-features) clean; cargo fmt --check clean;
cargo doc --no-deps at the pre-existing baseline (no new warnings).
- Public `(len, stream)` shape: `Store::get` returns
`Option<(u64, Blob)>`; `Blob` (src/facade.rs) is a bounded, re-entrant
windowed reader over the new crate-internal `AnyCursor` tier dispatch
(mem materializing / local pread body families) — engine cursors
never leak onto the surface; no chunk-iterator machinery.
- Verification-on-get pinned against ADR-006: kv-tier materialized
reads whole-blob hash-check at get time (mismatch = Err(Verification),
never a further fall-through); the large tier's streaming open is
metadata + handle only (put-path verification + slice digests are its
story); `read_range` carries slice digests only, on both tiers.
- `stat` rides the trait's `size` probe (never a content load) into
`EntryMeta { len, algorithm }`; `has` is the pure existence probe;
both fall through kv -> large like every key-addressed op (ADR-012
§6.1) — consult order, not routing (never consults `tier_for`).
- Miss shapes enforced (the error module's behavioral note): both-tier
misses are Ok(None) on get/stat, false on has, Err(Missing) on
read_range; `src/error.rs` wave-2 deferral notes updated to enforced
state.
- `list` decided Vec<Key>: materialized, sorted total-order union of
both tiers (the sweep consumes the engines' enumeration directly);
malformed pool bytes are fatal `Err(KeyInvalid)`, never a silent
skip.
- `KeyInvalid` at the facade boundary: ops take opaque key bytes and
convert via `Key::from_bytes` once (`boundary_key`); engines never
see typed keys.
- Twelve read-path tests: virgin-store shapes per mode (dual-tier,
mem-only, kv-only), the `(len, stream)` windows, fall-through,
kv-first (decoy content in the large tier), both verification
postures, list union/sort/pool-fatality, and malformed-key
rejection on every op.
Task: tasks/store-read-paths.md (design points recorded in Notes for
the wave-2 review gate).
Verification: cargo test (default), cargo test --features mem, cargo
test --all-features green; cargo clippy --all-targets -- -D warnings
green in all three feature shapes; cargo fmt --check green; cargo doc
--no-deps clean beyond the pre-existing private-intra-doc-links class.
The wave-2 facade skeleton and routing (tasks/store-construction.md):
the public surface consumers program against, with the ops methods
still to land against it in store-read-paths/gc-protocol/store-put-paths.
- src/store.rs — the public `Store` type (engine-blind, ADR-007/008/
010) over crate-internal tier enums (`KvEngine`{mem}, `LargeEngine`{
local}): the engine-representation design point decided as concrete
+ enum dispatch, generic rejected (pub(crate) engines, no dyn);
the three constructor modes as named constructors — `mem_only`,
`kv_only_mem`, `dual_tier_mem_local` (the ADR-012 §6.3
dispatch-coverage shape) — with `StoreMode` introspection; the
write-side routing seam (`tier_for`), the read-side fall-through
order (`kv()` then `large()`, ADR-012 §6.1), and the `GcHome`
GC-state field; the ADR-012 §3 fleet declaration ruled deferred to
the engine waves (nothing fleet-valid is constructible yet)
- src/dispatch.rs — the pure routing function (`route`, at-or-below
→ kv), `DEFAULT_DISPATCH_THRESHOLD` (128 KiB) exported at the
crate root, boundary-value unit tests (exactly-at-threshold,
degenerate tunings, purity)
- src/gc.rs — `GcHome`: the store-instance GC-state home the
gc-protocol task fills (in-process; fleet state stays on the
engine-state seam per ADR-010 §2/ADR-012 §4)
- tests/conformance — the wave-2 binding made as anticipated: the
factory's `Store` associated type collapsed into the concrete
`alkblobs::Store` (`open` vends it directly), recorded in
factory.rs + README; the wave-1 mock probe retired, replaced by
mem-gated binding demo factories (binding.rs) over both
constructible shapes
Verification: `cargo test` (default), `cargo test --features mem`,
`cargo test --all-features` green (41/53/53 unit + conformance
targets green in all three shapes); `cargo clippy --all-targets
-- -D warnings` green in all three feature shapes; `cargo fmt
--check` green; `cargo doc --no-deps` adds no warnings beyond the
pre-existing private-intra-doc-links class.
- LocalBackend: flat {hex-prefix}/{hex-prefix}/{hex} sharding over
lowercase-hex-of-Key::as_bytes filenames (self-describing; the
list-decode round-trip recorded for the review gate); virgin-store
reads are no-ops
- staged put: unique stage files under {root}/staging/, commit-rename
is the publish, CAS first-writer-wins, every failure path (discard,
failed commit, Drop cancellation) converges on zero residue
- read cursor: pread loop over the immutable committed file, EOF
clamping, provided read_range composing the slice-digest convention
- all file I/O in spawn_blocking; size is a stat, never a content load
- list walks the committed tree and is fatal (Error::Io, path named)
on anything that does not decode — complete and well-formed
- 11 in-module unit tests incl. exact-count stage hygiene over all
failure forms and the success form
Verification: cargo test (44 green), clippy --all-targets/--all-features
-D warnings, fmt --check — all clean
Task: tasks/engine-local.md
- src/mem.rs: MemBackend implements Backend (seven methods + put_staged,
name "mem") over Arc<parking_lot::Mutex<BTreeMap<..>>>; CAS
first-writer-wins puts, materializing MemCursor body, degenerate
in-memory MemStaging whose commit publishes via the same CAS clause
and self-discards on failure; discard leaves zero residue.
- CAS re-put is dedup for both put forms; reads are no-ops on the
virgin store; delete carries Missing; size is metadata-only.
- Eight in-module tests mirror the wave-1 double's assertions: method
contract, list well-formedness, cursor body read contract + ADR-006
range digest, empty-entry round-trip, staged happy path, and both
hygiene forms (fail_commit test hook stands in for media failure).
- backend.rs: clamped promoted pub(crate) — the shared EOF-clamping
arithmetic both mem cursor bodies compose (no per-engine duplicate).
Verification: cargo test --features mem (33+7 green); cargo test
(default) green; clippy --all-features --all-targets -D warnings green;
fmt --check green.
Nine tasks against the wave-1 contract surface as reviewed (no
amendments from the gate):
- engine-mem / engine-local (parallel, dependency-free): the two
engines; local owns the stage-hygiene exact-count tests and the
Drop-cancellation story the wave-1 review recorded
- store-construction: the Store type, constructor modes, size-threshold
dispatch; binds the conformance factory's Store associated type
- store-read-paths ∥ gc-protocol: read ops with the ADR-012 §6.1
fall-through rule; the ADR-005 in-process protocol (pins, liveness,
delete windows, abort-as-data, GcRefuse with the full protection set)
- store-put-paths: the two put paths behind one signature, ADR-003's
three numbered rules, pin-before-publish, Batch, kv-only rejection
- suite-column-mem → suite-column-local: the reference column, then the
dual-tier dispatch-coverage shape mirroring it
- review-wave-2: the gate (facade/dispatch/GC vs ADR-003/005/012)
Verification: dependency graph validated (all ids resolve, no cycles,
topological order clean); docs-only change.
Refs: docs/plans/implementation.md §Wave 2
Every gate check read against the cited ADR text: the key encoding
holds byte-exact against ADR-002 (tags, lengths, rejects, sort order,
preamble abstraction, live git-CLI interop, lowercase oid policy
recorded); the trait + I/O seams + engine-state seam match ADR-003/
010 and ADR-012 §5's reduced table; the error model's five variants
and single-enum altitude reading match store-api.md/ADR-012 §6.5; the
feature graph matches ADR-013 §4; all named design points audited
consistent; the suite convention and backlog are traceable; family
conventions clean. One inline fix: publish keyword `bao` -> `git`
(excluded technology named in metadata). Wave 2 decomposition
unblocked, no amendments.
Verified: cargo test (26 lib + 4 conformance + 3 git-interop passed),
cargo clippy --all-targets -- -D warnings, cargo clippy --all-features
--all-targets -- -D warnings, cargo fmt --check, cargo check
--all-features, cargo check --no-default-features --features pg-lo.
- tests/conformance/README.md: the convention doc — row naming (property-
stated names, engine dimension is the column), the Contract stamp:
format (the alkstore ADR-017 §4.2 convention adapted), the one-
normative-owner-per-property rule, the factory contract (fresh
isolated instance per open, idempotent teardown, safe over an
abandoned instance), the SKIP posture (SQL-attached columns skip
cleanly server-less; acceptance requires green against the server),
the invariant backlog (the seven store-api.md §Invariants registered
as the rows-to-grow table with pinning citations), and the mem-first
column plan (mem is the contract-reference engine, ADR-011 §2)
- harness skeleton, compile-able with zero rows: StoreFactory (fresh
+ isolated + idempotent-teardown contract; the Store associated type
is wave 2's binding point for the facade type), stamp.rs (the
marker + convention anchor), backlog.rs (in-code registry with a
traceability gate asserting INV-1..7 mirror §Invariants in order)
- no engine-specific code; no dependencies added
Verification: cargo test (33 passed across lib + 3 targets),
cargo clippy --all-targets -- -D warnings, cargo fmt --check
The wave-1 contract surface: everything engine-blind that waves 2-6
implement against. No engine bodies, no facade behavior logic.
- src/backend.rs: the pub(crate) Backend trait — seven methods +
put_staged, opaque byte keys/values, size metadata-only, list
complete-and-well-formed, virgin-store reads as no-ops (ADR-003,
ADR-008); the ReadCursor/StagingCursor I/O seams with the read_range
slice-digest convention (ADR-006) at one seam; unit tests against
both body-family doubles, a test-double engine, and the stage-hygiene
invariant's two forms (discard; commit failure self-discards).
- src/gc.rs: the engine-state companion seam as EngineWindowState /
EngineFleetState — ADR-012 §5's applicability table expressed
structurally (no dead machinery); JointTx ownership rule pinned in
the signature (store holds the tx; engine contributes mechanics).
- src/facade.rs: EntryMeta, Pin, Batch, SweepReport, GcAbortCause
(x3, #[non_exhaustive]), PinState with lifecycle contracts
(ADR-005, ADR-012 §1); re-exported from lib.rs.
- Design points pinned for the wave-1 review gate in
tasks/core-trait-and-types.md: pub(crate) trait visibility,
associated-type put-form shapes, AFIT + associated types (no dyn).
Verification: cargo test (26 lib + 3 git-interop), cargo test
--all-features, clippy --all-targets -D warnings (default and
--all-features), cargo fmt --check, cargo doc --no-deps — all green.
Wave 1 task core-hashing-keys: the crate's declared one-way door,
implemented byte-exact to ADR-002.
- src/hashing.rs: Algorithm (exactly GitBlobSha256 canonical /
GitBlobSha1 tolerated; BLAKE3 absent), Digest (known-length
derivation H("blob <len>\0" + content) as primary constructor;
from_git_oid_hex interop constructor, lowercase-only acceptance),
and the hashing::registry constants (0x01/0x02, 0x00 reserved; new
algorithm = new ADR)
- src/keys.rs: typed Key wrapper; as_bytes/from_bytes are the only
backend-boundary conversions; 1 algorithm byte + digest bytes
(33/21 total); rejects-never-guesses validation -> Error::KeyInvalid
- tests/git_interop.rs: the load-bearing test — byte-exact derivation
against the `git hash-object` CLI, both algorithms, small and
75-KiB content; external-oid round-trip into pool keys; both oid
formats coexisting in one flat pool
- named design point (oid hex policy): lowercase-only acceptance,
recorded in the task Notes and on from_git_oid_hex
Verified: cargo test (15 passed), cargo clippy --all-targets -- -D
warnings, cargo fmt --check, cargo test --all-features — all green.
- docs/plans/implementation.md: the meta plan (alkstore pattern) — nine
waves, dependency logic, decided points, review gates. Scope authority:
v0.1.0 ships the full surface (all five engines, fleet GC, ops).
- Wave 1 decomposed: scaffold-crate-features, core-error-model,
core-hashing-keys, core-trait-and-types, suite-scaffold,
review-wave-1 (the one-way-door gate).
- Waves 2-9 shaped in the plan; each decomposes after the prior wave's
review gate.
Verification: cargo test / clippy -D warnings / fmt --check green
(docs-only change).
- OQ-09 resolved closed-by-default (deny-unlisted), decided on risk
asymmetry in hand, not on a first deployment the crate itself must
create; named reopen condition instead of a parked wait
- delete oq-09-ops-visibility-tracker.md (watch-task for an event the
crate itself gates — never collapses)
- fix doc-lifecycle circularity: externally-owned OQs no longer block
a spec's `reviewed` promotion
- gc-and-namespaces: "until a consumer names a requirement" reframed
as re-entry via a new ADR, not a parked question
- README: state the corollary explicitly — facts this crate must
create (its own first deployment/consumer) are never deciding inputs
Verified: full-text sweep for stale OQ-09 deferral/tracker references
comes up clean across docs/ and tasks/.