Commit graph

8 commits

Author SHA1 Message Date
0e3facf4a8 fix(recovery): walks are healers — the typed/tolerant boundary redrawn where block-layer fault injection proved it belonged
All checks were successful
CI / Node 22 (push) Successful in 12m16s
CI / Node 24 (push) Successful in 12m13s
CI / Bun (latest) (push) Successful in 12m20s
The quiet-loss cure regressed recovery: the new typed torn-record error
was correct at identity-read time but threw inside init-time recovery
walks, killing opens that previously survived. The boundary, redrawn:

- IDENTITY READS (get-by-id of a specific record, CAS blob point-get):
  typed TornRecordError, unchanged — a caller who asked for THAT record
  can act on the answer.
- SET-SHAPED READS AND WALKS (enumeration, pagination, batch hydration —
  the paths recovery rebuilds and finds page over): HEAL PAST the torn
  victim. The adapter's loud floor (error log + counted gauge) fires at
  the encounter; the walk serves the remaining rows. One crash casualty
  can no longer kill every query on its shard — or the open itself.
- WRITES OVER TORN RECORDS ARE THE CURE: the save path's read-merge, the
  commit path's before-image capture, and the operations' rollback
  captures all treat a torn prior as the create sentinel, narrated — the
  incoming bytes replace the unreadable ones, and history for the id
  honestly restarts at that generation. Corruption can never block its
  own heal.
- THE NaN SOURCE: torn mapper state (nextId/entries carrying garbage)
  discards with narration and re-derives via the existing rebuild path;
  the mint gains a source guard healing a non-integer counter from the
  live map. The reopen and first-write RangeError shapes are dead at the
  source, both authority branches.

Pinned with the exact fault-injection scenarios: a torn entity record
(including the VFS root) no longer kills the open — walks heal past it,
the keeper rows serve, and the identity read of the victim itself is
typed-or-healed; a torn mapper reopens and mints sanely on the first
post-recovery write.

Gates: tsc 0 · unit 2065/2065 · integration 828 · conformance 31/31.
2026-08-11 09:20:30 -07:00
4679c89458 fix(namespace): noun-record updates preserve legacy inline HNSW adjacency — the placeholder-adjacency write stamped out pre-codec records' stored connections (crash-window unreachability); codec-era records were never at risk (empty field is the blob marker); pin covers the legacy shape
Some checks failed
CI / Node 22 (push) Failing after 7m32s
CI / Node 24 (push) Failing after 7m24s
CI / Bun (latest) (push) Successful in 12m17s
2026-08-03 15:37:04 -07:00
2e2ba9c9aa fix: honest counters — removal never re-reads the removed record + repairIndex recounts and persists all rollups
Persisted entity totals inflated permanently: a delete's count decrement
was sourced from re-reading the record being removed, so a null read
(replace race, or a ghost left by a pre-8.3.1 partial delete) silently
skipped the decrement while the paired add had counted — and
Math.max(persistedTotal, scanned) meant no disk cleanup could ever
lower the reported total. Reported by a production deployment with a
write→delete→re-create repro minting drift within hours.

- The caller's pre-delete read now rides through the entire delete path
  (remove()/removeMany()/plan → DeleteNoun/DeleteVerb operations →
  deleteNoun/deleteVerb → deleteNounMetadata/deleteVerbMetadata): a
  null internal read falls back to the known prior record instead of
  skipping the decrement. StorageAdapter.deleteNoun/deleteVerb gain an
  optional priorMetadata parameter (additive).
- rebuildTypeCounts() rebuilt only the type-statistics arrays and
  computed the total just to LOG it — the persisted scalar
  (counts.json) survived every rebuild. One canonical walk now rebuilds
  every counter rollup (scalar totals + per-type maps + type
  statistics) and persists them; repairIndex() runs the recount
  unconditionally, since counters can be inflated over clean shelves.
2026-07-14 11:51:44 -07:00
366f9a91f5 fix: full-removal canonical deletes + family-scoped migration gate
Two production-reported spine fixes:

- Canonical delete is a FULL removal: remove()/removeMany() deleted the
  metadata leg but never the canonical vectors.json leg or the <id>/
  directory, leaving ghost rows that inflated enumerated counts forever,
  read as damage scars, and caused duplicate readdir entries for
  re-created VFS paths (the stale-unpost path). The delete operation now
  routes through storage.deleteNoun — both legs + the entity container —
  with a full two-leg before-image rollback; deleteVerb symmetric; the
  blind 'no metadata file' catch that masked real faults is gone. The
  generation log still holds the delete's before-image, so asOf() history
  is unchanged. repairIndex() gains a conservative, loud orphan-prune
  sweep (containers with no metadata content leg) + count recompute for
  stores damaged by earlier versions.

