Commit graph

647 commits

Author SHA1 Message Date
33ea5e322a chore(release): 7.19.3 2026-02-19 17:04:37 -08:00
b6e3470b83 docs: add public frontmatter to docs for soulcraft.com/docs pipeline
Add YAML frontmatter (slug, public, category, template, order) to 8
existing docs and 2 new getting-started guides (installation, quick-start).
Include docs/**/*.md in npm package files so the portal sync-docs script
can read them from node_modules after publish.

Update CLAUDE.md with docs pipeline trigger phrases and release checklist.
2026-02-19 17:04:05 -08:00
9d5a74abe1 chore(release): 7.19.2 2026-02-18 15:38:59 -08:00
1a628daa83 fix: metadata index not cleaned up after delete/deleteMany
Three bugs caused deleted entities to persist in the metadata index:

1. idMapper never cleaned up — EntityIdMapper accumulated UUID→int mappings
   permanently. idMapper.getAllIntIds() is used as the universe for ne and
   exists:false operators, so deleted entities returned in those queries
   indefinitely. Fix: removeFromIndex() now calls idMapper.remove(id) and
   idMapper.flush() after all bitmap operations complete (must be last because
   removeFromChunk() reads idMapper.getInt(id) internally).

2. Optional fields indexed as __NULL__ but never unindexed — entityForIndexing
   in add() included confidence, weight, and createdBy as explicit keys even
   when undefined. Object.entries() preserves undefined-valued keys so
   extractIndexableFields() indexed them as '__NULL__' bitmap entries.
   storageMetadata omitted those keys via conditional spreading, so
   removeFromIndex() passed a structure without those keys and never cleaned
   them up. Fix: entityForIndexing now uses conditional spreading for
   confidence, weight, and createdBy matching storageMetadata exactly.

3. result.successful updated before transaction commits — deleteMany() pushed
   ids to result.successful inside the transaction builder, before
   transaction.execute() ran. A rollback would leave result.successful
   containing ids that were never actually deleted. Fix: queued ids are held
   in a local chunkQueued array and moved to result.successful only after
   executeTransaction() resolves without throwing.

Adds regression test suite (14 tests) covering delete() and deleteMany() for
type-index cleanup, ne operator, exists:false operator, optional-field indexing,
and partial deletion correctness.

Reported by wickworks team.
2026-02-18 15:33:56 -08:00
cc286ba2fc fix: include WASM pkg files in npm package
The pkg/ directory containing the Candle WASM binary was excluded from
the npm tarball because it contained its own package.json and .gitignore
(with `*` pattern). The build:copy-wasm script now skips these files
when copying to dist/, ensuring candle_embeddings.js/.wasm are included.

Also adds ./embeddings/wasm export subpath for clean ESM imports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:26:22 -08:00
21371786fb chore(release): 7.19.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:04:15 -08:00
b7c6752388 feat: add stddev/variance aggregation ops with Welford's online algorithm
- New aggregation ops: stddev and variance (incremental, O(1) per update)
- Welford's online algorithm for numerically stable running variance
- MetricState extended with m2 field for variance tracking
- AggregationProvider interface: defineAggregate, removeAggregate, restoreState, serializeState
- Export AggregateGroupState and MetricState types
- Plugin docs: aggregation provider, analytics providers (HyperLogLog, t-digest, etc.)
- Aggregation architecture and usage guide docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:04:11 -08:00
4602960e86 chore(release): 7.18.0 2026-02-16 16:58:31 -08:00
f024e56ee7 feat: add aggregation engine with incremental SUM/COUNT/AVG/MIN/MAX, GROUP BY, and time windows
Add a write-time incremental aggregation engine that maintains running
totals on every add/update/delete for O(1) read performance. Integrates
into brain.find({ aggregate }) for a unified query API.

