feat(log): log authority is the fleet default — adopt-at-open, oracle-gated; plus the power-cut throw-site cures and the loud torn-record contract
All checks were successful
CI / Node 22 (push) Successful in 12m16s
CI / Node 24 (push) Successful in 12m13s
CI / Bun (latest) (push) Successful in 12m20s

THE DEFAULT FLIP (ruled on proven evidence — at-ack survived 301/301
acked-writes-through-power-cut in block-layer fault injection; deferred
tree authority demonstrably loses flush-covered acks): a brain with NO
stored authority artifact now ADOPTS LOG AUTHORITY AT OPEN. The oracle
gates the flip exactly as the guarded adoption path always did — curable
divergences baseline-backfilled, the flip lands ONLY on a green verdict —
and a brain that cannot verify STAYS tree-authoritative loudly, with the
refusal recorded on the switch artifact so subsequent opens are cheap.
config logAuthority: 'defer' is the explicit documented opt-out (no
automatic adoption; declared flush-window loss; adoptLogAuthority() flips
later). A stored artifact always wins. RELEASES.md carries the posture.

Two standing .fails debt pins FLIP TO HOLDING under the default: the
at-ack crash-survival gap and the ack-at-log durability target — both now
permanent asserted truths, not aspirations.

POWER-CUT THROW SITES (fault-injection findings, brainy-alone config):
- A manifest-listed-but-unloadable column segment QUARANTINES at
  discovery (loud once, counted always, quarantinedSegments() exposed for
  the heal) and the field serves its remaining segments DEGRADED — never
  a raw throw killing every query on the field. Real storage faults still
  propagate untouched.
- Torn generation artifacts (NaN/garbage in manifest or counter) DISCARD
  with narration at the store's open and recovery re-derives — plus a
  defensive finite-integer guard at the init consumer. Never a RangeError
  killing an open.

THE LOUD TORN-RECORD CONTRACT: an existing-but-unparseable stored record
now surfaces as a typed, counted TornRecordError on every entity-read
surface (including fifteen previously-blind per-item batch catches);
ENOENT stays clean-absent; artifact readers with designed absent-recovery
keep null-tolerance behind the loud floor. Disk corruption can no longer
read as silent data invisibility.

Suite migration: the default's pins inverted deliberately, generation
baselines made relative, quarantine-contract pins rewritten to the ruled
behavior.

Gates: tsc 0 · unit 2065/2065 (159 files) · integration 826 (93 files) ·
conformance 31/31 · kill-matrix 15/15 · torn-open guards 2/2.
This commit is contained in:
David Snelling 2026-08-11 08:37:38 -07:00
parent 67c606be69
commit 214c98b4d5
23 changed files with 833 additions and 154 deletions

View file

