java-codebase-rag 0.6.7__py3-none-any.whl → 0.9.0__py3-none-any.whl
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.
- ast_java.py +8 -3
- build_ast_graph.py +72 -16
- graph_enrich.py +2 -1
- graph_types.py +133 -0
- java_codebase_rag/_fdlimit.py +10 -2
- java_codebase_rag/_stdio.py +32 -0
- java_codebase_rag/cli.py +149 -25
- java_codebase_rag/config.py +128 -9
- java_codebase_rag/install_data/agents/explorer-rag-cli.md +148 -0
- java_codebase_rag/install_data/agents/explorer-rag-enhanced.md +78 -232
- java_codebase_rag/install_data/skills/explore-codebase/SKILL.md +49 -88
- java_codebase_rag/install_data/skills/explore-codebase-cli/SKILL.md +183 -0
- java_codebase_rag/installer.py +720 -107
- java_codebase_rag/jrag.py +4405 -0
- java_codebase_rag/jrag_envelope.py +1085 -0
- java_codebase_rag/jrag_hints.py +204 -0
- java_codebase_rag/jrag_render.py +697 -0
- java_codebase_rag/lance_optimize.py +18 -0
- java_codebase_rag/pipeline.py +34 -0
- {java_codebase_rag-0.6.7.dist-info → java_codebase_rag-0.9.0.dist-info}/METADATA +137 -94
- java_codebase_rag-0.9.0.dist-info/RECORD +43 -0
- {java_codebase_rag-0.6.7.dist-info → java_codebase_rag-0.9.0.dist-info}/WHEEL +1 -1
- {java_codebase_rag-0.6.7.dist-info → java_codebase_rag-0.9.0.dist-info}/entry_points.txt +1 -0
- {java_codebase_rag-0.6.7.dist-info → java_codebase_rag-0.9.0.dist-info}/top_level.txt +2 -0
- java_index_flow_lancedb.py +34 -19
- java_ontology.py +12 -0
- ladybug_queries.py +233 -52
- mcp_hints.py +6 -6
- mcp_v2.py +276 -632
- resolve_service.py +649 -0
- search_lancedb.py +159 -4
- server.py +31 -12
- java_codebase_rag-0.6.7.dist-info/RECORD +0 -34
- {java_codebase_rag-0.6.7.dist-info → java_codebase_rag-0.9.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -7,9 +7,7 @@ description: "MUST BE USED PROACTIVELY. Universal read-only codebase exploration
|
|
|
7
7
|
|
|
8
8
|
Read-only exploration combining **java-codebase-rag graph navigation** with **broad file-system search**.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Any time you need to search, locate, navigate, or explore the codebase. **Do NOT use when** the answer is already in open context or for a single known file — read that file directly.
|
|
10
|
+
Use any time you must search, locate, navigate, or explore. **Do NOT use when** the answer is already in context or for a single known file — read it directly.
|
|
13
11
|
|
|
14
12
|
## Core Principles
|
|
15
13
|
|
|
@@ -19,20 +17,9 @@ Any time you need to search, locate, navigate, or explore the codebase. **Do NOT
|
|
|
19
17
|
|
|
20
18
|
## Tool Inventory
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
`
|
|
25
|
-
|
|
26
|
-
**Node kinds:** `Symbol` (types/methods), `Route` (HTTP/messaging entry points), `Client` (outbound HTTP), `Producer` (outbound async).
|
|
27
|
-
**Indexed content:** Java sources + SQL + YAML (`table`: `java`, `sql`, `yaml`, or `all`).
|
|
28
|
-
|
|
29
|
-
### File-system tools
|
|
30
|
-
|
|
31
|
-
- **Grep** — content search by pattern/regex
|
|
32
|
-
- **Glob** — find files by name/path pattern (`**/*.java`, `**/*Controller*.java`, `**/application*.yml`)
|
|
33
|
-
- **Read** — read files (`offset`/`limit` for large files)
|
|
34
|
-
|
|
35
|
-
### Other: **Bash** (read-only: `git log`, `git blame`, `ls`, `find`), **WebSearch**/**WebFetch** (external lookups)
|
|
20
|
+
- **Graph (java-codebase-rag MCP):** `search`, `find`, `describe`, `neighbors`, `resolve`. Node kinds: `Symbol` (types/methods), `Route` (HTTP/messaging entry points), `Client` (outbound HTTP), `Producer` (outbound async). Indexed content: Java + SQL + YAML (`table`: `java`, `sql`, `yaml`, `all`).
|
|
21
|
+
- **File-system:** `Grep` (content/regex), `Glob` (name/path patterns), `Read` (`offset`/`limit` for large files).
|
|
22
|
+
- **Other:** `Bash` (read-only: `git log`, `git blame`, `ls`, `find`), `WebSearch`/`WebFetch`.
|
|
36
23
|
|
|
37
24
|
---
|
|
38
25
|
|
|
@@ -52,22 +39,20 @@ Any time you need to search, locate, navigate, or explore the codebase. **Do NOT
|
|
|
52
39
|
| Who hits this route? | route id | `neighbors(ids, "in", ["HTTP_CALLS","ASYNC_CALLS","EXPOSES"])` |
|
|
53
40
|
| Handler for route | route id | `neighbors(ids, "in", ["EXPOSES"])` |
|
|
54
41
|
| Who implements/injects T? | type symbol id | `neighbors(ids, "in", ["IMPLEMENTS"])` or `["INJECTS"]` |
|
|
55
|
-
| Impact of changing X? | bounded `neighbors` `in` loop
|
|
56
|
-
| Find files
|
|
57
|
-
| Search for text in files | `Grep` | `Read` |
|
|
42
|
+
| Impact of changing X? | bounded `neighbors` `in` loop (`CALLS`, `INJECTS`, …) | `Grep` fallback |
|
|
43
|
+
| Find files / text | `Glob` / `Grep` | `Read` |
|
|
58
44
|
| Who changed X and when? | Bash: `git log`/`git blame` | — |
|
|
59
|
-
| "How is this configured?" | `Glob` + `Grep
|
|
45
|
+
| "How is this configured?" | `Glob` + `Grep`; `search(query=…, table="yaml")` | `Read` sections |
|
|
60
46
|
|
|
61
|
-
**Escalation:** ① Most targeted tool first → ②
|
|
47
|
+
**Escalation:** ① Most targeted tool first → ② fall back gracefully (graph empty → `Grep`/`Glob`) → ③ cross-validate (graph vs file disagree → **trust the file**).
|
|
62
48
|
|
|
63
|
-
**Rules of thumb:**
|
|
49
|
+
**Rules of thumb:** structure beats vector for exact questions (`resolve`/`find`+`neighbors`); vector beats structure for fuzzy discovery (`search`); file-system beats stale index.
|
|
64
50
|
|
|
65
51
|
---
|
|
66
52
|
|
|
67
53
|
## Graph Navigation Reference (java-codebase-rag MCP)
|
|
68
54
|
|
|
69
|
-
**Ontology: 17
|
|
70
|
-
Responses may include `hints_structured` (suggested next calls) and `advisories` — advisory only; ignore when `success` is false.
|
|
55
|
+
**Ontology: 17.** If results look structurally wrong or empty across tools, the index may be missing/stale — ask the operator to rebuild. Responses may carry `hints_structured` (suggested next calls) and `advisories` — advisory only; ignore when `success` is false.
|
|
71
56
|
|
|
72
57
|
### Forced reasoning preamble (every MCP call)
|
|
73
58
|
|
|
@@ -76,17 +61,13 @@ Q-class: <semantic | structured | inspect | walk>
|
|
|
76
61
|
Pick: <search|find|describe|neighbors|resolve> Why: <≤8 words>
|
|
77
62
|
```
|
|
78
63
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
1. **Locate** — `resolve` for identifier-shaped; `search` for NL/code fragments; `find` for structured `NodeFilter`.
|
|
82
|
-
2. **Inspect** — `describe(id)` for full record + `edge_summary`.
|
|
83
|
-
3. **Walk** — `neighbors` in a loop with explicit `direction` and `edge_types`.
|
|
64
|
+
**Workflow:** locate (`resolve`/`search`/`find`) → inspect (`describe`) → walk (`neighbors`, explicit `direction` + `edge_types`).
|
|
84
65
|
|
|
85
66
|
### Edge taxonomy
|
|
86
67
|
|
|
87
68
|
Use these strings **verbatim** in `neighbors(..., edge_types=[...])`.
|
|
88
69
|
|
|
89
|
-
**Stored
|
|
70
|
+
**Stored (one hop):**
|
|
90
71
|
|
|
91
72
|
| Edge type | Semantics |
|
|
92
73
|
| --------- | --------- |
|
|
@@ -97,50 +78,41 @@ Use these strings **verbatim** in `neighbors(..., edge_types=[...])`.
|
|
|
97
78
|
| `EXPOSES` | Method Symbol → Route (handler exposes route) |
|
|
98
79
|
| `HTTP_CALLS`, `ASYNC_CALLS` | Cross-service: Client/Producer → Route |
|
|
99
80
|
|
|
100
|
-
**Composed
|
|
101
|
-
|
|
102
|
-
`DECLARES.DECLARES_CLIENT` — members' HTTP clients | `DECLARES.DECLARES_PRODUCER` — members' async producers | `DECLARES.EXPOSES` — members' exposed routes
|
|
103
|
-
|
|
104
|
-
**Composed edges — non-static method Symbol origin (`direction="out"` only):**
|
|
81
|
+
**Composed (`direction="out"` only):** type-Symbol origin — `DECLARES.DECLARES_CLIENT` (members' HTTP clients), `DECLARES.DECLARES_PRODUCER` (async producers), `DECLARES.EXPOSES` (exposed routes). Non-static-method-Symbol origin — `OVERRIDDEN_BY`, `OVERRIDDEN_BY.DECLARES_CLIENT`, `OVERRIDDEN_BY.DECLARES_PRODUCER`, `OVERRIDDEN_BY.EXPOSES`.
|
|
105
82
|
|
|
106
|
-
`OVERRIDDEN_BY
|
|
83
|
+
> Don't mix `DECLARES.*` and `OVERRIDDEN_BY.*` in one list. Large composed counts in `edge_summary` → raise `limit` or issue separate calls.
|
|
107
84
|
|
|
108
|
-
|
|
85
|
+
**Argument shapes — JSON, not stringified:** `edge_types=["CALLS"]` not `"CALLS"`; `filter={"role":"CONTROLLER"}` not nested string; `ids=["sym:…","sym:…"]` not comma-joined. Omit unneeded keys. Empty `""` is often a real filter that matches nothing.
|
|
109
86
|
|
|
110
|
-
|
|
87
|
+
**Node id prefixes:** Symbol `sym:`, Route `route:`/`r:`, Client `client:`/`c:`, Producer `producer:`/`p:`. Use exact ids from prior calls.
|
|
111
88
|
|
|
112
|
-
**
|
|
113
|
-
|
|
114
|
-
**Node id prefixes:** Symbol `sym:`, Route `route:`/`r:`, Client `client:`/`c:`, Producer `producer:`/`p:`. Use exact ids from previous calls.
|
|
115
|
-
|
|
116
|
-
**Symbol FQNs:** `<package>.<Type>[.<NestedType>]#<methodName>(<SimpleType1>,<SimpleType2>,…)`. Generics erased, no spaces after commas. No-arg: `()`. Constructor: `#<init>(…)`.
|
|
89
|
+
**Symbol FQNs:** `<package>.<Type>[.<NestedType>]#<methodName>(<SimpleType1>,<SimpleType2>,…)`. Generics erased, no spaces after commas. No-arg `()`. Constructor `#<init>(…)`.
|
|
117
90
|
|
|
118
91
|
### `neighbors` — required every time
|
|
119
92
|
|
|
120
|
-
- **`direction
|
|
121
|
-
- **Batching:** multiple `ids` expand first; `limit`/`offset` slice the **merged**
|
|
122
|
-
- **`CALLS
|
|
123
|
-
- **`edge_filter`** (only with `edge_types=['CALLS']`): `min_confidence`; `include_strategies`/`exclude_strategies`; `callee_declaring_role`/`callee_declaring_roles`/`exclude_callee_declaring_roles
|
|
124
|
-
- **Cross-service edges:** read `attrs.confidence
|
|
93
|
+
- **`direction`** `"in"`/`"out"` (no default); **`edge_types`** non-empty list.
|
|
94
|
+
- **Batching:** multiple `ids` expand first; `limit`/`offset` slice the **merged** list — raise `limit` when batching.
|
|
95
|
+
- **`CALLS`:** `attrs.resolved=false` = external (JDK/Spring), not missing. `include_unresolved=True` (`out` only) interleaves unresolved sites; exclusive with `edge_filter`. `dedup_calls=True` collapses identical (origin, callee) pairs.
|
|
96
|
+
- **`edge_filter`** (only with `edge_types=['CALLS']`): `min_confidence`; `include_strategies`/`exclude_strategies`; `callee_declaring_role`/`callee_declaring_roles`/`exclude_callee_declaring_roles` (callee stereotype filter — not `filter.role`, which filters the neighbor node).
|
|
97
|
+
- **Cross-service edges:** read `attrs.confidence`/`attrs.match` — low confidence or `unresolved`/`phantom`/`ambiguous` = resolver signal, not ground truth.
|
|
125
98
|
|
|
126
99
|
### NodeFilter (`find`, `search.filter`, `neighbors.filter`)
|
|
127
100
|
|
|
128
|
-
For `find`, `filter` is required — `{}`
|
|
101
|
+
For `find`, `filter` is required — `{}` = no predicates. **Strict frame:** unknown keys or inapplicable populated fields → `success=false`; invalid enums rejected at the schema layer (valid set listed).
|
|
129
102
|
|
|
130
103
|
| Applicable to | Keys |
|
|
131
104
|
| ------------- | ---- |
|
|
132
105
|
| All kinds | `microservice`, `module` |
|
|
133
|
-
| **symbol** only | `role`, `exclude_roles`, `annotation`, `capability`, `
|
|
134
|
-
| **route** only | `http_method`, `
|
|
135
|
-
| **client** only | `source_layer`, `client_kind`, `target_service`, `
|
|
136
|
-
| **producer** only | `source_layer`, `producer_kind`, `
|
|
106
|
+
| **symbol** only | `role`, `exclude_roles`, `annotation`, `capability`, `fqn_contains`, `symbol_kind`, `symbol_kinds` |
|
|
107
|
+
| **route** only | `http_method`, `path_contains`, `framework` |
|
|
108
|
+
| **client** only | `source_layer`, `client_kind`, `target_service`, `target_path_contains`, `http_method` |
|
|
109
|
+
| **producer** only | `source_layer`, `producer_kind`, `topic_contains` |
|
|
137
110
|
|
|
138
|
-
|
|
111
|
+
Substring fields (`fqn_contains`, `path_contains`, `target_path_contains`, `topic_contains`) match literally via `CONTAINS` — no `*`/`?`; use `search(query=…)` for ranked text.
|
|
139
112
|
|
|
140
113
|
### `resolve` — identifier lookup
|
|
141
114
|
|
|
142
|
-
**Input:** FQN/suffix, `sym:`/`route:`/`client:`/`producer:` id, `METHOD /path`, route path, client target_service, producer topic.
|
|
143
|
-
**`hint_kind`:** optional `symbol`|`route`|`client`|`producer` (narrows generators).
|
|
115
|
+
**Input:** FQN/suffix, `sym:`/`route:`/`client:`/`producer:` id, `METHOD /path`, route path, client target_service, producer topic. **`hint_kind`:** optional `symbol`|`route`|`client`|`producer`.
|
|
144
116
|
|
|
145
117
|
| `status` | Action |
|
|
146
118
|
| -------- | ------ |
|
|
@@ -150,55 +122,44 @@ No wildcards in prefix fields — use `search(query=…)` for ranked text.
|
|
|
150
122
|
|
|
151
123
|
Prefer `resolve` → `describe(id=…)` over `describe(fqn=…)` when FQN may collide.
|
|
152
124
|
|
|
153
|
-
### Tool signatures
|
|
125
|
+
### Tool signatures
|
|
154
126
|
|
|
155
|
-
- **`search`** — `query`, `table` (`java`|`sql`|`yaml`|`all`), `hybrid` (bool), `limit` (
|
|
156
|
-
- **`find`** — `kind` (`symbol`|`route`|`client`|`producer`), **`filter`** (required
|
|
157
|
-
- **`describe`** — `id` (any
|
|
127
|
+
- **`search`** — `query`, `table` (`java`|`sql`|`yaml`|`all`), `hybrid` (bool), `limit` (5), `offset`, `path_contains`, optional `filter` (symbol only).
|
|
128
|
+
- **`find`** — `kind` (`symbol`|`route`|`client`|`producer`), **`filter`** (required), `limit` (25), `offset`.
|
|
129
|
+
- **`describe`** — `id` (any) or `fqn` (symbol; `id` wins). Returns node + `edge_summary`.
|
|
158
130
|
- **`resolve`** — `identifier`, optional `hint_kind`.
|
|
159
131
|
|
|
160
132
|
### Ontology glossary
|
|
161
133
|
|
|
162
|
-
**Roles:** `CONTROLLER` | `SERVICE` | `REPOSITORY` | `COMPONENT` | `CONFIG` | `ENTITY` | `CLIENT` | `MAPPER` | `DTO` | `OTHER`.
|
|
163
|
-
Exclude `DTO`, `OTHER`, `MAPPER` with `exclude_roles` when tracing business logic. On `CALLS` out: `edge_filter={"exclude_callee_declaring_roles":["OTHER"]}` drops framework calls.
|
|
164
|
-
|
|
134
|
+
**Roles:** `CONTROLLER` | `SERVICE` | `REPOSITORY` | `COMPONENT` | `CONFIG` | `ENTITY` | `CLIENT` | `MAPPER` | `DTO` | `OTHER`. Exclude `DTO`/`OTHER`/`MAPPER` via `exclude_roles` when tracing business logic; on `CALLS` out, `edge_filter={"exclude_callee_declaring_roles":["OTHER"]}` drops framework calls.
|
|
165
135
|
**Capabilities:** `MESSAGE_LISTENER`, `MESSAGE_PRODUCER`, `HTTP_CLIENT`, `SCHEDULED_TASK`, `EXCEPTION_HANDLER`.
|
|
166
|
-
|
|
167
136
|
**Symbol kinds:** `class`, `interface`, `enum`, `record`, `annotation`, `method`, `constructor`.
|
|
168
|
-
|
|
169
|
-
**Route frameworks:** `spring_mvc`, `webflux`. (Route *kinds* are `http_endpoint`, `http_consumer`, `kafka_topic`, `rabbit_queue`, `jms_destination`, `stream_binding`.)
|
|
170
|
-
**Client kinds:** `feign_method`, `rest_template`, `web_client`. **Producer kinds:** `kafka_send`, `stream_bridge_send`. **Source layers (client/producer):** `builtin`, `layer_a_meta`, `layer_b_ann`, `layer_b_fqn`, `layer_c_source`.
|
|
171
|
-
**Match types:** `cross_service`, `intra_service`, `ambiguous`, `phantom`, `unresolved`.
|
|
137
|
+
**Route frameworks:** `spring_mvc`/`webflux` (HTTP), `kafka`/`rabbitmq`/`jms`/`stream` (messaging), `feign` (client mirrors). (Route *kinds*: `http_endpoint`, `http_consumer`, `kafka_topic`, `rabbit_queue`, `jms_destination`, `stream_binding`.) **Client kinds:** `feign_method`, `rest_template`, `web_client`. **Producer kinds:** `kafka_send`, `stream_bridge_send`. **Source layers (client/producer):** `builtin`, `layer_a_meta`, `layer_b_ann`, `layer_b_fqn`, `layer_c_source`. **Match types:** `cross_service`, `intra_service`, `ambiguous`, `phantom`, `unresolved`.
|
|
172
138
|
|
|
173
139
|
---
|
|
174
140
|
|
|
175
141
|
## Recovery Playbook
|
|
176
142
|
|
|
177
|
-
**After two failed attempts on the same intent, stop and report tool
|
|
143
|
+
**After two failed attempts on the same intent, stop and report tool, args, and response snippet.**
|
|
178
144
|
|
|
179
145
|
| Symptom | Fix |
|
|
180
146
|
| ------- | --- |
|
|
181
|
-
| `neighbors` validation error | Add both `direction` and `edge_types`
|
|
182
|
-
| Empty `neighbors` | Read `describe.edge_summary`; check edge type
|
|
183
|
-
| Cannot find symbol | `resolve`/`search`; `find` with `
|
|
184
|
-
| `find`
|
|
185
|
-
| Empty `search` | Try `table="all"`; `find` with `
|
|
186
|
-
| Empty
|
|
147
|
+
| `neighbors` validation error | Add both `direction` and `edge_types` |
|
|
148
|
+
| Empty `neighbors` | Read `describe.edge_summary`; check edge type + direction |
|
|
149
|
+
| Cannot find symbol | `resolve`/`search`; `find` with `fqn_contains`; fallback `Grep` |
|
|
150
|
+
| `find` too broad | Add `microservice`, `fqn_contains`, `path_contains`, `topic_contains` |
|
|
151
|
+
| Empty `search` | Try `table="all"`; `find` with `fqn_contains`; `Grep` |
|
|
152
|
+
| Empty across tools | Index missing/stale → `Grep`/`Glob`/`Read`; ask operator to rebuild |
|
|
187
153
|
| Graph vs file disagree | **Trust the file**; report stale index |
|
|
188
|
-
| Mixed composed families on one id | Split
|
|
189
|
-
| `Glob`/`Grep` too
|
|
190
|
-
| `Grep` no results | Broaden pattern; check working directory; try alternate terms |
|
|
154
|
+
| Mixed composed families on one id | Split — type keys need type id; override keys need method id |
|
|
155
|
+
| `Glob`/`Grep` too broad | Narrow pattern; add directory prefix / `path_filter` |
|
|
191
156
|
|
|
192
157
|
---
|
|
193
158
|
|
|
194
159
|
## Workflow Patterns
|
|
195
160
|
|
|
196
|
-
**"Explain feature X":** `search` → pick 1–3 hits → `describe` → `neighbors` with targeted edges → stop when answered.
|
|
197
|
-
|
|
198
|
-
**"
|
|
199
|
-
|
|
200
|
-
**"
|
|
201
|
-
|
|
202
|
-
**"Trace flow from A to B":** Resolve both → walk `CALLS`/`EXPOSES`/`HTTP_CALLS` from A → `Grep` gaps → report with file:line.
|
|
203
|
-
|
|
204
|
-
**"How is this configured?":** `Glob` for `**/application*.yml` → `Grep` for key → `Read` sections → `search(query=…, table="yaml")` supplement.
|
|
161
|
+
- **"Explain feature X":** `search` → pick 1–3 hits → `describe` → `neighbors` with targeted edges → stop when answered.
|
|
162
|
+
- **"Where is X used?":** `resolve`/`search` → `neighbors("in", ["CALLS","INJECTS","IMPLEMENTS"])` → `Grep` fallback → report sites with file:line.
|
|
163
|
+
- **"Find all Y":** structural → `find(kind=…, filter={…})`; textual → `Grep`; broad → `Glob`+`Grep`. Summarize, don't dump.
|
|
164
|
+
- **"Trace flow A→B":** resolve both → walk `CALLS`/`EXPOSES`/`HTTP_CALLS` from A → `Grep` gaps → report with file:line.
|
|
165
|
+
- **"How is this configured?":** `Glob` `**/application*.yml` → `Grep` the key → `Read` sections → `search(query=…, table="yaml")` supplement.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: explore-codebase-cli
|
|
3
|
+
description: "MUST BE USED PROACTIVELY. Universal read-only codebase exploration via the `jrag` CLI — one command per engineering intent (callers, callees, routes, clients, producers, impact, search, inspect, flow, overview). Use for any exploration: locating code, tracing dependencies, finding patterns, 'where is X', 'who calls Y', 'find all controllers', 'trace the flow from A to B'. Combines graph navigation with file-system search (grep, glob, file reading). Do NOT use when the answer is already in open context or for a single known file — read that file directly."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /explore-codebase-cli — Universal codebase exploration via `jrag`
|
|
7
|
+
|
|
8
|
+
Read-only exploration combining **graph navigation through the `jrag` CLI** with **broad file-system search**. `jrag` loads the same index as the MCP server but exposes one shell command per intent instead of five MCP tools.
|
|
9
|
+
|
|
10
|
+
Use any time you must search, locate, navigate, or explore. **Do NOT use when** the answer is already in context or for a single known file — read it directly.
|
|
11
|
+
|
|
12
|
+
## Core Principles
|
|
13
|
+
|
|
14
|
+
1. **Read-only.** Never edit, write, or modify any file.
|
|
15
|
+
2. **Names in, names out.** Every `<query>` is human-readable (FQN / simple name / route path / topic). Raw node IDs never required.
|
|
16
|
+
3. **One command per intent.** `jrag` collapses resolve + walk into one call — don't chain resolve→describe→neighbors manually.
|
|
17
|
+
4. **Stop when answered.** Don't prefetch unrelated subgraphs or directories.
|
|
18
|
+
|
|
19
|
+
**One surface per project.** This is the CLI surface; the MCP surface (`search`/`find`/`describe`/`neighbors`/`resolve`) is mutually exclusive — running both strands the agent in two vocabularies.
|
|
20
|
+
|
|
21
|
+
## Prerequisite: index must exist
|
|
22
|
+
|
|
23
|
+
`jrag` is a thin layer over the existing index. If unindexed, every command exits 2:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
status: error
|
|
27
|
+
message: No index at <path>. Run: java-codebase-rag init --source-root <root>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Verify with `jrag status` when in doubt.
|
|
31
|
+
|
|
32
|
+
## Tool Inventory
|
|
33
|
+
|
|
34
|
+
### `jrag` command groups
|
|
35
|
+
|
|
36
|
+
Run `jrag --help` for the canonical list.
|
|
37
|
+
|
|
38
|
+
| Group | Commands |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| **Orientation** | `status`, `microservices`, `map`, `conventions`, `overview` |
|
|
41
|
+
| **Locate** | `find`, `search` |
|
|
42
|
+
| **Listings** | `http-routes`, `http-clients`, `producers`, `topics`, `jobs`, `listeners`, `entities` |
|
|
43
|
+
| **Traversal** | `callers`, `callees`, `hierarchy`, `implementations`, `subclasses`, `overrides`, `overridden-by`, `dependents`, `impact`, `flow`, `decompose`, `dependencies`, `connection` |
|
|
44
|
+
| **Inspection** | `inspect`, `outline`, `imports` |
|
|
45
|
+
|
|
46
|
+
### Common flags
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
--service <name> Filter by microservice
|
|
50
|
+
--module <name> Filter by module
|
|
51
|
+
--limit <N> Cap on results (default 20; 10 for fan-out)
|
|
52
|
+
--format text|json Output format (default: text)
|
|
53
|
+
--detail brief|normal|full How much of each node/edge is shown (default: normal);
|
|
54
|
+
orthogonal to --format. brief=name @service;
|
|
55
|
+
normal=+module/role/file/score; full=+signature/
|
|
56
|
+
annotations/snippet. inspect + orientation default to full.
|
|
57
|
+
--index-dir <path> Index directory override (default: discovered from cwd)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`--offset` is supported **only** on `find` and `search`. Other commands emit `truncated: more results — narrow your query` when capped.
|
|
61
|
+
|
|
62
|
+
### File-system tools
|
|
63
|
+
|
|
64
|
+
`Grep` (content/regex), `Glob` (name/path patterns), `Read` (`offset`/`limit`). Plus `Bash` (read-only: `git log`, `git blame`, `ls`, `find`), `WebSearch`/`WebFetch`.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Decision Framework
|
|
69
|
+
|
|
70
|
+
| User asks… | First `jrag` command | Follow-up |
|
|
71
|
+
| ---------- | -------------------- | --------- |
|
|
72
|
+
| "Is the index fresh?" | `jrag status` | — |
|
|
73
|
+
| Identifier (FQN / simple name) | `jrag inspect <query>` | `callers` / `callees` |
|
|
74
|
+
| Fuzzy / NL "where is X" | `jrag search "<text>"` | `inspect <hit>` |
|
|
75
|
+
| All controllers in S | `jrag find --role CONTROLLER --service S` | `callees` |
|
|
76
|
+
| Interfaces in S | `jrag find --java-kind interface --service S` | `implementations` |
|
|
77
|
+
| HTTP / messaging entry points | `jrag http-routes [--framework …] [--method …]` | `inspect <route>` |
|
|
78
|
+
| Outbound HTTP clients | `jrag http-clients [--calls-service …]` | `callees <client>` |
|
|
79
|
+
| Outbound async producers | `jrag producers [--topic-contains …]` | `callees <producer>` |
|
|
80
|
+
| Topics + consumers/producers | `jrag topics [--topic-contains …]` | — |
|
|
81
|
+
| Who calls / what does M call? | `jrag callers <M>` / `jrag callees <M>` | `inspect` |
|
|
82
|
+
| Who hits this route? | `jrag callers <route>` | — |
|
|
83
|
+
| Implementations / subtypes of T? | `jrag implementations <T>` / `jrag subclasses <T>` | — |
|
|
84
|
+
| Overriding / overridden methods? | `jrag overrides <method>` (UP) / `jrag overridden-by <method>` | — |
|
|
85
|
+
| Who injects / depends on T? | `jrag dependencies <T>` / `jrag dependents <T>` | — |
|
|
86
|
+
| Blast-radius of changing X? | `jrag impact <X>` (bounded fan-in) | `Grep` fallback |
|
|
87
|
+
| Trace request flow A→B | `jrag flow <route>` | `connection <A> <B>` |
|
|
88
|
+
| File outline / imports | `jrag outline <file>` / `jrag imports <file>` | `inspect <row>` |
|
|
89
|
+
| "Explain service S" | `jrag overview <service>` | `http-routes`/`http-clients`/`producers` |
|
|
90
|
+
| "Explain route /topic" | `jrag overview <subject>` | `flow` |
|
|
91
|
+
| Find files / text | `Glob` / `Grep` | `Read` |
|
|
92
|
+
| Who changed X and when? | Bash: `git log`/`git blame` | — |
|
|
93
|
+
| "How is this configured?" | `Glob` + `Grep`; `jrag search "<key>" --table yaml` | `Read` sections |
|
|
94
|
+
|
|
95
|
+
**Escalation:** ① Most targeted command first → ② fall back gracefully (`callers` empty → `Grep`) → ③ cross-validate (CLI vs file disagree → **trust the file** — index may be stale).
|
|
96
|
+
|
|
97
|
+
**Rules of thumb:** structure beats vector for exact questions (`find`/`inspect` + traversal); vector beats structure for fuzzy discovery (`search`); file-system beats stale index.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Resolve-first contract (every `<query>` command)
|
|
102
|
+
|
|
103
|
+
Every `jrag` command that takes a `<query>` runs `resolve_v2` internally:
|
|
104
|
+
|
|
105
|
+
| `resolve_v2` status | `jrag` behavior |
|
|
106
|
+
| --- | --- |
|
|
107
|
+
| `one` | Run the traversal/listing against the resolved node. |
|
|
108
|
+
| `many` | Return the candidate list and stop. **No auto-pick.** Disambiguate with `--kind`/`--role`/`--fqn-contains`/`--service`; re-run. |
|
|
109
|
+
| `none` | `status: not_found` envelope (exit 0). Fall back to `search` or `Grep`. |
|
|
110
|
+
|
|
111
|
+
Never look up a raw node ID — pass an FQN, simple name, prior `sym:`/`route:`/`client:`/`producer:` id, route path, or topic. Only `--kind` is a true resolve input; `--role`/`--java-kind`/`--fqn-contains` post-filter client-side, while `--service`/`--module` are resolve-time filters on `inspect`/`callers` and result filters elsewhere.
|
|
112
|
+
|
|
113
|
+
## Output envelope
|
|
114
|
+
|
|
115
|
+
`--format` (text|json) picks the representation; `--detail` (brief|normal|full) picks how much of each node/edge shows — **both honor the same detail level**. Default: `text` + `normal`. `inspect` and orientation commands default to `full`. `--format json` emits the projected envelope (empty fields dropped):
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"status": "ok|not_found|error",
|
|
120
|
+
"nodes": {"<id>": {...}},
|
|
121
|
+
"edges": [{...}],
|
|
122
|
+
"candidates": [{...}],
|
|
123
|
+
"truncated": false,
|
|
124
|
+
"agent_next_actions": ["jrag callers <id>", "..."],
|
|
125
|
+
"file_location": {"filename": "...", "start_line": 123}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`truncated` is computed via +1-fetch on `find`/`search` (use `--limit`, then `--offset`); other commands emit the `more results` message when capped. `agent_next_actions` (≤5) maps result edges to next commands — a starting point, not a directive. `file_location` populates only on `one`-hit resolve.
|
|
130
|
+
|
|
131
|
+
## Traversal direction reference
|
|
132
|
+
|
|
133
|
+
`jrag` abstracts away `direction`/`edge_types` — you name the intent, it picks the edges:
|
|
134
|
+
|
|
135
|
+
| Intent (command) | Underlying edges |
|
|
136
|
+
| --- | --- |
|
|
137
|
+
| `callers` / `callees` | `CALLS` in / out |
|
|
138
|
+
| `hierarchy` | `EXTENDS` + `IMPLEMENTS`, both directions (parents + children) |
|
|
139
|
+
| `implementations` / `subclasses` | `IMPLEMENTS` / `EXTENDS` in |
|
|
140
|
+
| `overrides` / `overridden-by` | `OVERRIDES` out (subtype→supertype) / in |
|
|
141
|
+
| `dependencies` / `dependents` | `INJECTS` out / in |
|
|
142
|
+
| `impact` | bounded fan-in: `INJECTS`/`IMPLEMENTS`/`EXTENDS` in (depth ≤2) |
|
|
143
|
+
| `flow <route>` | `EXPOSES`/`HTTP_CALLS`/`ASYNC_CALLS`/`CALLS` |
|
|
144
|
+
| `connection A B` | bounded search over the same edge set |
|
|
145
|
+
|
|
146
|
+
**Node id prefixes (from prior results):** `sym:` (Symbol), `route:`/`r:` (Route), `client:`/`c:` (Client), `producer:`/`p:` (Producer). **Symbol FQN:** `<package>.<Type>[.<NestedType>]#<methodName>(<SimpleType1>,…)` — generics erased, no spaces after commas, no-arg `()`, constructor `#<init>(...)`.
|
|
147
|
+
|
|
148
|
+
## Ontology glossary
|
|
149
|
+
|
|
150
|
+
**Roles:** `CONTROLLER` | `SERVICE` | `REPOSITORY` | `COMPONENT` | `CONFIG` | `ENTITY` | `CLIENT` | `MAPPER` | `DTO` | `OTHER`.
|
|
151
|
+
**Capabilities:** `MESSAGE_LISTENER`, `MESSAGE_PRODUCER`, `HTTP_CLIENT`, `SCHEDULED_TASK`, `EXCEPTION_HANDLER`.
|
|
152
|
+
**Symbol kinds:** `class`, `interface`, `enum`, `record`, `annotation`, `method`, `constructor`.
|
|
153
|
+
**Route frameworks:** `spring_mvc`/`webflux` (HTTP), `kafka`/`rabbitmq`/`jms`/`stream` (messaging), `feign` (client mirrors). Route *kinds*: `http_endpoint`, `http_consumer`, `kafka_topic`, `rabbit_queue`, `jms_destination`, `stream_binding`. **Client kinds:** `feign_method`, `rest_template`, `web_client`. **Producer kinds:** `kafka_send`, `stream_bridge_send`. **Source layers:** `builtin`, `layer_a_meta`, `layer_b_ann`, `layer_b_fqn`, `layer_c_source`.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Recovery Playbook
|
|
158
|
+
|
|
159
|
+
**After two failed attempts on the same intent, stop and report command, args, and result snippet.**
|
|
160
|
+
|
|
161
|
+
| Symptom | Fix |
|
|
162
|
+
| ------- | --- |
|
|
163
|
+
| `status: error` "No index at …" | Run `java-codebase-rag init --source-root <root>`; retry |
|
|
164
|
+
| `status: not_found` | `jrag search "<query>"`; or `find --fqn-contains …`; fallback `Grep` |
|
|
165
|
+
| `many` candidates | Add `--kind`/`--role`/`--fqn-contains`/`--service`; re-run |
|
|
166
|
+
| `find` too broad | Add `--service`, `--fqn-contains`, `--path-contains`, `--topic-contains` |
|
|
167
|
+
| Empty `search` | Try `--table all`; `find --fqn-contains`; `Grep` |
|
|
168
|
+
| `truncated: true` | Narrow, or page with `--offset` (`find`/`search` only) |
|
|
169
|
+
| Empty across commands | Index missing/stale → `Grep`/`Glob`/`Read`; ask operator to rebuild (`java-codebase-rag reprocess`) |
|
|
170
|
+
| CLI vs file disagree | **Trust the file**; report stale index |
|
|
171
|
+
| `--offset` rejected | Only `find`/`search` accept it; others narrow via filters |
|
|
172
|
+
| Wrong node picked | Resolve ambiguous — pass `--kind` |
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Workflow Patterns
|
|
177
|
+
|
|
178
|
+
- **"Explain feature X":** `jrag search "X"` → pick 1–3 hits → `jrag inspect <hit>` → targeted traversal (`callees`/`implementations`) → stop when answered.
|
|
179
|
+
- **"Where is X used?":** `jrag inspect <X>` → `jrag callers <X>` + `jrag dependents <X>` → `Grep` fallback → report sites with file:line.
|
|
180
|
+
- **"Find all Y":** structural → `jrag find --role <ROLE> [--service <S>]`; textual → `Grep`; broad → `Glob`+`Grep`. Summarize, don't dump.
|
|
181
|
+
- **"Trace flow A→B":** `jrag flow <route-A>` → `jrag connection A B` → `Grep` gaps → report with file:line.
|
|
182
|
+
- **"How is this configured?":** `Glob` `**/application*.yml` → `Grep` the key → `Read` sections → `jrag search "<key>" --table yaml`.
|
|
183
|
+
- **"Orient in a new service":** `jrag overview <S>` → `jrag conventions --service <S>` → `jrag map --service <S>` → `jrag http-routes --service <S>`.
|