java-codebase-rag 0.11.2__py3-none-any.whl → 0.12.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.
Files changed (37) hide show
  1. java_codebase_rag/_deprecation.py +103 -0
  2. java_codebase_rag/_version.py +2 -2
  3. java_codebase_rag/ast/ast_java.py +22 -0
  4. java_codebase_rag/ast/ast_kotlin.py +1794 -0
  5. java_codebase_rag/ast/chunk_heuristics.py +26 -5
  6. java_codebase_rag/ast/language.py +117 -0
  7. java_codebase_rag/cli.py +17 -17
  8. java_codebase_rag/cli_dispatch.py +251 -0
  9. java_codebase_rag/config.py +8 -8
  10. java_codebase_rag/eval/runner.py +3 -3
  11. java_codebase_rag/graph/build_ast_graph.py +130 -8
  12. java_codebase_rag/graph/graph_enrich.py +8 -5
  13. java_codebase_rag/graph/ladybug_queries.py +1 -1
  14. java_codebase_rag/graph/path_filtering.py +39 -7
  15. java_codebase_rag/index/java_index_flow_lancedb.py +160 -15
  16. java_codebase_rag/install_data/agents/explorer-rag-cli.md +6 -4
  17. java_codebase_rag/install_data/agents/explorer-rag-enhanced.md +4 -4
  18. java_codebase_rag/install_data/skills/explore-codebase/SKILL.md +4 -4
  19. java_codebase_rag/install_data/skills/explore-codebase-cli/SKILL.md +5 -5
  20. java_codebase_rag/installer.py +15 -15
  21. java_codebase_rag/jrag.py +25 -11
  22. java_codebase_rag/lance_optimize.py +7 -7
  23. java_codebase_rag/mcp/mcp_v2.py +2 -2
  24. java_codebase_rag/mcp/server.py +6 -4
  25. java_codebase_rag/pipeline.py +4 -4
  26. java_codebase_rag/progress.py +1 -1
  27. java_codebase_rag/search/search_lexical.py +1 -1
  28. java_codebase_rag/search/search_scoring.py +19 -5
  29. java_codebase_rag/watch/lock.py +1 -1
  30. java_codebase_rag/watch/watcher.py +45 -21
  31. {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.0.dist-info}/METADATA +31 -22
  32. {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.0.dist-info}/RECORD +36 -32
  33. java_codebase_rag-0.12.0.dist-info/entry_points.txt +5 -0
  34. java_codebase_rag-0.11.2.dist-info/entry_points.txt +0 -4
  35. {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.0.dist-info}/WHEEL +0 -0
  36. {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.0.dist-info}/licenses/LICENSE +0 -0
  37. {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.0.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: explorer-rag-cli
3
- description: "MUST BE USED PROACTIVELY. Universal read-only explorer agent. Combines graph navigation via the `jrag` CLI (call chains, routes, service boundaries, clients, producers, impact, FQN resolution) with broad file-system search (grep, glob, excerpt reading). Use for any exploration task: locating code, tracing dependencies, finding patterns, answering 'where is X' or 'who calls Y'. Read-only — never edits files. CLI-surface counterpart to explorer-rag-enhanced (which uses the MCP tools)."
3
+ description: "MUST BE USED PROACTIVELY. Universal read-only explorer agent for navigating and exploring JVM (Java + Kotlin) codebases. Combines graph navigation via the `jrag` CLI (call chains, routes, service boundaries, clients, producers, impact, FQN resolution) with `jrag search` (locate code/config by meaning, keywords, or natural language) and broad file-system search (grep, glob, excerpt reading). Use for any exploration task: locating code, tracing dependencies, finding patterns, answering 'where is X' or 'who calls Y'. Read-only — never edits files. CLI-surface counterpart to explorer-rag-enhanced (which uses the MCP tools)."
4
4
  ---
5
5
 
6
- You are a universal codebase explorer — a read-only search and navigation specialist that combines **graph navigation via the `jrag` CLI** (the agent-facing surface of java-codebase-rag: one command per engineering intent) with **broad file-system search** (`Grep`/`Glob`/`Read`) as a first-class peer. Reach for `jrag` on structural questions and `Grep`/`Glob`/`Read` on raw text, config, or a stale index — whichever is lighter.
6
+ You are a universal codebase explorer — a read-only search and navigation specialist. Your tools are **graph navigation via the `jrag` CLI** (the agent-facing surface of jrag: one command per engineering intent), **`jrag search`** (locate code/config by meaning, keywords, or natural language), and **broad file-system search** (`Grep`/`Glob`/`Read`) — all first-class peers. Reach for `jrag` navigation on structural questions, `jrag search` on fuzzy or conceptual ones, and `Grep`/`Glob`/`Read` on raw text, config, or a stale index — whichever is lighter.
7
7
 
8
8
  **Self-contained.** Do not invoke the `/explore-codebase-cli` skill and do not spawn another explorer subagent — the methodology below is baked in. Apply it directly.
9
9
 
@@ -18,7 +18,7 @@ You drive **`jrag` shell commands**, not the MCP tools (`search`/`find`/`describ
18
18
 
19
19
  ## Tool Inventory
20
20
 
21
- - **Graph (`jrag` CLI):** one command per intent (`callers`, `callees`, `hierarchy`, `implementations`, `dependents`, `impact`, `flow`, `http-routes`, `http-clients`, `producers`, `topics`, `find`, `search`, `inspect`, `overview`, …). Use for whole-codebase structural queries — callers/callees, route handlers, HTTP/async seams, clients/producers, service boundaries, impact analysis, FQN resolution, implementations, DI chains. Pass it names; it resolves internally (no raw IDs). Requires an index (see **jrag surface**).
21
+ - **`jrag` CLI — navigate & search:** one command per intent — graph navigation (`callers`, `callees`, `hierarchy`, `implementations`, `dependents`, `impact`, `flow`, `http-routes`, `http-clients`, `producers`, `topics`, `overview`), `search` (locate code or config by meaning, keywords, or natural language), and `find`/`inspect` (resolve identifiers; list nodes by role/kind). Whole-codebase structural queries and fuzzy discovery alike. Pass it names; it resolves internally (no raw IDs). Requires an index (see **jrag surface**).
22
22
  - **File-system:** `Grep` (contents), `Glob` (name/path patterns), `Read` (files — `offset`/`limit`; excerpts over dumps). Use for text searches, file discovery, and anything outside the graph index (config, build, test, CI, docs) — and whenever they're lighter than a `jrag` call.
23
23
  - **Other:** `Bash` (read-only: `git log`, `git blame`, `ls`, `find`), `WebSearch`, `WebFetch`.
24
24
 
@@ -56,6 +56,8 @@ You drive **`jrag` shell commands**, not the MCP tools (`search`/`find`/`describ
56
56
 
57
57
  **Escalation:** ① Most targeted tool first (identifier → `jrag inspect`; structural → matching `jrag` traversal; raw text / config / history → `Grep`/`Glob`/`Bash`). ② Fall back gracefully (`jrag` empty / `not_found` / exit 2 → `Grep`/`Glob`). ③ Cross-validate (`jrag` vs file disagree → **trust the file** — the index may be stale; report it).
58
58
 
59
+ **Rules of thumb:** structure beats search for exact questions (`jrag find`/`inspect` + traversal); search beats structure for fuzzy discovery (`jrag search`); raw text / config / history beats both (`Grep`/`Glob`/`Bash`); file-system beats a stale index.
60
+
59
61
  ---
60
62
 
61
63
  ## Workflow Patterns
@@ -72,7 +74,7 @@ You drive **`jrag` shell commands**, not the MCP tools (`search`/`find`/`describ
72
74
 
73
75
  | Symptom | Fix |
74
76
  | ------- | --- |
75
- | `jrag status` exits 2 | Run `java-codebase-rag init --source-root <root>`; retry |
77
+ | `jrag status` exits 2 | Run `jrag init --source-root <root>`; retry |
76
78
  | `status: not_found` | `jrag search "<query>"`; or `find --fqn-contains`; fallback `Grep` |
77
79
  | `many` candidates | Add `--kind`/`--role`/`--fqn-contains`/`--service`; re-run |
78
80
  | `find` too broad | Add `--service`, `--fqn-contains`, `--path-contains`, `--topic-contains` |
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: explorer-rag-enhanced
3
- description: "MUST BE USED PROACTIVELY. Universal read-only explorer agent. Combines java-codebase-rag graph navigation (call chains, service boundaries, routes, impact analysis, FQN resolution) with broad file-system search (grep, glob, excerpt reading). Use for any exploration task: locating code, tracing dependencies, finding patterns, answering 'where is X' or 'who calls Y' questions. Read-only — never edits files."
3
+ description: "MUST BE USED PROACTIVELY. Universal read-only explorer agent. Combines jrag graph navigation (call chains, service boundaries, routes, impact analysis, FQN resolution) with broad file-system search (grep, glob, excerpt reading). Use for any exploration task: locating code, tracing dependencies, finding patterns, answering 'where is X' or 'who calls Y' questions. Read-only — never edits files."
4
4
  ---
5
5
 
6
- You are a universal codebase explorer — a read-only search and navigation specialist that combines **graph-based structural analysis** (java-codebase-rag MCP) with **broad file-system search** (grep, glob, file reading).
6
+ You are a universal codebase explorer — a read-only search and navigation specialist that combines **graph-based structural analysis** (jrag MCP) with **broad file-system search** (grep, glob, file reading).
7
7
 
8
8
  ## Core Principles
9
9
 
@@ -14,7 +14,7 @@ You are a universal codebase explorer — a read-only search and navigation spec
14
14
 
15
15
  ## Tool Inventory
16
16
 
17
- - **Graph (java-codebase-rag MCP):** `search`, `find`, `describe`, `neighbors`, `resolve`. Use for whole-codebase structural queries — callers/callees, route handlers, HTTP/async seams, clients/producers, service boundaries, impact analysis, FQN resolution, implementations, DI chains. 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`). **Do NOT use** for specific known files, git history, test/build/CI files, or anything answerable from open context.
17
+ - **Graph (jrag MCP):** `search`, `find`, `describe`, `neighbors`, `resolve`. Use for whole-codebase structural queries — callers/callees, route handlers, HTTP/async seams, clients/producers, service boundaries, impact analysis, FQN resolution, implementations, DI chains. 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`). **Do NOT use** for specific known files, git history, test/build/CI files, or anything answerable from open context.
18
18
  - **File-system:** `Grep` (contents), `Glob` (name/path patterns), `Read` (files — `offset`/`limit` for large; excerpts over dumps). Use for text searches, file discovery, and any content outside the graph index (config, build, test, CI, docs).
19
19
  - **Other:** `Bash` (read-only: `git log`, `git blame`, `ls`, `find`), `WebSearch`, `WebFetch`.
20
20
 
@@ -45,7 +45,7 @@ You are a universal codebase explorer — a read-only search and navigation spec
45
45
 
46
46
  ---
47
47
 
48
- ## Graph Navigation Reference (java-codebase-rag MCP)
48
+ ## Graph Navigation Reference (jrag MCP)
49
49
 
50
50
  ### Forced reasoning preamble (every MCP call)
51
51
 
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: explore-codebase
3
- description: "MUST BE USED PROACTIVELY. Universal read-only codebase exploration. Combines java-codebase-rag graph navigation (call chains, routes, service boundaries, impact analysis, FQN resolution) with broad file-system search (grep, glob, file reading). 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'. Do NOT use when the answer is already in open context or for a single known file — read that file directly."
3
+ description: "MUST BE USED PROACTIVELY. Universal read-only codebase exploration. Combines jrag graph navigation (call chains, routes, service boundaries, impact analysis, FQN resolution) with broad file-system search (grep, glob, file reading). 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'. Do NOT use when the answer is already in open context or for a single known file — read that file directly."
4
4
  ---
5
5
 
6
6
  # /explore-codebase — Universal codebase exploration
7
7
 
8
- Read-only exploration combining **java-codebase-rag graph navigation** with **broad file-system search**.
8
+ Read-only exploration combining **jrag graph navigation** with **broad file-system search**.
9
9
 
10
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
11
 
@@ -17,7 +17,7 @@ Use any time you must search, locate, navigate, or explore. **Do NOT use when**
17
17
 
18
18
  ## Tool Inventory
19
19
 
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`).
20
+ - **Graph (jrag 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
21
  - **File-system:** `Grep` (content/regex), `Glob` (name/path patterns), `Read` (`offset`/`limit` for large files).
22
22
  - **Other:** `Bash` (read-only: `git log`, `git blame`, `ls`, `find`), `WebSearch`/`WebFetch`.
23
23
 
@@ -50,7 +50,7 @@ Use any time you must search, locate, navigate, or explore. **Do NOT use when**
50
50
 
51
51
  ---
52
52
 
53
- ## Graph Navigation Reference (java-codebase-rag MCP)
53
+ ## Graph Navigation Reference (jrag MCP)
54
54
 
55
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.
56
56
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: explore-codebase-cli
3
- description: "MUST BE USED PROACTIVELY. Universal codebase exploration (CLI surface). Use for any exploration task: locating code, tracing dependencies, finding patterns, 'where is X', 'who calls Y', 'find all controllers', 'trace the flow from A to B'. Do NOT use when the answer is already in open context or for a single known file — read that file directly."
3
+ description: "MUST BE USED PROACTIVELY. Universal JVM (Java + Kotlin) codebase exploration (CLI surface): graph navigation (`jrag` callers/callees/routes/impact/flow/…) plus `jrag search` (locate code/config by meaning or keywords) and file-system search. Use for any exploration task: locating code, tracing dependencies, finding patterns, 'where is X', 'who calls Y', 'find all controllers', 'trace the flow from A to B'. Do NOT use when the answer is already in open context or for a single known file — read that file directly."
4
4
  ---
5
5
 
6
6
  ## Core Principles
@@ -11,7 +11,7 @@ description: "MUST BE USED PROACTIVELY. Universal codebase exploration (CLI surf
11
11
 
12
12
  ## Tool Inventory
13
13
 
14
- - **Graph (`jrag` CLI):** one command per intent — `callers`, `callees`, `hierarchy`, `implementations`, `dependents`, `impact`, `flow`, `http-routes`, `http-clients`, `producers`, `topics`, `find`, `search`, `inspect`, `overview`, … Drives the same index as the MCP server. Fast path for structural questions: call chains, route handlers, HTTP/async seams, clients/producers, service boundaries, impact, FQN resolution, implementations, DI chains. Pass it names (FQN / simple name / route path / topic) — it resolves internally; raw node IDs are never required. Requires an index; if unindexed every command exits 2 (see **jrag surface**).
14
+ - **`jrag` CLI — navigate & search:** one command per intent — graph navigation (`callers`, `callees`, `hierarchy`, `implementations`, `dependents`, `impact`, `flow`, `http-routes`, `http-clients`, `producers`, `topics`, `overview`), `search` (locate code or config by meaning, keywords, or natural language), and `find`/`inspect` (resolve identifiers; list nodes by role/kind). Drives the same index as the MCP server. Fast path for structural questions (call chains, route handlers, HTTP/async seams, clients/producers, service boundaries, impact, FQN resolution, implementations, DI chains) and fuzzy discovery alike. Pass it names (FQN / simple name / route path / topic) — it resolves internally; raw node IDs are never required. Requires an index; if unindexed every command exits 2 (see **jrag surface**).
15
15
  - **File-system:** `Grep` (content/regex), `Glob` (name/path patterns), `Read` (`offset`/`limit`). First-class for text searches, file discovery, and anything outside the graph index (config, build, test, CI, docs) — and the right answer whenever they're lighter than a `jrag` call.
16
16
  - **Other:** `Bash` (read-only: `git log`, `git blame`, `ls`, `find`), `WebSearch`/`WebFetch`.
17
17
 
@@ -51,7 +51,7 @@ description: "MUST BE USED PROACTIVELY. Universal codebase exploration (CLI surf
51
51
 
52
52
  **Escalation:** ① Most targeted tool first (identifier → `jrag inspect`; structural → matching `jrag` traversal; raw text / config / history → `Grep`/`Glob`/`Bash`). ② Fall back gracefully (`jrag` empty / `not_found` / exit 2 → `Grep`/`Glob`). ③ Cross-validate (`jrag` vs file disagree → **trust the file** — the index may be stale; report it).
53
53
 
54
- **Rules of thumb:** structure beats vector for exact questions (`jrag find`/`inspect` + traversal); vector beats structure for fuzzy discovery (`jrag search`); raw text / config / history beats both (`Grep`/`Glob`/`Bash`); file-system beats a stale index.
54
+ **Rules of thumb:** structure beats search for exact questions (`jrag find`/`inspect` + traversal); search beats structure for fuzzy discovery (`jrag search`); raw text / config / history beats both (`Grep`/`Glob`/`Bash`); file-system beats a stale index.
55
55
 
56
56
  ---
57
57
 
@@ -70,13 +70,13 @@ description: "MUST BE USED PROACTIVELY. Universal codebase exploration (CLI surf
70
70
 
71
71
  | Symptom | Fix |
72
72
  | ------- | --- |
73
- | `status: error` "No index at …" | Run `java-codebase-rag init --source-root <root>`; retry |
73
+ | `status: error` "No index at …" | Run `jrag init --source-root <root>`; retry |
74
74
  | `status: not_found` | `jrag search "<query>"`; or `find --fqn-contains …`; fallback `Grep` |
75
75
  | `many` candidates | Add `--kind`/`--role`/`--fqn-contains`/`--service`; re-run |
76
76
  | `find` too broad | Add `--service`, `--fqn-contains`, `--path-contains`, `--topic-contains` |
77
77
  | Empty `search` | Try `--table all`; `find --fqn-contains`; `Grep` |
78
78
  | `truncated: true` | Narrow, or page with `--offset` (`find`/`search` only) |
79
- | Empty across commands | Index missing/stale → `Grep`/`Glob`/`Read`; ask operator to rebuild (`java-codebase-rag reprocess`) |
79
+ | Empty across commands | Index missing/stale → `Grep`/`Glob`/`Read`; ask operator to rebuild (`jrag reprocess`) |
80
80
  | CLI vs file disagree | **Trust the file**; report stale index |
81
81
  | `--offset` rejected | Only `find`/`search` accept it; others narrow via filters |
82
82
  | Wrong node picked | Resolve ambiguous — pass `--kind` |
@@ -1,4 +1,4 @@
1
- """Interactive installer module for java-codebase-rag.
1
+ """Interactive installer module for jrag.
2
2
 
3
3
  This module provides the `install` subcommand that walks users through:
4
4
  1. Java source detection
@@ -605,13 +605,13 @@ def resolve_mcp_command(*, non_interactive: bool, surface: Surface = "mcp") -> s
605
605
  print(f"Error: `{display_name}` not found on PATH.")
606
606
  if surface == "mcp":
607
607
  print(
608
- "Ensure `java-codebase-rag` is installed, then re-run with "
608
+ "Ensure `jrag` is installed, then re-run with "
609
609
  "`--non-interactive --agent <host>`."
610
610
  )
611
611
  else:
612
612
  print(
613
- "Ensure `java-codebase-rag` is installed (provides the `jrag` "
614
- "console script), then re-run with `--non-interactive --agent <host>`."
613
+ "Ensure the `jrag` console script is installed, "
614
+ "then re-run with `--non-interactive --agent <host>`."
615
615
  )
616
616
  raise SystemExit(2)
617
617
 
@@ -982,7 +982,7 @@ def update_gitignore(cwd: Path) -> None:
982
982
 
983
983
  if not already_present:
984
984
  lines.append("")
985
- lines.append("# java-codebase-rag index directory")
985
+ lines.append("# jrag index directory")
986
986
  lines.append(".java-codebase-rag/")
987
987
  gitignore_path.write_text("\n".join(lines), encoding="utf-8")
988
988
 
@@ -998,7 +998,7 @@ def _index_progress_header(subcommand: str, source_root: Path, index_dir: Path)
998
998
 
999
999
  print(
1000
1000
  bold(
1001
- f"java-codebase-rag {subcommand} · source={source_root.resolve()} "
1001
+ f"jrag {subcommand} · source={source_root.resolve()} "
1002
1002
  f"· index={index_dir.resolve()}"
1003
1003
  ),
1004
1004
  file=sys.stderr,
@@ -1013,7 +1013,7 @@ def _index_progress_footer(subcommand: str, started: float, *, ok: bool) -> None
1013
1013
  elapsed = time.perf_counter() - started
1014
1014
  marker = styled_check() if ok else styled_cross()
1015
1015
  print(
1016
- f"{marker} {bold(f'java-codebase-rag {subcommand} · finished in {elapsed:.2f}s')}",
1016
+ f"{marker} {bold(f'jrag {subcommand} · finished in {elapsed:.2f}s')}",
1017
1017
  file=sys.stderr,
1018
1018
  flush=True,
1019
1019
  )
@@ -1061,7 +1061,7 @@ def run_init_if_needed(
1061
1061
 
1062
1062
  has_existing, _ = index_dir_has_existing_artifacts(index_dir)
1063
1063
  if has_existing:
1064
- print("Index already exists. Run `java-codebase-rag reprocess` to rebuild.")
1064
+ print("Index already exists. Run `jrag reprocess` to rebuild.")
1065
1065
  return None # skipped, not failed
1066
1066
 
1067
1067
  cfg = resolve_operator_config(
@@ -1109,7 +1109,7 @@ def run_init_if_needed(
1109
1109
  else:
1110
1110
  if vectors_skipped:
1111
1111
  print(
1112
- "java-codebase-rag: vectors skipped — vector stack not installed on this "
1112
+ "jrag: vectors skipped — vector stack not installed on this "
1113
1113
  "platform (graph-only mode). Building graph only; semantic search is unavailable.",
1114
1114
  file=sys.stderr,
1115
1115
  )
@@ -1750,7 +1750,7 @@ def run_update(
1750
1750
 
1751
1751
  if not configured_hosts:
1752
1752
  print("No configured agent hosts found.")
1753
- print("Run `java-codebase-rag install` first.")
1753
+ print("Run `jrag install` first.")
1754
1754
  return EXIT_FATAL
1755
1755
 
1756
1756
  print(f"Found {len(configured_hosts)} configured host(s).")
@@ -1800,7 +1800,7 @@ def run_update(
1800
1800
  f"'{chosen_surface}' surface."
1801
1801
  )
1802
1802
  print(
1803
- "Ensure `java-codebase-rag` is installed, then re-run `update "
1803
+ "Ensure `jrag` is installed, then re-run `update "
1804
1804
  f"--surface {chosen_surface}`."
1805
1805
  )
1806
1806
  return EXIT_PARTIAL
@@ -1907,11 +1907,11 @@ def run_update(
1907
1907
 
1908
1908
  if not index_exists:
1909
1909
  print("\nNo index found.")
1910
- print("Run `java-codebase-rag install` to create one.")
1910
+ print("Run `jrag install` to create one.")
1911
1911
  return EXIT_PARTIAL if has_artifact_failures else EXIT_SUCCESS
1912
1912
 
1913
1913
  # Run increment: LanceDB catch-up + incremental graph rebuild.
1914
- # Mirrors `java-codebase-rag increment` so both index layers stay current.
1914
+ # Mirrors `jrag increment` so both index layers stay current.
1915
1915
  # The "graph not implemented" warning belongs only on the vectors-only path
1916
1916
  # (increment --vectors-only), where the graph step is deliberately skipped.
1917
1917
  if not dry_run:
@@ -1955,7 +1955,7 @@ def run_update(
1955
1955
  else:
1956
1956
  if vectors_skipped:
1957
1957
  print(
1958
- "java-codebase-rag: vectors skipped — vector stack not installed on this "
1958
+ "jrag: vectors skipped — vector stack not installed on this "
1959
1959
  "platform (graph-only mode). Running graph catch-up only.",
1960
1960
  file=sys.stderr,
1961
1961
  )
@@ -1977,7 +1977,7 @@ def run_update(
1977
1977
  # check + the Warning line carrying the graph caveat.
1978
1978
  print(
1979
1979
  f"\nWarning: incremental graph update failed (exit {g.returncode}). "
1980
- "Run `java-codebase-rag reprocess` for a full rebuild.",
1980
+ "Run `jrag reprocess` for a full rebuild.",
1981
1981
  file=sys.stderr,
1982
1982
  )
1983
1983
  except BaseException:
java_codebase_rag/jrag.py CHANGED
@@ -1095,8 +1095,9 @@ def build_parser() -> argparse.ArgumentParser:
1095
1095
  help="List imports declared in a file (tree-sitter parse + resolve_v2).",
1096
1096
  parents=[_common_parser()],
1097
1097
  description=(
1098
- "Parse <file> with tree-sitter (ast_java.parse_java), walk its "
1099
- "import_declaration nodes, and resolve each imported FQN via resolve_v2 "
1098
+ "Parse <file> with tree-sitter via the language backend "
1099
+ "(backend_for(...).parse — parse_java for .java, parse_kotlin for "
1100
+ ".kt), walk its import nodes, and resolve each imported FQN via resolve_v2 "
1100
1101
  "against the graph. Returns one node per import: resolved graph Symbol "
1101
1102
  "when resolve_v2 hits, or an unresolved placeholder carrying the raw FQN "
1102
1103
  "otherwise. Static and wildcard imports are included (marked in the row)."
@@ -1355,7 +1356,7 @@ def _load_graph(cfg): # type: ignore[no-untyped-def]
1355
1356
  """Load the LadybugGraph with actionable error envelopes.
1356
1357
 
1357
1358
  * missing index -> ``_IndexNotFound`` (caught in ``main`` -> envelope with
1358
- a ``java-codebase-rag init --source-root <root>`` remediation).
1359
+ a ``jrag init --source-root <root>`` remediation).
1359
1360
  * ontology-mismatch (``RuntimeError`` from ``LadybugGraph.get``) ->
1360
1361
  ``_IndexStale`` (caught in ``main`` -> envelope with a rebuild hint).
1361
1362
  """
@@ -1365,7 +1366,7 @@ def _load_graph(cfg): # type: ignore[no-untyped-def]
1365
1366
  if not LadybugGraph.exists(ladybug_path):
1366
1367
  raise _IndexNotFound(
1367
1368
  f"No index at {cfg.ladybug_path}. "
1368
- "Run: java-codebase-rag init --source-root <root>"
1369
+ "Run: jrag init --source-root <root>"
1369
1370
  )
1370
1371
  try:
1371
1372
  return LadybugGraph.get(ladybug_path)
@@ -3604,12 +3605,13 @@ def _cmd_imports(args: argparse.Namespace) -> int:
3604
3605
  """imports <file> — tree-sitter parse + resolve_v2 per imported FQN.
3605
3606
 
3606
3607
  Reads <file> from disk (cfg.source_root / <file> for relative paths),
3607
- parses with ast_java.parse_java, walks explicit_imports (dict: simple_name
3608
+ parses via the language backend (backend_for(...).parse — parse_java for
3609
+ .java, parse_kotlin for .kt), walks explicit_imports (dict: simple_name
3608
3610
  -> FQN), then resolves each FQN via resolve_v2 against the graph. Returns
3609
3611
  a node per import: resolved graph Symbol when resolve_v2 hits (status=one),
3610
3612
  or an unresolved placeholder carrying the raw FQN otherwise.
3611
3613
  """
3612
- from java_codebase_rag.ast.ast_java import parse_java
3614
+ from java_codebase_rag.ast.language import backend_for
3613
3615
  from java_codebase_rag.analysis.resolve_service import resolve_v2
3614
3616
 
3615
3617
  from java_codebase_rag.jrag_envelope import Envelope, next_actions_hook
@@ -3638,14 +3640,26 @@ def _cmd_imports(args: argparse.Namespace) -> int:
3638
3640
  print(render(env, fmt=args.format, detail=args.detail))
3639
3641
  return 2
3640
3642
 
3641
- # parse_java is robust to invalid source (returns an empty JavaFileAst on
3642
- # parse errors, never raises). It builds imports from the
3643
- # `import_declaration` tree-sitter nodes via `_import_declaration_is_static`
3644
- # (ast_java.py:905) and the scoped_identifier child walk (ast_java.py:2658).
3643
+ # The backend parse (backend_for(...).parse — parse_java / parse_kotlin)
3644
+ # is robust to invalid source (returns an empty JavaFileAst on parse
3645
+ # errors, never raises). It builds imports from the `import_declaration`
3646
+ # tree-sitter nodes (Java path: `_import_declaration_is_static` at
3647
+ # ast_java.py:905 and the scoped_identifier child walk at ast_java.py:2658).
3645
3648
  # explicit_imports: dict[str, str] = simple_name -> FQN (non-wildcard,
3646
3649
  # non-static); we also surface wildcard/static imports as unresolved rows so
3647
3650
  # the agent sees the full import block.
3648
- ast = parse_java(src, filename=args.file)
3651
+ backend = backend_for(args.file)
3652
+ if backend is None:
3653
+ env = Envelope(
3654
+ status="error",
3655
+ message=(
3656
+ f"no language backend registered for {args.file!r} "
3657
+ f"(suffix {Path(args.file).suffix!r} not in registry)"
3658
+ ),
3659
+ )
3660
+ print(render(env, fmt=args.format, detail=args.detail))
3661
+ return 2
3662
+ ast = backend.parse(src, filename=args.file)
3649
3663
  nodes: dict[str, dict] = {}
3650
3664
  edges: list[dict] = []
3651
3665
  warnings: list[str] = []
@@ -139,7 +139,7 @@ async def optimize_lance_tables(
139
139
  existing = await _list_table_names(db)
140
140
  except Exception as exc:
141
141
  print(
142
- f"java-codebase-rag: optimize: failed to list tables in "
142
+ f"jrag: optimize: failed to list tables in "
143
143
  f"{index_dir}: {exc}",
144
144
  file=sys.stderr,
145
145
  )
@@ -151,7 +151,7 @@ async def optimize_lance_tables(
151
151
  results[name] = "skipped"
152
152
  if not quiet:
153
153
  print(
154
- f"java-codebase-rag: optimize: {name} absent, skipped",
154
+ f"jrag: optimize: {name} absent, skipped",
155
155
  file=sys.stderr,
156
156
  )
157
157
  continue
@@ -161,7 +161,7 @@ async def optimize_lance_tables(
161
161
  results[name] = f"error: open failed: {exc}"
162
162
  failed = True
163
163
  print(
164
- f"java-codebase-rag: optimize: {name} open failed: {exc}",
164
+ f"jrag: optimize: {name} open failed: {exc}",
165
165
  file=sys.stderr,
166
166
  )
167
167
  continue
@@ -205,7 +205,7 @@ async def optimize_lance_tables(
205
205
  w in low for w in ("exist", "duplicate", "already", "same name")
206
206
  ) and not quiet:
207
207
  print(
208
- f"java-codebase-rag: optimize: {name} id-index skipped: {exc}",
208
+ f"jrag: optimize: {name} id-index skipped: {exc}",
209
209
  file=sys.stderr,
210
210
  )
211
211
  # Best-effort FTS index at index time (PR-SEARCH-3) so hybrid
@@ -223,19 +223,19 @@ async def optimize_lance_tables(
223
223
  w in low for w in ("exist", "duplicate", "already", "same name")
224
224
  ) and not quiet:
225
225
  print(
226
- f"java-codebase-rag: optimize: {name} fts skipped: {exc}",
226
+ f"jrag: optimize: {name} fts skipped: {exc}",
227
227
  file=sys.stderr,
228
228
  )
229
229
  if not quiet:
230
230
  print(
231
- f"java-codebase-rag: optimize: {name} ok",
231
+ f"jrag: optimize: {name} ok",
232
232
  file=sys.stderr,
233
233
  )
234
234
  else:
235
235
  results[name] = f"error: {last_exc}"
236
236
  failed = True
237
237
  print(
238
- f"java-codebase-rag: optimize: {name} failed: {last_exc}",
238
+ f"jrag: optimize: {name} failed: {last_exc}",
239
239
  file=sys.stderr,
240
240
  )
241
241
  finally:
@@ -1265,7 +1265,7 @@ def find_v2(
1265
1265
  _DESCRIBE_UCS_ID_MESSAGE = (
1266
1266
  "UnresolvedCallSite ids (ucs:…) are not describable — use describe(caller_method_id) "
1267
1267
  "for record.data.unresolved_call_sites, neighbors(..., include_unresolved=True), "
1268
- "or java-codebase-rag unresolved-calls list --method-id <caller_id>"
1268
+ "or jrag unresolved-calls list --method-id <caller_id>"
1269
1269
  )
1270
1270
 
1271
1271
 
@@ -1363,7 +1363,7 @@ def describe_v2(
1363
1363
  if total > len(inline):
1364
1364
  data["unresolved_call_sites_footer"] = (
1365
1365
  f"{total} unresolved call sites — see "
1366
- f"java-codebase-rag unresolved-calls list --method-id {node_id} for the full list"
1366
+ f"jrag unresolved-calls list --method-id {node_id} for the full list"
1367
1367
  )
1368
1368
  record = NodeRecord(id=ref.id, kind=kind, fqn=ref.fqn, data=data, edge_summary=edge_summary)
1369
1369
  raw_struct, raw_advisories = _hints_or_skip("describe", {"success": True, "record": record.model_dump()})
@@ -9,6 +9,7 @@ import time
9
9
  from pathlib import Path
10
10
  from typing import Literal
11
11
 
12
+ from java_codebase_rag._deprecation import maybe_warn_legacy_alias
12
13
  from java_codebase_rag.mcp import mcp_v2
13
14
  from java_codebase_rag.analysis import resolve_service
14
15
  from java_codebase_rag.search.index_common import SBERT_MODEL
@@ -52,7 +53,7 @@ _INSTRUCTIONS = (
52
53
  "Successful responses from any tool may include `hints_structured` (tool call suggestions with a `reason` field) and `advisories` (pure informational text) when hints are enabled. "
53
54
  "Edge labels: EXTENDS, IMPLEMENTS, INJECTS, OVERRIDES, DECLARES, DECLARES_CLIENT, DECLARES_PRODUCER, CALLS, EXPOSES, HTTP_CALLS, ASYNC_CALLS; "
54
55
  "type Symbols may also use composed neighbors edge_types DECLARES.DECLARES_CLIENT, DECLARES.DECLARES_PRODUCER, DECLARES.EXPOSES (out only, type Symbol origin). "
55
- "Reprocess/init, meta, tables, diagnose-ignore, analyze-pr: use java-codebase-rag CLI — not MCP."
56
+ "Reprocess/init, meta, tables, diagnose-ignore, analyze-pr: use jrag CLI — not MCP."
56
57
  )
57
58
 
58
59
 
@@ -249,7 +250,7 @@ def _graph_meta_output() -> GraphMetaOutput:
249
250
  success=True,
250
251
  enabled=False,
251
252
  db_path=resolve_ladybug_path(),
252
- message="Ladybug graph not present; run java-codebase-rag reprocess or build_ast_graph.py",
253
+ message="Ladybug graph not present; run jrag reprocess or build_ast_graph.py",
253
254
  )
254
255
  try:
255
256
  graph = LadybugGraph.get()
@@ -480,7 +481,7 @@ async def run_refresh_pipeline(
480
481
  await drop_proc.communicate()
481
482
  except Exception as exc:
482
483
  print(
483
- f"java-codebase-rag: drop-before-reprocess failed ({exc!s}); "
484
+ f"jrag: drop-before-reprocess failed ({exc!s}); "
484
485
  "falling back to in-place update",
485
486
  file=sys.stderr,
486
487
  )
@@ -575,7 +576,7 @@ async def run_refresh_pipeline(
575
576
  await optimize_lance_tables(idx_dir, quiet=quiet, on_progress=on_progress)
576
577
  except Exception as exc:
577
578
  optimize_error = f"lance optimize failed: {exc}"
578
- print(f"java-codebase-rag: {optimize_error}", file=sys.stderr)
579
+ print(f"jrag: {optimize_error}", file=sys.stderr)
579
580
  graph_code, graph_out, graph_err, graph_started = await _run_graph_phase(
580
581
  root, quiet=quiet, verbose=verbose,
581
582
  on_progress=on_progress, on_progress_console=on_progress_console,
@@ -861,6 +862,7 @@ def create_mcp_server() -> FastMCP:
861
862
 
862
863
 
863
864
  def main() -> None:
865
+ maybe_warn_legacy_alias()
864
866
  raise_fd_limit()
865
867
  emit_legacy_env_hints_if_present()
866
868
 
@@ -24,7 +24,7 @@ COCOINDEX_TARGET = "java_index_flow_lancedb.py:JavaCodeIndexLance"
24
24
  # Single source of truth — imported by cli.py (init/increment) and server.py
25
25
  # (reprocess) so the wording can't drift between the two paths.
26
26
  VECTORS_SKIPPED_GRAPH_ONLY = (
27
- "java-codebase-rag: vectors skipped — vector stack not installed on this platform "
27
+ "jrag: vectors skipped — vector stack not installed on this platform "
28
28
  "(graph-only mode). The graph is built/refreshed; semantic search is unavailable."
29
29
  )
30
30
 
@@ -212,7 +212,7 @@ def run_cocoindex_update(
212
212
  drop = run_cocoindex_drop(env, quiet=quiet)
213
213
  if drop.returncode != 0 and not is_cocoindex_preflight_blocker(drop):
214
214
  print(
215
- "java-codebase-rag: drop-before-reprocess failed "
215
+ "jrag: drop-before-reprocess failed "
216
216
  f"(exit {drop.returncode}); falling back to in-place update: "
217
217
  f"{(drop.stderr or '').strip()[:200]}",
218
218
  file=sys.stderr,
@@ -252,7 +252,7 @@ def _maybe_run_serialized_optimize(
252
252
  idx_raw = env.get("JAVA_CODEBASE_RAG_INDEX_DIR", "").strip()
253
253
  if not idx_raw:
254
254
  print(
255
- "java-codebase-rag: optimize skipped — JAVA_CODEBASE_RAG_INDEX_DIR "
255
+ "jrag: optimize skipped — JAVA_CODEBASE_RAG_INDEX_DIR "
256
256
  "not set in subprocess env",
257
257
  file=sys.stderr,
258
258
  )
@@ -263,7 +263,7 @@ def _maybe_run_serialized_optimize(
263
263
  asyncio.run(optimize_lance_tables(Path(idx_raw), quiet=quiet, on_progress=on_progress))
264
264
  except Exception as exc:
265
265
  # Never crash the CLI on an optimize failure — surface on stderr only.
266
- print(f"java-codebase-rag: optimize failed: {exc}", file=sys.stderr)
266
+ print(f"jrag: optimize failed: {exc}", file=sys.stderr)
267
267
 
268
268
 
269
269
  def is_cocoindex_preflight_blocker(proc: subprocess.CompletedProcess[str]) -> bool:
@@ -531,7 +531,7 @@ class ProgressRelay:
531
531
  self._renderer.apply(ev)
532
532
  except Exception as exc:
533
533
  sys.stderr.write(
534
- f"java-codebase-rag: progress renderer error: {exc}\n"
534
+ f"jrag: progress renderer error: {exc}\n"
535
535
  )
536
536
  sys.stderr.flush()
537
537
  return
@@ -300,7 +300,7 @@ def run_lexical_search(
300
300
  if graph is None and not LadybugGraph.exists():
301
301
  raise RuntimeError(
302
302
  "lexical search unavailable: no symbol graph found; "
303
- "run `java-codebase-rag init` or `java-codebase-rag reprocess` to build one"
303
+ "run `jrag init` or `jrag reprocess` to build one"
304
304
  )
305
305
  g = graph or LadybugGraph.get()
306
306
 
@@ -37,7 +37,7 @@ _SYMBOL_MATCH_BONUS_CAP = 0.06
37
37
 
38
38
  # Action verbs that typically mark behavioural entry points in this codebase.
39
39
  # A chunk whose symbols begin with one of these verbs earns a small flat bump
40
- # — again only for java chunks and only when role-filtering is off.
40
+ # — again only for JVM (Java/Kotlin) chunks and only when role-filtering is off.
41
41
  _ACTION_VERB_PREFIXES: tuple[str, ...] = (
42
42
  "process", "handle", "on", "pick", "select", "assign",
43
43
  "notify", "dispatch", "publish", "consume", "route",
@@ -64,7 +64,7 @@ _STOPWORDS: frozenset[str] = frozenset({
64
64
  "may", "might", "happens", "happen", "happened", "get", "gets", "got",
65
65
  })
66
66
 
67
- # Role-aware reweighting for Java chunks. Positive values favour actionable
67
+ # Role-aware reweighting for Java/Kotlin chunks. Positive values favour actionable
68
68
  # behavioural code (entrypoints, orchestrators, integrations) over configuration,
69
69
  # schema, and persistence stubs for "what happens when..."-style queries.
70
70
  # Applied to the similarity score (higher = better); distance-based sort subtracts
@@ -236,13 +236,27 @@ def build_fts_query(text: str) -> str:
236
236
  return " ".join(out)
237
237
 
238
238
 
239
+ def _is_jvm_row(r: dict) -> bool:
240
+ """True when a row is Java or Kotlin source (both indexed in the java table).
241
+
242
+ The additive role/bonus weighting applies to both JVM languages. Kotlin
243
+ chunks live in the java LanceDB table (``_kind == "java"``), but we key off
244
+ the semantic ``language`` field when present so detection is robust to the
245
+ row's table-key and any future language-keyed table split.
246
+ """
247
+ lang = str(r.get("language") or "").lower()
248
+ if lang in ("java", "kotlin"):
249
+ return True
250
+ return str(r.get("_kind", "")) == "java"
251
+
252
+
239
253
  def _symbol_bonus(r: dict, query_toks: set[str]) -> float:
240
- """Symbol-name overlap + action-verb bump for java chunks.
254
+ """Symbol-name overlap + action-verb bump for Java/Kotlin chunks.
241
255
 
242
256
  Caps at `_SYMBOL_MATCH_BONUS_CAP + _ACTION_VERB_BONUS` to avoid runaway
243
257
  ranks on chunks declaring many symbols.
244
258
  """
245
- if str(r.get("_kind", "")) != "java":
259
+ if not _is_jvm_row(r):
246
260
  return 0.0
247
261
  raw = r.get("symbols") or []
248
262
  if isinstance(raw, str):
@@ -289,7 +303,7 @@ def _role_weight(r: dict) -> float:
289
303
  cached = comps.get("role_weight")
290
304
  if cached is not None:
291
305
  return float(cached)
292
- if r.get("_skip_role_weight") or str(r.get("_kind", "")) != "java":
306
+ if r.get("_skip_role_weight") or not _is_jvm_row(r):
293
307
  comps["role_weight"] = 0.0
294
308
  return 0.0
295
309
  role = (r.get("role") or "").upper()
@@ -2,7 +2,7 @@
2
2
 
3
3
  ``ProjectLock`` is the single-writer primitive the watch daemon (Task 11)
4
4
  acquires so that at most one watcher — and no concurrent manual
5
- ``java-codebase-rag increment`` — runs per project.
5
+ ``jrag increment`` — runs per project.
6
6
 
7
7
  The lock is keyed on the project's index dir: the pidfile path comes from
8
8
  ``paths.pid_path(index_dir)`` (Task 3). We hold an advisory exclusive flock on