brainy/src
David Snelling 3b8fa51161 fix: transact durability barrier — committed transactions are durable on return
A committed transact() reported success while its canonical entity writes were
still only in the OS page cache (tmp+rename, not fsync'd), even though the
generation counter and manifest were fsync'd. A hard kill in that window could
leave the durable counter ahead of the persisted entity bytes — phantom
progress for any generation-based consumer resuming from the counter. Reported
from a downstream migration's crash-lifecycle forensics.

Add an optional transaction durability barrier to GenerationStorage
(beginWriteBarrier / flushWriteBarrier). FileSystemStorage implements it:
writeObjectToPath records each successful canonical write and
deleteObjectFromPath records each delete's parent dir, between begin and flush;
flush fsyncs every recorded write (contents + rename dir entries, via
syncRawObjects) and the parent dir of every delete. commitTransaction opens the
barrier before running the planned operations and flushes it after, BEFORE
persisting the counter and manifest — so the batch's entire canonical footprint
is durable before the generation stamp advances. The barrier is optional: the
generation store calls it through optional chaining, so in-memory and
durable-per-call (cloud object-PUT) adapters treat it as a no-op.

The single-op group-commit path is unchanged (deferred durability is the
Model-B design that avoids a 3-5x per-write fsync regression), but its
durability contract is now documented explicitly on commitSingleOp: transact =
durable on return; single-op = durable at the next flush()/close(), with the
counter buffered alongside the data so a crash loses both together (never a
torn counter-ahead-of-state store).

Regression (tests/integration/transact-durability-barrier.test.ts): the entity
writes fsync in an earlier syncRawObjects batch than the manifest for single-op
and multi-op (add+relate) transactions; a precommit-rejected batch opens no
barrier and advances nothing; MemoryStorage exposes no barrier (optional-chain
no-op).
2026-07-12 08:54:14 -07:00
..
aggregation docs: rename the native provider to @soulcraft/cor across public docs and JSDoc 2026-07-02 15:11:41 -07:00
cli refactor(8.0): remove dead, unreachable, and unwired modules 2026-06-24 15:18:40 -07:00
db fix: transact durability barrier — committed transactions are durable on return 2026-07-12 08:54:14 -07:00
embeddings docs: rename the native provider to @soulcraft/cor across public docs and JSDoc 2026-07-02 15:11:41 -07:00
errors fix: validate where-operators and align the in-memory matcher to the documented set 2026-07-07 12:23:36 -07:00
events feat: brain.onChange — the in-process change feed for every committed mutation 2026-07-10 11:24:31 -07:00
graph fix: cold-open no longer re-derives durable indexes — complete the readiness contract for all three providers 2026-07-07 10:39:00 -07:00
hnsw docs: rename the native provider to @soulcraft/cor across public docs and JSDoc 2026-07-02 15:11:41 -07:00
import refactor(8.0): remove dead, unreachable, and unwired modules 2026-06-24 15:18:40 -07:00
importers refactor(8.0): remove dead/deprecated code (legacy sweep) 2026-06-29 10:09:39 -07:00
indexes/columnStore docs: rename the native provider to @soulcraft/cor across public docs and JSDoc 2026-07-02 15:11:41 -07:00
integrations chore(8.0): ES2023 target + drop DOM lib + downlevelIteration (config truth-up) 2026-07-01 10:58:04 -07:00
mcp refactor(8.0): remove dead, unreachable, and unwired modules 2026-06-24 15:18:40 -07:00
migration feat(8.0)!: delete fork/branch/commit/history/versions — superseded by the Db API 2026-06-10 15:22:47 -07:00
neural docs: rename the native provider to @soulcraft/cor across public docs and JSDoc 2026-07-02 15:11:41 -07:00
patterns chore(8.0): final pre-RC1 sweep — API consistency, named errors, orphans, zero-cast codebase 2026-06-11 14:51:00 -07:00
storage fix: transact durability barrier — committed transactions are durable on return 2026-07-12 08:54:14 -07:00
streaming chore(8.0): final pre-RC1 sweep — API consistency, named errors, orphans, zero-cast codebase 2026-06-11 14:51:00 -07:00
transaction fix: transaction timeout rolls back applied operations (no torn state) 2026-07-11 13:44:15 -07:00
triple chore(8.0): Phase A + B — purge all @deprecated APIs + cacheManager dead branches 2026-06-09 15:33:56 -07:00
types feat: guarded plugin auto-detection — installing @soulcraft/cor is the opt-in 2026-07-02 16:19:55 -07:00
universal refactor(8.0): remove dead, unreachable, and unwired modules 2026-06-24 15:18:40 -07:00
utils fix: validate where-operators and align the in-memory matcher to the documented set 2026-07-07 12:23:36 -07:00
vfs feat: temporal VFS — file content joins the Model-B immutability model 2026-07-10 16:43:48 -07:00
brainy.ts fix: transact forward references resolve graph endpoint ints at execute time 2026-07-10 18:06:37 -07:00
coreTypes.ts feat(8.0): auto pre-upgrade backup — hard-link snapshot before the 7.x→8.0 migration 2026-07-01 15:04:01 -07:00
index.ts feat: temporal VFS — file content joins the Model-B immutability model 2026-07-10 16:43:48 -07:00
internals.ts docs: rename the native provider to @soulcraft/cor across public docs and JSDoc 2026-07-02 15:11:41 -07:00
plugin.ts fix: cold-open no longer re-derives durable indexes — complete the readiness contract for all three providers 2026-07-07 10:39:00 -07:00
setup.ts chore(8.0): collapse dead defensive guards + redundant polyfills 2026-06-09 16:46:16 -07:00