Core features:
- AggregationIndex with defineAggregate()/removeAggregate() API
- Five aggregation operations: SUM, COUNT, AVG, MIN, MAX
- GROUP BY with multiple dimensions including time windows
- Time window bucketing: hour, day, week, month, quarter, year, custom
- Materialization of results as NounType.Measurement entities
- Debounced persistence of definitions and state to storage
- Definition change detection via FNV-1a hashing with auto-rebuild
- Infinite loop prevention for materialized entities
- 'aggregation' plugin provider key for native acceleration
- Lazy initialization (created on first defineAggregate() call)
- 73 tests (unit + integration) covering all functionality

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:57:53 -08:00
089a4d4141 docs: add Claude Code project guide and verified architecture reference
Contributor-friendly CLAUDE.md with setup, conventions, and architecture
overview. Comprehensive skills/architecture.md verified against actual
codebase covering all 31 source directories, 38+ exports, and major
subsystems (distributed, transactions, neural, CLI, MCP, COW, etc).

Remove CLAUDE.md from .gitignore since the new version is designed
for public contributors.
2026-02-10 09:09:18 -08:00
d453539a4d chore(release): 7.17.0 2026-02-09 16:13:52 -08:00
39b099cafc feat: add migration system with error handling, validation, and enterprise hardening
- MigrationRunner: per-entity error tracking (non-fatal), maxErrors bail-out,
  static validateMigrations() called in constructor, branch error propagation
- RefManager: updateRefMetadata() method for clean metadata updates
- brainy.ts: eliminate as-any casts in migration methods, use updateRefMetadata,
  forward maxErrors through full chain including branch migrations
- Types: MigrationError interface, errors field on MigrationResult, maxErrors on MigrateOptions
- Package exports: MigrationError type, migrate() on BrainyInterface, autoMigrate config
- 31 integration tests covering error handling, validation, branch error propagation
- Documentation: docs/guides/schema-migrations.md
2026-02-09 16:13:14 -08:00
e9f6a1b461 chore(release): 7.16.0 2026-02-09 12:08:34 -08:00
0ddc05a5bb feat: enforce data/metadata separation, numeric range queries, improved docs
- Store data opaquely in add() and update() instead of spreading object
  properties into top-level metadata. data is for semantic search (HNSW),
  metadata is for structured where-filter queries (MetadataIndex).
- Fix numeric range queries in MetadataIndex — use numeric-aware comparison
  instead of lexicographic string comparison for normalized values.
- Add data field to RelateParams and Relation types for relationship content.
- Add where.type → where.noun alias in metadata-only find() path.
- Rewrite README: focused ~350 lines from 791, quick start first, feature
  showcase with mini-snippets, organized doc links, no version callouts.
- Add DATA_MODEL.md and QUERY_OPERATORS.md reference docs.
- Remove 10 outdated/redundant doc files consolidated into API reference.
- Improve JSDoc on Entity, Relation, AddParams, FindParams, and core methods.
- Fix tests asserting data properties appear in metadata (data model violation).
- Deprecate verb.source/target in favor of from/to (public) and sourceId/targetId (storage).
2026-02-09 12:07:54 -08:00
edb5ec4696 chore(release): 7.15.5 2026-02-02 09:29:53 -08:00
c0bb413a2e docs: update plugin docs to reflect opt-in behavior
Plugins are no longer auto-detected. Updated README and PLUGINS.md
to show explicit plugins config, document all config values, and
fix manual registration example to use brain.use() API.
2026-02-02 09:29:41 -08:00
a88268fd25 chore(release): 7.15.4 2026-02-02 09:21:31 -08:00
932fb9520b fix: set verb.source/target to entity UUID instead of NounType
relate() was setting verb.source = fromEntity.type (a NounType like
"concept") instead of the entity UUID. Cortex's graph index indexes by
verb.source, so lookups by UUID found nothing — causing in-session
reads to return 0 results.

Also fixes:
- PathResolver calling private getIdsFromChunks() → public getIds()
- Plugin auto-detection removed; cortex loads only via explicit config
- GraphVerb types accept number timestamps and sourceId/targetId aliases
- Dead autoDetect() method removed from PluginRegistry
- In-session regression tests added for getRelations after relate()
2026-02-02 09:20:38 -08:00
0ec3d85c39 chore(release): 7.15.3 2026-02-02 08:52:53 -08:00
6625385913 feat: add explicit plugins config to control plugin auto-detection
Previously, plugins: [] still auto-detected cortex because autoDetect()
always tried importing @soulcraft/cortex regardless of config. Now:
- undefined (default): auto-detect installed plugins
- false: no plugins, skip auto-detection entirely
- []: no plugins, skip auto-detection entirely
- ['@soulcraft/cortex']: load only specified, no auto-detection

