From 4e9be08f44bba021984ac65e11e4e4bb247a4344 Mon Sep 17 00:00:00 2001 From: David Snelling Date: Fri, 10 Jul 2026 11:24:32 -0700 Subject: [PATCH] docs: RELEASES.md entry for 8.1.0 (brain.onChange change feed) --- RELEASES.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 2a24e17d..9368a864 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -10,6 +10,38 @@ Full auto-generated changelog: `CHANGELOG.md` · Releases: https://github.com/so --- +## v8.1.0 — 2026-07-10 (`brain.onChange` — the in-process change feed) + +New public API: subscribe to every committed mutation with +`brain.onChange(cb) → unsubscribe`. One event per affected record, for **every** +canonical write regardless of origin — direct calls, batch methods, `transact()`, +imports, and Virtual Filesystem writes all funnel through the same commit point the +feed is emitted from. This is the authoritative in-process signal for live UIs, +cache invalidation, and realtime sync layers (downstream SDKs can forward it over +their own transports to make local and remote brains uniform). + +Event shape (`BrainyChangeEvent`, exported): `kind` (`entity`/`relation`/`store`), +`op` (`add`/`update`/`remove`/`relate`/`unrelate`/`updateRelation`/`clear`/`restore`), +the post-commit `entity` or `relation` view (type + full custom metadata), the +committed `generation`, and `timestamp`. Notable properties: + +- **Post-commit only** — an aborted write (a losing `ifRev` CAS, a rejected + transaction) never emits. If you got the event, the write is durable. +- **Deletes fully described** — `remove`/`unrelate` carry the record's last + committed state (from the commit's own history record), not just an id; batch + deletes included. +- **Batches emit per item**; a `transact()` batch's events share its single + generation. Entity deletes also emit `unrelate` for each cascaded relationship. +- **Commit-ordered, asynchronous, isolated** — events arrive in commit order, + dispatched in a microtask so a slow listener never delays a write and a throwing + listener never affects the write or other listeners. Zero overhead with no + subscribers. +- **`kind: 'store'`** events for `clear()`/`restore()` mean "refetch everything". +- Fire-and-forget by design; each event's `generation` composes with + `asOf()`/`transactionLog()` for catch-up after a gap. + +Guide: `docs/guides/reacting-to-changes.md`. No behavior changes for existing code. + ## v8.0.17 — 2026-07-08 (count recovery scans the real layout · ~1,100 lines of dead 7.x machinery removed) A cleanup of the vestigial 7.x "hnsw sharding" machinery that turned up two real fixes.