brainy/tests
David Snelling bafb4e4caa feat: per-entity _rev + update({ ifRev }) CAS + add({ ifAbsent })
Optimistic concurrency for multi-writer coordination — the read-then-CAS
lock pattern + idempotent-bootstrap singleton inserts. Lands the surface the
SDK scheduler asked for in BRAINY-EXPOSE-TRANSACTIONS, scoped to what ships
cleanly without painting the 8.0 transact() API into a corner.

A. PER-ENTITY _rev FIELD

- src/coreTypes.ts — HNSWNounWithMetadata gains optional `_rev?: number`;
  STANDARD_ENTITY_FIELDS includes it so resolveEntityField routes correctly.
- src/types/brainy.types.ts — Entity<T> gains optional `_rev?: number`;
  Result<T> mirrors it on the convenience flatten layer.
- src/brainy.ts add() — initializes `_rev: 1` in storageMetadata. New entities
  always start at 1.
- src/brainy.ts update() — reads currentRev off the persisted metadata
  (falls back to 1 for pre-7.31.0 entities with no _rev), writes
  `_rev: currentRev + 1` into the updated metadata. Every successful update()
  bumps by exactly 1.
- src/brainy.ts convertNounToEntity + convertMetadataToEntity — both pull
  _rev out of the storage metadata and surface it at the top level of Entity.
  Pre-7.31.0 entities (no _rev in storage) read as `_rev: 1` so consumers
  see a consistent value.
- src/storage/baseStorage.ts — six destructure sites updated to pull _rev
  out of the metadata bag so it doesn't leak into customMetadata. Noun-side
  returns surface _rev; verb-side destructures correctly but doesn't expose
  it on HNSWVerbWithMetadata (verb CAS is future work).
- src/brainy.ts createResult() — flattens entity._rev onto the Result for
  backward compat with the existing convenience-field layer.

B. update({ ifRev }) OPTIMISTIC CONCURRENCY

- src/types/brainy.types.ts — UpdateParams<T> gains optional `ifRev?: number`.
- src/transaction/RevisionConflictError.ts (NEW) — carries `{ id, expected,
  actual }`. Message names the recipe: refetch with brain.get() and retry
  with the latest _rev. Subclass of Error.
- src/brainy.ts update() — when params.ifRev is provided, compares against
  currentRev (the rev we just read) and throws RevisionConflictError on
  mismatch before any storage write. Omitting ifRev keeps the prior
  unconditional-update behavior; existing consumers see no change.
- src/transaction/index.ts — exports RevisionConflictError.
- src/index.ts — public export of RevisionConflictError.

C. add({ ifAbsent }) BY-ID IDEMPOTENT INSERT

- src/types/brainy.types.ts — AddParams<T> gains optional `ifAbsent?: boolean`;
  AddManyParams<T> mirrors it as a batch-level flag.
- src/brainy.ts add() — when params.id AND params.ifAbsent, pre-reads
  storage.getNounMetadata(id); if present, returns the existing id without
  writing. No throw, no overwrite. Ignored when id is omitted (a fresh UUID
  can never collide).
- src/brainy.ts addMany() — propagates the batch-level ifAbsent to each
  item's add() call. Per-item ifAbsent takes precedence so callers can
  override individual rows.

WHAT'S NOT SHIPPED (and why)

A public brain.transaction(fn) wrapper was on the table but was cut. The
internal TransactionManager exposes raw Operation classes (SaveNounMetadata,
etc.) that take StorageAdapter as a constructor argument. A clean high-level
facade in 7.31.0 would have meant either:

  (a) Delegate to brain.add() / update() / relate(). Each of those opens its
      own internal transaction and commits before the closure returns. Looks
      atomic, isn't — a footgun.
  (b) Thread an optional `tx?` through every internal write site in
      brainy.ts (8 transactionManager.executeTransaction sites). ~2 days of
      real refactor with regression surface, and the API shape changes again
      in 8.0 anyway.

The SDK scheduler's actual ask (BRAINY-EXPOSE-TRANSACTIONS) is the
read-then-CAS lock pattern. _rev + ifRev solves it completely. Multi-write
atomicity is the 8.0 brain.transact() use case where the Datomic-style
immutable Db makes it atomic by construction — that's the right home.

TESTS

- New tests/integration/rev-and-ifabsent.test.ts (18 tests):
  - _rev initialization (1 on add) and surface on get fast/full paths + find
  - _rev auto-bump on update across multiple writes
  - update({ ifRev }) pass / fail / message format / omitted / legacy-no-rev
  - add({ ifAbsent }) writes when absent / no-op when present / id-required
  - addMany({ ifAbsent }) propagation + per-item override
  - SDK-scheduler scenario: two concurrent CAS updates, one wins one throws
- Unit suite unchanged: 1468/1468.
- All integration subtype + verb + strict + find-limits + new rev suites
  pass: 96/96.

DOCS

