feat(8.0): brain.graph.subgraph(query) query→expand fusion (#61)

The subgraph seed selector now accepts not just entity id(s) but a find() result
or a FindParams query — brain.graph.subgraph({ where: { team: 'platform' } },
{ depth: 1 }) runs the query and expands the neighborhood of every match in one
call. Existing id-seeded calls are unchanged.

The win is the native query→expand path: for a metadata-only query, the matched
universe is forwarded to traverse() as an OpaqueIdSet (a roaring Buffer) with NO
id materialization in TypeScript — the find() result never leaves the engine's
representation (the O(1)-crossing the cor 3.0 contract is built around). The
pure-JS path (or any query carrying vector/text/proximity criteria) materializes
the matched ids via find() and seeds the traversal from them, capped at a bounded
default when the caller pins no limit.

- New public `SubgraphSelector<T>` union (id | id[] | Result[] | FindParams).
- find()'s metadata filter-builder extracted to a shared `buildMetadataFilter`
  (reused by the opaque universe producer); behavior unchanged.
- graphSubgraphNative generalized to accept `bigint[] | OpaqueIdSet` seeds.

Tested: JS query→expand + Result[] selector + empty-match in graph-subgraph, and
the native opaque pass-through (Buffer reaches traverse unmaterialized) vs the
find()-materialized bigint[] seeds via the 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 13:30:30 -07:00
parent dd325f2f94
commit 82dde92077
5 changed files with 233 additions and 57 deletions

View file

@ -73,6 +73,13 @@ no separate migration doc. **`8.0.0-rc.2` is live** — install with
> matches that DO pass the filter, rather than coming back empty. No API change. With the native
> `@soulcraft/cor` 3.0 stack the matched universe is forwarded as an opaque roaring buffer with
> zero id materialization in TypeScript; the pure-JS path restricts the beam walk with a string set.
> - **`brain.graph.subgraph()` accepts a query (query→expand).** The seed selector now takes not
> just entity id(s) but a `find()` result or a `FindParams` query — `brain.graph.subgraph({ where:
> { team: 'platform' } }, { depth: 1 })` runs the query and expands the neighborhood of every
> match in one call. With the native engine a metadata-only query's matched universe is handed to
> the traversal as an opaque set with no id materialization in TypeScript (the query→expand
> fusion); the pure-JS path materializes the matched ids and expands from them. Existing
> id-seeded calls are unchanged.
### Headline: Database as a Value