java-codebase-rag 0.9.7__tar.gz → 0.10.1__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.
- {java_codebase_rag-0.9.7/src/java_codebase_rag.egg-info → java_codebase_rag-0.10.1}/PKG-INFO +30 -31
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/README.md +24 -26
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/pyproject.toml +6 -5
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/analysis/pr_analysis.py +33 -3
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/ast/ast_java.py +2 -1
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/cli.py +23 -8
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/config.py +68 -1
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/graph/build_ast_graph.py +123 -4
- java_codebase_rag-0.10.1/src/java_codebase_rag/graph/graph_types.py +224 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/graph/ladybug_queries.py +45 -2
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/index/java_index_flow_lancedb.py +10 -16
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/install_data/agents/explorer-rag-cli.md +3 -1
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/install_data/skills/explore-codebase-cli/SKILL.md +3 -1
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/jrag.py +627 -661
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/jrag_render.py +160 -3
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/lance_optimize.py +11 -12
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/mcp/mcp_v2.py +2 -1
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/pipeline.py +47 -1
- java_codebase_rag-0.10.1/src/java_codebase_rag/read_payloads.py +781 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/search/search_lancedb.py +138 -6
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/search/search_lexical.py +140 -30
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/search/search_scoring.py +108 -0
- java_codebase_rag-0.10.1/src/java_codebase_rag/watch/__init__.py +0 -0
- java_codebase_rag-0.10.1/src/java_codebase_rag/watch/client.py +230 -0
- java_codebase_rag-0.10.1/src/java_codebase_rag/watch/daemon.py +368 -0
- java_codebase_rag-0.10.1/src/java_codebase_rag/watch/lock.py +201 -0
- java_codebase_rag-0.10.1/src/java_codebase_rag/watch/paths.py +76 -0
- java_codebase_rag-0.10.1/src/java_codebase_rag/watch/protocol.py +122 -0
- java_codebase_rag-0.10.1/src/java_codebase_rag/watch/server.py +273 -0
- java_codebase_rag-0.10.1/src/java_codebase_rag/watch/warm.py +105 -0
- java_codebase_rag-0.10.1/src/java_codebase_rag/watch/watcher.py +352 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1/src/java_codebase_rag.egg-info}/PKG-INFO +30 -31
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag.egg-info/SOURCES.txt +13 -1
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag.egg-info/requires.txt +5 -4
- java_codebase_rag-0.10.1/tests/test_config_watch.py +164 -0
- java_codebase_rag-0.10.1/tests/test_docs_watch.py +76 -0
- java_codebase_rag-0.9.7/src/java_codebase_rag/graph/graph_types.py +0 -137
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/LICENSE +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/setup.cfg +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/__init__.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/_fdlimit.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/_stdio.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/_version.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/absence/__init__.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/absence/absence_diagnosis.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/absence/absence_types.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/absence/absence_vocab.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/analysis/__init__.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/analysis/resolve_service.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/ast/__init__.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/ast/brownfield_events.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/ast/chunk_heuristics.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/cli_format.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/cli_progress.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/graph/__init__.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/graph/graph_enrich.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/graph/java_ontology.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/graph/path_filtering.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/index/__init__.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/index/java_index_v1_common.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/install_data/__init__.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/install_data/agents/explorer-rag-enhanced.md +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/install_data/skills/explore-codebase/SKILL.md +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/installer.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/jrag_envelope.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/jrag_hints.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/mcp/__init__.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/mcp/mcp_hints.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/mcp/server.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/progress.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/search/__init__.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/search/index_common.py +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag.egg-info/dependency_links.txt +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag.egg-info/entry_points.txt +0 -0
- {java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag.egg-info/top_level.txt +0 -0
{java_codebase_rag-0.9.7/src/java_codebase_rag.egg-info → java_codebase_rag-0.10.1}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: java-codebase-rag
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.1
|
|
4
4
|
Summary: MCP server for semantic + structural search over Java codebases
|
|
5
5
|
Author: HumanBean17
|
|
6
6
|
License-Expression: MIT
|
|
@@ -21,21 +21,22 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
21
21
|
Requires-Python: >=3.11
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
|
24
|
-
Requires-Dist: cocoindex[lancedb]<2,>=1.0.
|
|
24
|
+
Requires-Dist: cocoindex[lancedb]<2,>=1.0.15; sys_platform != "darwin" or platform_machine != "x86_64"
|
|
25
25
|
Requires-Dist: ladybug<0.18,>=0.17.1
|
|
26
|
-
Requires-Dist: lancedb<0.
|
|
26
|
+
Requires-Dist: lancedb<0.36,>=0.34; sys_platform != "darwin" or platform_machine != "x86_64"
|
|
27
27
|
Requires-Dist: mcp<2,>=1.27.0
|
|
28
28
|
Requires-Dist: numpy<2.5,>=1.26.4
|
|
29
29
|
Requires-Dist: pathspec<2,>=1.0.4
|
|
30
|
-
Requires-Dist: pyarrow<
|
|
30
|
+
Requires-Dist: pyarrow<26,>=23.0.1
|
|
31
31
|
Requires-Dist: pydantic<3,>=2.0
|
|
32
32
|
Requires-Dist: PyYAML<7,>=6.0.3
|
|
33
33
|
Requires-Dist: questionary<3,>=2.0
|
|
34
|
-
Requires-Dist: rich<
|
|
34
|
+
Requires-Dist: rich<16,>=14
|
|
35
35
|
Requires-Dist: sentence-transformers<6,>=5.4.0; sys_platform != "darwin" or platform_machine != "x86_64"
|
|
36
36
|
Requires-Dist: tree-sitter<0.26,>=0.25.2
|
|
37
37
|
Requires-Dist: tree-sitter-java<0.24,>=0.23.5
|
|
38
38
|
Requires-Dist: unidiff<1,>=0.7.3
|
|
39
|
+
Requires-Dist: watchdog<7,>=6
|
|
39
40
|
Provides-Extra: dev
|
|
40
41
|
Requires-Dist: pytest>=7; extra == "dev"
|
|
41
42
|
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
@@ -45,18 +46,16 @@ Dynamic: license-file
|
|
|
45
46
|
|
|
46
47
|
# java-codebase-rag
|
|
47
48
|
|
|
48
|
-
A graph-native code intelligence layer for Java microservice estates —
|
|
49
|
+
A graph-native code intelligence layer for Java microservice estates, surfaced through the **`jrag` CLI** — one command per engineering intent. A **legacy MCP server** (`search` / `find` / `describe` / `neighbors` / `resolve`) is also available for existing setups. Both are thin surfaces over the same **AST Graph**: a deterministic property graph extracted from Java source with tree-sitter, stored **locally** in **LadybugDB** (graph) alongside a **LanceDB** vector index (chunks). There is no server to host and no cloud round-trip — the index lives on your disk and your source never leaves the machine. Both surfaces collapse onto three primitive operations: **locate**, **inspect**, **walk**.
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
> **What this MCP is:** a **GPS for code navigation**, not a reasoning engine.
|
|
51
|
+
> **What this is: a GPS for code navigation**, not a reasoning engine.
|
|
53
52
|
> Agents use a simple loop:
|
|
54
53
|
>
|
|
55
|
-
> 1. **Locate** entry nodes (`
|
|
56
|
-
> 2. **Inspect** what a node is (`
|
|
57
|
-
> 3. **Walk** one hop at a time (`
|
|
54
|
+
> 1. **Locate** entry nodes (`jrag find`, `jrag search`, or identifier-shaped lookup)
|
|
55
|
+
> 2. **Inspect** what a node is (`jrag inspect`)
|
|
56
|
+
> 3. **Walk** one hop at a time (`jrag callers` / `callees` / `hierarchy` / …) until enough evidence is gathered
|
|
58
57
|
>
|
|
59
|
-
> The
|
|
58
|
+
> The tool exposes structure and adjacency; the agent owns multi-hop reasoning and stop conditions.
|
|
60
59
|
|
|
61
60
|
For the design rationale, the GPS metaphor, and the full ontology, see [`docs/paper/paper.pdf`](./docs/paper/paper.pdf) (architecture report).
|
|
62
61
|
|
|
@@ -66,7 +65,7 @@ For the design rationale, the GPS metaphor, and the full ontology, see [`docs/pa
|
|
|
66
65
|
|
|
67
66
|
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.
|
|
68
67
|
|
|
69
|
-
- **Hybrid RAG +
|
|
68
|
+
- **Hybrid RAG + AST Graph, not either-or.** Semantic recall (LanceDB chunk vectors) and structural navigation (the LadybugDB AST 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.
|
|
70
69
|
|
|
71
70
|
- **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.
|
|
72
71
|
|
|
@@ -86,7 +85,7 @@ The rest of this README is the install, the tool/command orientation, and the re
|
|
|
86
85
|
pip install java-codebase-rag
|
|
87
86
|
```
|
|
88
87
|
|
|
89
|
-
Python **3.11+** required, on **Linux, macOS, and Windows**. On Linux, Windows, and **Apple Silicon** Macs every native dependency (LanceDB, LadybugDB
|
|
88
|
+
Python **3.11+** required, on **Linux, macOS, and Windows**. On Linux, Windows, and **Apple Silicon** Macs every native dependency (LanceDB, LadybugDB, CocoIndex) ships a wheel and you get the full semantic + graph search. **Intel Macs (x86_64) install graph-only**: PyTorch ≥2.3 and LanceDB ≥0.26 dropped macOS Intel wheels, so the vector stack is auto-excluded via PEP 508 markers — `pip install java-codebase-rag` works out of the box, the graph layer (`find` / `describe` / `neighbors` / `resolve`) is fully usable, and the `search` tool falls back to **lexical search** over the symbol graph — BM25-ranked over a LadybugDB full-text index (same tool contract, keyword-ranked instead of semantic; an advisory notes the mode). Semantic/vector search needs Apple Silicon, Linux, or Windows. After install, `java-codebase-rag --help` should print the CLI groups.
|
|
90
89
|
The package includes the CocoIndex lifecycle dependency used by `init`, `increment`, `reprocess`, and `erase` on platforms that have it (it is absent on Intel Mac).
|
|
91
90
|
|
|
92
91
|
### Interactive setup (recommended)
|
|
@@ -122,19 +121,7 @@ If you prefer manual configuration, see [`docs/JAVA-CODEBASE-RAG-CLI.md`](./docs
|
|
|
122
121
|
|
|
123
122
|
## Tools & commands at a glance
|
|
124
123
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
**MCP surface — five tools over stdio**
|
|
128
|
-
|
|
129
|
-
| Tool | Purpose | Required args |
|
|
130
|
-
|---|---|---|
|
|
131
|
-
| `search` | Locate nodes by NL / code text. | `query` |
|
|
132
|
-
| `find` | Locate nodes by structured filter. | `kind`, `filter` |
|
|
133
|
-
| `describe` | Full record + edge counts for one node. | `id` |
|
|
134
|
-
| `resolve` | Identifier-shaped lookup (FQN-collision-safe). Returns `one` / `many` / `none`. | `identifier` |
|
|
135
|
-
| `neighbors` | Graph walk, one hop. | `ids`, `direction`, `edge_types` |
|
|
136
|
-
|
|
137
|
-
Full schemas, `NodeFilter` / `EdgeFilter` semantics, and the hints contract live in [`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md). Edge types and traversal directions are listed in [`docs/EDGE-NAVIGATION.md`](./docs/EDGE-NAVIGATION.md).
|
|
124
|
+
`jrag` is the default and recommended surface (`java-codebase-rag install --surface cli`). The **MCP server** (`--surface mcp`) is kept as a **legacy** option for existing setups. Both surfaces walk the same LanceDB vectors + LadybugDB **AST Graph**. Switch an existing install later with `java-codebase-rag update --surface mcp|cli`.
|
|
138
125
|
|
|
139
126
|
**CLI surface — `jrag`, one command per engineering intent**
|
|
140
127
|
|
|
@@ -143,7 +130,7 @@ Full schemas, `NodeFilter` / `EdgeFilter` semantics, and the hints contract live
|
|
|
143
130
|
jrag status # index health (ontology version, freshness, counts)
|
|
144
131
|
jrag microservices # microservices with resolved type counts
|
|
145
132
|
jrag map # counts per kind per service/module
|
|
146
|
-
jrag map --module
|
|
133
|
+
jrag map --by module # group by module instead (--module filters)
|
|
147
134
|
jrag conventions # dominant roles + framework tallies
|
|
148
135
|
jrag overview chat-core # bundle for a microservice
|
|
149
136
|
jrag overview /chat/assign # route flow (inbound callers + outbound CALLS)
|
|
@@ -191,9 +178,21 @@ jrag search "audit" --offset 5 # paginated
|
|
|
191
178
|
|
|
192
179
|
Every `<query>` command takes human-readable identifiers (FQN / simple name / route path / topic) — never raw node IDs. Output contract, flags, and the resolve-first rule are in [`jrag` — agent CLI](#jrag--agent-cli) below.
|
|
193
180
|
|
|
181
|
+
**MCP surface — five tools over stdio (legacy)**
|
|
182
|
+
|
|
183
|
+
| Tool | Purpose | Required args |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| `search` | Locate nodes by NL / code text. | `query` |
|
|
186
|
+
| `find` | Locate nodes by structured filter. | `kind`, `filter` |
|
|
187
|
+
| `describe` | Full record + edge counts for one node. | `id` |
|
|
188
|
+
| `resolve` | Identifier-shaped lookup (FQN-collision-safe). Returns `one` / `many` / `none`. | `identifier` |
|
|
189
|
+
| `neighbors` | Graph walk, one hop. | `ids`, `direction`, `edge_types` |
|
|
190
|
+
|
|
191
|
+
Full schemas, `NodeFilter` / `EdgeFilter` semantics, and the hints contract live in [`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md). Edge types and traversal directions are listed in [`docs/EDGE-NAVIGATION.md`](./docs/EDGE-NAVIGATION.md).
|
|
192
|
+
|
|
194
193
|
### Three-layer architecture
|
|
195
194
|
|
|
196
|
-
Layer 1 (storage) → Layer 2 (
|
|
195
|
+
Layer 1 (storage) → Layer 2 (the `jrag` CLI, **or** the legacy 5-tool MCP) → Layer 3 (skill). The CLI-surface skill **[`/explore-codebase-cli`](./skills/explore-codebase-cli/SKILL.md)** documents the `jrag` CLI; the MCP-surface skill **[`/explore-codebase`](./skills/explore-codebase/SKILL.md)** documents the legacy 5-tool MCP (PR-JRAG-5). See the [architecture diagram in `skills/README.md`](./skills/README.md#three-layer-architecture).
|
|
197
196
|
|
|
198
197
|
---
|
|
199
198
|
|
|
@@ -303,7 +302,7 @@ full design and per-PR breakdown.
|
|
|
303
302
|
| [`docs/CONFIGURATION.md`](./docs/CONFIGURATION.md) | Environment variables, project YAML, graph ontology, brownfield overrides, ignore patterns. |
|
|
304
303
|
| [`docs/JAVA-CODEBASE-RAG-CLI.md`](./docs/JAVA-CODEBASE-RAG-CLI.md) | CLI operator playbook: workflows, exit codes, env alignment. |
|
|
305
304
|
| [`docs/EDGE-NAVIGATION.md`](./docs/EDGE-NAVIGATION.md) | MCP-traversable edges, directions, dot-key composition. |
|
|
306
|
-
| [`skills/`](./skills/) | `/explore-codebase` (
|
|
305
|
+
| [`skills/`](./skills/) | `/explore-codebase-cli` (CLI surface) + `/explore-codebase` (legacy MCP surface) skills — operating manuals for hosts with skill discovery (alternative to copy-pasting AGENT-GUIDE). See [`skills/README.md`](./skills/README.md). |
|
|
307
306
|
| [`docs/MANUAL-VERIFICATION-CHECKLIST.md`](./docs/MANUAL-VERIFICATION-CHECKLIST.md) | 7-phase agent-driven verification after indexing your project. |
|
|
308
307
|
| [`docs/CODEBASE_REQUIREMENTS.md`](./docs/CODEBASE_REQUIREMENTS.md) | Assumptions about your Java repo + per-file edit map for non-conforming codebases. |
|
|
309
308
|
| [`docs/PRODUCT-VISION.md`](./docs/PRODUCT-VISION.md) | Long-term product direction. |
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
# java-codebase-rag
|
|
2
2
|
|
|
3
|
-
A graph-native code intelligence layer for Java microservice estates —
|
|
3
|
+
A graph-native code intelligence layer for Java microservice estates, surfaced through the **`jrag` CLI** — one command per engineering intent. A **legacy MCP server** (`search` / `find` / `describe` / `neighbors` / `resolve`) is also available for existing setups. Both are thin surfaces over the same **AST Graph**: a deterministic property graph extracted from Java source with tree-sitter, stored **locally** in **LadybugDB** (graph) alongside a **LanceDB** vector index (chunks). There is no server to host and no cloud round-trip — the index lives on your disk and your source never leaves the machine. Both surfaces collapse onto three primitive operations: **locate**, **inspect**, **walk**.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
> **What this MCP is:** a **GPS for code navigation**, not a reasoning engine.
|
|
5
|
+
> **What this is: a GPS for code navigation**, not a reasoning engine.
|
|
8
6
|
> Agents use a simple loop:
|
|
9
7
|
>
|
|
10
|
-
> 1. **Locate** entry nodes (`
|
|
11
|
-
> 2. **Inspect** what a node is (`
|
|
12
|
-
> 3. **Walk** one hop at a time (`
|
|
8
|
+
> 1. **Locate** entry nodes (`jrag find`, `jrag search`, or identifier-shaped lookup)
|
|
9
|
+
> 2. **Inspect** what a node is (`jrag inspect`)
|
|
10
|
+
> 3. **Walk** one hop at a time (`jrag callers` / `callees` / `hierarchy` / …) until enough evidence is gathered
|
|
13
11
|
>
|
|
14
|
-
> The
|
|
12
|
+
> The tool exposes structure and adjacency; the agent owns multi-hop reasoning and stop conditions.
|
|
15
13
|
|
|
16
14
|
For the design rationale, the GPS metaphor, and the full ontology, see [`docs/paper/paper.pdf`](./docs/paper/paper.pdf) (architecture report).
|
|
17
15
|
|
|
@@ -21,7 +19,7 @@ For the design rationale, the GPS metaphor, and the full ontology, see [`docs/pa
|
|
|
21
19
|
|
|
22
20
|
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
21
|
|
|
24
|
-
- **Hybrid RAG +
|
|
22
|
+
- **Hybrid RAG + AST Graph, not either-or.** Semantic recall (LanceDB chunk vectors) and structural navigation (the LadybugDB AST 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
23
|
|
|
26
24
|
- **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
25
|
|
|
@@ -41,7 +39,7 @@ The rest of this README is the install, the tool/command orientation, and the re
|
|
|
41
39
|
pip install java-codebase-rag
|
|
42
40
|
```
|
|
43
41
|
|
|
44
|
-
Python **3.11+** required, on **Linux, macOS, and Windows**. On Linux, Windows, and **Apple Silicon** Macs every native dependency (LanceDB, LadybugDB
|
|
42
|
+
Python **3.11+** required, on **Linux, macOS, and Windows**. On Linux, Windows, and **Apple Silicon** Macs every native dependency (LanceDB, LadybugDB, CocoIndex) ships a wheel and you get the full semantic + graph search. **Intel Macs (x86_64) install graph-only**: PyTorch ≥2.3 and LanceDB ≥0.26 dropped macOS Intel wheels, so the vector stack is auto-excluded via PEP 508 markers — `pip install java-codebase-rag` works out of the box, the graph layer (`find` / `describe` / `neighbors` / `resolve`) is fully usable, and the `search` tool falls back to **lexical search** over the symbol graph — BM25-ranked over a LadybugDB full-text index (same tool contract, keyword-ranked instead of semantic; an advisory notes the mode). Semantic/vector search needs Apple Silicon, Linux, or Windows. After install, `java-codebase-rag --help` should print the CLI groups.
|
|
45
43
|
The package includes the CocoIndex lifecycle dependency used by `init`, `increment`, `reprocess`, and `erase` on platforms that have it (it is absent on Intel Mac).
|
|
46
44
|
|
|
47
45
|
### Interactive setup (recommended)
|
|
@@ -77,19 +75,7 @@ If you prefer manual configuration, see [`docs/JAVA-CODEBASE-RAG-CLI.md`](./docs
|
|
|
77
75
|
|
|
78
76
|
## Tools & commands at a glance
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
**MCP surface — five tools over stdio**
|
|
83
|
-
|
|
84
|
-
| Tool | Purpose | Required args |
|
|
85
|
-
|---|---|---|
|
|
86
|
-
| `search` | Locate nodes by NL / code text. | `query` |
|
|
87
|
-
| `find` | Locate nodes by structured filter. | `kind`, `filter` |
|
|
88
|
-
| `describe` | Full record + edge counts for one node. | `id` |
|
|
89
|
-
| `resolve` | Identifier-shaped lookup (FQN-collision-safe). Returns `one` / `many` / `none`. | `identifier` |
|
|
90
|
-
| `neighbors` | Graph walk, one hop. | `ids`, `direction`, `edge_types` |
|
|
91
|
-
|
|
92
|
-
Full schemas, `NodeFilter` / `EdgeFilter` semantics, and the hints contract live in [`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md). Edge types and traversal directions are listed in [`docs/EDGE-NAVIGATION.md`](./docs/EDGE-NAVIGATION.md).
|
|
78
|
+
`jrag` is the default and recommended surface (`java-codebase-rag install --surface cli`). The **MCP server** (`--surface mcp`) is kept as a **legacy** option for existing setups. Both surfaces walk the same LanceDB vectors + LadybugDB **AST Graph**. Switch an existing install later with `java-codebase-rag update --surface mcp|cli`.
|
|
93
79
|
|
|
94
80
|
**CLI surface — `jrag`, one command per engineering intent**
|
|
95
81
|
|
|
@@ -98,7 +84,7 @@ Full schemas, `NodeFilter` / `EdgeFilter` semantics, and the hints contract live
|
|
|
98
84
|
jrag status # index health (ontology version, freshness, counts)
|
|
99
85
|
jrag microservices # microservices with resolved type counts
|
|
100
86
|
jrag map # counts per kind per service/module
|
|
101
|
-
jrag map --module
|
|
87
|
+
jrag map --by module # group by module instead (--module filters)
|
|
102
88
|
jrag conventions # dominant roles + framework tallies
|
|
103
89
|
jrag overview chat-core # bundle for a microservice
|
|
104
90
|
jrag overview /chat/assign # route flow (inbound callers + outbound CALLS)
|
|
@@ -146,9 +132,21 @@ jrag search "audit" --offset 5 # paginated
|
|
|
146
132
|
|
|
147
133
|
Every `<query>` command takes human-readable identifiers (FQN / simple name / route path / topic) — never raw node IDs. Output contract, flags, and the resolve-first rule are in [`jrag` — agent CLI](#jrag--agent-cli) below.
|
|
148
134
|
|
|
135
|
+
**MCP surface — five tools over stdio (legacy)**
|
|
136
|
+
|
|
137
|
+
| Tool | Purpose | Required args |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| `search` | Locate nodes by NL / code text. | `query` |
|
|
140
|
+
| `find` | Locate nodes by structured filter. | `kind`, `filter` |
|
|
141
|
+
| `describe` | Full record + edge counts for one node. | `id` |
|
|
142
|
+
| `resolve` | Identifier-shaped lookup (FQN-collision-safe). Returns `one` / `many` / `none`. | `identifier` |
|
|
143
|
+
| `neighbors` | Graph walk, one hop. | `ids`, `direction`, `edge_types` |
|
|
144
|
+
|
|
145
|
+
Full schemas, `NodeFilter` / `EdgeFilter` semantics, and the hints contract live in [`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md). Edge types and traversal directions are listed in [`docs/EDGE-NAVIGATION.md`](./docs/EDGE-NAVIGATION.md).
|
|
146
|
+
|
|
149
147
|
### Three-layer architecture
|
|
150
148
|
|
|
151
|
-
Layer 1 (storage) → Layer 2 (
|
|
149
|
+
Layer 1 (storage) → Layer 2 (the `jrag` CLI, **or** the legacy 5-tool MCP) → Layer 3 (skill). The CLI-surface skill **[`/explore-codebase-cli`](./skills/explore-codebase-cli/SKILL.md)** documents the `jrag` CLI; the MCP-surface skill **[`/explore-codebase`](./skills/explore-codebase/SKILL.md)** documents the legacy 5-tool MCP (PR-JRAG-5). See the [architecture diagram in `skills/README.md`](./skills/README.md#three-layer-architecture).
|
|
152
150
|
|
|
153
151
|
---
|
|
154
152
|
|
|
@@ -258,7 +256,7 @@ full design and per-PR breakdown.
|
|
|
258
256
|
| [`docs/CONFIGURATION.md`](./docs/CONFIGURATION.md) | Environment variables, project YAML, graph ontology, brownfield overrides, ignore patterns. |
|
|
259
257
|
| [`docs/JAVA-CODEBASE-RAG-CLI.md`](./docs/JAVA-CODEBASE-RAG-CLI.md) | CLI operator playbook: workflows, exit codes, env alignment. |
|
|
260
258
|
| [`docs/EDGE-NAVIGATION.md`](./docs/EDGE-NAVIGATION.md) | MCP-traversable edges, directions, dot-key composition. |
|
|
261
|
-
| [`skills/`](./skills/) | `/explore-codebase` (
|
|
259
|
+
| [`skills/`](./skills/) | `/explore-codebase-cli` (CLI surface) + `/explore-codebase` (legacy MCP surface) skills — operating manuals for hosts with skill discovery (alternative to copy-pasting AGENT-GUIDE). See [`skills/README.md`](./skills/README.md). |
|
|
262
260
|
| [`docs/MANUAL-VERIFICATION-CHECKLIST.md`](./docs/MANUAL-VERIFICATION-CHECKLIST.md) | 7-phase agent-driven verification after indexing your project. |
|
|
263
261
|
| [`docs/CODEBASE_REQUIREMENTS.md`](./docs/CODEBASE_REQUIREMENTS.md) | Assumptions about your Java repo + per-file edit map for non-conforming codebases. |
|
|
264
262
|
| [`docs/PRODUCT-VISION.md`](./docs/PRODUCT-VISION.md) | Long-term product direction. |
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "java-codebase-rag"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.10.1"
|
|
8
8
|
description = "MCP server for semantic + structural search over Java codebases"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -32,21 +32,22 @@ classifiers = [
|
|
|
32
32
|
# lexical (keyword) backend over the symbol graph (search_lexical.py); every other platform
|
|
33
33
|
# is unchanged.
|
|
34
34
|
dependencies = [
|
|
35
|
-
"cocoindex[lancedb]>=1.0.
|
|
35
|
+
"cocoindex[lancedb]>=1.0.15,<2; sys_platform != 'darwin' or platform_machine != 'x86_64'",
|
|
36
36
|
"ladybug>=0.17.1,<0.18",
|
|
37
|
-
"lancedb>=0.
|
|
37
|
+
"lancedb>=0.34,<0.36; sys_platform != 'darwin' or platform_machine != 'x86_64'",
|
|
38
38
|
"mcp>=1.27.0,<2",
|
|
39
39
|
"numpy>=1.26.4,<2.5",
|
|
40
40
|
"pathspec>=1.0.4,<2",
|
|
41
|
-
"pyarrow>=23.0.1,<
|
|
41
|
+
"pyarrow>=23.0.1,<26",
|
|
42
42
|
"pydantic>=2.0,<3",
|
|
43
43
|
"PyYAML>=6.0.3,<7",
|
|
44
44
|
"questionary>=2.0,<3",
|
|
45
|
-
"rich>=14,<
|
|
45
|
+
"rich>=14,<16",
|
|
46
46
|
"sentence-transformers>=5.4.0,<6; sys_platform != 'darwin' or platform_machine != 'x86_64'",
|
|
47
47
|
"tree-sitter>=0.25.2,<0.26",
|
|
48
48
|
"tree-sitter-java>=0.23.5,<0.24",
|
|
49
49
|
"unidiff>=0.7.3,<1",
|
|
50
|
+
"watchdog>=6,<7",
|
|
50
51
|
]
|
|
51
52
|
|
|
52
53
|
[project.optional-dependencies]
|
{java_codebase_rag-0.9.7 → java_codebase_rag-0.10.1}/src/java_codebase_rag/analysis/pr_analysis.py
RENAMED
|
@@ -377,6 +377,31 @@ def _route_ids_for_symbol(graph: Any, symbol_id: str) -> list[str]:
|
|
|
377
377
|
return out
|
|
378
378
|
|
|
379
379
|
|
|
380
|
+
def _route_natural_id(graph: Any, rid: str) -> str:
|
|
381
|
+
"""Map a raw Route node id to its agent-facing natural identifier.
|
|
382
|
+
|
|
383
|
+
Mirrors the envelope contract (``METHOD path`` for HTTP endpoints,
|
|
384
|
+
``topic:<name>`` for kafka topics surfaced as :Route) so ``routes_touched``
|
|
385
|
+
in the PR risk report is readable instead of leaking raw graph ids like
|
|
386
|
+
``r:970ffaa960a4f65d``. Falls back to ``rid`` only if the route vanished.
|
|
387
|
+
"""
|
|
388
|
+
rows = graph._rows(
|
|
389
|
+
"MATCH (r:Route {id: $rid}) "
|
|
390
|
+
"RETURN r.method AS method, r.path_template AS path_template, "
|
|
391
|
+
"r.path AS path, r.topic AS topic LIMIT 1",
|
|
392
|
+
{"rid": rid},
|
|
393
|
+
)
|
|
394
|
+
if not rows:
|
|
395
|
+
return rid
|
|
396
|
+
r = rows[0]
|
|
397
|
+
method = str(r.get("method") or "")
|
|
398
|
+
path = str(r.get("path_template") or r.get("path") or "")
|
|
399
|
+
if method or path:
|
|
400
|
+
return f"{method} {path}".strip()
|
|
401
|
+
topic = str(r.get("topic") or "")
|
|
402
|
+
return f"topic:{topic}" if topic else rid
|
|
403
|
+
|
|
404
|
+
|
|
380
405
|
def compute_risk(graph: Any, changed: list[ChangedSymbol]) -> PrRiskReport:
|
|
381
406
|
"""Aggregate blast radius, routes, cross-service callers, and v1 risk score.
|
|
382
407
|
|
|
@@ -415,7 +440,9 @@ def compute_risk(graph: Any, changed: list[ChangedSymbol]) -> PrRiskReport:
|
|
|
415
440
|
needle = _impact_needle_for_changed(graph, fqn, cs.kind)
|
|
416
441
|
ia = graph.impact_analysis(needle, depth=2, limit=400)
|
|
417
442
|
n = len(ia)
|
|
418
|
-
|
|
443
|
+
# Key blast radius by the symbol's FQN (agent-facing identifier), not
|
|
444
|
+
# its raw graph id — the report is operator-facing JSON.
|
|
445
|
+
blast_by[fqn or cs.symbol_id] = n
|
|
419
446
|
blast_total += n
|
|
420
447
|
|
|
421
448
|
for e in graph.find_callers(cs.fqn, depth=2, limit=400):
|
|
@@ -429,8 +456,11 @@ def compute_risk(graph: Any, changed: list[ChangedSymbol]) -> PrRiskReport:
|
|
|
429
456
|
cs_cross_service = 0
|
|
430
457
|
route_ids = _route_ids_for_symbol(graph, cs.symbol_id)
|
|
431
458
|
for rid in route_ids:
|
|
432
|
-
|
|
433
|
-
|
|
459
|
+
# Record the route by its natural identifier (METHOD path /
|
|
460
|
+
# topic:name), not the raw graph id.
|
|
461
|
+
label = _route_natural_id(graph, rid)
|
|
462
|
+
if label and label not in routes:
|
|
463
|
+
routes.append(label)
|
|
434
464
|
callers = graph._rows(
|
|
435
465
|
"MATCH (s:Symbol)-[:DECLARES_CLIENT]->(c:Client)-[e:HTTP_CALLS]->(r:Route {id: $rid}) "
|
|
436
466
|
"WHERE e.match = 'cross_service' "
|
|
@@ -84,7 +84,8 @@ _DTO_LOMBOK_ANNOTATIONS: frozenset[str] = frozenset({
|
|
|
84
84
|
# Phase 11: `EDGE_SCHEMA` in `java_ontology.py` (canonical edge navigation schema; v14 re-index).
|
|
85
85
|
# Phase 12: CALLS `callee_declaring_role`, supertype-walk dedup, pass3 unresolved counters (v15 re-index).
|
|
86
86
|
# Bumps whenever extraction / enrichment semantics change.
|
|
87
|
-
|
|
87
|
+
# Phase 13: Symbol.search_text + LadybugDB FTS (Okapi BM25) index for lexical search (v19 re-index).
|
|
88
|
+
ONTOLOGY_VERSION = 19
|
|
88
89
|
|
|
89
90
|
ROLE_ANNOTATIONS: dict[str, str] = {
|
|
90
91
|
# Spring Web
|
|
@@ -846,7 +846,15 @@ def _cmd_unresolved_calls_list(args: argparse.Namespace) -> int:
|
|
|
846
846
|
callee_simple=args.callee_simple,
|
|
847
847
|
limit=int(args.limit),
|
|
848
848
|
)
|
|
849
|
-
|
|
849
|
+
# Drop the raw caller symbol id: the row already carries the agent-facing
|
|
850
|
+
# ``caller_fqn``, so ``caller_id`` is redundant noise in an operator-facing
|
|
851
|
+
# report. The call-site ``id`` (``ucs:``) is kept — it's each site's
|
|
852
|
+
# primary key, not a caller reference.
|
|
853
|
+
sites = [
|
|
854
|
+
{k: v for k, v in row.items() if k != "caller_id"}
|
|
855
|
+
for row in rows
|
|
856
|
+
]
|
|
857
|
+
_emit({"success": True, "count": len(sites), "sites": sites})
|
|
850
858
|
return 0
|
|
851
859
|
|
|
852
860
|
|
|
@@ -1060,12 +1068,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1060
1068
|
)
|
|
1061
1069
|
_add_index_embedding_flags(erase)
|
|
1062
1070
|
erase.add_argument("--yes", action="store_true", help="Confirm destructive deletion (required in CI)")
|
|
1063
|
-
erase
|
|
1064
|
-
"--quiet", "-q",
|
|
1065
|
-
action="store_true",
|
|
1066
|
-
dest="quiet",
|
|
1067
|
-
help="Suppress stderr progress relay; stdout payload unchanged.",
|
|
1068
|
-
)
|
|
1071
|
+
_add_verbosity_flags(erase)
|
|
1069
1072
|
erase.set_defaults(handler=_cmd_erase)
|
|
1070
1073
|
|
|
1071
1074
|
meta = subparsers.add_parser("meta", help="Print graph meta and embedding resolution.")
|
|
@@ -1162,8 +1165,20 @@ def _console_script_main() -> None:
|
|
|
1162
1165
|
racy teardown — the command has already done its work and emitted its result.
|
|
1163
1166
|
``main()`` stays return-based so in-process test callers (``cli.main(...)``)
|
|
1164
1167
|
keep working.
|
|
1168
|
+
|
|
1169
|
+
``KeyboardInterrupt`` (Ctrl+C during a long indexing step) is caught here
|
|
1170
|
+
rather than left to propagate: an uncaught interrupt bypasses this function
|
|
1171
|
+
and runs full interpreter finalization (traceback + thread teardown),
|
|
1172
|
+
whereas routing it through the same flush + ``os._exit`` path gives a clean,
|
|
1173
|
+
immediate exit (code 130) and avoids the finalization-time SIGABRT noted
|
|
1174
|
+
above for commands that loaded lancedb.
|
|
1165
1175
|
"""
|
|
1166
|
-
|
|
1176
|
+
try:
|
|
1177
|
+
rc = main()
|
|
1178
|
+
except KeyboardInterrupt:
|
|
1179
|
+
sys.stderr.write("\nInterrupted.\n")
|
|
1180
|
+
sys.stderr.flush()
|
|
1181
|
+
rc = 130
|
|
1167
1182
|
sys.stdout.flush()
|
|
1168
1183
|
sys.stderr.flush()
|
|
1169
1184
|
os._exit(rc)
|
|
@@ -378,6 +378,14 @@ class ResolvedOperatorConfig:
|
|
|
378
378
|
# used with no config file). Recorded into the index dir at index time so a
|
|
379
379
|
# later discovery run from a sibling/cwd can relocate this config.
|
|
380
380
|
yaml_config_path: Path | None = None
|
|
381
|
+
# ``watch:`` block knobs (jrag watch / watcher). Defaults make the block
|
|
382
|
+
# optional; no env vars are introduced for these (CLI flag > YAML > default).
|
|
383
|
+
watch_debounce_ms: int = 1500
|
|
384
|
+
watch_backend: str = "auto"
|
|
385
|
+
watch_poll_interval_ms: int = 2000
|
|
386
|
+
watch_debounce_ms_source: SettingSource = "default"
|
|
387
|
+
watch_backend_source: SettingSource = "default"
|
|
388
|
+
watch_poll_interval_ms_source: SettingSource = "default"
|
|
381
389
|
|
|
382
390
|
def apply_to_os_environ(self) -> None:
|
|
383
391
|
"""Make downstream modules (server, ladybug_queries, flows) see a consistent environment.
|
|
@@ -506,16 +514,20 @@ def _pick_float(
|
|
|
506
514
|
|
|
507
515
|
def _pick_int(
|
|
508
516
|
*,
|
|
517
|
+
cli_val: int | None = None,
|
|
509
518
|
env_key: str,
|
|
510
519
|
yaml_dict: dict[str, Any],
|
|
511
520
|
yaml_path: tuple[str, ...],
|
|
512
521
|
default: int,
|
|
513
522
|
) -> tuple[int, SettingSource]:
|
|
514
|
-
"""Pick an int setting from env (parsed via int(...)), YAML, or default.
|
|
523
|
+
"""Pick an int setting from CLI, env (parsed via int(...)), YAML, or default.
|
|
515
524
|
|
|
516
525
|
Precedence: CLI > env > YAML > default. Env values that fail to parse as int
|
|
517
526
|
fall back to the default (matching the brief's requirement for graceful degradation).
|
|
527
|
+
``cli_val`` defaults to ``None`` so existing callers are unaffected.
|
|
518
528
|
"""
|
|
529
|
+
if cli_val is not None:
|
|
530
|
+
return int(cli_val), "cli"
|
|
519
531
|
env_raw = os.environ.get(env_key, "").strip()
|
|
520
532
|
if env_raw:
|
|
521
533
|
try:
|
|
@@ -577,6 +589,9 @@ def resolve_operator_config(
|
|
|
577
589
|
cli_index_dir: str | None = None,
|
|
578
590
|
cli_embedding_model: str | None = None,
|
|
579
591
|
cli_embedding_device: str | None = None,
|
|
592
|
+
cli_watch_debounce_ms: int | None = None,
|
|
593
|
+
cli_watch_backend: str | None = None,
|
|
594
|
+
cli_watch_poll_interval_ms: int | None = None,
|
|
580
595
|
) -> ResolvedOperatorConfig:
|
|
581
596
|
# Phase 1: Find the config file directory
|
|
582
597
|
if source_root is not None:
|
|
@@ -671,6 +686,52 @@ def resolve_operator_config(
|
|
|
671
686
|
yaml_path=("absence", "diag_enabled"),
|
|
672
687
|
default=True,
|
|
673
688
|
)
|
|
689
|
+
# ``watch:`` block knobs. No env vars are introduced for watch (CLI > YAML >
|
|
690
|
+
# default), so an empty env_key is passed to the ``_pick_*`` helpers —
|
|
691
|
+
# ``os.environ.get("", "")`` never matches, leaving the env tier inert.
|
|
692
|
+
w_debounce, w_debounce_src = _pick_int(
|
|
693
|
+
cli_val=cli_watch_debounce_ms,
|
|
694
|
+
env_key="",
|
|
695
|
+
yaml_dict=yaml_dict,
|
|
696
|
+
yaml_path=("watch", "debounce_ms"),
|
|
697
|
+
default=1500,
|
|
698
|
+
)
|
|
699
|
+
w_backend, w_backend_src = _pick_str(
|
|
700
|
+
cli_val=cli_watch_backend,
|
|
701
|
+
env_key="",
|
|
702
|
+
yaml_dict=yaml_dict,
|
|
703
|
+
yaml_path=("watch", "backend"),
|
|
704
|
+
default="auto",
|
|
705
|
+
)
|
|
706
|
+
w_poll, w_poll_src = _pick_int(
|
|
707
|
+
cli_val=cli_watch_poll_interval_ms,
|
|
708
|
+
env_key="",
|
|
709
|
+
yaml_dict=yaml_dict,
|
|
710
|
+
yaml_path=("watch", "poll_interval_ms"),
|
|
711
|
+
default=2000,
|
|
712
|
+
)
|
|
713
|
+
# Inline floors/validation (mirror the existing graceful-degradation style).
|
|
714
|
+
if w_debounce < 100:
|
|
715
|
+
print(
|
|
716
|
+
f"java-codebase-rag: watch.debounce_ms={w_debounce} is below the 100 ms "
|
|
717
|
+
"floor; falling back to 1500.",
|
|
718
|
+
file=sys.stderr,
|
|
719
|
+
)
|
|
720
|
+
w_debounce, w_debounce_src = 1500, "default"
|
|
721
|
+
if w_backend not in ("auto", "watchdog", "polling"):
|
|
722
|
+
print(
|
|
723
|
+
f"java-codebase-rag: watch.backend={w_backend!r} is not one of "
|
|
724
|
+
"auto/watchdog/polling; falling back to 'auto'.",
|
|
725
|
+
file=sys.stderr,
|
|
726
|
+
)
|
|
727
|
+
w_backend, w_backend_src = "auto", "default"
|
|
728
|
+
if w_poll < 200:
|
|
729
|
+
print(
|
|
730
|
+
f"java-codebase-rag: watch.poll_interval_ms={w_poll} is below the 200 ms "
|
|
731
|
+
"floor; falling back to 2000.",
|
|
732
|
+
file=sys.stderr,
|
|
733
|
+
)
|
|
734
|
+
w_poll, w_poll_src = 2000, "default"
|
|
674
735
|
ku = index_dir / "code_graph.lbug"
|
|
675
736
|
coco = index_dir / "cocoindex.db"
|
|
676
737
|
return ResolvedOperatorConfig(
|
|
@@ -696,6 +757,12 @@ def resolve_operator_config(
|
|
|
696
757
|
absence_ngram_q_source=abs_q_src,
|
|
697
758
|
absence_diag_enabled_source=abs_diag_src,
|
|
698
759
|
yaml_config_path=find_yaml_config_file(config_dir),
|
|
760
|
+
watch_debounce_ms=w_debounce,
|
|
761
|
+
watch_backend=w_backend,
|
|
762
|
+
watch_poll_interval_ms=w_poll,
|
|
763
|
+
watch_debounce_ms_source=w_debounce_src,
|
|
764
|
+
watch_backend_source=w_backend_src,
|
|
765
|
+
watch_poll_interval_ms_source=w_poll_src,
|
|
699
766
|
)
|
|
700
767
|
|
|
701
768
|
|