java-codebase-rag 0.6.3__tar.gz → 0.6.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. {java_codebase_rag-0.6.3/java_codebase_rag.egg-info → java_codebase_rag-0.6.5}/PKG-INFO +10 -10
  2. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/README.md +9 -9
  3. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/ast_java.py +28 -57
  4. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/build_ast_graph.py +486 -262
  5. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/graph_enrich.py +13 -35
  6. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/cli.py +10 -10
  7. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/install_data/agents/explorer-rag-enhanced.md +3 -3
  8. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/install_data/skills/explore-codebase/SKILL.md +5 -5
  9. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5/java_codebase_rag.egg-info}/PKG-INFO +10 -10
  10. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag.egg-info/SOURCES.txt +1 -0
  11. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_index_flow_lancedb.py +95 -21
  12. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/ladybug_queries.py +45 -51
  13. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/mcp_v2.py +9 -17
  14. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/path_filtering.py +24 -19
  15. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/pr_analysis.py +3 -4
  16. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/pyproject.toml +1 -1
  17. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/search_lancedb.py +2 -2
  18. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_ast_graph_build.py +164 -1
  19. java_codebase_rag-0.6.5/tests/test_ast_java_thread_safety.py +66 -0
  20. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_incremental_graph.py +409 -1
  21. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_lancedb_e2e.py +41 -0
  22. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_path_filtering.py +110 -14
  23. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_schema_consistency.py +4 -1
  24. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/LICENSE +0 -0
  25. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/brownfield_events.py +0 -0
  26. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/chunk_heuristics.py +0 -0
  27. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/index_common.py +0 -0
  28. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/__init__.py +0 -0
  29. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/_fdlimit.py +0 -0
  30. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/cli_format.py +0 -0
  31. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/cli_progress.py +0 -0
  32. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/config.py +0 -0
  33. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/installer.py +0 -0
  34. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/lance_optimize.py +0 -0
  35. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/pipeline.py +0 -0
  36. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag/progress.py +0 -0
  37. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag.egg-info/dependency_links.txt +0 -0
  38. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag.egg-info/entry_points.txt +0 -0
  39. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag.egg-info/requires.txt +0 -0
  40. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_codebase_rag.egg-info/top_level.txt +0 -0
  41. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_index_v1_common.py +0 -0
  42. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/java_ontology.py +0 -0
  43. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/mcp_hints.py +0 -0
  44. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/server.py +0 -0
  45. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/setup.cfg +0 -0
  46. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_agent_skills_static.py +0 -0
  47. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_assign_endpoint_client_extraction.py +0 -0
  48. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_ast_java_calls.py +0 -0
  49. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_ast_java_capabilities.py +0 -0
  50. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_bank_chat_brownfield_integration.py +0 -0
  51. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_brownfield_clients.py +0 -0
  52. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_brownfield_events.py +0 -0
  53. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_brownfield_overrides.py +0 -0
  54. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_brownfield_routes.py +0 -0
  55. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_call_edge_matching.py +0 -0
  56. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_call_edges_e2e.py +0 -0
  57. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_call_graph_receiver_resolution.py +0 -0
  58. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_call_graph_smoke_roundtrip.py +0 -0
  59. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_call_invariant.py +0 -0
  60. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_cli_progress_stdout_invariant.py +0 -0
  61. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_cli_quiet_parity.py +0 -0
  62. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_client_hint_recovery.py +0 -0
  63. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_client_node_extraction.py +0 -0
  64. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_client_role_rename.py +0 -0
  65. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_config.py +0 -0
  66. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_cross_service_resolution_flag.py +0 -0
  67. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_edge_navigation_doc.py +0 -0
  68. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_fd_limit.py +0 -0
  69. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_feign_not_exposer.py +0 -0
  70. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_graph_enrich.py +0 -0
  71. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_installer.py +0 -0
  72. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_installer_integration.py +0 -0
  73. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_java_codebase_rag_cli.py +0 -0
  74. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_ladybug_queries.py +0 -0
  75. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_lance_optimize.py +0 -0
  76. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_mcp_hints.py +0 -0
  77. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_mcp_server_project_root.py +0 -0
  78. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_mcp_tools.py +0 -0
  79. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_mcp_v2.py +0 -0
  80. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_mcp_v2_compose.py +0 -0
  81. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_meta_chain_core.py +0 -0
  82. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_microservice_scope.py +0 -0
  83. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_outgoing_call_extraction.py +0 -0
  84. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_packaging_metadata.py +0 -0
  85. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_pr_analysis.py +0 -0
  86. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_progress.py +0 -0
  87. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_resolve_routes_messaging_layer_c.py +0 -0
  88. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_route_extraction.py +0 -0
  89. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_search_lancedb.py +0 -0
  90. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_search_lancedb_capability.py +0 -0
  91. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_string_value_atoms.py +0 -0
  92. {java_codebase_rag-0.6.3 → java_codebase_rag-0.6.5}/tests/test_vectors_progress.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: java-codebase-rag