Also adds typed plugins field to BrainyConfig interface.
2026-02-02 08:52:18 -08:00
389e9d6258 chore(release): 7.15.2 2026-02-01 17:56:14 -08:00
ab2493af02 fix: flush graph LSM-trees on close to prevent data loss across restarts
GraphAdjacencyIndex.flush() was a no-op — LSM MemTables were never
written to SSTables for datasets under the 100K auto-flush threshold.
This caused readdir, getRelations, and getDescendants to return empty
results after close + reopen.

Three fixes:
- LSMTree.get(): merge MemTable + SSTable results (data spans both
  after flush, old early-return missed SSTable data)
- GraphAdjacencyIndex.flush(): actually flush all 4 LSM-trees
- GraphAdjacencyIndex.close(): close all 4 trees (was only closing 2)

Also: brain.close() and shutdown hooks now call close() on graphIndex,
HNSW index, and metadataIndex to release timers and file handles.
2026-02-01 17:55:40 -08:00
0add0af45a chore(release): 7.15.1 2026-02-01 16:25:05 -08:00
773c5171c3 fix: flush all native providers on shutdown to prevent data loss
Shutdown/close/flush now properly flushes all 4 components in parallel:
metadataIndex, graphIndex, HNSW dirty nodes, and storage counts. Previously
only counts were flushed, causing native provider data loss on restart.

Also:
- Wire roaring, msgpack, entityIdMapper provider consumption from plugins
- Fix allOf filter O(n²) intersection → O(n) Set-based
- Fix ne/exists negation filter to use Set-based exclusion
- Add setMsgpackImplementation() swap in SSTable for native msgpack
- Add setRoaringImplementation() swap for native CRoaring bitmaps
- Add getAllIntIds() to EntityIdMapper for bitmap operations
- Remove TypeAwareHNSWIndex from default index creation path
- Export memory detection utilities from internals
- Clean up 26 permanently-skipped dead tests
2026-02-01 16:23:49 -08:00
b87426409d chore(release): 7.15.0 2026-02-01 13:05:10 -08:00
401e300ff2 feat: harden plugin system wiring and add developer diagnostics
Fix critical wiring bugs that prevented plugin-provided implementations
from being used at runtime. All CRUD operations, fork/checkout/clear,
batch embedding, neural APIs, and VFS path resolution now properly
dispatch through the plugin registry.

Changes:
- Wire graphIndex to storage for getVerbsBySource() fast path
- Replace instanceof checks with duck-typing (indexIsTypeAware flag)
  so plugin HNSW indexes work in add/update/delete/search
- Add createIndex() shared helper for plugin HNSW factory
- Fix fork/checkout/clear to use plugin factories for metadataIndex,
  graphIndex, and HNSW instead of hardcoding JS constructors
- Add three-tier embedBatch priority: embedBatch > embeddings > WASM
- Skip WASM warmup/eagerEmbeddings when plugin provides embeddings
- Fix PathResolver metadataIndex access (was looking on storage)
- Use global UnifiedCache in SemanticPathResolver
- Wire plugin distance function through neural APIs
- Add diagnostics() method and CLI command for provider inspection
- Add requireProviders() for production fail-fast assertions
- Add init-time provider summary log
- Add plugin developer documentation (docs/PLUGINS.md)
- Export DiagnosticsResult type
2026-02-01 13:03:15 -08:00
3a21bf62b7 chore(release): 7.14.0 2026-02-01 11:12:35 -08:00
36db644eca refactor: remove src/cortex/ directory and fix README claims
- Move neuralImport.ts and neuralImportAugmentation.ts to src/neural/
- Delete 3 dead files (healthCheck, backupRestore, performanceMonitor)
- Remove cortex entries from package.json browser field
- Fix unsubstantiated performance claims in README (add PROJECTED labels)
- Delete stale dist/cortex/ artifacts
2026-02-01 11:07:26 -08:00
0292cf2ddf chore(release): 7.13.0 2026-02-01 10:49:36 -08:00
d1db3510be refactor: remove augmentation system and semantic type matching
Remove the entire augmentation pipeline infrastructure (52 files,
~15,000 lines) and the semantic type matching system. These were
unused middleware layers adding complexity without value.

