From c95bea88878e41804d2eddcc7757d1d7392e67d4 Mon Sep 17 00:00:00 2001 From: David Snelling Date: Mon, 10 Aug 2026 11:02:40 -0700 Subject: [PATCH] =?UTF-8?q?feat(conformance):=20the=20golden-log=20fold=20?= =?UTF-8?q?oracle=20=E2=80=94=20encoder=20bytes=20and=20fold=20semantics?= =?UTF-8?q?=20pinned=20by=20content=20hash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One deterministic v2 log (nine facts covering every fold-relevant behavior: genesis, after-images with minted ints, a deferred embed pending→landed, a sameAsGeneration vector ref, a verb, a tombstone, and an all-deduped empty commit) whose ENCODED BYTES and FOLDED STATE are both pinned by sha256 literals. The fixture (tests/fixtures/golden-log-v2.bin, 4128 B, byte-verified against the encoder on every run) is the shared artifact a second reader implementation consumes — it must reproduce the identical fold digest; the pair is normative on disagreement. The fold law is stated in prose beside the code: generation-ordered latest-per-id, tombstone masking, embed.landed vector application, single-hop ref resolution, key-sorted digest. Also: decodeGroupV2 discriminated pad filler by RECORD COUNT, silently swallowing legitimate empty commits (an all-deduped batch at a real generation). Pads carry generation 0 — which writers can never mint — so the generation is the honest discriminator; empty commits stay visible. Pins: 4/4 (encode-exact, fixture-identical, fold-exact, human-readable spot checks beside the hashes). --- src/db/factLogFormat.ts | 6 +- tests/conformance/golden-log-fold.test.ts | 170 ++++++++++++++++++++++ tests/fixtures/golden-log-v2.bin | Bin 0 -> 4128 bytes 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 tests/conformance/golden-log-fold.test.ts create mode 100644 tests/fixtures/golden-log-v2.bin diff --git a/src/db/factLogFormat.ts b/src/db/factLogFormat.ts index 8642d890..0ac93e1f 100644 --- a/src/db/factLogFormat.ts +++ b/src/db/factLogFormat.ts @@ -1298,7 +1298,11 @@ export function decodeGroupV2(bytes: Uint8Array, options?: DecodeFactV2Options): const payload = bytes.subarray(start, end) if (crc32c(payload) !== expectedCrc) break // torn tail: payload CRC mismatch const fact = decodeFactV2(payload, options) - if (fact.records.length > 0) facts.push(fact) // zero-record fact = pad filler + // Pad filler carries generation 0 (writers can never mint it — encode + // refuses generation < 1). A zero-record fact at a REAL generation is a + // legitimate commit (an all-deduped batch) and must stay visible — + // discriminating on record count would silently swallow generations. + if (fact.generation > 0) facts.push(fact) offset = end } return { facts, validBytes: offset } diff --git a/tests/conformance/golden-log-fold.test.ts b/tests/conformance/golden-log-fold.test.ts new file mode 100644 index 00000000..c480bee5 --- /dev/null +++ b/tests/conformance/golden-log-fold.test.ts @@ -0,0 +1,170 @@ +/** + * @module tests/conformance/golden-log-fold + * @description THE GOLDEN-LOG FOLD-CONFORMANCE ORACLE (brainy leg). + * + * One deterministic v2 log — fixed ids, ints, timestamps, vectors — whose + * ENCODED BYTES and whose FOLDED STATE are both pinned by content hash. + * The second (native) reader implementation consumes the identical fixture + * (tests/fixtures/golden-log-v2.bin, written and verified here) and must + * produce the identical fold digest; the pair is normative on disagreement. + * + * What the pins catch, loudly: + * - Any byte drift in the encoder (envelope, msgpack layout, seals, CRC). + * - Any semantic drift in the fold (tombstone masking, vector landing, + * sameAsGeneration resolution, last-writer-wins ordering). + * - Any divergence between the two implementations, before the cut. + * + * The pinned hashes change ONLY with a deliberate, versioned format or + * fold-law change — never silently. Updating them requires updating the + * fixture AND the native side in the same train. + */ +import { describe, it, expect } from 'vitest' +import { createHash } from 'node:crypto' +import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs' +import { join, dirname } from 'node:path' +import { + encodeFactV2, + encodeSegmentHeaderV2, + sealGroup, + decodeGroupV2, + SEGMENT_HEADER_BYTES, + type CommitFactV2, + type LogRecord +} from '../../src/db/factLogFormat.js' +import { recordDigest } from '../../src/db/logAuthority.js' + +const FIXTURE = join(__dirname, '../fixtures/golden-log-v2.bin') + +const sha256 = (b: Uint8Array): string => createHash('sha256').update(b).digest('hex') + +// Fixed identities — never regenerate. +const BRAIN = '00000000-0000-4000-8000-00000000b1a1' +const A = '00000000-0000-4000-8000-0000000000a1' +const B = '00000000-0000-4000-8000-0000000000b2' +const C = '00000000-0000-4000-8000-0000000000c3' +const V = '00000000-0000-4000-8000-0000000000d4' + +const vec = (seed: number): number[] => [seed + 0.25, seed + 0.5, seed + 0.75] + +/** The golden fact sequence — every fold-relevant behavior in nine facts. */ +function goldenFacts(): CommitFactV2[] { + const f = (generation: number, records: LogRecord[]): CommitFactV2 => ({ + generation, + timestamp: 1_700_000_000_000 + generation, + records + }) + return [ + f(1, [{ type: 'log.genesis', idSpaceWidth: 64, brainId: BRAIN, createdAt: 1_700_000_000_000 }]), + f(2, [{ type: 'noun.afterImage', id: A, entityInt: 1n, metadata: { name: 'alpha', rank: 1 }, vectorLeg: vec(1) }]), + f(3, [ + { type: 'noun.afterImage', id: B, entityInt: 2n, metadata: { name: 'beta' }, vectorLeg: null }, + { type: 'embed.pending', id: B, enqueuedAt: 1_700_000_000_003 } + ]), + // A metadata-only update: the vector rides by reference to generation 2. + f(4, [{ type: 'noun.afterImage', id: A, entityInt: 1n, metadata: { name: 'alpha', rank: 2 }, vectorLeg: { sameAsGeneration: 2 } }]), + // B's deferred vector lands. + f(5, [{ type: 'embed.landed', id: B, vector: vec(9) }]), + // A relationship. + f(6, [{ type: 'verb.afterImage', id: V, verbInt: 3n, metadata: { w: 0.5 }, vectorLeg: null, verb: 'relatedTo', sourceId: A, sourceInt: 1n, targetId: B, targetInt: 2n }]), + // C exists briefly… + f(7, [{ type: 'noun.afterImage', id: C, entityInt: 4n, metadata: { name: 'gamma' }, vectorLeg: vec(7) }]), + // …and is tombstoned (masking must hold in the fold). + f(8, [{ type: 'noun.tombstone', id: C }]), + // An all-deduped batch: a real generation with zero records. + f(9, []) + ] +} + +/** Build the golden segment: v2 header + sealed frame group. */ +function goldenSegment(): Uint8Array { + // Single-hop law: generation 2 carried A's inline vector (5 carries B's + // via embed.landed); the ref in generation 4 must verify against it. + const inline = new Set([2, 5, 7]) + const frames = goldenFacts().map((fact) => encodeFactV2(fact, { inlineVectorGenerations: inline })) + const sealed = sealGroup(frames, 4096) + const out = new Uint8Array(SEGMENT_HEADER_BYTES + sealed.length) + out.set(encodeSegmentHeaderV2(1, 4096), 0) + out.set(sealed, SEGMENT_HEADER_BYTES) + return out +} + +/** + * THE FOLD LAW (shared with the native implementation, normative): + * fold facts in generation order → per-id latest state with tombstone + * masking; embed.landed applies the vector to the id's current state; + * {sameAsGeneration: N} resolves to the inline vector the log carried at N; + * verbs fold like nouns under their own ids. Digest = recordDigest (key- + * sorted JSON sha256) of the id-sorted state map. + */ +function foldGoldenLog(bytes: Uint8Array): string { + const group = decodeGroupV2(bytes.slice(SEGMENT_HEADER_BYTES)) + const state = new Map>() + const inlineVectorAt = new Map() + for (const fact of group.facts) { + for (const rec of fact.records) { + if (rec.type === 'noun.afterImage' || rec.type === 'verb.afterImage') { + let vector: number[] | null = null + if (Array.isArray(rec.vectorLeg)) { + vector = rec.vectorLeg + inlineVectorAt.set(fact.generation, vector) + } else if (rec.vectorLeg && typeof rec.vectorLeg === 'object' && 'sameAsGeneration' in rec.vectorLeg) { + vector = inlineVectorAt.get((rec.vectorLeg as { sameAsGeneration: number }).sameAsGeneration) ?? null + } + state.set(rec.id, { + kind: rec.type === 'noun.afterImage' ? 'noun' : 'verb', + int: (rec.type === 'noun.afterImage' + ? (rec as { entityInt: bigint }).entityInt + : (rec as { verbInt: bigint }).verbInt + ).toString(), + metadata: rec.metadata, + vector, + generation: fact.generation + }) + } else if (rec.type === 'noun.tombstone' || rec.type === 'verb.tombstone') { + state.delete(rec.id) + } else if (rec.type === 'embed.landed') { + const cur = state.get(rec.id) + if (cur) state.set(rec.id, { ...cur, vector: rec.vector, generation: fact.generation }) + inlineVectorAt.set(fact.generation, rec.vector) + } + // embed.pending / genesis / blob / projection notes carry no fold state here. + } + } + const sorted = [...state.entries()].sort(([x], [y]) => (x < y ? -1 : 1)) + return recordDigest(sorted) +} + +// ── THE PINS ──────────────────────────────────────────────────────────────── +// Byte-exact encode + semantics-exact fold. These literals are the contract. +const GOLDEN_BYTES_SHA256 = 'f898ed29f6f7d41135c6c85eb07725348b20cf8efec5f050ff50ad6d54a09dad' +const GOLDEN_FOLD_DIGEST = 'fad1b1d9865d6c9c84493c5481599ebd39b7ecf4cd203af4c435dfea7cd78ed4' + +describe('golden-log fold conformance (brainy leg)', () => { + it('the encoder reproduces the golden bytes exactly', () => { + const seg = goldenSegment() + expect(seg.length % 4096, 'sealed to the sector boundary (header excluded)').toBe(SEGMENT_HEADER_BYTES % 4096) + expect(sha256(seg)).toBe(GOLDEN_BYTES_SHA256) + }) + + it('the fixture on disk is byte-identical (the shared artifact both readers consume)', () => { + const seg = goldenSegment() + if (!existsSync(FIXTURE)) { + mkdirSync(dirname(FIXTURE), { recursive: true }) + writeFileSync(FIXTURE, seg) + } + const onDisk = new Uint8Array(readFileSync(FIXTURE)) + expect(sha256(onDisk), 'fixture bytes match the encoder').toBe(GOLDEN_BYTES_SHA256) + }) + + it('folding the golden log yields the pinned state digest', () => { + expect(foldGoldenLog(goldenSegment())).toBe(GOLDEN_FOLD_DIGEST) + }) + + it('fold semantics spot-checks (human-readable guardrails beside the hash)', () => { + const group = decodeGroupV2(goldenSegment().slice(SEGMENT_HEADER_BYTES)) + expect(group.facts.length, 'nine facts, pads invisible').toBe(9) + const gens = group.facts.map((f) => f.generation) + expect(gens).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]) + expect(group.facts[8].records).toEqual([]) + }) +}) diff --git a/tests/fixtures/golden-log-v2.bin b/tests/fixtures/golden-log-v2.bin new file mode 100644 index 0000000000000000000000000000000000000000..c1e4cabd8074c9820d9ea0fb901c257f545ccb24 GIT binary patch literal 4128 zcmeHEze~eF82v8kPb{>Pn+ghogR`5B3W9@+ExHLQjTUUHgo0~padI&YtuCU)cIc>o zK>45wg$!LfI_Tiy)WJcjgV&^Y1&xBEa0kgf?z{KB_q|(QU0R9903-k)^s`rl0e}Sx zA7+ck<<9VoP(V&P&naS@jS)cQZg^XPynW@S%5DH+k{-3qM1<2NR+Nl$Lg`=GFkst@ z9M!UFMyspogOpm+)$ATIt>~*$w4!eed^i9xL4jOOg}Ii@wB(Yz)-BVL3bs})q2*Mp z_}qLA?%H$9h?`VtBhqYgB@Zil{yvpdy4JNF?gVj-cJE#GuXuMa>+Urwephd%rA+53 z4Zu=n?0o?8HbN}YJ^$VwHT1EDKI1}mYuIIWX!eJhPp zM%<>I^u?`pKAWFe@&Axqi&^nFZ&cq^GZ~c*JmHwKlt~7rhBk4Yg1JWjg{uUZO28;f zZUeUv$0;csOKF@GWTfCJVlM>nq{qCx3d|Q6CXoA3*AW+gk$^}*Bp?zH35Wzl0wMvC NfJi_j@IMnk`~(Gu$Atg@ literal 0 HcmV?d00001