v10.1.0 — Trustworthy reads
The first tagged release. Every fix here sits in the read or audit path, and they shared one signature: returning something plausible instead of erroring. The write path was already guarded, templated, deduped, snapshotted and linted — for a system whose whole value is being trusted later, that asymmetry ran the wrong way.
New — consistency(pattern, domain?, kinds?)
The cross-note agreement check. Give it a regex with one capture group naming the value that should agree:
consistency("(\d+) Titan mailboxes")
consistency("BRAINLLM_MODE[=: ]+(\w+)")
It returns every note asserting a value, grouped, with agreement: "unanimous" or "DISAGREEMENT".
Nothing else detected the same fact recorded differently across several notes, where every copy reads as authoritative. recall() ranks by relevance; maintain() checks structure; a correction applied to one note leaves its siblings silently wrong.
Read path
recall()title matching is OR + per-token scoring, not AND, with an exact-title bonus. A note titled exactly Tool Surface previously scored zero from titles fortool surface full mode— "full" and "mode" are not in its title — and lost to full-text noise on recency.- The empty-result hint no longer recommends
remember()-ing the content, which walked callers into duplicating something already stored.
Audit path
maintain(ack=)now covers every pass. Theentity-corruptedandrevision-bloatpasses bypassed the acknowledgement filter, so an acknowledged finding re-fired every run — the exact failureack=exists to prevent, occurring inside the ack mechanic.- The structural lint window rotates by date and names what it skipped. It read the same 40 of ~70 notes every run, leaving a third of the brain an unnamed permanent blind spot.
- The lint checks completeness, not just well-formedness. A thread that lost its Resolution and a Sources note with no Revision table both passed every check that existed.
- Near-title duplicate subjects are flagged within a domain. Equality-matching fires on the case that never happens; nobody writes a byte-identical title.
- The unlabeled-node check covers Knowledge/Master and Knowledge/Domains, whose omission let an entire strategy layer sit invisible to every read path.
The untyped-note trap — three halves of one problem
A note missing #noteType is invisible to every read. Previously there was no way back:
- Dedup now falls back to title-and-container, so
remember()adopts an untyped note instead of minting a duplicate beside it. label()can repairnoteTypeon a note that has none (still refuses to change or remove an existing one).undelete_notere-applies the label set for its container — Trilium's restore drops attributes, which is the root cause of the incident where two thirds of a brain went invisible.
Silent-loss guard
forget(hard=true) now refuses a note with children or multiple parents, naming what would be destroyed — Trilium deletes the whole subtree on the last branch.
Structure
The thread Resolution guard rejected the placeholder that remember() itself writes and template("thread") documents, so a thread repaired via revise() could not be made to match one created via remember(). It now rejects only a filled or duplicate Resolution.
Packaging
npm install brainllm works for the first time. The package had no bin, no main, and no files — so npm fell back to .gitignore, which ignores dist/, meaning the tarball would have shipped all of src/ and none of the built bundle.
CI
GitHub Actions was disabled at the repository level while the workflow reported state: active, which is why seven commits triggered zero runs. Re-enabled, plus an explicit tsc --noEmit step (bun build does not type-check) and oauth.test.ts added to the run — the CIMD impersonation and code-harvesting tests were outside CI entirely.