What was removed:
- src/augmentations/ directory (all augmentation implementations)
- src/augmentationManager.ts (pipeline orchestrator)
- src/types/augmentations.ts, src/types/pipelineTypes.ts
- src/shared/default-augmentations.ts
- Semantic type suggestion (BrainyTypes.suggestNoun/suggestVerb)
- src/utils/typeMatching/ (embedding-based type matcher)

What was preserved by relocating:
- Import handlers (CSV, PDF, Excel) -> src/importers/handlers/
- NeuralImportAugmentation -> src/cortex/neuralImportAugmentation.ts
- Type matching utilities -> heuristic inference in consumers

What was simplified:
- brainy.ts: operations call storage directly (no execute() wrapper)
- IntegrationBase: standalone class (no BaseAugmentation parent)
- BrainyTypes: validation-only (nouns, verbs, isValid*, get*)
- Pipeline: direct execution (no augmentation interception)
- index.ts: removed TypeSuggestion, suggestType exports
- package.json: removed stale types/augmentations export

Build passes, 1176 tests pass, 0 failures.
2026-02-01 10:48:56 -08:00
ac7a1f772c chore(release): 7.12.0 2026-02-01 08:25:50 -08:00
490a14af5f refactor: remove deprecated Cortex class (replaced by brain.augmentations API) 2026-02-01 08:22:11 -08:00
7f9d2a70a5 feat: update plugin references from @soulcraft/brainy-cortex to @soulcraft/cortex 2026-02-01 08:22:07 -08:00
b0439fbc26 chore(release): 7.11.0 2026-01-31 12:43:40 -08:00
0f3a88429d feat: add SQ8 vector quantization, lazy loading, and two-phase rerank to HNSW
- SQ8 scalar quantization (8-bit) for 4x vector storage reduction
- Lazy vector loading: evict float32 vectors after graph construction,
  load on-demand from storage via UnifiedCache
- Two-phase search: over-retrieve with SQ8 approximate distances,
  rerank top candidates with exact float32 distances
- Configuration surface: hnsw.quantization and hnsw.vectorStorage in BrainyConfig
- All features disabled by default (zero behavior change for existing users)
- 27 new tests covering quantization accuracy, lazy loading, reranking
- Remove GitHub Actions CI (build locally, cortex CI handles native builds)
2026-01-31 12:41:53 -08:00
e384afcdac chore(release): 7.10.0 2026-01-31 12:02:59 -08:00
1513e297ef feat: wire plugin system with provider resolution, storage factories, and browser deprecation
- Wire PluginRegistry into Brainy init() with provider resolution for distance,
  metadataIndex, graphIndex, embeddings, roaring, msgpack, and storage adapters
- Add setupStorage() factory that resolves storage:* providers from plugins before
  falling back to built-in createStorage()
- Export internals API (setGlobalCache, UnifiedCache, EntityIdMapper, etc.) for
  cortex plugin consumption
- Add plugin.test.ts verifying registration, activation, and provider resolution
- Deprecate browser support (OPFS, Web Workers, WASM embeddings) with warnings
  in preparation for v8.0 server-only release
- FileSystemStorage: fix setupStorage resolution for mmap-filesystem provider
2026-01-31 12:02:13 -08:00
25912b5728 chore: sync package-lock.json after dependency install 2026-01-31 09:30:43 -08:00
cc50ac3776 feat: add plugin system for cortex and storage adapters
Simple plugin architecture with two use cases:
1. Native acceleration (@soulcraft/brainy-cortex) — auto-detected
2. Custom storage adapters (e.g., Redis, DynamoDB)

