ADR 0002: Managed immutable generations and an ACTIVE pivot
August 28, 2026 ยท View on GitHub
Audience: maintainers and compiler contributors.
- Status: accepted
- Date: 2026-08-11
Context
RFC 0001 requires successful multi-file transactions to publish every verified operation or none. Portable sequential replacement of ordinary source paths cannot provide that property: after the first rename and before the last, a reader can observe a mixed generation. The existing A0 boundary is deliberately single-file and must remain byte-, API-, and behavior-compatible.
The repository needs one substantial but honest architecture tranche that can publish a bounded set of existing canonical source files without pretending to solve repository-wide Graph semantics, raw working-tree materialization, or crash/power-loss durability.
Decision
Semantic Workspace Transaction v1 owns a hidden managed control tree under
.semaprax-workspace. A complete source generation is immutable and named by
the domain-separated digest of its canonical manifest. One canonical ACTIVE
file selects the generation. Cooperating readers acquire the permanent shared
lock, authenticate ACTIVE, and read only the selected generation. Writers
hold the permanent exclusive lock, prepare and authenticate the complete
candidate generation, publish it without replacement, and replace only
ACTIVE after two final checks.
Initialization is the separate authority that creates generation zero and the
first ACTIVE. Ordinary apply never rewrites the original source files. The
wire, limits, reader contract, diagnostics, and nonclaims are frozen in
Semantic Workspace Transaction v1.
Consequences
- Cooperating managed readers observe one complete old or new generation; no sequence of per-source renames is exposed to them.
- Raw paths, Git, editors, build tools, and noncooperating readers are outside the atomic-visibility claim.
- A fully authenticated candidate can remain after a rejected pre-pivot apply. Bounded staging and retained-generation residue is inventory, not a selected commit.
- Failure after the
ACTIVEreplacement is an explicitSPX-I212ambiguity; the implementation does not silently roll back a possibly selected new generation. - Garbage collection, rollback policy, flat materialization, repository migration, and power-loss recovery remain future protocols.
- Existing single-file Patch/A0/Impact/Review/Repair/Target/Evidence protocols are unchanged. Workspace v1 embeds admitted patches per file but grants those artifacts no new authority.
Rejected alternatives
Sequential per-file replacement
Rejected because portable readers can observe a mixture of old and new files. Recovery also cannot infer a unique committed set from an interrupted rename sequence without another publication record.
Filesystem-specific directory exchange
Rejected as the public contract because portable Rust and the supported host matrix do not expose one identical no-replace/exchange primitive with the required semantics. It would also overstate network and hostile-filesystem behavior.
Git commit as transaction authority
Rejected because Git state is not the compiler's authenticated live source authority, ordinary working trees can be dirty, and editor/raw-file readers would still observe path-by-path materialization.
Database or opaque package as canonical source
Rejected for this tranche because readable .spx remains the canonical Git
projection. The managed tree is an opt-in publication layer, not a replacement
language storage format.
Widen single-file A0
Rejected because it would conflate two trust boundaries and risk changing the
frozen single-file protocol. Workspace v1 has its own permanent lock,
generation inventory, and ACTIVE publication authority.