feat(8.0): brain.graph.subgraph() + native-provider routing

Introduces the brain.graph namespace and its first op, subgraph() — bounded
multi-hop neighborhood extraction returning a hydrated GraphView (nodes with hop
depth + type/subtype, edges as Relations, a truncated flag). The one-call answer
to 'show me everything around this node, N hops out' the graph-viz path needs.

- brain.graph.subgraph(seeds, { depth, direction, type, subtype, includeInternal,
  includeSystem, maxNodes, maxEdges, hydrateNodes }). seeds: id or id[].
- Feature-detect routing: when a GraphAccelerationProvider is registered
  (isGraphAccelerationProvider on the 'graphAcceleration' provider) it routes to
  native traverse() and hydrates the columnar Subgraph (node ints↔ids paired with
  depth position-preserving, edge verb ints → Relations); otherwise a pure-TS BFS
  fallback expands each frontier through the O(degree) related() adjacency.
- Both paths produce the identical GraphView, so CI exercises the shape via the
  fallback; the native path is cross-layer-tested against cor's provider.
- New public types: GraphView, GraphNode, SubgraphOptions, GraphApi (the surface
  grows: export/rank/path/communities follow). isGraphAccelerationProvider guard
  added to plugin.ts.

Test: graph-subgraph.test.ts — depth tracking, direction, type filter, default-
hides-internal, node hydration on/off, maxNodes truncation, multi-seed.
This commit is contained in:
David Snelling 2026-06-21 09:23:33 -07:00
parent d4de48d004
commit 8c2b57a488
4 changed files with 417 additions and 1 deletions

View file

@ -681,6 +681,27 @@ export function isVersionedIndexProvider(
)
}
/**
* @description Feature-detect an optional {@link GraphAccelerationProvider} (the
* native graph engine). Brainy probes the registered `'graphAcceleration'`
* provider with this: present `brain.graph.*` routes to native `traverse` /
* cursor / analytics; absent Brainy serves the same operations from its
* pure-TS adjacency fallback. Checks the two anchor methods (`traverse` +
* `graphCursorOpen`) a partial implementation that lacks them is treated as
* absent (fall back rather than crash).
* @param candidate - The value registered under `'graphAcceleration'`, or undefined.
* @returns Whether `candidate` is a usable {@link GraphAccelerationProvider}.
*/
export function isGraphAccelerationProvider(
candidate: unknown
): candidate is GraphAccelerationProvider {
if (candidate === null || typeof candidate !== 'object') {
return false
}
const c = candidate as Record<string, unknown>
return typeof c.traverse === 'function' && typeof c.graphCursorOpen === 'function'
}
/**
* The object returned by the `'vector'` provider factory Brainy's vector
* index contract. Implementations include Brainy's own JS HNSW index and any