- Family-scoped migration gate: every read blocked on the whole-brain
  migration lock even when the migrating index was irrelevant. The gate
  now scopes to the index families a read actually consults — canonical
  reads never wait; find() waits only on its query shape's families;
  graph traversals wait only on the graph family. Writes keep the
  conservative whole-brain wait. A read that needs the migrating family
  still blocks (bounded) with the retryable MigrationInProgressError.
2026-07-14 10:11:53 -07:00
1f7e365a4e chore(8.0): final pre-RC1 sweep — API consistency, named errors, orphans, zero-cast codebase 2026-06-11 14:51:00 -07:00
8f93add705 feat(8.0)!: delete fork/branch/commit/history/versions — superseded by the Db API
The COW version-control surface (fork, branches, checkout, commit,
getHistory/streamHistory, asOfCommit, brain.versions) is gone, along with
its subsystems: src/versioning/, the COW object store (CommitLog,
CommitObject, RefManager, TreeObject), HistoricalStorageAdapter, and the
TypeAwareHNSWIndex path it kept alive. The Db API (now/transact/asOf/
with/persist/restore) is the one versioning model in 8.0.

Survivors and replacements:
- BlobStorage survives (the VFS stores file content through it), relocated
  to src/storage/blobStorage.ts with binaryDataCodec.ts; its adapter
  interface is now BlobStoreAdapter, slimmed to the consumed surface
  (write/read/has/delete/getMetadata + MIME-aware compression policy).
- brain.migrate() backup branches are replaced by persist-before-migrate:
  MigrateOptions.backupTo persists a hard-link snapshot of the current
  generation before any transform runs; MigrationResult.backupPath reports
  it, and brain.restore(path) brings it back wholesale.
- CLI: cow.ts (fork/branch/checkout/history/migrate) is replaced by
  snapshot.ts — snapshot <path>, restore <path>, history (tx-log),
  generation.
- New public read API: brain.transactionLog({limit}) exposes the reified
  tx-log (generation/timestamp/meta, newest first) that backs the CLI
  history command; TxLogEntry is exported.

Tests: superseded suites deleted; fork/commit blocks excised from shared
suites; BlobStorage tests relocated + reworked against the slimmed store;
migration tests now prove the backupTo snapshot/restore round trip; new
transactionLog coverage in db-mvcc.
2026-06-10 15:22:47 -07:00
35cb674157 perf: optimize init() and rebuild performance
- Remove detectAndRepairCorruption from init() hot path — was loading all
  metadata chunks sequentially on startup. Now available via checkHealth()
  and repairIndex() methods.
- Short-circuit warmCache on empty workspace — skip 4-6 wasted storage reads.
- Parallelize MetadataIndex.init() and getGraphIndex() via Promise.all().
- Defer metadata writes during rebuild to batch boundaries (every 5000
  entities) instead of flushing per-entity.
- Skip pre-reads for new entities in transactions — saves 2 storage
  round-trips per add() on cloud storage.
2026-01-31 09:14:51 -08:00
e40fee39d8 feat: add v5.8.0 features - transactions, pagination, and comprehensive docs
**Transaction System (TIER 1.2)**
- Atomic operations with automatic rollback
- 36 unit tests + 35 integration tests passing
- Full documentation in docs/transactions.md

**Duplicate Check Optimization (TIER 1.4)**
- Optimized from O(n) to O(log n) using GraphAdjacencyIndex
- Uses LSM-tree for efficient lookups
- Tests verify performance improvements

**GraphIndex Pagination (TIER 1.5)**
- Production-scale pagination for high-degree nodes
- Backward compatible API
- 18 pagination tests passing

**Comprehensive Filter Documentation (TIER 1.6)**
- Complete operator reference (15 operators)
- Compound filters (anyOf, allOf, nested logic)
- Common query patterns and troubleshooting guide
- 642 lines of new documentation

**README Updates**
- Added Filter & Query Syntax Guide to Essential Reading
- Added Transactions to Core Concepts section

All changes tested and production-ready for v5.8.0 release.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:26:23 -08:00