feat(graph): add a labeled relation graph with a query surface - #161
Merged
Conversation
Add buildKnowledgeRelationGraph, neighbors, walk, and isReachable over KnowledgeRelation edges keyed by (sourceId, targetId, predicate), with KnowledgeRelationSchema, KnowledgeRelationNodeSchema, and KnowledgeRelationGraphSchema so a persisted graph round-trips its metadata. Add knowledgePageRelations and derive buildKnowledgeGraph from it; the collapsed page graph bytes do not change. Closes #124
tangletools
approved these changes
Aug 21, 2026
tangletools
left a comment
Contributor
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 9b6870b3
This PR was opened by the trusted drewstone account.
This approval is provisional and was applied by the local stand-in because the pr-reviewer webhook host is unreachable (2026-08-21). CI on this head is fully green. The full PR reviewer audit re-runs via the resweep when the service returns and will publish findings if it detects issues.
17 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
buildKnowledgeGraphis hardcoded to page links and keys edges bysource->target, so two predicates between one pair collapse into one edge with mergedreasons.KnowledgeRelationhas an arbitrary predicate, but nothing builds a graph from it and nothing queries one. A consumer with labeled provenance (runs, claims, models;branched-from,supersedes,cites-evidence) had to hand-roll the builder and every query.What
src/relation-graph.ts:buildKnowledgeRelationGraph({ nodes?, relations })builds aKnowledgeRelationGraphwith one edge per(sourceId, targetId, predicate)in first-seen order. A repeated triple is accepted only when its weight and metadata are byte-identical in canonical JSON; any other repeat, an endpoint outside declarednodes, a duplicate node id, an empty id/kind/predicate, a non-finite weight, or non-JSON metadata is refused with a typedKnowledgeRelationGraphError(code). Withoutnodes, the graph carries edges only.neighbors(graph, id, { predicate?, direction }),walk(graph, id, { predicate?, direction, maxDepth? })(breadth-first, visited set, cycle-safe; ancestors =outoverbranched-from, descendants =in),isReachable(graph, from, to, { predicate?, direction }). An unknown node or malformed query is refused, never an empty answer.KnowledgeRelationSchema(hoisted out ofKnowledgeBaseCandidateSchema, one definition),KnowledgeRelationNodeSchema,KnowledgeRelationGraphSchema, each with an explicitmetadata: z.record(z.string(), z.unknown()).optional()so a persisted graph round-trips.knowledgePageRelations(pages)emits the labeled page relations (wikilink,citation,shared-source,contradicts), one per triple with occurrence weights.buildKnowledgeGraphnow collapses that list into its weighted edges (one source of truth);contradictsstays out of the collapsed projection and the implicitshared-sourcepass stays out of the relation graph.docs/architecture.mdlines;CHANGELOG8.1.0;api-surface.jsonregenerated (20 added exports, additive → minor).Proof (local, macOS, Node 24.11.1)
pnpm run typecheck: pass (src + contracts).pnpm run lint: 227 files, no fixes.pnpm test: 672 passed, 16 skipped, 48 failed — all 48 intests/kb-improvement/*(6 files), which throwexact knowledge candidate workflows require Linux directory descriptorson macOS; unrelated to this change. Focused:src/relation-graph.test.ts11/11,src/graph.test.ts5/5,src/citation-storage.test.ts4/4,tests/core.test.ts+src/search.test.ts24/24.buildKnowledgeGraph(pages)over a fixture covering double-resolved links, origin-qualified and malformed citations, ambiguous duplicate ids, self links, shared sources, andcontradictsisJSON.stringify-identical to the output recorded from the pre-refactor implementation (key order, edge order, weights, degrees).pnpm run build: 35 files.pnpm api:surface: 926 exports across 6 entry points.pnpm run check:version-bump: 20 export changes needing a minor bump, paid for by 8.0.10 -> 8.1.0.git merge-tree --write-tree origin/main HEAD: clean.Closes #124