open-brainy/tests/unit/db/pad-frame-total.test.ts
David Snelling cbe34d115e
All checks were successful
CI / Node 22 (push) Successful in 12m14s
CI / Node 24 (push) Successful in 12m7s
CI / Bun (latest) (push) Successful in 12m21s
fix(log): pad-frame construction is total; the at-ack sync-failure compensation splits by phase — a production adoption's two write-path defects, cured at their roots
An adopter's full suite found two v2 write-path defects on fresh brains,
reproduced with stacks; both cured and both pinned with their exact
production shapes:

1. PAD-FRAME CONSTRUCTIBILITY: a single msgpack bin filler steps its
   header by one byte at each size class (bin8→bin16→bin32), leaving one
   unreachable payload size per boundary — the sealer requested a
   291-byte pad, the encoder threw 'not constructible', and sync() died
   whole. Construction is now TOTAL: the class-boundary holes bridge with
   a trailing fixint beside the bin ({bin(n)} ∪ {bin(n)+fixint} covers
   every size ≥ minimum). Pinned exhaustively: every size from the
   minimum through a full sector plus boundary spill constructs
   byte-exact and decodes as reader-invisible filler.

2. THE NON-MONOTONIC REFUSAL LOOP: the append-failure compensation
   rewound the generation counter on ANY throw — including a covering
   SYNC failure after a SUCCESSFUL append. The log carried generation N
   while the counter re-minted N, and every later append refused
   'non-monotonic (N ≤ head N)' — the write path wedged in a refusal
   loop through deferred-embed retries and flush backoff. The
   compensation now splits by phase: an append failure (log never took
   the fact) fully compensates — un-buffer and rewind; a sync failure
   after append earns the rewind ONLY if the appended fact is provably
   dropped, otherwise the generation stays consumed and buffered — the
   counter never re-mints a number the log may carry. Pinned: an
   injected one-shot sync failure fails its write loudly and the very
   next write mints fresh and succeeds, with the log scanning strictly
   ascending end to end.

Also probed against the adopter's carried report: the 9.0 vfs.rename
stale-ghost shape does NOT reproduce on this head (old path cleanly
unresolvable on exists/stat/readdir after rename).

Gates: unit 2067/2067 (160 files) · integration 833 (97 files) ·
conformance 36/36.
2026-08-12 16:09:48 -07:00

29 lines
1.3 KiB
TypeScript

/**
* @module tests/unit/db/pad-frame-total
* @description Pad-frame construction is TOTAL: every size from the minimum
* through 4096+257 is constructible byte-exact (a production adoption found
* the msgpack class-boundary hole at 291 bytes — sync died whole, and the
* failure cascaded into a counter rewind after a successful append). Every
* constructed pad decodes as skip-by-definition filler.
*/
import { describe, it, expect } from 'vitest'
import { encodePadFrame, minPadFrameBytes, decodeGroupV2 } from '../../../src/db/factLogFormat.js'
describe('pad frames are constructible at EVERY size', () => {
it('exact construction from the minimum through a full sector + boundary spill', () => {
const min = minPadFrameBytes()
for (let size = min; size <= 4096 + 257; size++) {
const frame = encodePadFrame(size)
expect(frame.length, `size ${size}`).toBe(size)
}
})
it('the production case (291) and its class-boundary siblings decode as invisible filler', () => {
for (const size of [291, minPadFrameBytes(), 300, 511, 512, 513, 4096]) {
const frame = encodePadFrame(size)
const group = decodeGroupV2(frame)
expect(group.facts, `size ${size} is reader-invisible`).toEqual([])
expect(group.validBytes).toBe(size)
}
})
})