Skip to content

Commit 67a76de

Browse files
HumanBean17claude
andauthored
feat: incremental graph rebuild (3-PR sequence: G1+G2+G3) (#284)
* feat: add source_file to edge schemas and FileHashTracker for incremental graph rebuild (PR-G1) This commit implements PR-G1 of the incremental graph rebuild plan: - Bump ONTOLOGY_VERSION to 17 (requires re-index) - Add source_file STRING column to all 12 edge DDL constants - Update _write_edges() to pass source_file for EXTENDS, IMPLEMENTS, INJECTS, DECLARES, OVERRIDES, CALLS, UNRESOLVED_AT - Update _write_routes_and_exposes() to pass source_file for EXPOSES, DECLARES_CLIENT, DECLARES_PRODUCER, HTTP_CALLS, ASYNC_CALLS - Add FileHashTracker class for detecting file changes (added, changed, removed) - Add 9 tests for FileHashTracker and edge schema validation Scope: PR-G1 (Hash tracker + source_file edge schema) Plan: plans/active/PLAN-INCREMENTAL-GRAPH.md Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: pass2_edges in test setup and crash marker cleanup in fallback path Tests that verify EXTENDS edge dependent expansion were missing pass2_edges() calls in their setup, resulting in no EXTENDS edges being written to the graph. Also fixed crash marker not being cleaned up in the _fallback_to_full code path and invalid Kuzu SHOW_TABLES syntax in test_incremental_pass5_6_always_global. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: restructure _delete_file_scope to handle cross-file edge deletion Process edge deletions across all scope files before deleting any nodes. The previous per-file loop could fail when file B has an EXTENDS edge to file A — deleting A's nodes first left dangling edges that Kuzu refused to drop. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat: add run_incremental_graph() wrapper for incremental rebuild (PR-G2) Add subprocess wrapper that passes --incremental flag to build_ast_graph.py. Part of incremental graph rebuild implementation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat: CLI integration for incremental graph rebuild (PR-G3) - Update increment command to run both CocoIndex catch-up and incremental Kuzu graph update - Add --vectors-only flag to preserve old Lance-only behavior - Update CLI help texts and documentation - Emit JSON output from incremental_rebuild for mode detection - Add/update tests for new increment behavior Increment now updates both Lance and Kuzu by default. The old stale warning is only emitted when --vectors-only is used. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: correct Cypher parameter names and close db on fallback in incremental rebuild - Fix _write_clients_producers_and_calls: use correct parameter names ($sid/$cid/$pid/$rid) matching Cypher templates, add missing fields (strategy, method_call, raw_uri, match, direction, raw_topic) - Use dict lookup instead of O(n) list scan for client/producer source_file - Use keyword args for MemberEntry placeholder construction - Delete db+conn before fallback to avoid file lock - Remove redundant import json inside main() - Remove stale duplicate comment in pass1_parse Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: critical runtime bugs in incremental rebuild found by code review - Fix _write_clients_producers_and_calls: use asdict(row) for Client/Producer nodes instead of manually constructed dicts with wrong field names (kind vs client_kind, target vs target_service, missing 10+ fields) - Fix _delete_file_scope: add ALL edge tables to Phase 1 deletion (was missing EXPOSES, DECLARES_CLIENT, DECLARES_PRODUCER, HTTP_CALLS, ASYNC_CALLS — would crash on any Spring codebase with controllers) - Use DETACH DELETE for Route/Client/Producer nodes as safety net - Fix N+1 query in dependent expansion: single IN-query instead of per-file Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor: deduplicate incremental rebuild code per code review - Merge _load_existing_types/_load_existing_types_filtered into single function with optional exclude_files parameter (same for members) - Simplify _find_dependents: loop over edge type strings instead of six identical if/elif branches - Factor _write_nodes and _write_nodes_merge to shared _write_nodes_impl accepting the query template as parameter (~70 lines deduplicated) - Extract _build_file_by_node_id and share between _write_edges and _write_routes_and_exposes (was built twice independently) - Extract _init_hash_tracker helper for duplicated hash-init logic in _fallback_to_full and no-DB branch of incremental_rebuild - Add warning log in FileHashTracker.save() instead of silent OSError - Update AGENTS.md ontology_version references from 15 to 17 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: phantom route writes, duplicate members, and minor issues from review round 2 - Write phantom Route nodes in _write_clients_producers_and_calls using MERGE (pass5 creates phantom routes for cross-service calls that were never persisted to Kuzu, silently dropping HTTP_CALLS/ASYNC_CALLS edges) - Remove redundant _load_existing_members before full pass1_parse in global pass 5-6 step (was creating duplicate stub members alongside full entries) - Use conn.close() + del instead of bare del for Kuzu handle cleanup on fallback (avoids relying on CPython ref-counting for file lock release) - Add FileNotFoundError handling in FileHashTracker.detect_changes for files that vanish between listing and hashing - Remove redundant inline import json in cli.py _cmd_increment - Update stale _delete_file_scope docstring to match implementation Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 263935f commit 67a76de

9 files changed

Lines changed: 1866 additions & 79 deletions

File tree

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ when needed.
4343
variables, full `.java-codebase-rag.yml` reference, **graph layer**
4444
(node kinds, edges, capabilities, ranking, "Re-index required"
4545
callouts), brownfield overrides, ignore patterns. The current
46-
`ontology_version` is **15** (`EDGE_SCHEMA` in `java_ontology.py`;
46+
`ontology_version` is **17** (`EDGE_SCHEMA` in `java_ontology.py`;
4747
material `OVERRIDES` Symbol→Symbol edges: subtype instance method →
4848
supertype declaration with matching `signature`, one
4949
`IMPLEMENTS`/`EXTENDS` hop; valid `neighbors` `EdgeType`).
@@ -190,7 +190,7 @@ template):
190190
`VALID_RESOLVE_REASONS`, `VALID_UNRESOLVED_CALL_REASONS`.
191191
- Schema changes that affect the Lance index or Kuzu graph need a
192192
matching update to the README "Re-index required" callout. Bump
193-
`ontology_version` when enrichment semantics change (currently **15**).
193+
`ontology_version` when enrichment semantics change (currently **17**).
194194
- Brownfield is a first-class surface: any new auto-detection (route,
195195
role, capability, http client, async producer) must compose with the
196196
matching `BrownfieldOverrides` layer. Last writer wins (outermost layer

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ Run `java-codebase-rag --help` to list grouped subcommands. Operator playbook wi
168168
| Group | Subcommand | What it does |
169169
|---|---|---|
170170
| Lifecycle | `init` | First-time index. Refuses if artifacts already exist. |
171-
| Lifecycle | `increment` | CocoIndex catch-up (Lance only); Kuzu stays stale until `reprocess`. |
171+
| Lifecycle | `increment` | CocoIndex catch-up + incremental Kuzu update. `--vectors-only` for Lance only. |
172172
| Lifecycle | `reprocess` | Full Lance + Kuzu rebuild. `--vectors-only` / `--graph-only` for a single phase. |
173173
| Lifecycle | `erase` | Delete index artifacts. Requires `--yes` or TTY confirm. |
174174
| Introspection | `meta`, `tables`, `diagnose-ignore`, `unresolved-calls` | Health, table listing, ignore-layer diagnostics, receiver-failure call sites. |
@@ -212,5 +212,4 @@ The default embedding model is `sentence-transformers/all-MiniLM-L6-v2` (downloa
212212

213213
- `get_service_topology` — microservice-level summary aggregating `HTTP_CALLS` / `ASYNC_CALLS`.
214214
- Agentic routing layer (query classifier → vector / graph / both).
215-
- Incremental Kuzu updates (per-changed-file).
216215
- Optional `codegraph_nodes` LanceDB table embedding symbol summaries so the graph itself is vector-searchable.

ast_java.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
# Phase 11: `EDGE_SCHEMA` in `java_ontology.py` (canonical edge navigation schema; v14 re-index).
8484
# Phase 12: CALLS `callee_declaring_role`, supertype-walk dedup, pass3 unresolved counters (v15 re-index).
8585
# Bumps whenever extraction / enrichment semantics change.
86-
ONTOLOGY_VERSION = 16
86+
ONTOLOGY_VERSION = 17
8787

8888
ROLE_ANNOTATIONS: dict[str, str] = {
8989
# Spring Web

0 commit comments

Comments
 (0)