3
- Version: 0.6.3
3
+ Version: 0.6.5
4
4
  Summary: MCP server for semantic + structural search over Java codebases
5
5
  Author: HumanBean17
6
6
  License-Expression: MIT
@@ -44,7 +44,7 @@ Dynamic: license-file
44
44
 
45
45
  A graph-native code intelligence layer for Java microservice estates, exposed to LLM agents via the **Model Context Protocol (MCP)**.
46
46
 
47
- The system extracts a deterministic property graph from Java source (tree-sitter), stores it in **Kuzu** (graph) alongside a **LanceDB** vector index (chunks), and exposes a deliberately small MCP surface — **five tools**: `search`, `find`, `describe`, `neighbors`, `resolve` — that collapse onto three primitive agent operations: **locate**, **inspect**, **walk**.
47
+ The system extracts a deterministic property graph from Java source (tree-sitter), stores it in **LadybugDB** (graph) alongside a **LanceDB** vector index (chunks), and exposes a deliberately small MCP surface — **five tools**: `search`, `find`, `describe`, `neighbors`, `resolve` — that collapse onto three primitive agent operations: **locate**, **inspect**, **walk**.
48
48
 
49
49
  > **What this MCP is:** a **GPS for code navigation**, not a reasoning engine.
50
50
  > Agents use a simple loop:
