diff --git a/RELEASES.md b/RELEASES.md index 6698493f..99f2947d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -10,6 +10,47 @@ Full auto-generated changelog: `CHANGELOG.md` · Releases: https://github.com/so --- +## v8.0.12 — 2026-07-07 (7→8 VFS-content recovery · zero-rebuild cold open · strict query operators) + +Three consumer-facing fixes. + +**1 — A 7→8 upgrade recovers Virtual Filesystem content automatically (data-integrity).** +7.x stored VFS file content as blobs in the branch system's copy-on-write area (`_cow/`). 8.0 +removed that system and stores content blobs in the content-addressed store (`_cas/`), but the +one-time layout migration only moved entities — it never adopted the `_cow/` content blobs. On a +store that used the VFS (for example, a CMS with published pages), that left every VFS-backed read +throwing `Blob metadata not found` and the pages 500ing. **8.0.12 adds an on-open recovery pass** +that adopts every orphaned `_cow/` blob into `_cas/` — copying both the bytes and the metadata, +idempotently and **non-destructively** (the `_cow/` originals are never deleted). It heals both a +fresh 7→8 upgrade and a store **already** upgraded by an earlier 8.0.x that stranded them, with no +operator action: just open the store under 8.0.12. An explicit force path is exposed as +`brain.vfs.adoptOrphanedBlobs()` (returns `{ cowBlobs, adopted, alreadyPresent, incomplete }`). The +automatic pre-upgrade backup is now **retained** if any blob can't be fully adopted +(`incomplete > 0`) instead of being removed on entity-migration "success" alone. Affects any 7.x +store that used the VFS; native-8.0 and non-VFS stores no-op on a cheap existence check. Full guide: +`docs/guides/upgrading-7-to-8.md`. + +**2 — A cold open no longer re-derives durable indexes it can just load.** +Opening a persisted store rebuilt the vector, graph, and metadata indexes from the canonical +records even when the durable index state was present and loadable — an O(N) cost paid on every +boot (measured at ~48 s on an ~11k-entity store). The rebuild gate now consults an honest +per-provider durability signal (`init()` / `isReady()`) instead of an in-memory size heuristic, so +a provider that has loaded (or can cheaply demand-load) its persisted index is not rebuilt. The +built-in JS indexes keep today's behavior (a rebuild *is* their load path); the live query-time +guards that self-heal a genuinely lost index are unchanged. **The zero-rebuild boot activates when +the accelerator exposes the durability signal (`@soulcraft/cor@3.0.5`);** on earlier accelerator +versions 8.0.12 falls back to the previous behavior safely — no regression, just no speedup yet. + +**3 — Unknown query operators now throw instead of silently returning nothing.** +`find({ where })` had two gaps: the in-memory matcher (used for egress re-validation and historical +reads) was missing several documented operators (`in`, `greaterThanOrEqual`, `lessThanOrEqual`), so +it silently disagreed with the index path; and an unknown operator key (a typo, or `notIn` written +where `not: { in }` was meant) was treated as a nested-object field and silently matched nothing. +8.0.12 aligns the matcher to the full documented operator set and **validates the `where` filter +up front**, throwing a typed `BrainyError('INVALID_QUERY')` naming the bad operator. Dotted paths +remain the supported form for nested fields. If you relied on an unknown key silently returning `[]`, +it now throws — the fix is to use the documented operator or dot-notation. + ## v8.0.11 — 2026-07-02 (no script shape can hang on brainy's internals) Completes v8.0.10's exit fix for every operation class. Two further mechanisms found and fixed: