feat: brain.auditGraph() — read-only graph-truth audit

- New public API: walks every canonical relationship record, queries the same
  read path applications use (related() with all visibility tiers included),
  and classifies every discrepancy into its failure family: missingFromReads
  (records the read path omits — stale adjacency), danglingEndpoints
  (endpoint entity gone — the partial-delete scar class), readOnlyVerbIds
  (read-path edges with no canonical record — ghosts). Design-hidden
  internal/system edges are counted separately so intentional hiding is never
  misclassified as loss. Counts exact; example lists capped with an explicit
  truncatedExamples flag; loud narration on incoherence; mutates nothing.
- Classification core lives in src/graph/graphAudit.ts behind injected seams
  (canonical walks + the end-to-end read) so the discrepancy logic is testable
  in isolation; brainy wires the seams to storage walks and related().
- getNounIdsWithPagination now refuses an undecodable resume cursor loudly —
  the third and final pagination walk brought under the 8.5.2 cursor contract.
- Types exported: GraphAuditReport, GraphAuditDiscrepancy. Docs: the
  inspection guide gains the audit -> repair -> audit verification ritual.
This commit is contained in:
David Snelling 2026-07-17 16:34:45 -07:00
parent 07144ead86
commit 2a03fae0e2
7 changed files with 522 additions and 0 deletions

View file

@ -10,6 +10,27 @@ Full auto-generated changelog: `CHANGELOG.md` · Releases: https://github.com/so
---
## v8.6.0 — 2026-07-17 (brain.auditGraph — the graph-truth verification instrument)
A minor release adding one new public API, from the fleet's graph-trust program: a read-only
audit that **proves whether relationship reads return stored truth** on a given brain.
- **`brain.auditGraph(options?)`** walks every canonical relationship record, queries the same
read path applications use (`related()` / VFS `readdir`) with all visibility tiers included,
and classifies every discrepancy into its failure family: `missingFromReads` (records the
read path omits — a stale adjacency index), `danglingEndpoints` (relationships whose endpoint
entity no longer exists — the historical partial-delete scar class), and `readOnlyVerbIds`
(read-path edges with no stored record — ghosts). Design-hidden internal/system edges are
counted separately so intentional hiding is never misclassified as loss. Counts are exact;
example lists cap at `maxExamples` with an explicit `truncatedExamples` flag; the result is
narrated loudly on incoherence. Mutates nothing — safe on a live brain.
- The operational pairing: audit → if incoherent, `repairIndex()` → audit again. A `coherent`
report after the repair is the verified all-clear. Run it after any engine upgrade, restore,
or migration. Guide: `docs/guides/inspection.md`.
- Also: `getNounIds` pagination now refuses an undecodable resume cursor loudly (the same
contract `getNouns`/`getVerbs` gained in 8.5.2 — the third and final walk brought under it).
- Types exported: `GraphAuditReport`, `GraphAuditDiscrepancy`.
## v8.5.2 — 2026-07-17 (aggregation backfill: exception-safe, generation-verified, and loud)
Hardening patch from a migration incident (a byte-copied store on new hardware; the service