feat(core): backend-neutral federation, mixed Kuzu + DuckDB subrepos#24
Merged
Conversation
Eighth and final step of the Kuzu -> DuckDB migration. Federation
now opens child read-only connections via the GraphDB protocol so
the same MCP tool can fan out across subrepos using either backend
without any per-tool branching. Parent on Kuzu, children on DuckDB
(or any mix) all work.
What lands:
- codegraph/analysis/federation.py: detection + adapter wiring.
- new _detect_backend_file(repo_root) inspects .codegraph/ for
graph.duckdb (wins) or graph.db (fallback). Returns None when
neither is present.
- open_kuzu_ro renamed open_graphdb_ro. The detected backend is
opened via DuckDBGraphDB or KuzuGraphDB; both implement the
GraphDB protocol so the caller sees the same interface either
way. Always closes — Kuzu still holds an OS file lock that
must be released so child owners can keep writing.
- for_each_kuzu / for_each_child_kuzu / _run_one_kuzu renamed
for_each_graphdb / for_each_child_graphdb / _run_one_graphdb.
Signature changed from kuzu.Connection to GraphDB — every
existing caller already uses the helper methods (find_nodes,
find_neighbors, count_nodes, ...) introduced in #19-#23, so
no caller-side changes needed.
Backward-compat aliases (open_kuzu_ro = open_graphdb_ro, etc.)
keep existing imports working. The 4 callers in server/tools_*.py
import the old names — they'll be migrated to the new names
in 0.6 when the Kuzu code path is removed.
- ChildStatus dataclass gains has_duckdb + has_graphdb. The .ok
property now uses has_graphdb (either backend counts as "ready").
End-to-end verification on a mixed-backend repo layout:
/tmp/cgh_fed/
child_a/.codegraph/graph.db # Kuzu
child_b/.codegraph/graph.duckdb # DuckDB
open_graphdb_ro(child_a) -> KuzuGraphDB, Files=1 Functions=1
open_graphdb_ro(child_b) -> DuckDBGraphDB, Files=1 Functions=1
Both children answer count_nodes / find_neighbors / etc. through
the same protocol — federated MCP tools work transparently.
Migration status:
| File | Cypher emit | PR |
|---------------------------|-------------|-----|
| indexer.py | 41 -> 0 | #19 |
| server/tools_query.py | 13 -> 0 | #20 |
| server/tools_arch.py | 3 -> 0 | #21 |
| server/tools_docs.py | 6 -> 0 | #21 |
| analysis/dead_code.py | 2 -> 0 | #21 |
| analysis/context_builder | 3 -> 0 | #21 |
| server/tools_viz.py | 19 -> 0 | #22 |
| cli/commands_monitor.py | 12 -> 0 | #23 |
| analysis/federation.py | n/a | #24 |
| TOTAL | 99 -> 0 | |
CGH_DB=duckdb now works end-to-end: index, query, viz, stats, and
federated subrepo aggregation all return identical results to the
Kuzu default backend.
Next: release/0.5.0 flips the default to DuckDB, marks Kuzu deprecated
in the README, lifts the Python <3.14 cap. release/0.6.0 deletes
the Kuzu code path and dependency.
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.
Summary
Eighth and final step of the Kuzu → DuckDB migration. Federation now opens child read-only connections via the GraphDB protocol, so the same MCP tool can fan out across subrepos using either backend (any mix) without per-tool branching.
What lands
Detection
`_detect_backend_file(repo_root)` looks at `.codegraph/`:
DuckDB wins when both are present (handles a half-migrated repo cleanly).
End-to-end verification — mixed backends
```
/tmp/cgh_fed/
child_a/.codegraph/graph.db # Kuzu
child_b/.codegraph/graph.duckdb # DuckDB
open_graphdb_ro(child_a) → KuzuGraphDB, Files=1, Functions=1
open_graphdb_ro(child_b) → DuckDBGraphDB, Files=1, Functions=1
```
Both children answer `count_nodes` / `find_neighbors` / etc. through the same protocol — federated MCP tools work transparently.
Migration complete
`CGH_DB=duckdb` now works end-to-end: index, query, viz, stats, and federated subrepo aggregation all return identical results to the Kuzu default.
Next