brainy/tests/unit/brainy
David Snelling 61c247c923 fix: cold-open no longer re-derives durable indexes — complete the readiness contract for all three providers
A production deployment measured ~48 seconds on EVERY reopen of an
11k-entity brain. Root cause: brainy's rebuild gate decided from in-memory
size()/count, which read 0 for a durable-but-not-resident index, so it
re-read every entity file to rebuild from scratch. At GA we gave only the
GRAPH provider a readiness contract (init() eager cold-load + isReady()
honest signal) so it would never eat that spurious rebuild; the vector and
metadata providers never got it, and brainy never even eager-inited the
vector provider.

Complete the contract symmetrically:

- plugin.ts: VectorIndexProvider gains optional init()+isReady();
  MetadataIndexProvider gains isReady() — mirroring GraphIndexProvider.
  Additive and optional; a provider that exposes nothing keeps today's
  behavior.
- brainy.ts: eager-init every provider that exposes init() (after metadata
  init() so the id-mapper is hydrated first), then decide per leg in
  precedence order — migrating (skip) -> epoch drift (rebuild) -> isReady()
  -> a per-leg empty fallback. The old instant fast-path keyed off
  this.index.size()>0, a dishonest proxy that skipped the metadata/graph
  checks whenever the vector was warm and never fired on a real cold process
  anyway; removed.

The per-leg fallbacks differ because "empty" means different things: the JS
vector's rebuild() IS its load, so size()===0 correctly triggers it; the
id-mapper backs metadata, so totalEntries===0 (past the empty-store return)
is a real load failure; but entities do not imply edges, so a graph
size()===0 is a valid empty state, not a load failure.

- The JS graph now COLD-LOADS its durable LSM instead of re-deriving from a
  full canonical verb scan on every boot (baseStorage._initializeGraphIndex
  loads the persisted SSTables via a new GraphAdjacencyIndex.init(); it
  self-heals from canonical only when the durable state is genuinely missing).
  This removes an O(E)-per-open cost every filesystem consumer paid.
- LSMTree.loadManifest loads its SSTables BEFORE publishing the relationship
  count, and resets to an honest-empty state on load failure — a tree can no
  longer claim persisted relationships while holding none (the silent-empty
  cold-load class the query-time guards exist to prevent).

Verified end-to-end against a built brain: a warm reopen (with edges and
edgeless) reloads only the JS vector; the graph and metadata cold-load with
no rebuild, and queries return correct results. New tests in
cold-open-rebuild-gate.test.ts pin the contract (isReady() defers, self-heal
still fires); migration-deference updated to drive size-based deference
through the vector, the leg where empty->rebuild remains correct.

Pairs with the native provider's isReady()/init() implementation — brainy's
gate defers only to a signal the provider exposes.
2026-07-07 10:39:00 -07:00
..
add.test.ts fix: flush all native providers on shutdown to prevent data loss 2026-02-01 16:23:49 -08:00
batch-operations.test.ts refactor(8.0): API-surface + quality polish from the readiness audit 2026-06-29 10:04:19 -07:00
brain-format-handshake.test.ts feat(8.0): version-handshake marker (formatInfo + indexEpoch) for whole-brain auto-upgrade 2026-06-30 09:53:10 -07:00
counts-by-type-fix.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
fill-subtypes.test.ts chore(8.0): final pre-RC1 sweep — API consistency, named errors, orphans, zero-cast codebase 2026-06-11 14:51:00 -07:00
find-agg-edge-cases.test.ts fix(8.0): distinctCount aggregates distinct values of any type + edge-case regression tests 2026-06-17 12:03:06 -07:00
find-complement-operators.test.ts perf(8.0): negation/absence where-operators via roaring-bitmap difference 2026-06-29 11:19:18 -07:00
find-include-vectors.test.ts feat(8.0): upsert + FindParams.includeVectors + removeMany adaptive chunking 2026-06-20 16:34:20 -07:00
find-index-integrity-guard.test.ts fix(8.0): re-validate find() results against the predicate (index-integrity guard) 2026-06-24 16:25:12 -07:00
find-orderby-pagek.test.ts perf(8.0): bound find({ where, orderBy }) sort to the page (CTX-BR-FIND-ORDERBY) 2026-06-23 15:01:49 -07:00
find.test.ts feat(8.0)!: flip requireSubtype default to true (BRAINY-8.0-SUBTYPE-CONTRACT § C-1) 2026-06-09 14:58:25 -07:00
get.test.ts test(8.0): get() resolves null for absent custom ids instead of throwing 2026-06-16 10:47:10 -07:00
graph-analytics.test.ts feat(8.0): graph analytics — brain.graph.rank / communities / path 2026-06-23 12:32:03 -07:00
graph-export.test.ts feat(8.0): brain.graph.export() + noun-walk cursor + noun visibility hydration 2026-06-21 10:22:12 -07:00
graph-native-routing.test.ts fix(8.0): gate native graph analytics on the provider readiness flag 2026-06-24 15:18:50 -07:00
graph-subgraph.test.ts feat(8.0): brain.graph.subgraph(query) query→expand fusion (#61) 2026-06-23 13:30:30 -07:00
hybrid-search.test.ts feat(8.0)!: flip requireSubtype default to true (BRAINY-8.0-SUBTYPE-CONTRACT § C-1) 2026-06-09 14:58:25 -07:00
metadata-provider-contract.test.ts feat(8.0): wire the two cor-confirmed metadata-provider contract additions 2026-06-29 12:11:00 -07:00
migration-deference.test.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
relate-duplicate-optimization.test.ts chore(8.0): final pre-RC1 sweep — API consistency, named errors, orphans, zero-cast codebase 2026-06-11 14:51:00 -07:00
relate.test.ts chore(8.0): final pre-RC1 sweep — API consistency, named errors, orphans, zero-cast codebase 2026-06-11 14:51:00 -07:00
related-node-bidirectional.test.ts feat(8.0): related({ node }) — one-call both-direction incident edges 2026-06-21 08:43:55 -07:00
related-visibility-fast-path.test.ts perf(8.0): visibility-aware fast adjacency — related() stays O(degree) under default visibility 2026-06-20 16:34:32 -07:00
reserved-field-policy.test.ts feat(8.0): reserved-field enforcement — reservedFieldPolicy defaults to throw 2026-06-20 15:37:21 -07:00
similar-threshold.test.ts feat(8.0): API simplification — remove neural()/Db.search, one storage path key, integration→0 2026-06-20 13:31:11 -07:00
update-reserved-metadata-remap.test.ts feat(8.0): reserved-field enforcement — reservedFieldPolicy defaults to throw 2026-06-20 15:37:21 -07:00
update.test.ts feat(8.0): full query surface at historical generations via ephemeral index materialization 2026-06-11 08:12:11 -07:00
upsert.test.ts feat(8.0): upsert + FindParams.includeVectors + removeMany adaptive chunking 2026-06-20 16:34:20 -07:00
visibility.test.ts feat(8.0): reserved-field enforcement — reservedFieldPolicy defaults to throw 2026-06-20 15:37:21 -07:00