feat(8.0): graph analytics — brain.graph.rank / communities / path

Adds three intent-level graph reads to the `brain.graph` namespace, each
native-dispatched to the optional `@soulcraft/cor` 3.0 graph engine when present
and served from pure-TS kernels otherwise (identical public shapes, default
visibility filter respected on both paths):

- `rank(opts?)` → `{ id, score }[]` descending — importance / centrality.
  TS fallback: PageRank power-iteration with dangling-mass redistribution.
- `communities(opts?)` → `{ groups, count }` — connected grouping. TS fallback:
  union-find weakly-connected components, or iterative Tarjan SCC when
  `{ directed: true }`.
- `path(from, to, opts?)` → `{ nodes, relationships, cost } | null` — best route.
  TS fallback: BFS for fewest hops, Dijkstra (min-heap) for least summed edge
  weight (`by: 'weight'`); on-demand frontier expansion so short paths terminate
  early. `direction` / `type` / `maxDepth` filters apply.

These are intent contracts, not algorithm contracts — the question is the
promise, the algorithm is the engine's choice.

Pure kernels live in src/graph/analyticsFallback.ts (PageRank, connected
components, Tarjan SCC, MinHeap) — unit-tested in isolation. The full surface is
tested end-to-end through the TS fallback, and the native dispatch + int↔uuid
hydration paths are covered by a mock provider in graph-native-routing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
David Snelling 2026-06-23 12:32:03 -07:00
parent 4d0b64f455
commit 632d90aac5
7 changed files with 1164 additions and 11 deletions

View file

@ -50,6 +50,23 @@ no separate migration doc. **`8.0.0-rc.2` is live** — install with
> carry `visibility`; whole-graph/`getNouns` streaming no longer leaks `system`/`internal` entities;
> and small-page cursor walks over nouns no longer loop. No API change — just correct behavior.
> **rc.3 additions (2026-06-23):**
> - **Graph analytics on the `brain.graph` namespace.** Three intent-level reads that answer
> whole-graph questions in one call:
> - **`brain.graph.rank(opts?)`** → `{ id, score }[]` descending — "which entities matter most"
> (importance / centrality). `topK` to cap.
> - **`brain.graph.communities(opts?)`** → `{ groups: string[][], count }` — "which things group
> together". Weakly-connected components by default; `{ directed: true }` returns
> strongly-connected components.
> - **`brain.graph.path(from, to, opts?)`** → `{ nodes, relationships, cost } | null` — the best
> route between two entities. Fewest hops by default; `{ by: 'weight' }` minimizes summed edge
> weight (the 01 connection strength); `direction`, `type`, and `maxDepth` filters apply.
> These are **intent contracts, not algorithm contracts** — the question is the promise, the
> algorithm is the engine's choice. They transparently use the native `@soulcraft/cor` 3.0 graph
> engine when present, and fall back to pure-TS kernels (PageRank, connected components / Tarjan
> SCC, BFS / Dijkstra) otherwise. Both paths return identical shapes and respect the default
> visibility filter (opt in with `includeInternal` / `includeSystem`).
### Headline: Database as a Value
8.0 replaces Brainy's two overlapping version-control subsystems (copy-on-write