@@ -63,9 +63,9 @@ For the design rationale, the GPS metaphor, and the full ontology, see [`docs/pa
63
63
 
64
64
  Generic code-search tools (grep, ctags, vector-only RAG) hit a ceiling on real Java microservice estates: they find files but lose the structure that makes a Spring/JAX-RS system navigable. This project is built around five choices that target that gap.
65
65
 
66
- - **Hybrid RAG + GraphRAG, not either-or.** Semantic recall (LanceDB chunk vectors) and structural navigation (Kuzu property graph) are composed in one surface. `search` finds candidate nodes by meaning; `neighbors` walks the exact edge you care about (`CALLS`, `IMPLEMENTS`, `INJECTS`, `DECLARES_ROUTE`, …). The agent picks the right primitive per step instead of being forced into pure-vector or pure-symbol search.
66
+ - **Hybrid RAG + GraphRAG, not either-or.** Semantic recall (LanceDB chunk vectors) and structural navigation (LadybugDB property graph) are composed in one surface. `search` finds candidate nodes by meaning; `neighbors` walks the exact edge you care about (`CALLS`, `IMPLEMENTS`, `INJECTS`, `EXPOSES`, …). The agent picks the right primitive per step instead of being forced into pure-vector or pure-symbol search.
67
67
 
68
- - **A Java-tuned role model.** Symbols are labelled with stereotypes inferred from Spring and JAX-RS conventions — `CONTROLLER`, `SERVICE`, `REPOSITORY`, `CLIENT`, `PRODUCER`, `MAPPER`, `DTO`. Agents can ask "list controllers" or "who injects this repository" directly, instead of grep-ing for `@RestController` and hoping for the best. Roles drive both filtering (`find` with a `NodeFilter`) and ranking.
68
+ - **A Java-tuned role model.** Symbols are labelled with stereotypes inferred from Spring and JAX-RS conventions — `CONTROLLER`, `SERVICE`, `REPOSITORY`, `COMPONENT`, `CONFIG`, `ENTITY`, `CLIENT`, `MAPPER`, `DTO`. Agents can ask "list controllers" or "who injects this repository" directly, instead of grep-ing for `@RestController` and hoping for the best. Roles drive both filtering (`find` with a `NodeFilter`) and ranking.
69
69
 
70
70
  - **Ranking specialized for Java codebases.** The composite ranker is aware of role, microservice, and FQN structure — not a generic BM25. A search for `"chat ingress"` surfaces controllers before utility classes; a search scoped to one microservice doesn't drown in matches from the other 19. Defaults are tuned on the bank-chat fixture and exposed in `docs/CONFIGURATION.md` for per-repo overrides.
71
71
 
@@ -113,7 +113,7 @@ All indexing lifecycle commands (`init`, `increment`, `reprocess`, `install`, `u
113
113
 
114
114
  If you prefer manual configuration, see [`docs/JAVA-CODEBASE-RAG-CLI.md`](./docs/JAVA-CODEBASE-RAG-CLI.md) for the full CLI reference.
115
115
 
116
- > **Stability disclaimer.** This package does **not** promise backward compatibility. MCP tool contracts, env vars, Lance/Kuzu schemas, config files, and Python APIs may change without a deprecation period. Track `main` and rebuild indexes when ontology or embedding settings change.
116
+ > **Stability disclaimer.** This package does **not** promise backward compatibility. MCP tool contracts, env vars, Lance/LadybugDB schemas, config files, and Python APIs may change without a deprecation period. Track `main` and rebuild indexes when ontology or embedding settings change.
117
117
 
118
118
  ---
119
119
 
@@ -126,7 +126,7 @@ This repo ships a small multi-module Spring fixture under [`tests/bank-chat-syst
126
126
  git clone https://github.com/HumanBean17/java-codebase-rag
127
127
  cd java-codebase-rag
128
128
 
129
- # 2. Build the index (Lance vectors + Kuzu graph). First run downloads the
129
+ # 2. Build the index (Lance vectors + LadybugDB graph). First run downloads the
130
130
  # embedding model (~90 MB) and takes ~30-60s on the fixture.
131
131
  java-codebase-rag init --source-root tests/bank-chat-system --index-dir /tmp/bank-chat-index
132
132
 
@@ -141,7 +141,7 @@ Smoke-test the index with two checks (`search_lancedb` ships with the package):
141
141
  JAVA_CODEBASE_RAG_INDEX_DIR=/tmp/bank-chat-index \
142
142
  python -m search_lancedb "chat ingress controller" --table java --limit 3
143
143
 
144
- # Vector + graph expansion — proves Kuzu is wired in
144
+ # Vector + graph expansion — proves LadybugDB is wired in
145
145
  JAVA_CODEBASE_RAG_INDEX_DIR=/tmp/bank-chat-index \
146
146
  python -m search_lancedb "chat ingress controller" --table java --limit 3 \
147
147
  --graph-expand --expand-depth 2
@@ -241,8 +241,8 @@ Run `java-codebase-rag --help` to list grouped subcommands. Operator playbook wi
241
241
  | Setup | `install` | Interactive setup wizard: config, MCP registration, skill/agent deployment, indexing. |
242
242
  | Setup | `update` | Refresh shipped artifacts (skill, agent, MCP entry) + incremental Lance/graph catch-up after pip upgrade. |
243
243
  | Lifecycle | `init` | First-time index. Refuses if artifacts already exist. |
244
- | Lifecycle | `increment` | CocoIndex catch-up + incremental Kuzu update. `--vectors-only` for Lance only. |
245
- | Lifecycle | `reprocess` | Full Lance + Kuzu rebuild. `--vectors-only` / `--graph-only` for a single phase. |
244
+ | Lifecycle | `increment` | CocoIndex catch-up + incremental LadybugDB update. `--vectors-only` for Lance only. |
245
+ | Lifecycle | `reprocess` | Full Lance + LadybugDB rebuild. `--vectors-only` / `--graph-only` for a single phase. |
246
246
  | Lifecycle | `erase` | Delete index artifacts. Requires `--yes` or TTY confirm. |
247
247
  | Introspection | `meta`, `tables`, `diagnose-ignore`, `unresolved-calls` | Health, table listing, ignore-layer diagnostics, receiver-failure call sites. |
248
248
  | Analysis | `analyze-pr` | Blast-radius / risk from a unified diff. |
@@ -277,7 +277,7 @@ python3 -m venv .venv
277
277
 
278
278
  The `cocoindex` package powers lifecycle commands that run the indexer (`init`, `increment`, `reprocess`, `erase`). Search and MCP navigation do not invoke it directly.
279
279
 
280
- The default embedding model is `sentence-transformers/all-MiniLM-L6-v2` (downloaded on first `init`). Override via the `EMBEDDING_MODEL` env var — see [`docs/CONFIGURATION.md` §1](./docs/CONFIGURATION.md#1-environment-variables).
280
+ The default embedding model is `sentence-transformers/all-MiniLM-L6-v2` (downloaded on first `init`). Override via the `SBERT_MODEL` env var — see [`docs/CONFIGURATION.md` §1](./docs/CONFIGURATION.md#1-environment-variables).
281
281
 
282
282
  ---
283
283
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  A graph-native code intelligence layer for Java microservice estates, exposed to LLM agents via the **Model Context Protocol (MCP)**.
4
4
 
5
- The system extracts a deterministic property graph from Java source (tree-sitter), stores it in **Kuzu** (graph) alongside a **LanceDB** vector index (chunks), and exposes a deliberately small MCP surface — **five tools**: `search`, `find`, `describe`, `neighbors`, `resolve` — that collapse onto three primitive agent operations: **locate**, **inspect**, **walk**.
5
+ The system extracts a deterministic property graph from Java source (tree-sitter), stores it in **LadybugDB** (graph) alongside a **LanceDB** vector index (chunks), and exposes a deliberately small MCP surface — **five tools**: `search`, `find`, `describe`, `neighbors`, `resolve` — that collapse onto three primitive agent operations: **locate**, **inspect**, **walk**.
6
6
 
7
7
  > **What this MCP is:** a **GPS for code navigation**, not a reasoning engine.
8
8
  > Agents use a simple loop:
@@ -21,9 +21,9 @@ For the design rationale, the GPS metaphor, and the full ontology, see [`docs/pa
21
21
 
22
22
  Generic code-search tools (grep, ctags, vector-only RAG) hit a ceiling on real Java microservice estates: they find files but lose the structure that makes a Spring/JAX-RS system navigable. This project is built around five choices that target that gap.
23
23
 
24
- - **Hybrid RAG + GraphRAG, not either-or.** Semantic recall (LanceDB chunk vectors) and structural navigation (Kuzu property graph) are composed in one surface. `search` finds candidate nodes by meaning; `neighbors` walks the exact edge you care about (`CALLS`, `IMPLEMENTS`, `INJECTS`, `DECLARES_ROUTE`, …). The agent picks the right primitive per step instead of being forced into pure-vector or pure-symbol search.
24
+ - **Hybrid RAG + GraphRAG, not either-or.** Semantic recall (LanceDB chunk vectors) and structural navigation (LadybugDB property graph) are composed in one surface. `search` finds candidate nodes by meaning; `neighbors` walks the exact edge you care about (`CALLS`, `IMPLEMENTS`, `INJECTS`, `EXPOSES`, …). The agent picks the right primitive per step instead of being forced into pure-vector or pure-symbol search.
25
25
 
26
- - **A Java-tuned role model.** Symbols are labelled with stereotypes inferred from Spring and JAX-RS conventions — `CONTROLLER`, `SERVICE`, `REPOSITORY`, `CLIENT`, `PRODUCER`, `MAPPER`, `DTO`. Agents can ask "list controllers" or "who injects this repository" directly, instead of grep-ing for `@RestController` and hoping for the best. Roles drive both filtering (`find` with a `NodeFilter`) and ranking.
26
+ - **A Java-tuned role model.** Symbols are labelled with stereotypes inferred from Spring and JAX-RS conventions — `CONTROLLER`, `SERVICE`, `REPOSITORY`, `COMPONENT`, `CONFIG`, `ENTITY`, `CLIENT`, `MAPPER`, `DTO`. Agents can ask "list controllers" or "who injects this repository" directly, instead of grep-ing for `@RestController` and hoping for the best. Roles drive both filtering (`find` with a `NodeFilter`) and ranking.
27
27
 
28
28
  - **Ranking specialized for Java codebases.** The composite ranker is aware of role, microservice, and FQN structure — not a generic BM25. A search for `"chat ingress"` surfaces controllers before utility classes; a search scoped to one microservice doesn't drown in matches from the other 19. Defaults are tuned on the bank-chat fixture and exposed in `docs/CONFIGURATION.md` for per-repo overrides.
29
29
 
@@ -71,7 +71,7 @@ All indexing lifecycle commands (`init`, `increment`, `reprocess`, `install`, `u
71
71
 
72
72
  If you prefer manual configuration, see [`docs/JAVA-CODEBASE-RAG-CLI.md`](./docs/JAVA-CODEBASE-RAG-CLI.md) for the full CLI reference.
73
73
 
74
- > **Stability disclaimer.** This package does **not** promise backward compatibility. MCP tool contracts, env vars, Lance/Kuzu schemas, config files, and Python APIs may change without a deprecation period. Track `main` and rebuild indexes when ontology or embedding settings change.
74
+ > **Stability disclaimer.** This package does **not** promise backward compatibility. MCP tool contracts, env vars, Lance/LadybugDB schemas, config files, and Python APIs may change without a deprecation period. Track `main` and rebuild indexes when ontology or embedding settings change.
75
75
 
76
76
  ---
77
77
 
@@ -84,7 +84,7 @@ This repo ships a small multi-module Spring fixture under [`tests/bank-chat-syst
84
84
  git clone https://github.com/HumanBean17/java-codebase-rag
85
85
  cd java-codebase-rag
86
86
 
87
- # 2. Build the index (Lance vectors + Kuzu graph). First run downloads the
87
+ # 2. Build the index (Lance vectors + LadybugDB graph). First run downloads the
88
88
  # embedding model (~90 MB) and takes ~30-60s on the fixture.
89
89
  java-codebase-rag init --source-root tests/bank-chat-system --index-dir /tmp/bank-chat-index
90
90
 
@@ -99,7 +99,7 @@ Smoke-test the index with two checks (`search_lancedb` ships with the package):
99
99
  JAVA_CODEBASE_RAG_INDEX_DIR=/tmp/bank-chat-index \
100
100
  python -m search_lancedb "chat ingress controller" --table java --limit 3
101
101
 
102
- # Vector + graph expansion — proves Kuzu is wired in
102
+ # Vector + graph expansion — proves LadybugDB is wired in
103
103
  JAVA_CODEBASE_RAG_INDEX_DIR=/tmp/bank-chat-index \
104
104
  python -m search_lancedb "chat ingress controller" --table java --limit 3 \
105
105
  --graph-expand --expand-depth 2
@@ -199,8 +199,8 @@ Run `java-codebase-rag --help` to list grouped subcommands. Operator playbook wi
199
199
  | Setup | `install` | Interactive setup wizard: config, MCP registration, skill/agent deployment, indexing. |
200
200
  | Setup | `update` | Refresh shipped artifacts (skill, agent, MCP entry) + incremental Lance/graph catch-up after pip upgrade. |
201
201
  | Lifecycle | `init` | First-time index. Refuses if artifacts already exist. |
202
- | Lifecycle | `increment` | CocoIndex catch-up + incremental Kuzu update. `--vectors-only` for Lance only. |
203
- | Lifecycle | `reprocess` | Full Lance + Kuzu rebuild. `--vectors-only` / `--graph-only` for a single phase. |
202
+ | Lifecycle | `increment` | CocoIndex catch-up + incremental LadybugDB update. `--vectors-only` for Lance only. |
203
+ | Lifecycle | `reprocess` | Full Lance + LadybugDB rebuild. `--vectors-only` / `--graph-only` for a single phase. |
204
204
  | Lifecycle | `erase` | Delete index artifacts. Requires `--yes` or TTY confirm. |
205
205
  | Introspection | `meta`, `tables`, `diagnose-ignore`, `unresolved-calls` | Health, table listing, ignore-layer diagnostics, receiver-failure call sites. |
206
206
  | Analysis | `analyze-pr` | Blast-radius / risk from a unified diff. |
@@ -235,7 +235,7 @@ python3 -m venv .venv
235
235
 
236
236
  The `cocoindex` package powers lifecycle commands that run the indexer (`init`, `increment`, `reprocess`, `erase`). Search and MCP navigation do not invoke it directly.
237
237
 
238
- The default embedding model is `sentence-transformers/all-MiniLM-L6-v2` (downloaded on first `init`). Override via the `EMBEDDING_MODEL` env var — see [`docs/CONFIGURATION.md` §1](./docs/CONFIGURATION.md#1-environment-variables).
238
+ The default embedding model is `sentence-transformers/all-MiniLM-L6-v2` (downloaded on first `init`). Override via the `SBERT_MODEL` env var — see [`docs/CONFIGURATION.md` §1](./docs/CONFIGURATION.md#1-environment-variables).
239
239
 
240
240
  ---
241
241
 
@@ -14,8 +14,8 @@ from __future__ import annotations
14
14
 
15
15
  import posixpath
16
16
  import sys
17
+ import threading
17
18
  from dataclasses import dataclass, field
18
- from functools import lru_cache
19
19
  from typing import Iterable
20
20
 
21
21
  import tree_sitter_java as _ts_java
@@ -215,10 +215,23 @@ _ANON_SUPER_AS_INTERFACE: frozenset[str] = frozenset({
215
215
  })
216
216
 
217
217
 
218
- @lru_cache(maxsize=1)
218
+ # tree-sitter's ``Parser`` mutates internal state during ``parse()`` and is NOT
219
+ # thread-safe, so each OS thread gets its own instance. ``parse_java`` is called
220
+ # concurrently from worker threads when indexing runs with cocoindex's inflight
221
+ # parallelism — both directly (java_index_flow_lancedb.py: process_java_file
222
+ # offloads parse+enrich to asyncio.to_thread) and transitively
223
+ # (graph_enrich.collect_annotation_meta_chain -> _collect_annotation_decl_index
224
+ # -> parse_java, reached from enrich_chunk). The ``Language`` is immutable and
225
+ # shared; per-thread ``Parser`` construction is lazy and cheap (once per thread),
226
+ # which also preserves parse parallelism instead of serializing it.
227
+ _parser_tls = threading.local()
228
+
229
+
219
230
  def _parser() -> Parser:
220
- lang = Language(_ts_java.language())
221
- return Parser(lang)
231
+ p = getattr(_parser_tls, "parser", None)
232
+ if p is None:
233
+ _parser_tls.parser = p = Parser(Language(_ts_java.language()))
234
+ return p
222
235
 
223
236
 
224
237
  # ---------- dataclasses ----------
@@ -1565,62 +1578,20 @@ def _parse_codebase_http_route_inner_annotation(
1565
1578
  return out
1566
1579
 
1567
1580
 
1568
- def _codebase_route_inner_annotation_nodes(container_ann: Node, src: bytes) -> list[Node]:
1569
- found: list[Node] = []
1570
-
1571
- def visit(n: Node) -> None:
1572
- if n.type == "annotation":
1573
- name_node = n.child_by_field_name("name")
1574
- n_simple = _txt(name_node, src).rsplit(".", 1)[-1] if name_node is not None else ""
1575
- if n_simple == "CodebaseHttpRoute":
1576
- found.append(n)
1577
- for c in n.children:
1578
- visit(c)
1581
+ def _inner_annotation_nodes(container_ann: Node, src: bytes, target_simple: str) -> list[Node]:
1582
+ """Collect nested ``@<target_simple>`` annotations anywhere under ``container_ann``.
1579
1583
 
1580
- visit(container_ann)
1581
- return found
1582
-
1583
-
1584
- def _codebase_async_route_inner_annotation_nodes(container_ann: Node, src: bytes) -> list[Node]:
1585
- found: list[Node] = []
1586
-
1587
- def visit(n: Node) -> None:
1588
- if n.type == "annotation":
1589
- name_node = n.child_by_field_name("name")
1590
- n_simple = _txt(name_node, src).rsplit(".", 1)[-1] if name_node is not None else ""
1591
- if n_simple == "CodebaseAsyncRoute":
1592
- found.append(n)
1593
- for c in n.children:
1594
- visit(c)
1595
-
1596
- visit(container_ann)
1597
- return found
1598
-
1599
-
1600
- def _codebase_http_client_inner_annotation_nodes(container_ann: Node, src: bytes) -> list[Node]:
1601
- found: list[Node] = []
1602
-
1603
- def visit(n: Node) -> None:
1604
- if n.type == "annotation":
1605
- name_node = n.child_by_field_name("name")
1606
- n_simple = _txt(name_node, src).rsplit(".", 1)[-1] if name_node is not None else ""
1607
- if n_simple == "CodebaseHttpClient":
1608
- found.append(n)
1609
- for c in n.children:
1610
- visit(c)
1611
-
1612
- visit(container_ann)
1613
- return found
1614
-
1615
-
1616
- def _codebase_producer_inner_annotation_nodes(container_ann: Node, src: bytes) -> list[Node]:
1584
+ Shared by the four brownfield container walkers — ``CodebaseHttpRoute``,
1585
+ ``CodebaseAsyncRoute``, ``CodebaseHttpClient``, ``CodebaseProducer`` — which
1586
+ differ only by the target annotation simple name.
1587
+ """
1617
1588
  found: list[Node] = []
1618
1589
 
1619
1590
  def visit(n: Node) -> None:
1620
1591
  if n.type == "annotation":
1621
1592
  name_node = n.child_by_field_name("name")
1622
1593
  n_simple = _txt(name_node, src).rsplit(".", 1)[-1] if name_node is not None else ""
1623
- if n_simple == "CodebaseProducer":
1594
+ if n_simple == target_simple:
1624
1595
  found.append(n)
1625
1596
  for c in n.children:
1626
1597
  visit(c)
@@ -1842,7 +1813,7 @@ def _outgoing_calls_from_codebase_http_client_producer_annotations(
1842
1813
  ),
1843
1814
  )
1844
1815
  elif simple == "CodebaseHttpClients":
1845
- for inner in _codebase_http_client_inner_annotation_nodes(ann, src):
1816
+ for inner in _inner_annotation_nodes(ann, src, "CodebaseHttpClient"):
1846
1817
  out.append(
1847
1818
  _parse_codebase_http_client_annotation(
1848
1819
  inner,
@@ -1869,7 +1840,7 @@ def _outgoing_calls_from_codebase_http_client_producer_annotations(
1869
1840
  ),
1870
1841
  )
1871
1842
  elif simple == "CodebaseProducers":
1872
- for inner in _codebase_producer_inner_annotation_nodes(ann, src):
1843
+ for inner in _inner_annotation_nodes(ann, src, "CodebaseProducer"):
1873
1844
  out.append(
1874
1845
  _parse_codebase_producer_annotation(
1875
1846
  inner,
@@ -2343,7 +2314,7 @@ def _collect_routes(
2343
2314
  ),
2344
2315
  )
2345
2316
  elif simple == "CodebaseHttpRoutes":
2346
- for inner in _codebase_route_inner_annotation_nodes(node, src):
2317
+ for inner in _inner_annotation_nodes(node, src, "CodebaseHttpRoute"):
2347
2318
  routes.extend(
2348
2319
  _parse_codebase_http_route_inner_annotation(
2349
2320
  inner,
@@ -2359,7 +2330,7 @@ def _collect_routes(
2359
2330
  elif simple in ("CodebaseAsyncRoute", "CodebaseAsyncRoutes"):
2360
2331
  nodes = [node]
2361
2332
  if simple == "CodebaseAsyncRoutes":
2362
- nodes = list(_codebase_async_route_inner_annotation_nodes(node, src))
2333
+ nodes = list(_inner_annotation_nodes(node, src, "CodebaseAsyncRoute"))
2363
2334
  for ann in nodes:
2364
2335
  pairs, _ = _annotation_kv_nodes(ann, src)
2365
2336
  topic_node = pairs.get("topic")