Skip to content

Commit 158c10f

Browse files
docs(adr): supersede ADR-0011 with ADR-0012 — json-family implemented (V-L2-F3) (#152)
Reconcile the decision record with main after a merge race: V-L2-F3 (#146, #148) reversed the V-L2-F2 json drop and implemented a JSON-family sidecar backend. Adds ADR-0012 (supersedes ADR-0011), nets the CHANGELOG to "Added: JSON-family backend", and lists json in the README example. Docs only. https://claude.ai/code/session_01Ux144vBDdySvLUqUrCgkT4
1 parent 00fd80f commit 158c10f

4 files changed

Lines changed: 102 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ this project aims to follow [Semantic Versioning](https://semver.org/spec/v2.0.0
2020

2121
### Added
2222

23+
- feat(sidecar): JSON-family sidecar storage backend — plain JSON / JSON-LD / NDJSON with SQLite-parity octad runtime (provenance incl. forks, temporal, drift, gc); new `[sidecar].format` key and a single `StorageKind::resolve` backend resolver (V-L2-F3, ADR-0012, closes #146) (#148)
2324
- feat(codegen): split sidecar DDL by dialect; reject json sidecar (#45) (#133)
2425
- feat(codegen): split sidecar DDL by dialect; reject json sidecar (#45) (#131)
2526
- feat(logging): tracing diagnostics with --log-format/--log-level (#51) (#124)
@@ -31,10 +32,6 @@ this project aims to follow [Semantic Versioning](https://semver.org/spec/v2.0.0
3132
- feat(codegen): split sidecar DDL by dialect; reject json sidecar (#45) (#113)
3233
- feat(provenance): fork-first-class chain model — ADR-0010 (#31; supersedes #32) (#109)
3334

34-
### Removed
35-
36-
- feat(manifest): drop the never-implemented `json` sidecar store; close `[sidecar].storage` to sqlite + postgres and reject unknown values at validate/doctor/generate (V-L2-F2, ADR-0011, closes #112) (#144, #147)
37-
3835
### Fixed
3936

4037
- fix(rhodibot): automated RSR compliance fixes (#135)

README.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ temporal-versioning = true # automatic version history
239239
drift-detection = true # cross-modal observer (Constraints symptom)
240240
241241
[tier1.provenance]
242-
sidecar = "sqlite" # sqlite | postgres (V-L2-F2 / ADR-0011)
242+
sidecar = "sqlite" # sqlite | postgres | json (V-L2-F3 / ADR-0012)
243243
sidecar-path = ".verisimiser/provenance.db"
244244
245245
[tier1.temporal]

docs/decisions/0011-sidecar-storage-is-relational.adoc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,19 @@ Date: 2026-05-30
88

99
## Status
1010

11-
Accepted (2026-05-30) — implemented in #144 (json dropped from the storage
12-
enum, docs, template, and validate/doctor messaging) with test coverage in
13-
#147. Closes #112 (V-L2-F2). Builds on #45 (V-L2-F1, the per-dialect DDL
14-
split) and ADR-0004 (octad ontology).
11+
**Superseded by [ADR-0012](0012-json-family-sidecar-storage.adoc)
12+
(V-L2-F3, #146 / #148).**
13+
14+
Originally Accepted (2026-05-30) and shipped as the V-L2-F2 drop — #144,
15+
test coverage in #147, closing #112. It was then reversed *within the same
16+
development cycle* by V-L2-F3 (#146), which re-opened and **implemented** the
17+
JSON sidecar capability as a deliberately-scoped family (plain / JSON-LD /
18+
NDJSON) at the maintainer's request. The "no storage-abstraction layer /
19+
relational-only" premise below no longer holds: #148 introduced
20+
`sidecar::StorageKind` and a format-independent `SidecarData` codec. This ADR
21+
is retained as the historical record of the F2 decision; see ADR-0012 for the
22+
current state. Builds on #45 (V-L2-F1, the per-dialect DDL split) and
23+
ADR-0004 (octad ontology).
1524

1625
## Context
1726

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
= Architecture Decision Record: 0012-json-family-sidecar-storage
2+
<!-- SPDX-License-Identifier: PMPL-1.0-or-later -->
3+
<!-- Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk> -->
4+
5+
# 12. Implement the JSON-family sidecar store (supersedes ADR-0011)
6+
7+
Date: 2026-05-31
8+
9+
## Status
10+
11+
Accepted (2026-05-31) — implemented in #148. Closes #146 (V-L2-F3).
12+
**Supersedes [ADR-0011](0011-sidecar-storage-is-relational.adoc)** (V-L2-F2,
13+
the json *drop*), reversing it at the maintainer's request.
14+
15+
## Context
16+
17+
ADR-0011 (V-L2-F2, shipped in #144) dropped the never-implemented `json`
18+
sidecar store on the grounds that the octad runtime is relational and no
19+
storage-abstraction layer existed to host a second backend. That reasoning
20+
was sound *at the time*, but it rested on an absence (no abstraction) rather
21+
than an impossibility.
22+
23+
The maintainer subsequently asked for a real JSON sidecar capability (#146,
24+
V-L2-F3) — deliberately reversing the drop — scoped as a *family* of on-disk
25+
encodings with **full parity** to the runtime operations the SQLite path
26+
implements today.
27+
28+
## Decision
29+
30+
Accept `[sidecar].storage = "json"` again, backed by a real implementation
31+
(#148):
32+
33+
* **`[sidecar].format`** selects the on-disk encoding — `plain` (default) |
34+
`ld` (JSON-LD) | `ndjson`. It is meaningful only for `json` and ignored
35+
for `sqlite`/`postgres`.
36+
* **One resolver.** `sidecar::StorageKind::resolve(storage, format)` is the
37+
single source of truth (`Sqlite | Postgres | Json(JsonFormat)`);
38+
`SqlDialect::from_storage` is folded into it, and `validate`/`doctor`,
39+
`generate`, `drift`, and `gc` all dispatch on it.
40+
* **Storage abstraction.** A single `SidecarData` model mirrors the
41+
`verisimdb_*` tables (provenance log + chain-head set, temporal versions,
42+
lineage edges, access policies). **Format is purely a codec** over that
43+
model — every octad operation is written once and is format-independent
44+
(plain = table→rows object; ld = `@context` + typed `@graph`; ndjson =
45+
one record per line). Writes are crash-safe (temp file + atomic rename).
46+
* **Octad parity.** Provenance (`append`, `append_fork`, `verify_chain`,
47+
`fork_points`) reuses `abi::ProvenanceEntry::compute_hash`, so hashing is
48+
identical across backends; temporal enforces monotonic versions and the
49+
exactly-one-current invariant in code; drift reuses the `tier1` temporal
50+
kernel; `gc` purges by age; `generate` emits a
51+
`sidecar_schema.{json,jsonld,ndjson}` scaffold instead of SQL DDL.
52+
53+
### Relationship to ADR-0011
54+
55+
ADR-0011's premise — *no abstraction; a JSON store would re-encode
56+
relational invariants in application code with weaker guarantees* — is
57+
answered rather than simply contradicted: #148 introduces the abstraction
58+
(`StorageKind` + the `SidecarData` codec) and re-encodes those invariants in
59+
Rust with documented parity. The one acknowledged difference is concurrency:
60+
the JSON store is single-writer (atomic whole-file rewrite) where SQLite
61+
serialises via `BEGIN IMMEDIATE` locks. The guarantees SQL enforced
62+
structurally (one current temporal row, monotonic versions, fork-aware
63+
chains, hash identity) are now enforced in code for the json path and
64+
covered by tests mirroring the SQLite suite, across all three formats.
65+
66+
## Consequences
67+
68+
### Positive
69+
70+
- `json` / `jsonld` / `ndjson` sidecars with octad parity — human-diffable,
71+
portable, dependency-light stores, plus a genuine linked-data (JSON-LD)
72+
option.
73+
- A single backend resolver (`StorageKind::resolve`) for every storage value.
74+
75+
### Negative
76+
77+
- The json path enforces invariants in application code rather than via SQL
78+
constraints, so it carries a heavier test burden and a documented
79+
single-writer limitation.
80+
- Two storage families to maintain in lockstep (the hash function is shared
81+
via `abi`, which mitigates the highest-risk drift).
82+
83+
## References
84+
85+
- Issue #146 (V-L2-F3); PR #148.
86+
- Supersedes ADR-0011 (V-L2-F2; issue #112, shipped in #144/#147).
87+
- ADR-0004 (octad ontology), ADR-0010 (provenance forks are first-class).

0 commit comments

Comments
 (0)