open-brainy/tests/integration/txlog-origin-and-reconcile.test.ts
David Snelling 9ac9e70686 feat(log): system commits carry their origin; the attested per-id reconcile door
Two consumer-driven cures sharing one stamp. (1) TX-LOG ORIGIN: engine-
originated commits stamp an optional origin on their tx-log entry AND the
commit fact's meta — 'system:embed-landing' (the deferred vector landing),
'system:adoption-backfill' (baseline re-commits), 'system:reconcile'. A
downstream activity feed showed a double tick because the landing commit was
indistinguishable from a user save, and the consumer rightly refused a
time-window collapse as a quiet loss; feeds now filter on fact. User writes
stay unstamped — absent origin is the user shape, every existing consumer
unchanged. (2) reconcileLogDivergence(id, {attest}): the human's door for
log-live-canonical-absent, the one class adoption refuses by design because
a lost-tombstone deletion is indistinguishable from canonical loss.
'deleted' mints the missing tombstone (history keeps the earlier live
record); 'restore' folds the log's only copy back into canonical; wrong-
class calls refuse typed with nothing written. Loud, narrated, single-row,
origin-stamped. From a production adoption's one surviving divergence.
2026-08-17 16:21:25 -07:00

142 lines
5.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @module tests/integration/txlog-origin-and-reconcile
* @description Two consumer-driven cures, pinned together because they share
* the origin stamp:
*
* 1. TX-LOG ORIGIN — engine-originated commits stamp `origin` on their
* tx-log entry (and the commit fact's meta) so activity feeds filter on
* fact: a downstream feed showed a "double tick" because the deferred
* vector-landing commit was indistinguishable from a user save, and the
* consumer rightly refused a time-window collapse as a quiet loss. User
* writes stay UNSTAMPED (absent origin) — the pre-existing reading of
* every consumer is exact.
*
* 2. THE RECONCILE DOOR — `log-live-canonical-absent` refuses auto-cure by
* design (a legitimate lost-tombstone deletion is indistinguishable from
* canonical loss); `reconcileLogDivergence(id, {attest})` is the human's
* door: 'deleted' mints the missing tombstone, 'restore' folds the log's
* copy back, wrong-class calls refuse typed with nothing written.
*/
import { describe, it, expect, afterEach } from 'vitest'
import { mkdtempSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { Brainy } from '../../src/index.js'
import { NounType } from '../../src/types/graphTypes.js'
type RawBox = {
storage: {
readNounRaw(id: string): Promise<{ metadata: unknown; vector: unknown }>
writeNounRaw(id: string, r: { metadata: unknown; vector: unknown }): Promise<void>
}
}
const dirs: string[] = []
const brains: Brainy[] = []
afterEach(async () => {
for (const b of brains.splice(0)) await b.close().catch(() => {})
for (const d of dirs.splice(0)) rmSync(d, { recursive: true, force: true })
})
async function fsBrain(): Promise<Brainy> {
const dir = mkdtempSync(join(tmpdir(), 'brainy-origin-reconcile-'))
dirs.push(dir)
const brain = new Brainy({
storage: { type: 'filesystem', path: dir },
requireSubtype: false
})
await brain.init()
brains.push(brain)
return brain
}
describe('tx-log origin stamp', () => {
it('the deferred-embed landing commit is stamped system:embed-landing; the user write is not', async () => {
const brain = await fsBrain()
await brain.add({
data: 'a row whose vector lands later',
type: NounType.Document,
metadata: { k: 1 },
deferEmbedding: true
})
await brain.awaitPendingEmbeds()
await brain.flush()
const entries = await brain.transactionLog()
const system = entries.filter((e) => (e as { origin?: string }).origin === 'system:embed-landing')
const user = entries.filter((e) => !(e as { origin?: string }).origin)
expect(system.length, 'the landing commit is stamped').toBeGreaterThanOrEqual(1)
expect(user.length, 'the user add stays unstamped').toBeGreaterThanOrEqual(1)
// The feed cure in one line: filtering !origin removes the double tick.
expect(user.length).toBeLessThan(entries.length)
}, 120000)
})
describe('reconcileLogDivergence — the attested door', () => {
/** Manufacture the class: a live log record whose canonical row is gone. */
async function manufactureDivergence(brain: Brainy): Promise<string> {
const id = await brain.add({
data: 'pre-era row whose deletion the log never saw',
type: NounType.Document,
metadata: { era: 'pre-spine' }
})
await brain.flush()
// Delete canonical BEHIND the log's back (raw write, no generation) —
// exactly the shape a deferred-durability-era crash left behind.
const storage = (brain as unknown as RawBox).storage
await storage.writeNounRaw(id, { metadata: null, vector: null })
return id
}
it("attest:'deleted' mints the missing tombstone — the oracle goes green and the commit is stamped system:reconcile", async () => {
const brain = await fsBrain()
const id = await manufactureDivergence(brain)
const before = await brain.verifyLogAuthority()
expect(
before.mismatches.some((m) => m.id === id && m.reason === 'log-live-canonical-absent'),
'the manufactured divergence is oracle-visible as the refused class'
).toBe(true)
const result = await brain.reconcileLogDivergence(id, { attest: 'deleted' })
expect(result.reconciled).toBe('tombstoned')
const after = await brain.verifyLogAuthority()
expect(after.mismatches.some((m) => m.id === id), 'the id no longer diverges').toBe(false)
expect(await brain.get(id), 'canonical stays absent').toBeNull()
await brain.flush()
const entries = await brain.transactionLog()
expect(
entries.some((e) => (e as { origin?: string }).origin === 'system:reconcile'),
'the reconcile commit is origin-stamped'
).toBe(true)
}, 120000)
it("attest:'restore' folds the log's copy back into canonical", async () => {
const brain = await fsBrain()
const id = await manufactureDivergence(brain)
const result = await brain.reconcileLogDivergence(id, { attest: 'restore' })
expect(result.reconciled).toBe('restored')
const row = await brain.get(id)
expect(row, 'the logs only copy lives again').not.toBeNull()
expect((row!.metadata as { era: string }).era).toBe('pre-spine')
expect((await brain.verifyLogAuthority()).mismatches.some((m) => m.id === id)).toBe(false)
}, 120000)
it('wrong-class calls refuse typed with nothing written', async () => {
const brain = await fsBrain()
const id = await brain.add({ data: 'healthy row', type: NounType.Document, metadata: { n: 1 } })
await brain.flush()
// Canonical present + log agrees: not the class — refuse, name the state.
await expect(brain.reconcileLogDivergence(id, { attest: 'deleted' })).rejects.toThrow(
/canonical is PRESENT/
)
expect(await brain.get(id), 'nothing was written').not.toBeNull()
// Unknown id: no log record at all — refuse, name it.
await expect(
brain.reconcileLogDivergence('00000000-0000-7000-8000-00000000dead', { attest: 'restore' })
).rejects.toThrow(/no record at all/)
}, 120000)
})