ADR-0021: Dual-Rail .stet — Composable, Governable Memory Graphs (KBs)
Status
Proposed / exploring. Prompted by the memory-posture discussion (2026-07-08).
Extends ADR-0013 (the git/Dolt split),
ADR-0015 (the .stet topology), and ADR-0017 (composable, importable, signed
configs), and realizes the "the repo is the graph" claim of ADR-0019 on a
queryable rail. Revisit for promotion to accepted (+ a spec) alongside the memory
ADRs, after the core loop (SPEC-0001..0003) is standing.
Context and Problem Statement
ADR-0019 claims Stet's differentiator is compounding project memory because a git repo already is a versioned knowledge graph. That is true for artifacts (git-grep, diffs, PR review), but the graph over them — provenance edges (this skill ← these trajectories), outcomes (merged/reverted), votes (ADR-0014), staleness — is relational, concurrently updated, and something you want to query ("what does this project know about error handling?", "which skills are stale?", "trace this convention to its origin"). git is the wrong rail for that; Dolt (git-for-data: versioned SQL, cell-wise branch/merge/diff, embeddable, syncable as a remote — already adopted in ADR-0013) is the right one.
The question that opened this ADR: should a .stet also be a Dolt repo, so the
knowledge graph rides that rail? Pursuing it surfaced two properties that make it
worth more than a storage note:
- 1:N, not 1:1. A
.stetrepo/folder should reference/compose many knowledge bases (KBs), not own exactly one. Memory federates. - Distribution + governance. If KBs are named, composable resources resolved
across the
.stettopology (ADR-0015), then a language/framework/community can publish a.stetwhose KB is distilled across community trajectories, and a higher tier can govern which KB sources are allowed — the dotfiles pattern pushed to ecosystem scale, with an org-enforceable trust boundary.
Framing — two rails, one topology
Do not turn .stet git repos into Dolt repos. Keep the ADR-0013 line intact —
trajectories & skills stay in git, never Dolt — and make the topology dual-rail:
| Rail | Holds | Why this rail |
|---|---|---|
git (.stet repo/dir) | reviewable artifacts: trajectories (ADR-0011), skills (ADR-0012), verbs, agent YAML (ADR-0015/0016) | line-diffable, PR-ceremony-gated, human-readable, harness-portable |
| Dolt (KB) | the queryable memory graph: provenance edges, outcomes, votes (ADR-0014), staleness, the distillation warehouse | relational, cell-wise mergeable, SQL-queryable, syncable |
git is the source of truth for anything reviewed as a file; a KB is a
materialized, rebuildable projection over those artifacts plus the genuinely
relational data that has no git form (votes, thread state, outcomes — already Dolt's
job in ADR-0013). The .stet unit binds the two.
Sketch / Decisions
Dual-rail binding (git source of truth, Dolt graph)
Each .stet tier (ADR-0015) pairs its git repo/dir with zero or more KBs. The KB
is derivable from the git artifacts (provenance travels in trajectory/skill metadata),
so it is an index, not a second master for artifacts. Two invariants hold:
- git stays authoritative for reviewable artifacts; the KB never becomes a side-door around file review.
- The graduation invariant (ADR-0019/0020) is untouched. Durable artifacts land via PR into git; the KB updates as a projection of that merge (or from votes). Nothing an agent durably knows arrives through the Dolt rail unreviewed.
KBs are the fourth primitive — composable, 1:N
Decided (2026-07-08): a KB is a first-class primitive, managed exactly like
Agents and Verbs (ADR-0015) — you curate a KB library the same way you manage those.
The reviewable git-side binding (source/address, ref pin, signer policy) is the
primitive; its payload is the Dolt memory graph. A .stet declares a set of KB
bindings it composes, resolved across the topology like the other primitives
(ADR-0015). Memory federates: your repo KB + your org KB
+ an imported language KB + a team KB, resolved with a precedence order. A KB
is addressed as an importable resource (à la ADR-0017), pinned to a ref via a
lockfile. Because Dolt syncs as a remote and merges cell-wise, a consumed community KB
can even be forked and contributed back — the collective flywheel (ADR-0014) at
ecosystem scale.
Distribution — the dotfiles pattern, extended
Because KBs are named and importable, an ecosystem project can ship a .stet whose
KB is distilled across community trajectories — e.g. a language/framework publishes
org/.stet carrying memory the whole community's dispatches produced. Downstream
projects import it (ADR-0017) and inherit a warm, queryable memory graph on day one
instead of starting cold. This generalizes ADR-0015's .github-style dotfiles
convention from config to distributed, versioned memory.
Governance — override, forbid, pin, sign
KB composition rides ADR-0015's resolution and ADR-0017's trust model, so governance is native, not bolted on:
- Precedence is a setting (soft): which KB wins when sources overlap.
- Hard pins (ADR-0015): a higher tier can pin a KB source non-overridable — auditable provenance of what an org mandated.
- Allow/deny sources: a tier can forbid specific KB sources (or restrict to an allowlist) — "this org's agents may not read community KB X."
- Signed provenance (ADR-0017): a policy can require an imported KB's pinned ref be GPG-signed by an allowed signer — git-native, org-enforced, Stet-is-not-a-central-authority.
This is the property that makes distribution safe: importing memory is powerful, so the same downstream controls that gate imported config (ADR-0017) gate imported memory.
Privacy gate on the publish path
Decided (2026-07-08): a KB is projected from trajectories and can carry sensitive
residue, so the ADR-0011 secret-scan + redaction gate runs at projection/publish
time (when a KB is built or pushed for others to consume) — mandatory and blocking,
exactly as for a committed trajectory. What a publishable KB may include is governed
by a .stetignore (the same mechanism ADR-0011 uses for trajectory capture,
extended to the graph): paths/entities/edges a project excludes from any KB meant to
leave the repo. Local, private KBs are gated the same way at the moment they publish,
not continuously.
Why it fits
- Good, because it puts each kind of data on the rail it deserves without breaking the ADR-0013 line — artifacts stay reviewable-as-files, the graph becomes queryable.
- Good, because 1:N + import/pin/sign makes memory composable and governable with the mechanics ADR-0015/0017 already define — no new trust primitive.
- Good, because it turns the compounding-memory posture (ADR-0019) into something that scales past one repo: ecosystem-published KBs, federated queries, contribute-back.
- Good, because the KB is a rebuildable projection, so it is never an un-auditable second source of truth for artifacts, and the graduation invariant still holds.
Open questions
- Poisoned / adversarial KBs. An imported community KB can encode hostile or low-quality conventions distilled from adversarial trajectories. Bounded by allow/deny + signed-source + pin (above), but the residual — importing curated memory is importing intent — mirrors ADR-0017's residual and must be named as accepted, with efficacy/vote gating (ADR-0014) as a compensating control.
- Identity & dedup across KBs. How a trajectory/skill referenced by multiple federated KBs is identified (content address? artifact SHA?) so provenance edges don't double-count or collide.
- Query federation & precedence semantics. How a query spans N KBs with a precedence order, and the cost/latency of federating across local + remote Dolt DBs.
- KB schema & versioning. The open, versioned KB schema and its migration story (Dolt schema changes as reviewable diffs), so KBs stay portable and not lock-in.
- PII policy for publishable KBs. The secret-scan gate +
.stetignoreare decided (above); the remaining nuance is the default PII/entity policy for a KB intended to be published to others (opt-in vs. opt-out, per-entity granularity) beyond secrets. - Sync topology. Local-first vs. DoltLab vs. forge-mediated sync (ADR-0013) for multi-consumer KBs, and conflict/merge policy when many consumers contribute back.
Consequences (tentative)
- Adds KB as a fourth first-class primitive (ADR-0015): a git-side KB binding
(source/address + lockfile, import/pin/sign per ADR-0017) bound 1:N to each
.stettier over a Dolt memory-graph payload, a resolution/precedence pass (ADR-0015), and allow/deny governance controls — curated as a "KB library" like Agents/Verbs. - Adds a projection pipeline (git artifacts + votes → KB) with the ADR-0011
secret-scan/redaction gate and a
.stetignore-governed exclusion on the publish path, and a rebuild-from-git guarantee. - Extends ADR-0013 (KBs are the concrete shape of its Dolt warehouse), ADR-0015 (memory joins the governed topology), and ADR-0017 (imports now include memory).
- Introduces an accepted residual (imported memory = imported intent) tracked with ADR-0017's; efficacy/vote gating (ADR-0014) is the compensating control.
More Information
Prompted by the memory-posture discussion (2026-07-08). Realizes ADR-0019's "the repo is the graph" on the Dolt rail; the KB is where the outer loop (ADR-0012) warehouses and the inner loop (ADR-0020) graduates to, and what agentic voting (ADR-0014) feeds. Distribution + governance reuse ADR-0015 (topology, pins) and ADR-0017 (import, lockfile, allowed-signer trust). Shared theme: the project — and the ecosystem — learns over time.