@ -96,11 +96,15 @@ describe('8.0 Db API — generational MVCC', () => {
}
/** Open (and track) a filesystem brain rooted at a fresh temp directory. */
async function openFsBrain(dir?: string): Promise<{ brain: Brainy; dir: string }> {
async function openFsBrain(
dir?: string,
logAuthority?: 'adopt' | 'defer'
): Promise<{ brain: Brainy; dir: string }> {
const rootDirectory = dir ?? makeTempDir()
const brain = new Brainy({
requireSubtype: false,
storage: { type: 'filesystem', path: rootDirectory }
storage: { type: 'filesystem', path: rootDirectory },
...(logAuthority ? { logAuthority } : {})
})
await brain.init()
brains.push(brain)
@ -647,7 +651,13 @@ describe('8.0 Db API — generational MVCC', () => {
// ==========================================================================
it('proof 8 — a crash before the manifest rename recovers to the exact pre-transaction state', async () => {
const dir = makeTempDir()
const { brain: first } = await openFsBrain(dir)
// 'defer' (tree authority): this proof pins the TREE commit-point
// contract — the manifest rename is the commit, so a crash before it
// rolls back. Under the adopt-at-open default (log authority) the same
// crash point legitimately REPLAYS the fsynced fact at reopen and the
// transaction lands — that contract is pinned in the durability kill
// matrix's at-ack rows, not here.
const { brain: first } = await openFsBrain(dir, 'defer')
await first.transact([
{
@ -689,9 +699,10 @@ describe('8.0 Db API — generational MVCC', () => {
// the realistic worst case for the recovery path.
await first.close()
// Reopen: recovery rolls the uncommitted generation back and rebuilds
// the indexes from the repaired records.
const { brain: second } = await openFsBrain(dir)
// Reopen ('defer' again — a reopen under the adopt default would adopt
// and change the recovery path): recovery rolls the uncommitted
// generation back and rebuilds the indexes from the repaired records.
const { brain: second } = await openFsBrain(dir, 'defer')
const recovered = await second.get(uid('crash-e'))
expect((recovered?.metadata as { v: number }).v).toBe(1)
expect(await second.get(uid('crash-new'))).toBeNull()
@ -1162,13 +1173,16 @@ describe('8.0 Db API — generational MVCC', () => {
const brain = await openMemoryBrain()
// Model-B: a single-op write is its OWN generation and IS logged (no meta —
// tx metadata is a transact()-only concept). It is generation 1 on a fresh
// brain (init-time infrastructure writes are the un-versioned gen-0 baseline).
// tx metadata is a transact()-only concept). Relative baseline: under the
// adopt-at-open fleet default the open-time baseline backfill is itself a
// logged single-op generation, so the log is not empty on a fresh brain —
// every pin below is expressed against that baseline.
const baseGens = (await brain.transactionLog()).map((entry) => entry.generation)
await brain.add({ id: uid('txlog-solo'), type: NounType.Document, data: 'solo', vector: vec(99), subtype: 'note' })
const soloLog = await brain.transactionLog()
expect(soloLog.map((entry) => entry.generation)).toEqual([1])
const soloGen = brain.generation()
expect(soloLog.map((entry) => entry.generation)).toEqual([soloGen, ...baseGens])
expect(soloLog[0].meta).toBeUndefined()
const soloGen = 1
const first = await brain.transact(
[{ op: 'add', id: uid('txlog-a'), type: NounType.Document, data: 'a', vector: vec(100), metadata: {} }],
@ -1181,12 +1195,14 @@ describe('8.0 Db API — generational MVCC', () => {
const third = await brain.transact([{ op: 'update', id: uid('txlog-a'), metadata: { v: 3 } }])
const entries = await brain.transactionLog()
// Newest first: the three transacts, then the single-op solo write (gen 1).
// Newest first: the three transacts, then the single-op solo write, then
// whatever the open baseline logged (the adopt-at-open backfill).
expect(entries.map((entry) => entry.generation)).toEqual([
third.generation,
second.generation,
first.generation,
soloGen
soloGen,
...baseGens
])
expect(entries[1].meta).toEqual({ author: 'job-2' })
expect(entries[2].meta).toEqual({ author: 'job-1' })
@ -1238,21 +1254,24 @@ describe('8.0 Db API — generational MVCC', () => {
const brain = await openMemoryBrain()
const a = uid('ov-a')
const b = uid('ov-b')
await (
await brain.transact([
{ op: 'add', id: a, type: NounType.Document, data: 'a', vector: vec(1), metadata: { v: 1 } },
{ op: 'add', id: b, type: NounType.Document, data: 'b', vector: vec(2), metadata: { v: 1 } }
])
).release()
const at1 = await brain.asOf(1)
// Pin RELATIVELY at the transact's own generation (not an absolute 1 —
// the adopt-at-open baseline backfill owns the first generation).
const tx = await brain.transact([
{ op: 'add', id: a, type: NounType.Document, data: 'a', vector: vec(1), metadata: { v: 1 } },
{ op: 'add', id: b, type: NounType.Document, data: 'b', vector: vec(2), metadata: { v: 1 } }
])
const txGen = tx.generation
await tx.release()
const at1 = await brain.asOf(txGen)
// A single-op REMOVE of `b` lands AFTER the pin and is NOT flushed (pending).
await brain.remove(b)
const liveIds = (await brain.find({})).map((r) => r.id)
const pastIds = (await at1.find({})).map((r) => r.id)
// Live: `b` is gone. Historical (pinned at gen 1): the un-flushed removal is
// overlaid out, so `b` is still present at its pinned state.
// Live: `b` is gone. Historical (pinned at the transact's generation): the
// un-flushed removal is overlaid out, so `b` is still present at its
// pinned state.
expect(liveIds).toContain(a)
expect(liveIds).not.toContain(b)
expect(pastIds).toContain(a)
@ -1262,11 +1281,14 @@ describe('8.0 Db API — generational MVCC', () => {
it('Model-B retention — explicit caps reclaim single-op history; committed history survives reopen', async () => {
const { brain, dir } = await openFsBrain()
// Relative baseline: the adopt-at-open backfill holds the first
// generation(s), so the 6 writes below land at base+1..base+6.
const base = brain.generation()
const a = uid('ret-a')
await brain.add({ id: a, type: NounType.Document, data: 'a', vector: vec(1), metadata: { v: 1 } })
for (let v = 2; v <= 6; v++) await brain.update({ id: a, metadata: { v } })
await brain.flush() // persist the per-write generations to disk
expect(brain.generation()).toBe(6)
expect(brain.generation()).toBe(base + 6)
// Cap to the 2 most recent generations — older single-op history is reclaimed.
const res = await brain.compactHistory({ maxGenerations: 2 })