From 4741e23d453a0b775f96a424b2918e53a2852326 Mon Sep 17 00:00:00 2001 From: David Snelling Date: Wed, 17 Jun 2026 12:05:00 -0700 Subject: [PATCH] =?UTF-8?q?docs(8.0):=20RELEASES=20=E2=80=94=20portable=20?= =?UTF-8?q?export/import=20(BackupData=20v1)=20+=20distinctCount=20any-typ?= =?UTF-8?q?e=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- RELEASES.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 84fd8b0f..f41d67ef 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -80,6 +80,47 @@ historical records) are documented in: - [docs/ADR-001-generational-mvcc.md](docs/ADR-001-generational-mvcc.md) — the design record: persisted layout, commit protocol, crash recovery, proof table +### Portable export & import (BackupData v1) + +A portable, versioned graph format that serializes part or all of a brain to a +single JSON document and restores it — the cross-environment, cross-version +(7.x↔8.0), partial-or-whole companion to the native `persist()` snapshot. + +```ts +// Export is a method on the immutable Db, so it composes with now()/asOf()/with() +const backup = await brain.export({ collection: id }, { includeVectors: true }) +await otherBrain.import(backup, { onConflict: 'merge' }) // dedup-by-id + +;(await brain.asOf(gen)).export(sel) // time-travel export +brain.now().with(ops).export(sel) // what-if export +``` + +- **`brain.export(selector?, options?)` / `db.export(...)`** → a versioned + `BackupData` document. Selectors reuse `find()`'s grammar: `{ ids }`, + `{ collection }` (alias `memberOf`, transitive `Contains`), + `{ connected: { from, depth } }`, `{ vfsPath }`, predicate + (`{ type, subtype, where, service }`), or the whole brain (omit) — and they + compose. Options: `includeVectors`, `includeContent` (VFS file bytes), + `includeSystem`, `edges: 'induced' | 'incident' | 'none'`. +- **`brain.import(backup, options?)`** is polymorphic: a `BackupData` document is + restored as **one atomic transaction** (`onConflict: 'merge' | 'replace' | 'skip'`, + `reembed: 'auto' | 'never'`, `remapIds` for cloning); a file/buffer routes to the + existing CSV/PDF/Excel/JSON ingestion. No migration for ingestion callers. +- **`validateBackup(data)`** — dry-run structural/version/endpoint check before import. +- **Format** (`format:'brainy-backup'`, `formatVersion: 1`) is identical on 7.x + (7.32.0) and 8.0; standard fields (`subtype`/`visibility`/`data`/…) are top-level, + `metadata` is custom-only. Current-state (no generation history — that lives in + `persist()`). Types exported from the package root. +- Guide: [docs/guides/export-and-import.md](docs/guides/export-and-import.md). + +### Aggregation: distinctCount over any value type + +`distinctCount` now counts distinct values of **any** type (strings, booleans, +numbers) — previously it silently returned `0` for non-numeric fields, missing its +primary use (distinct categories / users / tags). `percentile` (with `p`; median = +`p: 0.5`), `stddev`, and `variance` are exact and delete-safe alongside the +write-time `sum`/`count`/`avg`/`min`/`max`. + ### Removed surfaces and their replacements | Removed in 8.0 | Replacement |