docs(architecture): ADR-013 — family composition, reactive boundary, sweep lease; OQ-11 resolved
- No sibling (alkstore) dependency in-core; reactivity is deployment-layer composition above the facade — cadence stays embedder-owned (ADR-005), with alkstore the named substrate for it; in-crate notify/scheduler/queues/invalidation hooks are non-goals. - Fleet sweeper lock pinned as 'named exclusive sweep lease' semantics; shipped provider unchanged (pg advisory clause); provider swaps are ADR-007-shaped substitution doors. - Composition contract for downstream ADRs: co-tenancy of CAS/GC state + reactive machinery + consumer/liveness tables on one fleet host; no-cross-store-atomicity ruled; compensation rests on idempotent re-puts, windowed deletes, sweeps-as-report-data. - OQ-11 resolved (the register's one live circular hedge): engine features pull their own driver clusters — sqlite becomes feature 'sqlite' (default-on, carries rusqlite); 'kv'/'large' tier features retired; 'local' ungated; pg-pure builds are supported, non-default. Deciding fact already in-tree (REQ-2/ADR-009). - requirements.md: UC-4/REQ-5 records the composition facts (operator record 2026-10-11, corroborated by alkstore's consumer-inventory). - Publish guard stated pre-code: facade ships before publish; semver-is-contract from first publish (alkstore ADR-017 discipline). - Amended accepted ADRs' feature wording (ADR-010 §1, ADR-011 §3/§4, ADR-003) with supersession notes; README/overview/open-questions/ backends/store-api/gc aligned; parked index now empty. Verification: docs-only round (no Rust surface touched); full-tree single-value check on the feature graph and sweep-lease wording.
This commit is contained in:
1 parent
7b9d904b8a
commit
bee86b0dbd
11 files changed
+431
-62
No files matched your search
@@ -1,6 +1,6 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-10-03 (ADR-012 — pre-decomposition consistency rulings: sweep-abort shape, token wire shape, fleet activation, GC-state host)
|
||||
last_updated: 2026-10-11 (ADR-013 — family composition: no sibling dependency in-core, sweep-lease semantics, co-tenancy/no-cross-store-atomicity rulings, OQ-11 resolved, feature graph re-pinned to engine features)
|
||||
---
|
||||
|
||||
# alkblobs — Architecture
|
||||
@@ -106,6 +106,25 @@ there — not inherited as hedges:
|
||||
repaired (pin/sweep-lock bodies dropped; window staging for
|
||||
non-SQL engines is in-process). The tree is now single-valued on
|
||||
every implementation-facing signature.
|
||||
- **ADR-013** (2026-10-11, the composition round): with the sibling
|
||||
substrate **alkstore** shipped (v0.1.0 — the reactive coordination
|
||||
crate the first consumers co-deploy), this ADR rules the
|
||||
composition so nothing waits on anything downstream or upstream:
|
||||
the core keeps **no alkstore dependency and no reactive machinery**
|
||||
(notify/scheduler/queues/invalidation hooks are non-goals — cadence
|
||||
stays embedder-owned per ADR-005, with alkstore the named
|
||||
deployment-layer substrate for it); the fleet sweeper's
|
||||
single-flighter is pinned as **named exclusive sweep lease**
|
||||
semantics (shipped provider: the pg advisory-lock clause — provider
|
||||
swaps are new-ADR substitution doors); **co-tenancy and
|
||||
no-cross-store-atomicity** are ruled as the downstream-facing
|
||||
composition contract (consumer liveness tables co-tenant the fleet
|
||||
host; compensation rests on idempotent re-puts, windowed deletes,
|
||||
sweeps-as-report-data); and **OQ-11 is resolved** — engine features
|
||||
pull their own driver clusters (`sqlite` default-on carrying
|
||||
rusqlite; `kv`/`large` tier features retired; `local` ungated), so
|
||||
pg-pure builds are supported non-default configurations. REQ-5
|
||||
records the composition facts; the parked index is now empty.
|
||||
|
||||
## Architecture Documents
|
||||
|
||||
@@ -136,17 +155,21 @@ there — not inherited as hedges:
|
||||
| [010](decisions/010-backend-io-seams-and-fleet-state-home.md) | Backend I/O seams (read cursor, staged put); GC state store-core-owned via the engine-state seam; kv fleet-validity; pin-token renewal | Accepted |
|
||||
| [012](decisions/012-pre-decomposition-consistency-rulings.md) | Pre-decomposition rulings: sweep aborts are report data (`GcAborted` retired); pin-token wire shape; fleet-mode constructor declaration; GC state hosts on the kv engine; sqlite seam reduction | Accepted |
|
||||
| [011](decisions/011-vocabulary-tiers-engines-and-fleet-state.md) | Vocabulary: tier/engine/instance/node/fleet; mem joins kv; large tier renamed `large`; constructor modes | Accepted |
|
||||
| [013](decisions/013-family-composition-reactive-boundary-and-feature-graph.md) | Family composition: no sibling dependency in-core; sweep lease; co-tenancy & no-cross-store-atomicity; OQ-11 resolved (engine features pull own drivers) | Accepted |
|
||||
|
||||
## Open Questions
|
||||
|
||||
Tracked in [open-questions.md](open-questions.md). The Phase 0 register
|
||||
(OQ-BL-01..06) is promoted there with its resolutions; three questions
|
||||
are parked — OQ-07/OQ-08 externally-owned (alkgit seam mapping,
|
||||
alkfs intake; carried for visibility, gating nothing here) and
|
||||
OQ-11 `deferred(scope)` (the pg-only-kv feature graph; a named
|
||||
requirement from outside this crate decides it). OQ-09
|
||||
(OQ-BL-01..06) is promoted there with its resolutions; two questions
|
||||
remain externally-owned — OQ-07/OQ-08 (alkgit seam mapping,
|
||||
alkfs intake; carried for visibility, gating nothing here) — and the
|
||||
parked index is **empty**: OQ-09
|
||||
(namespace-visibility default) resolved closed-by-default; OQ-10
|
||||
(second kv engine) resolved by ADR-007. The pg-lo large-engine question
|
||||
(second kv engine) resolved by ADR-007; OQ-11 (the pg-only-kv feature
|
||||
graph, once `deferred(scope)` on a "named deployment requirement from
|
||||
outside") resolved by ADR-013 §4 — its deciding fact already existed
|
||||
in-tree (REQ-2's consolidation posture; ADR-009), the caught example
|
||||
of the circular form. The pg-lo large-engine question
|
||||
resolved to *sequenced work*, not a parked question: REQ-2/ADR-008
|
||||
named it the candidate large-tier engine and POC #7
|
||||
(`docs/research/poc-pglo-spec.md`) was its admission evidence — a
|
||||
@@ -167,7 +190,8 @@ corollary worth restating, because it recurs: a fact this crate must
|
||||
create (its own first deployment, its own first consumer) is never a
|
||||
deciding input — decisions stand on evidence in hand, and future needs
|
||||
reopen via named requirements, not via waiting. (Corollary
|
||||
applications so far: OQ-09 and OQ-10 both resolved on it.)
|
||||
applications so far: OQ-09, OQ-10, and OQ-11 — ADR-013's audit round —
|
||||
all resolved on it.)
|
||||
|
||||
## Lifecycle
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-10-03 (ADR-012 — composite predicate gains the pg-lo same-instance clause; kv-only rejection is put-time; GC state hosts on the kv engine; window wording)
|
||||
last_updated: 2026-10-11 (ADR-013 — feature graph re-pinned: engine features pull their own drivers; `kv`/`large` tier features retired, `sqlite` default-on, `local` ungated)
|
||||
---
|
||||
|
||||
# Backends, tiers, and dispatch
|
||||
@@ -111,13 +111,20 @@ the store's seams (see "What the Backend trait is").
|
||||
|
||||
| Tier | Engine | Feature | Default | Fleet-valid |
|
||||
|---|---|---|---|---|
|
||||
| kv | sqlite | — (tier default) | yes (tier default-on) | no |
|
||||
| kv | sqlite | `sqlite` | **yes (default-on)** | no |
|
||||
| kv | postgres | `postgres` | no | **yes** |
|
||||
| kv | mem | `mem` | no | no (test/reference engine) |
|
||||
| large | local | — (tier default) | yes (tier default-on) | shared media only, explicit assertion |
|
||||
| large | local | *(ungated — dependency-free)* | always present | shared media only, explicit assertion |
|
||||
| large | pg-lo | `pg-lo` | no | **yes** |
|
||||
|
||||
### kv tier (tier default-on, feature `kv`); engines sqlite (default) + postgres (feature `postgres`, default-off) + mem (feature `mem`, default-off)
|
||||
Features gate engines, each pulling only its own driver cluster
|
||||
(ADR-010 §1 extended to every engine — ADR-013 §4); tiers are
|
||||
constructor composition, not features. The tier table's "Feature"
|
||||
column is therefore the engine features: `sqlite` default-on carries
|
||||
rusqlite (the batteries-included default); a pg-pure build (`sqlite`
|
||||
off) is supported, non-default — REQ-2's consolidation posture.
|
||||
|
||||
### kv tier (ADR-003/007/011); engines sqlite (feature `sqlite`, default-on) + postgres (feature `postgres`, default-off) + mem (feature `mem`, default-off)
|
||||
|
||||
Small blobs — **`kv` is the tier name; the engine is a per-node
|
||||
constructor choice** between the shipped engines (ADR-007; ADR-003
|
||||
@@ -177,7 +184,7 @@ fleet-valid, and the **contract-reference engine**: every other
|
||||
engine's conformance tests mirror its suite (the role it already
|
||||
played in POC #1's miniature).
|
||||
|
||||
### large tier (tier default-on, feature `large`; the tier formerly named `fs` — renamed in ADR-011); engines `local` (default) + `pg-lo` (feature `pg-lo`, default-off)
|
||||
### large tier (ADR-003/008/011; the tier formerly named `fs` — renamed in ADR-011); engines `local` (ungated, always present) + `pg-lo` (feature `pg-lo`, default-off)
|
||||
|
||||
Large blobs. Like the kv tier (ADR-007), the large tier is **one
|
||||
contract, multiple engines** — the medium is a per-node constructor
|
||||
@@ -301,6 +308,7 @@ alkfs intake may name needs externally; OQ-08).
|
||||
| [010](decisions/010-backend-io-seams-and-fleet-state-home.md) | I/O seams + GC-state home | read cursor / staged put; store-core-owned GC state via the engine-state seam; the kv fleet-validity rule |
|
||||
| [011](decisions/011-vocabulary-tiers-engines-and-fleet-state.md) | Vocabulary | tier/engine/instance/node/fleet; mem is a kv engine; fs → large; constructor modes |
|
||||
| [012](decisions/012-pre-decomposition-consistency-rulings.md) | Fleet activation & GC-state host | `fleet:` constructor declaration; all fleet GC state on the kv engine; pg-lo same-instance clause; kv-only put-time rejection |
|
||||
| [013](decisions/013-family-composition-reactive-boundary-and-feature-graph.md) | Feature graph + fleet lease | engine features pull their own drivers (`kv`/`large` tier features retired); sweep lease semantics; no sibling dependency in-core |
|
||||
|
||||
## Open Questions
|
||||
|
||||
@@ -325,6 +333,8 @@ alkfs intake may name needs externally; OQ-08).
|
||||
not adopted (threshold dispatch chose the simpler policy;
|
||||
ADR-003 §Context)
|
||||
- ADR-003, ADR-004, ADR-005; ADR-012 (fleet activation, GC-state
|
||||
host, the composite predicate's same-instance clause); [store-api.md](store-api.md) (the invariants
|
||||
host, the composite predicate's same-instance clause); ADR-013 (the
|
||||
feature graph's engine-feature ruling, the sweep lease, the family
|
||||
composition contract); [store-api.md](store-api.md) (the invariants
|
||||
engines must satisfy); [requirements.md](requirements.md) (the pinned
|
||||
vocabulary)
|
||||
@@ -80,7 +80,10 @@ Evidence in hand (no further POC or consumer-waiting needed):
|
||||
engine.
|
||||
|
||||
Both production tiers are default-on (batteries-included, the
|
||||
alkgit feature-model precedent); `mem` is not.
|
||||
alkgit feature-model precedent); `mem` is not. *(Feature shape
|
||||
superseded by ADR-013 §4: "default-on" now reads as constructor-presence
|
||||
default — the sqlite and `local` engines — not tier features; engine
|
||||
features pull their own drivers.)*
|
||||
|
||||
### Dispatch policy
|
||||
|
||||
|
||||
@@ -128,7 +128,10 @@ store core programs the abstraction, never the engine shape.
|
||||
feature pulling the shared driver cluster (`tokio-postgres` +
|
||||
`deadpool-postgres`) independently — a `large`=pg-lo + kv=sqlite
|
||||
node is coherent and supported. overview.md's dependency table pins
|
||||
the edge.
|
||||
the edge. *(The same independent-driver discipline is extended to
|
||||
every engine by ADR-013 §4 — `sqlite` becomes its own default-on
|
||||
feature carrying rusqlite, the `kv`/`large` tier features retire, and
|
||||
pg-pure builds become supported, non-default.)*
|
||||
|
||||
### 2. GC state is store-core-owned; per-engine state seams are crate-internal and contract-tested
|
||||
|
||||
@@ -370,3 +373,7 @@ token-mapping note; nothing else changes.
|
||||
extends); [store-api.md](../store-api.md) (stage hygiene, sweep
|
||||
semantics, cursor-adjacent facade shapes); [requirements.md](../requirements.md)
|
||||
(REQ-2, the fleet requirement §2/§3 serve)
|
||||
- [ADR-013](013-family-composition-reactive-boundary-and-feature-graph.md)
|
||||
(family composition — §4's feature-graph extension of this ADR's §1
|
||||
consequence; §2's sweep-lease semantics for this ADR's sweep-lock
|
||||
clause)
|
||||
@@ -138,6 +138,9 @@ kept (its meaning — this node's own filesystem — stays the
|
||||
constructor's meaning even under the shared-media fleet posture,
|
||||
where it is explicitly *not* only-node-local; the constructor's
|
||||
explicit shared-media assertion, ADR-008 §3, is what disambiguates).
|
||||
*(The rename's feature clause is superseded by ADR-013 §4 — engine
|
||||
features pull their own driver clusters, tier features retire — the
|
||||
tier `large` and constructor wording stands.)*
|
||||
|
||||
### 4. The constructor table (the load-bearing copy of the fleet-validity summary; ADR-010 §3 points here)
|
||||
|
||||
@@ -149,6 +152,12 @@ explicit shared-media assertion, ADR-008 §3, is what disambiguates).
|
||||
| large | local | — (tier default) | yes (tier default-on) | shared media only, explicit assertion |
|
||||
| large | pg-lo | `pg-lo` | no | **yes** |
|
||||
|
||||
*(The table's engine/constructor columns stand; the Feature column's
|
||||
tier-default shape is superseded by ADR-013 §4 — engine features:
|
||||
`sqlite` default-on, `postgres`, `mem`, `pg-lo` default-off, `local`
|
||||
ungated. Fleet-validity, defaults as constructor presence, and modes
|
||||
are unchanged.)*
|
||||
|
||||
Constructor modes (dispatch shapes) — pinned here (implied by
|
||||
ADR-008 §3's re-routing bullet and the mem tests, but never named):
|
||||
- **dual-tier** (the default): kv + large, size-threshold dispatch
|
||||
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
# ADR-013: Family composition — the reactive boundary, the sweep lease, and the feature-graph resolution
|
||||
|
||||
## Status
|
||||
|
||||
Accepted (2026-10-11)
|
||||
|
||||
## Context
|
||||
|
||||
While this crate paused mid-pre-decomposition (ADR-012 was its last
|
||||
round), the sibling **alkstore** shipped v0.1.0: one reactive
|
||||
coordination contract (`Store` — notify/listen, named TTL locks,
|
||||
durable queues, streams with per-consumer offsets, outbox,
|
||||
leader-elected scheduler) behind engine crates (`-mem`, `-sqlite`,
|
||||
`-postgres`), contract-pinned by a factory-driven suite. Its
|
||||
consumer-inventory — built from the paused consumers' written
|
||||
documents under this crate's own deferral discipline — grades three
|
||||
needs of *this crate's specced machinery*:
|
||||
|
||||
- the fleet sweeper lock → named locks, **pinned**;
|
||||
- maintenance cadence (sweep scheduling, pin-renewal workers) →
|
||||
scheduler/queues, **documented** — against ADR-005's "embedder owns
|
||||
cadence";
|
||||
- fleet invalidation ("sweep/manifest changed" among fleet instances)
|
||||
→ notify, **documented**.
|
||||
|
||||
The first consumers (alkgit, alkfs) will deploy both crates together;
|
||||
composition facts are therefore inter-crate decisions that must be
|
||||
decided on evidence in hand, not parked on deployments that cannot
|
||||
pre-exist this crate (the Schrödinger's-code rule; the OQ register's
|
||||
OQ-09/OQ-10 precedents). The audit round that produced this ADR also
|
||||
found one live circular hedge in the register: OQ-11 parked the
|
||||
pg-only kv feature graph on "a named deployment requirement arriving
|
||||
from outside this crate" — a deciding fact *this tree already
|
||||
contains* (REQ-2's consolidation posture, which ADR-009 shipped as
|
||||
"a fleet node can consolidate on postgres-only"), the same
|
||||
shape-shifter OQ-09/OQ-10 were rejected for, and the last one in the
|
||||
register.
|
||||
|
||||
Additionally, the alkcall failure mode ("published doc surface
|
||||
promising unimplemented behavior, surviving versions") motivates
|
||||
stating this crate's publish discipline before anything ships.
|
||||
|
||||
## Decision
|
||||
|
||||
### 1. The reactive boundary: no sibling dependency in-core; reactivity is deployment-layer composition
|
||||
|
||||
**The core crate gains no alkstore dependency and no reactive
|
||||
machinery.** No in-crate notify, no in-crate scheduler, no queues,
|
||||
no invalidation hooks on any facade method. ADR-001's substrate
|
||||
posture extends by the same reasoning to the reactive substrate:
|
||||
the store layer ships bytes-and-addresses, and everything that makes
|
||||
bytes *reactive* is composition above the facade.
|
||||
|
||||
- **ADR-005's "embedder owns cadence" stands, with the substrate
|
||||
named.** An embedder wanting interval sweeps, pin-renewal workers
|
||||
(the TTL/3 cadence, ADR-008), or maintenance dispatch composes them
|
||||
above the facade — typically with the sibling substrate's
|
||||
scheduler/queues. The punt was always a placement decision, not a
|
||||
missing mechanism; the sibling's existence changes nothing here.
|
||||
- **Sweep outcomes are data (ADR-012 §1) — with a pinned consumer.**
|
||||
The report is what the embedder's reactive wiring consumes:
|
||||
`SweepReport` → sibling-notify/stream events (downstream cache
|
||||
invalidation), report cadence → the embedder's scheduler. No
|
||||
in-crate hook exists for any of it; this crate never references
|
||||
the sibling's types, channels, or names.
|
||||
- The engine-driver dependency posture is likewise untouched: no
|
||||
alkstore engine crate enters this crate's feature graph (see §4's
|
||||
graph, which names only storage engines).
|
||||
|
||||
### 2. The sweep lease: semantics pinned, provider shipped
|
||||
|
||||
The fleet sweep single-flighter (ADR-008 §2's advisory lock, whose
|
||||
state home is the engine-state seam's sweep-lock clause — ADR-010 §2,
|
||||
ADR-012 §5) is hereby pinned as a **named exclusive sweep lease**:
|
||||
|
||||
- at most one sweep in flight per pool;
|
||||
- acquisition is an atomic test-and-set at the fleet host;
|
||||
- holdership ends at explicit release, owner-process death, or the
|
||||
underlying engine session's loss;
|
||||
- contention is the `GcAbortCause::SweeperLock` report abort with
|
||||
nothing deleted (ADR-012 §1 — report data, never an error).
|
||||
|
||||
These are exactly pg advisory-lock semantics — the shipped provider
|
||||
(ADR-008's mechanism, unchanged; a lease whose life is the sweep's
|
||||
own) — and exactly what a named TTL lock provides when its lease
|
||||
spans the sweep run. Pinning the *semantics* is what makes the
|
||||
provider substitutable without a contract change: if the family ever
|
||||
wants the in-crate provider swapped (e.g. onto the sibling's lock),
|
||||
that is the ADR-007-shaped substitution door — a new ADR with its own
|
||||
evidence, not an open question.
|
||||
|
||||
A deployment may *additionally* serialize its maintenance above this
|
||||
crate: an embedder holding a named lease on the sibling substrate
|
||||
before invoking `sweep()` composes one discipline over its own
|
||||
scheduled tasks (sweeps, expiry reaping, renewal workers). This is
|
||||
composition above the facade — it changes no contract and is not
|
||||
required for fleet correctness, because the in-crate advisory clause
|
||||
is this crate's own guarantee regardless.
|
||||
|
||||
### 3. Co-tenancy and the no-cross-store-atomicity ruling (the downstream-facing composition contract)
|
||||
|
||||
A fleet pg instance hosts, as co-tenants: this crate's CAS rows and
|
||||
GC state (its pool; `gc_pins` / `gc_window` — ADR-012 §4); the
|
||||
sibling substrate's reactive machinery; consumer business tables
|
||||
(refs, manifests, path trees — outside this crate per ADR-004); and
|
||||
the consumer liveness tables this crate's fleet arbitration
|
||||
consults as named table references (ADR-012 §6.6). **No crate owns
|
||||
another's tables; co-tenancy is a named deployment statement** — the
|
||||
posture decisions/007 and ADR-008 §2 already assumed, now citable so
|
||||
downstream ADRs (alkgit's refs, alkfs's tree) reference it rather
|
||||
than re-derive it.
|
||||
|
||||
- **Cross-store atomicity is unachievable by construction** — each
|
||||
crate owns its own transaction scope, and no seam bridges them.
|
||||
The family posture downstream is the outbox/compensation pattern
|
||||
(alkstore's `outbox`/`notify_tx` are its substrate), and this
|
||||
crate's load-bearing properties for that pattern are already
|
||||
guaranteed and stay so: **puts are idempotent under CAS**
|
||||
(delete-then-recover is a byte-identical re-put, ADR-005),
|
||||
**deletes are windowed and re-arbitrated before execution**
|
||||
(ADR-005; ADR-012 §6.7), and **sweep outcomes are data** (ADR-012
|
||||
§1). Nothing downstream may rely on cross-store-atomic anything;
|
||||
nothing here relies on it either.
|
||||
- **Fleet liveness registration's two forms are the
|
||||
downstream-facing seam:** the fleet form — a named liveness table
|
||||
co-tenant on the fleet host (ADR-012 §6.6) — and the single-node
|
||||
form — the in-process callback (ADR-005). Every downstream crate
|
||||
plans against both. The requirement to keep a consumer's liveness
|
||||
protection expressible on the fleet host is a *composition
|
||||
constraint* on downstream schema placement: a consumer whose
|
||||
liveness lives on a non-co-tenant engine participates in fleet GC
|
||||
via pins (put-path) only, and its sweep-time liveness is expressed
|
||||
by materializing rows per ADR-008 §2's materialization rule.
|
||||
|
||||
### 4. OQ-11 resolved: engine features pull driver clusters independently — including sqlite
|
||||
|
||||
**Features gate engines; tiers are constructor composition, not
|
||||
features.** The ADR-010 §1 discipline ("engine features pull the
|
||||
driver cluster independently" — pg-lo does not imply postgres)
|
||||
extends to every engine:
|
||||
|
||||
| Engine | Feature | Default | Pulls |
|
||||
|---|---|---|---|
|
||||
| kv `sqlite` | `sqlite` | **on** | `rusqlite` |
|
||||
| kv `postgres` | `postgres` | off | `tokio-postgres` + `deadpool-postgres` |
|
||||
| kv `mem` | `mem` | off | nothing |
|
||||
| large `local` | *(ungated)* | always present | nothing |
|
||||
| large `pg-lo` | `pg-lo` | off | the shared pg driver cluster |
|
||||
|
||||
- The base `kv` feature — which existed because sqlite was the kv
|
||||
tier's only shippable driver carrier and so pulled `rusqlite` under
|
||||
the tier's name — is retired, as is the `large` tier feature
|
||||
(nothing was ever behind it; `local` is ungated because it pulls
|
||||
nothing). ADR-011 §3's `feature fs` → `feature large` rename line
|
||||
is superseded by this table; ADR-003's "tiers default-on" wording
|
||||
now reads as constructor-presence, not feature claims.
|
||||
- **A pg-pure build (`sqlite` off — kv=postgres, and `large`=pg-lo if
|
||||
wanted) is a supported configuration this crate does not default
|
||||
to.** This resolves OQ-11 on evidence in hand: REQ-2 (operator
|
||||
authority, 2026-10-03) is the deployment requirement the parked row
|
||||
awaited — its consolidation posture (ADR-009's postgres-only fleet
|
||||
node) is the pg-pure node, and parking the feature graph on it was
|
||||
circular (a deployment requirement whose name the tree already
|
||||
carries is not an absent fact). Mechanism unchanged from the
|
||||
precedent: engine features pull their own drivers, so sqlite's
|
||||
absence is one feature toggle, never a graph surgery.
|
||||
- **Default builds are unchanged**: `sqlite` default-on keeps the
|
||||
batteries-included default (the lean-base principle constrains
|
||||
default builds, which still pull only tokio/thiserror/parking_lot
|
||||
plus the default engine's driver).
|
||||
|
||||
### 5. Publish guard (stated pre-code, on the alkcall lesson)
|
||||
|
||||
The crate publishes only after its facade exists and passes the
|
||||
invariants' test gate. From first publish, its semver is the contract
|
||||
version — every published surface is implemented, every contract
|
||||
change cites its ADR — the discipline the sibling substrate pinned in
|
||||
its contract-versioning ADR. No published doc surface ever carries a
|
||||
"planned/not-implemented" promise.
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive**
|
||||
|
||||
- The composition contract exists as a named ADR: alkgit/alkfs cite
|
||||
§3 for schema co-tenancy, the two-form liveness seam, and the
|
||||
no-cross-store-atomicity posture, instead of re-deriving or
|
||||
guessing.
|
||||
- The register's one live circular hedge (OQ-11) is resolved on
|
||||
in-tree evidence, pre-consumer, where the fix is cheapest — the
|
||||
alkcall-shaped outcome this round exists to avoid.
|
||||
- A new fleet node's dependency tree is honest: pg-pure nodes do not
|
||||
compile rusqlite; nothing reactive is dead code in the core.
|
||||
- The sweep lease's semantics and provider are single-valued; a
|
||||
provider swap later is a mechanism ADR, not a contract break.
|
||||
|
||||
**Negative**
|
||||
|
||||
- One more ADR's worth of surface for every reader of the fleet GC
|
||||
story (§2 changes no signatures; it pins names for semantics the
|
||||
mechanisms already had).
|
||||
- The feature graph must be implemented as specced in §4's table — an
|
||||
implementation-facing edit arriving with the engine tasks rather
|
||||
than inside one of them.
|
||||
|
||||
**Neutral**
|
||||
|
||||
- No tier, engine, constructor mode, facade signature, error variant,
|
||||
or ops payload changes. `fleet: true` validation (ADR-012 §3) and
|
||||
the composite fleet-validity predicate are untouched.
|
||||
- The sibling substrate relationship is documentary here —
|
||||
requirements-level facts and boundary rules — with the eventual
|
||||
dependency edge (if any, e.g. an ops-layer convenience) requiring
|
||||
its own ADR through the substitution door.
|
||||
|
||||
## References
|
||||
|
||||
- ADR-001 (the substrate posture §1 extends to the reactive
|
||||
substrate), ADR-003/007 (the substitution door §2 applies), ADR-005
|
||||
(cadence ownership; delete-then-recover as the idempotency
|
||||
backstop), ADR-006 (the deferred-cost pattern this ADR's OQ-11
|
||||
resolution follows), ADR-008 (the fleet sweep lock §2 pins and the
|
||||
liveness materialization rule §3 reuses), ADR-010/012 (the
|
||||
engine-state seam, GC-state host, outcomes-as-data, the composite
|
||||
predicate), ADR-011 (vocabulary; the constructor tables §4
|
||||
supersedes in feature shape)
|
||||
- [requirements.md](../requirements.md) — REQ-2 (the fact OQ-11 parked
|
||||
on), REQ-5 (the composition requirement §3 serves)
|
||||
- [overview.md](../overview.md) (dependency posture, amended §4;
|
||||
non-goals, extended §1); [backends-and-dispatch.md](../backends-and-dispatch.md)
|
||||
(engine/features table, amended §4); [store-api.md](../store-api.md)
|
||||
(sweep semantics, §2's lease wording); [gc-and-namespaces.md](../gc-and-namespaces.md)
|
||||
(sweeper locking); [open-questions.md](../open-questions.md) (OQ-11
|
||||
resolved)
|
||||
- alkstore — `/workspace/@alkdev/alkstore`: its consumer-inventory
|
||||
(`docs/research/consumer-inventory.md`, the graded fleet rows),
|
||||
ADR-016 (deployment honesty), ADR-017 (contract versioning — §5's
|
||||
cited discipline); the sibling's payload model (JSON-only) is its
|
||||
own non-goal boundary, matching this crate's object-storage
|
||||
boundary here
|
||||
- The alkcall hedge precedent (published-doc-surface drift) — the
|
||||
failure mode §5 guards, on the operator's record
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-10-03 (ADR-012 — aborts are report data (GcAbortCause), never sweep errors; window executor = the next sweep; non-SQL engines stage in-process)
|
||||
last_updated: 2026-10-11 (ADR-013 — sweeper-lock semantics pinned as the named exclusive sweep lease; provider unchanged; composition boundary referenced)
|
||||
---
|
||||
|
||||
# Pooling, namespaces, and GC
|
||||
@@ -25,11 +25,15 @@ price, and this document specifies the mechanism the POCs validated
|
||||
per-repo stores. Git's `alternates`/object-pool mechanism (GitLab
|
||||
object pools) is the same idea done awkwardly; the pool generalizes it
|
||||
to unrelated repos and to p2p replication. **A fleet (REQ-2) — two
|
||||
or more store instances sharing one pool — is the one topology where
|
||||
or more store instances sharing one pool — is the one topology where
|
||||
the GC mechanism below extends beyond one instance: ADR-008 pins,
|
||||
sweeper locking, and delete arbitration move into the shared engine;
|
||||
the invariants are unchanged. Where this crate's GC state (fleet
|
||||
rows and locks) physically lives, and who holds the joint
|
||||
the invariants are unchanged — and the sweeper lock's semantics are
|
||||
the **named exclusive sweep lease** (one sweeper per pool; atomic
|
||||
test-and-set; holdership ends at release/owner death/engine-session
|
||||
loss; contention is the `SweeperLock` report abort — ADR-013 §2,
|
||||
shipped provider: the pg advisory lock). Where this crate's GC state
|
||||
(fleet rows and locks) physically lives, and who holds the joint
|
||||
entry+pin transaction, is ruled by ADR-010 §2: the store core owns
|
||||
all GC state; SQL-backed engines host it through a crate-internal,
|
||||
contract-tested seam; backends never learn liveness.**
|
||||
@@ -140,6 +144,7 @@ existence flips atomically per key).
|
||||
| [008](decisions/008-trait-size-probe-fleet-gc-and-large-engines.md) | Fleet GC extension | DB-backed pins, advisory-locked single sweeper, SQL delete arbitration — for shared-pool (fleet) topologies only; the in-process protocol is unchanged elsewhere |
|
||||
| [010](decisions/010-backend-io-seams-and-fleet-state-home.md) | GC-state home | the store core owns all GC state; SQL engines host it via the contract-tested engine-state seam; pin-tx ownership ruled |
|
||||
| [012](decisions/012-pre-decomposition-consistency-rulings.md) | Abort-as-data + window executor | sweep aborts are `GcAbortCause` report data, never errors; the next sweep executes overdue window rows; non-SQL engines stage in-process; GC state hosts on the fleet's kv engine |
|
||||
| [013](decisions/013-family-composition-reactive-boundary-and-feature-graph.md) | Sweep lease + composition boundary | the fleet sweeper lock's semantics = named exclusive sweep lease (provider unchanged: pg advisory lock); reactivity/cadence composition lives above the facade (alkstore the sibling substrate), never in-core |
|
||||
|
||||
## Open Questions
|
||||
|
||||
@@ -162,5 +167,6 @@ a future requirement does not create one retroactively.
|
||||
- rudolfs — the physical-namespace anti-pattern (inverted)
|
||||
- gix-odb — alternates/pool prior art for the p2p case
|
||||
- ADR-005; ADR-012 (the abort-as-data ruling, the window executor,
|
||||
the GC-state host); [store-api.md](store-api.md) (Pin semantics, sweep API);
|
||||
the GC-state host); ADR-013 (§2 the sweep lease; §1 the composition
|
||||
boundary); [store-api.md](store-api.md) (Pin semantics, sweep API);
|
||||
[ops-surface.md](ops-surface.md) (namespace-as-resource ACL)
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-10-03 (ADR-012 round — no new OQs; overview's pg-only-kv feature-graph deferral recorded in the parked index)
|
||||
last_updated: 2026-10-11 (ADR-013 round — OQ-11 resolved on in-tree evidence; the parked index is now empty)
|
||||
---
|
||||
|
||||
# Open Questions
|
||||
@@ -46,9 +46,9 @@ and not a hedge. A decision is not "unmade" because its verification
|
||||
is pending; deferral policy applies to decisions, not to work.
|
||||
|
||||
**Index of active OQs:** OQ-07, OQ-08 (externally-owned, carried
|
||||
for visibility). OQ-09 and OQ-10 are resolved (recorded below).
|
||||
OQ-11 (deferred(scope), parked index) records a feature-graph
|
||||
deferral. Promoted Phase 0 questions OQ-BL-01..06 are recorded here
|
||||
for visibility). OQ-09, OQ-10, and OQ-11 are resolved (recorded
|
||||
below). The parked index has no active rows —
|
||||
OQ-07/OQ-08 are externally-owned, not parked rows. Promoted Phase 0 questions OQ-BL-01..06 are recorded here
|
||||
with their resolutions for traceability.
|
||||
|
||||
---
|
||||
@@ -233,21 +233,33 @@ with their resolutions for traceability.
|
||||
|
||||
## Parked index (deciding fact / owner — externally-owned rows are not blockers)
|
||||
|
||||
No active parked rows remain. OQ-07/OQ-08 are externally-owned
|
||||
(above), not parked; OQ-09/OQ-10/OQ-11 are resolved with their
|
||||
records kept here for auditability.
|
||||
|
||||
| OQ | Status | Deciding fact / owner |
|
||||
|---|---|---|
|
||||
| OQ-07 | externally-owned | alkgit's architecture process (answerable on paper anytime; gates nothing here) |
|
||||
| OQ-08 | externally-owned | alkfs Phase 0 intake |
|
||||
| OQ-11 | deferred(scope) | a named deployment requirement for a pg-only kv node (postgres kv engine without rusqlite in the build) — overview.md's feature-graph note |
|
||||
|
||||
OQ-11 records [overview.md](overview.md)'s dependency-posture deferral
|
||||
(a pg-only kv node — the `kv` feature's rusqlite pull decoupled from
|
||||
default-on feature graphing) for auditability: the deciding fact is a
|
||||
*deployment requirement that arrives from outside this crate*
|
||||
(Schrödinger's-code rule compliant — it is not a fact this crate
|
||||
creates), the accepted v1 shape (base `kv` feature pulls rusqlite,
|
||||
default-on) stands until then, and the deferral is a feature-graph
|
||||
work item, not an open architecture decision. No spec or ADR gates on
|
||||
it.
|
||||
OQ-11 was `deferred(scope)` on "a named deployment requirement for a
|
||||
pg-only kv node arriving from outside this crate" (overview.md's
|
||||
feature-graph note; the audit trail of the parked wording is kept:
|
||||
the `kv` feature's rusqlite pull decoupled from default-on feature
|
||||
graphing). The 2026-10-11 audit round resolved it as a live circular
|
||||
hedge: the deciding fact already existed in this tree — REQ-2
|
||||
(operator authority, 2026-10-03, pre-POC) names the deployment
|
||||
requirement, and ADR-009 shipped its consolidation posture ("a fleet
|
||||
node can consolidate on postgres-only"), which is the pg-pure node
|
||||
whose feature graph was parked — the same invalid shape OQ-09/OQ-10
|
||||
were rejected for, with the deciding fact created by the tree's own
|
||||
progress and nobody re-auditing the row. Resolved by
|
||||
[ADR-013](decisions/013-family-composition-reactive-boundary-and-feature-graph.md)
|
||||
§4: engine features pull driver clusters independently (the ADR-010
|
||||
§1 discipline extended to sqlite — feature `sqlite`, default-on,
|
||||
carrying rusqlite; `kv`/`large` tier features retired; `local`
|
||||
ungated), and a pg-pure build is a supported configuration this
|
||||
crate does not default to. No deferral remains.
|
||||
|
||||
OQ-09 was `deferred(scope)` on the first embedded ops deployment — a
|
||||
deciding fact that could only exist once the ops module ships, i.e. a
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-10-03 (ADR-012 — OQ-11 parking reference; ADR-012 row added)
|
||||
last_updated: 2026-10-11 (ADR-013 — family composition & reactive boundary; OQ-11 resolved, feature graph re-pinned to engine features)
|
||||
---
|
||||
|
||||
# Overview
|
||||
@@ -72,8 +72,9 @@ or three times.
|
||||
┌──────────────────────┐ ┌─────────────────────────────────┐
|
||||
│ kv tier (ADR-003/ │ │ large tier (ADR-003/008/011; │
|
||||
│ 007/011) │ │ formerly "fs") │
|
||||
│ sqlite (default) │ │ local (default) │
|
||||
│ postgres ("postgres") │ pg-lo ("pg-lo"; ADR-009) │
|
||||
│ sqlite ("sqlite"; │ │ local (ungated; ADR-013 §4) │
|
||||
│ default engine) │ │ pg-lo ("pg-lo"; ADR-009) │
|
||||
│ postgres ("postgres") │ │
|
||||
│ mem ("mem"; tests + │ │
|
||||
│ contract reference) │ │
|
||||
└──────────────────────┘ └─────────────────────────────────┘
|
||||
@@ -90,24 +91,31 @@ or three times.
|
||||
|
||||
| Layer | Dependencies | Notes |
|
||||
|---|---|---|
|
||||
| base crate (store core + tier engines) | `tokio`, `thiserror`, `parking_lot`, plus `rusqlite` behind the `kv` feature and nothing behind `large`/`mem` | no alkcall, no serialization frameworks |
|
||||
| `postgres` engine feature (ADR-007) | adds `tokio-postgres` + `deadpool-postgres` behind the kv tier's second engine, default-off | depends on `kv`'s contract surface (the `Backend` trait definition is base-crate code); the engine's *impl* is additive. Same `Backend` contract, own sweep-safety CI gate under `--all-features` |
|
||||
| `pg-lo` engine feature (ADR-009) | Large Objects as the large tier's second engine, default-off | pulls the same `tokio-postgres`/`deadpool-postgres` cluster as the `postgres` kv engine (SQL `lo_*` functions, no additional dependency); **does not imply the `postgres` feature** — engine features pull the driver cluster independently (ADR-010 §1), so a `large`=pg-lo + kv=sqlite node is coherent and supported; same admission/test-gate shape |
|
||||
| `mem` engine feature (ADR-011) | the kv tier's ephemeral engine, default-off | `BTreeMap`-shaped; the contract-reference engine; no dependencies |
|
||||
| base crate (store core + tier dispatch + GC) | `tokio`, `thiserror`, `parking_lot` | no alkcall, no reactive substrate, no serialization frameworks |
|
||||
| engine features (ADR-010 §1, extended to every engine by ADR-013 §4) | each engine pulls only its own driver cluster | `sqlite` (default-on, `rusqlite`), `postgres` (default-off, `tokio-postgres`+`deadpool-postgres`), `mem` (default-off, nothing), `pg-lo` (default-off, the shared pg cluster); `local` is ungated (dependency-free). Every engine-feature combination is a coherent node shape (e.g. `large`=pg-lo + kv=sqlite, ADR-010 §1); the feature-gated engines' conformance/sweep-safety gates run under `--all-features` (ADR-007/009) |
|
||||
| `ops` feature | adds `alkcall` (feature-gated, default-off) | JSON op specs + binary channels + `AccessControl`; ADR-001 |
|
||||
| consumer crates | depend on alkblobs (and on alkcall directly when they speak ops) | alkgit, alkfs |
|
||||
| consumer crates | depend on alkblobs (and on alkcall directly when they speak ops) | alkgit, alkfs — which also deploy the sibling reactive substrate beside it (below) |
|
||||
|
||||
Tiers are feature-gated; both default-on (batteries-included, the
|
||||
alkgit feature-model pattern — default-on features, opt-out rather
|
||||
than opt-in); the engine features `postgres` and `pg-lo`, and `mem`,
|
||||
are default-off, as are `ops`. A pg-only kv node (postgres engine
|
||||
without rusqlite) is **not** a supported configuration this crate
|
||||
optimizes for — feature-graph work for it is deferred until a named
|
||||
requirement exists (the base `kv` feature pulling rusqlite is the
|
||||
accepted v1 shape; convention 8's lean-base principle applies to
|
||||
*default* builds, which stay lean since `kv` is what the feature model
|
||||
controls, not what default-on means downstream; tracked as OQ-11 in
|
||||
open-questions.md's parked index). Wasm: the tier
|
||||
**The sibling reactive substrate (ADR-013 §1/§3):** **alkstore**
|
||||
(v0.1.0 — notify/locks/queues/streams/outbox/scheduler behind its own
|
||||
engine crates) ships beside this crate, not under it. The core keeps
|
||||
no alkstore dependency and no reactive machinery: cadence and
|
||||
invalidation wiring are deployment-layer composition above the facade
|
||||
(ADR-005's "embedder owns cadence" stands, with the sibling the
|
||||
named substrate; sweep outcomes are report data — ADR-012 §1 — whose
|
||||
pinned consumer is that wiring). Cross-store atomicity is unachievable
|
||||
by construction; the composition properties are idempotent re-puts,
|
||||
windowed deletes, and reports-as-data (ADR-013 §3, the citable
|
||||
downstream contract).
|
||||
|
||||
Tiers are **constructor composition**, not features (ADR-013 §4);
|
||||
engine features as in the table above. The default build is
|
||||
batteries-included (sqlite default-on — opt-out rather than opt-in,
|
||||
the alkgit feature-model pattern), and a pg-pure build (sqlite off;
|
||||
kv=postgres, `large`=pg-lo if wanted) is a supported configuration
|
||||
this crate does not default to — REQ-2's consolidation posture
|
||||
(ADR-009), now carried by the feature graph instead of parked on it.
|
||||
Wasm: the tier
|
||||
engines are not a wasm story; a wasm client is a consumer of the `ops`
|
||||
surface (which rides alkcall, itself wasm-clean), never an in-process
|
||||
embedder (ADR-001 §Consequences).
|
||||
@@ -124,6 +132,10 @@ embedder (ADR-001 §Consequences).
|
||||
Backend to model paths (ADR-004).
|
||||
- No chunk-tree/CDC storage encoding; whole-file CAS is the store's only
|
||||
granularity (ADR-006).
|
||||
- No reactive coordination machinery in-core — no notify, no scheduler,
|
||||
no queues, no invalidation hooks: reactivity is the sibling
|
||||
substrate's (alkstore), composed at the deployment layer above the
|
||||
facade (ADR-013 §1).
|
||||
- No per-repo or per-namespace walled stores — one pooled CAS
|
||||
(ADR-005).
|
||||
|
||||
@@ -143,6 +155,7 @@ embedder (ADR-001 §Consequences).
|
||||
| [010](decisions/010-backend-io-seams-and-fleet-state-home.md) | I/O seams + GC-state home | read cursor / staged put; store-core-owned GC state via the engine-state seam; kv fleet-validity rule; pin-token renewal |
|
||||
| [012](decisions/012-pre-decomposition-consistency-rulings.md) | Sweep-abort shape + composition rulings | sweeps never error (`GcAborted` retired, `GcRefuse` for direct-delete); token wire shape; fleet mode = constructor declaration; GC state hosts on the kv engine; sqlite seam reduction |
|
||||
| [011](decisions/011-vocabulary-tiers-engines-and-fleet-state.md) | Vocabulary + rename | tier/engine/instance/node/fleet pinned; mem joins the kv tier; large tier renamed `large`; constructor modes |
|
||||
| [013](decisions/013-family-composition-reactive-boundary-and-feature-graph.md) | Family composition & reactive boundary | no sibling dependency in-core; sweep lease semantics (provider: raw advisory clause); co-tenancy + no-cross-store-atomicity; OQ-11 resolved (engine features pull own drivers) |
|
||||
|
||||
## Open Questions
|
||||
|
||||
@@ -157,8 +170,9 @@ crate level:
|
||||
open-read requirement)
|
||||
- **OQ-10**: second kv engine — resolved by ADR-007 (sqlite + postgres
|
||||
shipped behind one trait; per-node constructor choice)
|
||||
- **OQ-11**: pg-only kv node feature graph — deferred(scope), parked
|
||||
(see [open-questions.md](open-questions.md))
|
||||
- **OQ-11**: pg-only kv node feature graph — resolved by ADR-013 §4
|
||||
(engine features pull their own driver clusters; `sqlite` default-on;
|
||||
pg-pure builds supported, non-default)
|
||||
- **POC #7** (`docs/research/poc-pglo-findings.md`): pg Large Objects
|
||||
as the large tier's `pg-lo` engine — **passed** 2026-10-03; admitted as
|
||||
a shipped engine by ADR-009 (REQ-2's consolidation option)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-10-03 (vocabulary pinned by ADR-011 — tiers/engines/instances/fleet; large tier renamed `large`)
|
||||
last_updated: 2026-10-11 (ADR-013 composition round — REQ-5 added: the family's first consumers deploy this crate with the sibling reactive substrate; co-tenancy + liveness-form facts pinned)
|
||||
---
|
||||
|
||||
# Requirements
|
||||
@@ -102,12 +102,47 @@ path→hash manifests above.
|
||||
performance is what matters; the large tier is hit rarely (large
|
||||
workspace artifacts).
|
||||
|
||||
### UC-4: The family's first consumers run composition (alkgit + alkfs + the reactive substrate)
|
||||
|
||||
The first consumers of this crate — alkgit (its object backend,
|
||||
OQ-07) and alkfs (path trees/workspaces, OQ-08) — deploy
|
||||
**alkstore**, the sibling reactive coordination substrate (v0.1.0:
|
||||
notify/locks/queues/streams/outbox/scheduler behind its own engine
|
||||
crates) *together with* this crate, per an operator-authority
|
||||
planning fact (2026-10-11, recorded in alkstore's
|
||||
`docs/research/consumer-inventory.md` — which grades this crate's
|
||||
fleet needs against alkstore's surface). This forces composition
|
||||
facts on this crate regardless of whether its core takes a
|
||||
dependency:
|
||||
|
||||
- **REQ-5 (traces: ADR-013)** — composition facts (decided, not
|
||||
deferred; ADR-013 is the ruling):
|
||||
- The first consumers' nodes co-deploy both crates; this crate's
|
||||
core keeps **no alkstore dependency** (ADR-013 §1) — the reactive
|
||||
substrate is deployment-layer composition above the facade, the
|
||||
named substrate for the cadence ADR-005 assigns to embedders.
|
||||
- **No cross-store atomicity**: each crate owns its transaction
|
||||
scope; the compensation properties downstreams rely on are this
|
||||
crate's idempotent re-puts (CAS; delete-then-recover backstop),
|
||||
windowed deletes, and reports-as-data sweep outcomes (ADR-013
|
||||
§3).
|
||||
- Consumer **liveness tables co-tenant the fleet host** (the
|
||||
named-table-reference form, ADR-012 §6.6) or ride the in-process
|
||||
callback form single-node — the two-form liveness seam every
|
||||
downstream plans against (ADR-013 §3).
|
||||
- The fleet sweeper's single-flighter is a named exclusive sweep
|
||||
lease whose shipped provider is the pg advisory lock; other
|
||||
providers (the substrate's lock) are composition above the
|
||||
facade or a new-ADR substitution door (ADR-013 §2).
|
||||
|
||||
## What this document is not
|
||||
|
||||
- **Not consumer architecture**: how alkgit maps refs/manifests onto
|
||||
the store remains OQ-07 (externally-owned); how alkfs shapes
|
||||
workspaces remains OQ-08. This document records what each use case
|
||||
*forces on this crate*, not what each consumer *is*.
|
||||
*forces on this crate*, not what each consumer *is* — UC-4's rows
|
||||
are the one composition shape the use cases themselves force
|
||||
(REQ-5/ADR-013), stated as constraints, not as a consumer design.
|
||||
- **Not a requirements-change process substitute**: a new or changed
|
||||
REQ arrives here with a dated note and owner; ADRs that depended on
|
||||
the old fact state their reopen conditions and reopen when this
|
||||
@@ -121,3 +156,4 @@ path→hash manifests above.
|
||||
| REQ-2 | 2026-10-03 (fact: use case origin discussion, pre-POC) | user/planning record | ADR-007, ADR-008 |
|
||||
| REQ-3 | 2026-10-03 (fact: phase-0 §deployment posture) | POC #5 B3/B4 | ADR-007 |
|
||||
| REQ-4 | 2026-10-03 (fact: phase-0 §vision) | POC #1, ADR-002 | ADR-002, ADR-005 |
|
||||
| REQ-5 | 2026-10-11 (fact: composition planning; corroborated by alkstore's consumer-inventory) | operator record | ADR-013 |
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-10-03 (ADR-012 — sweep-abort = Ok(report) with GcAbortCause; GcAborted retired; fall-through for all key-addressed ops; put-time kv-only rejection; delete/missing/error-model ruling)
|
||||
last_updated: 2026-10-11 (ADR-013 — the fleet sweeper lock's semantics pinned as the named exclusive sweep lease; provider unchanged; composition boundary referenced)
|
||||
---
|
||||
|
||||
# Store API
|
||||
@@ -138,10 +138,15 @@ mechanism lives in the engine-state seam, ADR-010 §2).
|
||||
mechanism-extended by ADR-008: pins are DB-backed rows committed
|
||||
atomically with entries (the store core holds the joint tx,
|
||||
ADR-010 §2; all GC state hosts on the fleet's kv engine —
|
||||
ADR-012 §4), one sweeper holds the advisory lock (contention is a
|
||||
report abort, not an error — ADR-012 §1), and delete
|
||||
ADR-012 §4), one sweeper holds the advisory lock (named exclusive
|
||||
sweep lease semantics: one sweeper per pool, atomic test-and-set,
|
||||
holdership ends at release/owner death/engine-session loss;
|
||||
contention is a report abort, not an error — ADR-012 §1, semantics
|
||||
pinned ADR-013 §2), and delete
|
||||
arbitration is SQL-level — the facade's invariant text is
|
||||
unchanged.
|
||||
unchanged. The facade owns no reactive machinery: cadence,
|
||||
maintenance dispatch, and invalidation wiring are embedder
|
||||
composition above it (ADR-005; ADR-013 §1).
|
||||
|
||||
## Error model
|
||||
|
||||
@@ -231,6 +236,7 @@ lesson generalizes to any kv engine).
|
||||
| [008](decisions/008-trait-size-probe-fleet-gc-and-large-engines.md) | Trait `size` + fleet GC | stat/accounting ride the trait's `size` probe; fleet pins/sweeps are engine-backed |
|
||||
| [010](decisions/010-backend-io-seams-and-fleet-state-home.md) | I/O seams + GC-state home | read cursor / staged put behind the facade; the store core holds the joint entry+pin tx |
|
||||
| [012](decisions/012-pre-decomposition-consistency-rulings.md) | Sweep-abort shape + wire/activation rulings | swept = Ok(report) always, `GcRefuse` for direct-delete refusal; fleet mode is a constructor declaration; GC state hosts on the kv engine |
|
||||
| [013](decisions/013-family-composition-reactive-boundary-and-feature-graph.md) | Sweep lease + composition boundary | the advisory lock's semantics = named exclusive sweep lease (provider unchanged); no reactive machinery/facade hooks in-core |
|
||||
|
||||
## Open Questions
|
||||
|
||||
|
||||
Reference in new issue
Block a user