- New docs/guides/optimistic-concurrency.md (public: true) — full reference:
  the lock pattern, read-modify-write retry, idempotent bootstrap, how _rev
  interacts with brain.versions, branches/fork, and VFS, what's coming in 8.0.
- docs/api/README.md — add() and update() entries get the new params + tips
  pointing at the new guide.
- RELEASES.md v7.31.0 entry.

CORTEX COMPATIBILITY

Zero changes required. _rev is a metadata column already supported by
NativeColumnStore. The auto-bump runs in Brainy JS before any storage call;
Cortex never sees the per-entity counter.

8.0 FORWARD-COMPAT

_rev, ifRev, RevisionConflictError, and ifAbsent survive the 8.0 Db redesign
unchanged. 8.0 layers brain.transact(tx, { ifAtGeneration }) for whole-tx CAS
on top of the same per-entity mechanism — per-entity for single-record
patterns (job locks, idempotent state machines), generation-based for
"did the world move under me." Locked in .strategy/BRAINY-8.0-SUBTYPE-CONTRACT.md § C-6.

Verification

- npx tsc --noEmit: clean
- npm test: 1468 / 1468 unit
- All integration suites including new rev-and-ifabsent: 96/96
- npm run build: clean
- Closed-source product reference audit: clean
2026-06-09 10:04:24 -07:00
..
api feat: add stddev/variance aggregation ops with Welford's online algorithm 2026-02-17 17:04:11 -08:00
benchmarks refactor: remove augmentation system and semantic type matching 2026-02-01 10:48:56 -08:00
comprehensive feat: add stddev/variance aggregation ops with Welford's online algorithm 2026-02-17 17:04:11 -08:00
configs fix: eliminate flaky test timeouts and add storage adapters guide 2026-01-31 09:11:20 -08:00
fixtures/import feat: add intelligent import for CSV, Excel, and PDF files 2025-10-01 16:51:03 -07:00
helpers perf: eliminate N+1 patterns across all APIs for 10-20x faster cloud storage 2025-11-20 15:18:26 -08:00
integration feat: per-entity _rev + update({ ifRev }) CAS + add({ ifAbsent }) 2026-06-09 10:04:24 -07:00
integrations feat: Integration Hub for external tool connectivity 2026-01-20 16:21:11 -08:00
manual fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
performance fix: update all Stage 2 references to Stage 3 CANONICAL type counts 2025-11-06 09:40:33 -08:00
regression fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
scripts feat: Brainy 3.0 - Production-ready Triple Intelligence database 2025-09-11 16:23:32 -07:00
transaction feat: add v5.8.0 features - transactions, pagination, and comprehensive docs 2025-11-14 10:26:23 -08:00
unit fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
vfs fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
brainy-3.test.ts refactor: remove augmentation system and semantic type matching 2026-02-01 10:48:56 -08:00
critical-error-handling.test.ts feat: Brainy 3.0 - Production-ready Triple Intelligence database 2025-09-11 16:23:32 -07:00
critical-neural-validation.test.ts feat: enforce data/metadata separation, numeric range queries, improved docs 2026-02-09 12:07:54 -08:00
critical-performance-benchmark.test.ts feat: Brainy 3.0 - Production-ready Triple Intelligence database 2025-09-11 16:23:32 -07:00
distributed-demo.test.ts feat: Brainy 3.0 - Production-ready Triple Intelligence database 2025-09-11 16:23:32 -07:00
model-loading.test.ts 🧠 Brainy 2.0.0 - Zero-Configuration AI Database with Triple Intelligence™ 2025-08-26 12:32:21 -07:00
opfs-storage.test.ts 🧠 Brainy 2.0.0 - Zero-Configuration AI Database with Triple Intelligence™ 2025-08-26 12:32:21 -07:00
package-size-breakdown.test.ts 🧠 Brainy 2.0.0 - Zero-Configuration AI Database with Triple Intelligence™ 2025-08-26 12:32:21 -07:00
package-size-limit.test.ts 🧠 Brainy 2.0.0 - Zero-Configuration AI Database with Triple Intelligence™ 2025-08-26 12:32:21 -07:00
setup-integration.ts 🧠 Brainy 2.0.0 - Zero-Configuration AI Database with Triple Intelligence™ 2025-08-26 12:32:21 -07:00
setup-unit.ts 🧠 Brainy 2.0.0 - Zero-Configuration AI Database with Triple Intelligence™ 2025-08-26 12:32:21 -07:00
setup.ts 🧠 Brainy 2.0.0 - Zero-Configuration AI Database with Triple Intelligence™ 2025-08-26 12:32:21 -07:00
streaming-pipeline.test.ts refactor: remove augmentation system and semantic type matching 2026-02-01 10:48:56 -08:00
type-utils.test.ts 🧠 Brainy 2.0.0 - Zero-Configuration AI Database with Triple Intelligence™ 2025-08-26 12:32:21 -07:00
typeAwareHNSWIndex.test.ts feat: Phase 2 Type-Aware HNSW - 87% memory reduction @ billion scale 2025-10-15 15:39:28 -07:00