Plugins implement BrainyPlugin interface with activate/deactivate lifecycle.
Auto-detection tries dynamic import of known packages during init().
Manual registration via brain.use(plugin) before init().

Provider keys: metadataIndex, graphIndex, entityIdMapper, cache, hnsw,
roaring, embeddings, distance, msgpack, storage:<name>
2026-01-31 09:22:32 -08: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
cd875294ad fix: eliminate flaky test timeouts and add storage adapters guide
- Switch vitest pool from threads to forks for process isolation
- Disable v8 coverage by default (causes vitest worker RPC timeout)
- Increase hookTimeout 30s to 60s for MetadataIndexManager init under load
- Reduce O(1) space test entity count, replace brittle timing assertions
- Add docs/guides/storage-adapters.md with verified batch config values
2026-01-31 09:11:20 -08:00
92d9420a5c fix: eliminate cloud storage write amplification and rate limiting
brain.add() was generating 26-40 immediate cloud writes per call, causing
HTTP 429 rate limit errors and high latency on GCS/S3/R2/Azure. Three-layer
fix: (1) deferred metadata writes with dirty-marking, (2) MetadataWriteBuffer
for write coalescing, (3) retry/backoff on all cloud storage adapters.
2026-01-31 09:09:36 -08:00
23e1c56ae0 fix: distribute metadata index keys across sub-prefixes to avoid cloud rate limits
All metadata index files were stored under a single _system/ prefix, causing
per-prefix rate limiting on GCS/S3/R2/Azure during cold starts and bulk imports.
Distributes high-volume system keys across 256 sub-prefixes using FNV-1a hash.
Backward-compatible with legacy path fallback.
2026-01-31 09:09:23 -08:00
66d7aa736c fix: invalidate VFS caches recursively on rmdir to prevent orphaned reads
When rmdir({ recursive: true }) deleted a directory tree, child file paths
remained in contentCache and statCache, causing readFile() to return stale
data for deleted files. Adds recursive flag to invalidateCaches() that
evicts all descendant keys by prefix.
2026-01-31 09:09:12 -08:00
88d0c89143 chore(release): 7.9.3 2026-01-28 08:52:52 -08:00
df7d467a4b perf: optimize addMany() with batch embedding for 5-10x speedup
Uses embedBatch() to pre-compute all vectors in a single WASM forward
pass instead of N individual embed() calls. Items that already have
vectors are skipped.

Before: 100 entities = 100 separate WASM calls
After:  100 entities = 1 batched WASM call (micro-batched internally)
2026-01-28 08:50:24 -08:00
f8dd93c93c fix: cancel abandoned highlight() semantic work and harden WASM engine recovery
highlight() used Promise.race with a 10s timeout, but the losing
semantic phase promise continued running 25 WASM micro-batches,
saturating the event loop and degrading all subsequent operations
(find() going from ~200ms to ~10,000ms).

Add AbortController to highlight() so the semantic phase stops
immediately on timeout or error. Pass abort signal through
embedBatch() → EmbeddingManager → micro-batch loop.

Also add defensive hardening:
- CandleEmbeddingEngine: try/catch around WASM calls resets engine
  state on failure so next call triggers re-initialization
- WASMEmbeddingEngine: initialize() now checks underlying Candle
  engine state, not just its own flag, completing the recovery chain
2026-01-27 18:26:37 -08:00
279fccebfe chore(release): 7.9.2 2026-01-27 16:51:48 -08:00
bf71317d21 fix: prevent WASM embedding from blocking event loop during highlight()
embedBatch() with large inputs (e.g. 500 chunks from highlight()) runs
a single synchronous WASM forward pass that blocks the event loop for
200-500ms. Split large batches into micro-batches of 20 with setTimeout(0)
yields between each, keeping max blocking per batch to ~10-30ms.

Also change Cargo.toml opt-level from "z" (size) to 3 (speed) for
~15-20% faster WASM inference. Requires WASM rebuild to take effect.
2026-01-27 16:49:26 -08:00
1ffdfa70ae chore(release): 7.9.1 2026-01-27 15:40:46 -08:00