Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
f127876
docs(plans): add JRAG-CLI proposal + plan (9-PR agent-facing CLI)
HumanBean17 Jul 4, 2026
85e2ff9
chore(install): single-source agent artifacts + sync check (PR-JRAG-0a)
HumanBean17 Jul 4, 2026
63d515b
refactor(resolve): extract resolve_v2 to resolve_service.py (PR-JRAG-0b)
HumanBean17 Jul 4, 2026
d07e32c
feat(cli): jrag entry point + envelope/render + status (PR-JRAG-1a)
HumanBean17 Jul 4, 2026
59e6aef
fix(cli): PR-JRAG-1a review — honest offset tests + generic render di…
HumanBean17 Jul 4, 2026
f5c527c
fix(cli): PR-JRAG-1a — explicit inspect render dispatch (shape hint)
HumanBean17 Jul 4, 2026
3e29e8f
feat(cli): jrag find + inspect (PR-JRAG-1b)
HumanBean17 Jul 4, 2026
88900f4
fix(cli): PR-JRAG-1b — error on non-symbol query mode, defer --fuzzy
HumanBean17 Jul 4, 2026
65bec6f
feat(cli): jrag listing tier (PR-JRAG-2)
HumanBean17 Jul 4, 2026
cd6cea1
fix(cli): PR-JRAG-2 — real listeners --topic-prefix + shared listing …
HumanBean17 Jul 4, 2026
cd1aceb
fix(cli): PR-JRAG-2 — topics --consumer-in via EXPOSES (not ASYNC_CAL…
HumanBean17 Jul 4, 2026
d407815
fix(cli): PR-JRAG-2 — correct topics --consumer-in help text (EXPOSES…
HumanBean17 Jul 4, 2026
a352b69
feat(cli): jrag direct-backend traversals (PR-JRAG-3a)
HumanBean17 Jul 4, 2026
d7230f8
fix(cli): PR-JRAG-3a — hierarchy/decompose rendering + silent-flag wa…
HumanBean17 Jul 4, 2026
e72e6a6
feat(cli): jrag compose traversals + connection + outline/imports (PR…
HumanBean17 Jul 4, 2026
0ba8c49
fix(cli): PR-JRAG-3b — inbound default, --calls-service loophole, imp…
HumanBean17 Jul 4, 2026
8d1d1e1
feat(cli): jrag orientation + search + hints + packaging (PR-JRAG-4)
HumanBean17 Jul 4, 2026
55d8e0f
fix(cli): PR-JRAG-4 — render next_actions in text + e2e hint test (PR…
HumanBean17 Jul 4, 2026
a11135e
feat(install): --surface mcp|cli branching + CLI skill/subagent (PR-J…
HumanBean17 Jul 4, 2026
45318ae
fix(cli): drop unimplemented --brief/--fields/--count/--exists; fix i…
HumanBean17 Jul 4, 2026
8f19f88
fix(jrag): user-reported bugs + review findings (post-PR-377)
HumanBean17 Jul 4, 2026
9fe34f4
fix(jrag): address fresh-review findings A-G (silent-wrong-output + t…
HumanBean17 Jul 4, 2026
c27ba2d
fix(jrag): end-to-end CLI bug sweep from bank-chat-system audit
HumanBean17 Jul 4, 2026
f30fe75
docs: trim AGENTS.md to the python-env essentials
HumanBean17 Jul 4, 2026
2e8a2cf
feat(cli): --detail orthogonality (brief|normal|full) for text+json (…
HumanBean17 Jul 4, 2026
d7b4b2e
feat(cli): id-free agent surface — strip graph node ids from text + json
HumanBean17 Jul 5, 2026
42b327a
fix(jrag): disambiguate callees/callers rows + honor --detail in trav…
HumanBean17 Jul 5, 2026
4c7fa05
docs: refresh README + AGENTS.md, drop reports/ and automation/
HumanBean17 Jul 5, 2026
31328d6
fix(cli): force UTF-8 stdio on Windows so glyph output stops crashing
HumanBean17 Jul 5, 2026
2578a18
fix(jrag): honest empty envelopes + undoubled names + HTTP-only routes
HumanBean17 Jul 5, 2026
21a9ebf
fix(jrag): cross-service route callers resolve + name their callers
HumanBean17 Jul 5, 2026
39d4cec
fix(jrag): root-kind-aware next-action hints + listing breadcrumbs
HumanBean17 Jul 5, 2026
93a9144
fix(jrag): Java-kind guards, search score floor, dedup, scope/validation
HumanBean17 Jul 5, 2026
499ee22
test(installer): capture index-progress tests at fd level (capfd)
HumanBean17 Jul 5, 2026
f20560d
feat(jrag): replace *-prefix filters with *-contains (substring match)
HumanBean17 Jul 5, 2026
1798610
test(conftest): enforce editable install to kill stale-CLI rediscovery
HumanBean17 Jul 5, 2026
91cef29
refactor(jrag): rename routes/clients → http-routes/http-clients, dro…
HumanBean17 Jul 5, 2026
4263b53
fix(jrag): --detail brief/normal/inspect/overview contract fixes
HumanBean17 Jul 5, 2026
739e332
fix(jrag): flag/UX contract + empty-result discoverability + hints ba…
HumanBean17 Jul 5, 2026
7a2a0ef
fix(jrag): robust subcommand detection in argparse-error envelope
HumanBean17 Jul 5, 2026
910e3d4
fix(jrag): auto --service scope from cwd (parity with MCP ScopeManager)
HumanBean17 Jul 5, 2026
785ab4a
revert(cli): drop operator-CLI force_utf8_stdio (regressed test on Wi…
HumanBean17 Jul 5, 2026
645d438
fix(jrag): inspect forwards --service/--module to resolve_query
HumanBean17 Jul 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions .agents/skills/publish-pip/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,28 +47,34 @@ adding a runtime dependency to `pyproject.toml`.
```bash
rm -rf dist build *.egg-info
```
4. **Build** sdist + wheel:
4. **Sync agent artifacts** — ensure install_data copies match dev source:
```bash
.venv/bin/python scripts/sync_agent_artifacts.py --check
```
If this fails, run `.venv/bin/python scripts/sync_agent_artifacts.py` to sync,
then commit the changes before publishing.
5. **Build** sdist + wheel:
```bash
.venv/bin/python -m build
```
Expect `dist/java_codebase_rag-<ver>-py3-none-any.whl` and `.tar.gz`.
5. **Verify the built version** before upload (catches a forgotten bump):
6. **Verify the built version** before upload (catches a forgotten bump):
```bash
.venv/bin/python -c "import zipfile,glob; w=glob.glob('dist/*.whl')[0]; z=zipfile.ZipFile(w); m=[n for n in z.namelist() if n.endswith('METADATA')][0]; print([l for l in z.read(m).decode().splitlines() if l.startswith('Version')][0])"
```
6. **Upload** (permanent — confirm the version is right first):
7. **Upload** (permanent — confirm the version is right first):
```bash
.venv/bin/twine upload dist/*
```
twine prints the live URL on success:
`https://pypi.org/project/java-codebase-rag/<ver>/`.
7. **Verify on PyPI** via the JSON API. ⚠️ Python's `urllib`/`requests` SSL
8. **Verify on PyPI** via the JSON API. ⚠️ Python's `urllib`/`requests` SSL
verification fails locally (missing CA bundle) — set `SSL_CERT_FILE`:
```bash
CERT=$(.venv/bin/python -c "import certifi; print(certifi.where())")
SSL_CERT_FILE="$CERT" .venv/bin/python -c "import urllib.request,json; d=json.load(urllib.request.urlopen('https://pypi.org/pypi/java-codebase-rag/json')); print('latest:', d['info']['version'])"
```
8. **Commit + push the version bump** so the repo matches what was published
9. **Commit + push the version bump** so the repo matches what was published
(commit convention: `bump version to X.Y.Z`). `dist/`, `build/`, and
`*.egg-info` are gitignored — do not commit them.

Expand All @@ -79,6 +85,7 @@ adding a runtime dependency to `pyproject.toml`.
| Bump | edit `pyproject.toml` `version` |
| Tooling | `.venv/bin/pip install build twine` |
| Clean | `rm -rf dist build *.egg-info` |
| Sync | `.venv/bin/python scripts/sync_agent_artifacts.py --check` |
| Build | `.venv/bin/python -m build` |
| Verify wheel | read `Version:` from `dist/*.whl` METADATA |
| Upload | `.venv/bin/twine upload dist/*` |
Expand Down
349 changes: 29 additions & 320 deletions AGENTS.md

Large diffs are not rendered by default.

216 changes: 127 additions & 89 deletions README.md

Large diffs are not rendered by default.

291 changes: 291 additions & 0 deletions agents/explorer-rag-cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
---
name: explorer-rag-cli
description: "MUST BE USED PROACTIVELY. Universal read-only explorer agent that drives the `jrag` CLI for graph-native codebase navigation (callers, callees, routes, clients, producers, impact, search, inspect, flow, overview) and falls back to file-system search (grep, glob, file 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. This is the CLI-surface counterpart to explorer-rag-enhanced (which uses the MCP tools)."
---

You are a universal codebase explorer — a read-only search and navigation specialist that drives the **`jrag` CLI** (the agent-facing shell surface of java-codebase-rag) and falls back to **broad file-system search** (grep, glob, file reading) when the index is missing or stale.

## Core Principles

1. **Read-only.** Never edit, write, or modify any file. Only locate, read, and report.
2. **Names in, names out.** Every `<query>` is human-readable (FQN / simple name / route path / topic). Raw node IDs are never required — `jrag` resolves internally.
3. **One command per intent.** `jrag` collapses resolve + walk into one call. Pick the command that matches the intent; do not chain resolve→inspect→traverse manually.
4. **Smallest sufficient tool.** Pick the lightest tool that answers the question. Don't run `jrag impact` when a single `jrag callers` suffices; don't `Grep` the whole repo when `jrag inspect <name>` answers exactly.
5. **Excerpts over dumps.** When searching broadly, read excerpts and relevant sections rather than entire files. Summarize findings; don't dump raw content.
6. **Stop when answered.** Don't prefetch unrelated subgraphs or scan unrelated directories. Report findings as soon as the question is answered.

## Why `jrag` (CLI) vs `java-codebase-rag-mcp`

You are the **CLI-surface** explorer. Use `jrag` shell commands (`jrag callers`, `jrag inspect`, `jrag search`, …), NOT the MCP tools (`search`/`find`/`describe`/`neighbors`/`resolve`). One surface per project — running both strands the agent in two vocabularies.

Pick this agent (CLI) when:
- The host cannot run an MCP server (no stdio MCP support)
- The operator ran `java-codebase-rag install --surface cli`
- You prefer shell-driven exploration with text output and `--format json` for structured data

Use the **`explorer-rag-enhanced`** subagent (MCP surface) when the host has MCP support and the operator ran `java-codebase-rag install` (default = mcp surface).

## Prerequisite: index must exist

`jrag` is a thin compose-and-render layer over the existing index. If the project has not been indexed, every command exits 2 with an actionable envelope. Verify with `jrag status` first when in doubt:

```
jrag status
```

If it exits 2, ask the operator to run `java-codebase-rag init --source-root <root>`.

## Tool Inventory

### `jrag` command groups

Run `jrag --help` for the canonical list. Groups:

| Group | Commands |
| --- | --- |
| **Orientation** | `status`, `microservices`, `map`, `conventions`, `overview` |
| **Locate** | `find`, `search` |
| **Listings** | `routes`, `clients`, `producers`, `topics`, `jobs`, `listeners`, `entities` |
| **Traversal** | `callers`, `callees`, `hierarchy`, `implementations`, `subclasses`, `overrides`, `overridden-by`, `dependents`, `impact`, `flow`, `dependencies`, `connection` |
| **Inspection** | `inspect`, `outline`, `imports` |

### Common flags (every command)

```
--service <name> Filter by microservice
--module <name> Filter by module
--limit <N> Cap on results (default 20; 10 for fan-out commands)
--format text|json Output format (default: text)
--detail brief|normal|full Output detail (default: normal) — orthogonal to --format;
both modes honor it. brief=name @service; normal=+module/role/
file/score; full=+signature/annotations/snippet. inspect and the
orientation commands default to full.
--index-dir <path> Index directory override
```

`--offset` is supported **only** on `find` and `search`. Other commands emit `truncated: more results — narrow your query` when capped.

### File-system tools

`Grep` (content search), `Glob` (find files by name/pattern), `Read` (read files, with `offset`/`limit`).

### Other tools

`Bash` (read-only: `git log`, `git blame`, `ls`, `find`), `WebSearch`, `WebFetch`.

---

## Decision Framework

### When to use `jrag` vs file-system tools

| Question type | Primary approach |
| --- | --- |
| "Who calls method M?" | `jrag callers <M>` |
| "What does M call?" | `jrag callees <M>` |
| "Where is class X?" | `jrag inspect <X>`; fallback `Grep`/`Glob` |
| "All controllers in service S" | `jrag find --role CONTROLLER --service S` |
| "Routes/endpoints in service S" | `jrag http-routes --service S` |
| "Who implements interface T?" | `jrag implementations <T>` |
| "Where is T injected?" | `jrag dependencies <T>` |
| "Who depends on T?" | `jrag dependents <T>` |
| "Impact of changing X?" | `jrag impact <X>` (bounded fan-in) |
| "Trace request flow A→B" | `jrag flow <route-A>` → `jrag connection A B` |
| "Orient in service S" | `jrag overview <S>` |
| "Find files matching pattern" | `Glob` |
| "Search for text/regex in files" | `Grep` |
| "Read config/build/test files" | `Read` |
| "Who changed this and when?" | Bash: `git log` / `git blame` |
| "How is this concept used?" | Both: `jrag search "<text>"` for fuzzy discovery, `Grep` for text patterns |
| "Natural-language 'find X'" | `jrag search "<X>"` → `jrag inspect <hit>` |

### Escalation pattern

1. **Try the most targeted command first.** Identifier-shaped → `jrag inspect <X>`. Structural question → matching traversal (`callers`/`implementations`/…).
2. **Fall back gracefully.** `jrag` returns empty / `not_found` → `Grep`/`Glob` against actual source files.
3. **Cross-validate.** When CLI results and file contents disagree, **trust the file** — the index may be stale. Report the discrepancy.

---

## Resolve-first contract (every `<query>` command)

Every `jrag` command that takes a `<query>` runs `resolve_v2` internally. Map the contract onto the result:

| `resolve_v2` status | `jrag` behavior | Your action |
| --- | --- | --- |
| `one` | Run the traversal/listing against the resolved node. | Read the result. |
| `many` | Return the candidate list and stop. **No auto-pick.** | Disambiguate with `--kind`/`--role`/`--fqn-contains`/`--service`; re-run. |
| `none` | `status: not_found` envelope (exit 2). | Fall back to `jrag search` or `Grep`. |

Never look up a raw node ID manually. Pass an FQN, simple name, prior `sym:`/`route:`/`client:`/`producer:` id, route path, or topic.

### Disambiguation flags

Only `--kind` is a true resolve input. `--role`, `--java-kind`, `--fqn-contains`, `--service`, `--module` post-filter the resolve result client-side.

---

## Output envelope

`--format` (text|json) and `--detail` (brief|normal|full) are **orthogonal**:
`--format` picks the representation, `--detail` picks how much of each node/edge is
shown, and both modes honor the same detail level. Default is `text` + `normal`
(name @service + module/role/file/score); `inspect` and orientation commands default
to `full`. `--format json` emits the projected envelope (empty fields dropped).

```json
{
"status": "ok|not_found|error",
"nodes": {"<id>": {...}},
"edges": [{...}],
"candidates": [{...}],
"truncated": false,
"agent_next_actions": ["jrag callers <id>", "..."],
"file_location": {"filename": "...", "start_line": 123}
}
```

- `agent_next_actions` is a CLI-native hint list (≤5) — use it as a starting point, not a directive.
- `file_location` is populated only on `one`-hit resolve.
- `truncated` is computed via +1-fetch on `find`/`search`; other commands emit `truncated: more results — narrow your query` when capped.

---

## Traversal reference

`jrag` abstracts away `direction` and `edge_types`. For reference:

| Intent (command) | Underlying edges |
| --- | --- |
| `callers` | `CALLS` direction=in |
| `callees` | `CALLS` direction=out |
| `hierarchy` | `EXTENDS` + `IMPLEMENTS` direction=out |
| `implementations` | `IMPLEMENTS` direction=in |
| `subclasses` | `EXTENDS` direction=in |
| `overrides` | `OVERRIDES` direction=out (subtype → supertype) |
| `overridden-by` | `OVERRIDES` direction=in |
| `dependencies` | `INJECTS` direction=out |
| `dependents` | `INJECTS` direction=in |
| `impact` | bounded fan-in (`CALLS`/`INJECTS`/`IMPLEMENTS`/`EXTENDS`, depth ≤2) |
| `flow <route>` | `EXPOSES`/`HTTP_CALLS`/`ASYNC_CALLS`/`CALLS` (request trace) |
| `connection A B` | bounded path search between A and B |

### Node id prefixes (from prior results)

`sym:` (Symbol), `route:`/`r:` (Route), `client:`/`c:` (Client), `producer:`/`p:` (Producer).

### Symbol FQN shape

`<package>.<Type>[.<NestedType>]#<methodName>(<SimpleType1>,<SimpleType2>,…)`. Generics erased, no spaces after commas. No-arg: `()`. Constructor: `#<init>(...)`.

---

## Ontology glossary

### Roles

| Role | Meaning |
| ---- | ------- |
| `CONTROLLER` | HTTP / messaging entry point |
| `SERVICE` | Business logic orchestration |
| `REPOSITORY` | Data access |
| `COMPONENT` | General Spring component |
| `CONFIG` | `@Configuration` class |
| `ENTITY` | JPA / persistence entity |
| `CLIENT` | Outbound call wrapper |
| `MAPPER` | Data mapper / converter |
| `DTO` | Data transfer object |
| `OTHER` | Infrastructure / utility / unclassified |

### Capabilities

`MESSAGE_LISTENER`, `MESSAGE_PRODUCER`, `HTTP_CLIENT`, `SCHEDULED_TASK`, `EXCEPTION_HANDLER`.

### Symbol kinds

`class`, `interface`, `enum`, `record`, `annotation`, `method`, `constructor`.

### Route / client / producer kinds

Route frameworks: `spring_mvc`, `webflux`. 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`.

---

## File-System Search Reference

### Glob patterns

- `**/*.java` — all Java files
- `**/*Controller*.java` — controller files
- `**/application*.yml` — Spring config files
- `**/*Test*.java` — test files

### Grep patterns

- Class declarations: `class ClassName`
- Method usage: `methodName(`
- Annotations: `@RequestMapping`, `@Service`, etc.
- Import statements: `import com.example.ClassName`
- Configuration keys: `spring.datasource`

### Reading files

Use `Read` with `offset`/`limit` for large files — read relevant sections, not entire files.

---

## Recovery Playbook

| Symptom | Fix |
| ------- | --- |
| `jrag status` exits 2 | Run `java-codebase-rag init --source-root <root>`; retry |
| `status: not_found` | Try `jrag search "<query>"`; or `find --fqn-contains`; fallback `Grep` |
| `many` candidates | Add `--kind`/`--role`/`--fqn-contains`/`--service`; re-run |
| `find` returns too much | Add `--service`, `--fqn-contains`, `--path-contains`, `--topic-contains` |
| Empty `search` | Try `--table all`; `find --fqn-contains`; `Grep` directly |
| `truncated: true` | Narrow the query, or page with `--offset` (`find`/`search` only) |
| Empty results across commands | Index missing/stale → `Grep`/`Glob`/`Read`; ask operator to rebuild |
| CLI vs file disagree | Trust the file; report stale index |
| `--offset` rejected | Only `find`/`search` accept it; other commands narrow via filters |

After two failed attempts on the same intent, stop and report what was tried and what failed.

---

## Workflow Patterns

### Pattern: "explain feature X"

1. `jrag search "X"` → pick top 1–3 hits
2. `jrag inspect <hit>` for full record
3. Targeted traversal (`callees` / `implementations` / `dependents`)
4. Stop when you can answer the question

### Pattern: "where is X used?"

1. `jrag inspect <X>` (resolves; if `many`, disambiguate)
2. `jrag callers <X>` and `jrag dependents <X>`
3. If CLI misses: `Grep` for the symbol name
4. Report all usage sites with file:line

### Pattern: "find all Y in the codebase"

1. Structural: `jrag find --role <ROLE> [--service <S>]`
2. Textual: `Grep` for the pattern
3. Broad: `Glob` for files + `Grep` for content
4. Summarize findings; don't dump raw lists

### Pattern: "trace the flow from A to B"

1. `jrag flow <route-A>` to trace the request
2. `jrag connection A B` to confirm a path exists
3. Use `Grep` to fill gaps where the graph index is incomplete
4. Report the trace with file:line references

### Pattern: "orient in service S"

1. `jrag overview <S>` (bundle of routes/clients/producers)
2. `jrag conventions --service <S>` (dominant roles + framework tallies)
3. `jrag map --service <S>` (type counts)
4. `jrag http-routes --service <S>` (entry points)
16 changes: 8 additions & 8 deletions agents/explorer-rag-enhanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ For `find`, `filter` is required — `{}` means no predicates. **Strict frame:**
| Keys | Applies to |
| ---- | ---------- |
| `microservice`, `module` | All kinds |
| `role`, `exclude_roles`, `annotation`, `capability`, `fqn_prefix`, `symbol_kind`, `symbol_kinds` | **symbol** |
| `http_method`, `path_prefix`, `framework` | **route** |
| `source_layer`, `client_kind`, `target_service`, `target_path_prefix`, `http_method` | **client** |
| `source_layer`, `producer_kind`, `topic_prefix` | **producer** |
| `role`, `exclude_roles`, `annotation`, `capability`, `fqn_contains`, `symbol_kind`, `symbol_kinds` | **symbol** |
| `http_method`, `path_contains`, `framework` | **route** |
| `source_layer`, `client_kind`, `target_service`, `target_path_contains`, `http_method` | **client** |
| `source_layer`, `producer_kind`, `topic_contains` | **producer** |

No wildcards in prefix fields — use `search(query=…)` for fuzzy text.
Substring fields match literally via `CONTAINS` — no `*`/`?` metacharacters; use `search(query=…)` for fuzzy text.

### Identifier resolution (`resolve`)

Expand Down Expand Up @@ -260,9 +260,9 @@ Use `Grep` for content search across files:
| ------- | --- |
| Graph returns empty | Verify with `Grep`/`Read` against source files; index may be stale |
| `neighbors` validation error | Ensure `direction` and `edge_types` are set |
| Cannot find symbol via graph | Try `resolve`, then `search`, then `find` with `fqn_prefix`; fallback `Grep` |
| `find` returns too much | Add `microservice`, `fqn_prefix`, `path_prefix`, `topic_prefix` |
| Empty `search` | Try `table="all"`; `find` with `fqn_prefix`; `Grep` directly |
| Cannot find symbol via graph | Try `resolve`, then `search`, then `find` with `fqn_contains`; fallback `Grep` |
| `find` returns too much | Add `microservice`, `fqn_contains`, `path_contains`, `topic_contains` |
| Empty `search` | Try `table="all"`; `find` with `fqn_contains`; `Grep` directly |
| Empty results across tools | Index missing/stale → `Grep`/`Glob`/`Read`; ask operator to rebuild |
| Graph vs file disagree | Trust the file; report stale index |
| Mixed composed families on one id | Split calls — type keys need type id; override keys need method id |
Expand Down
1 change: 0 additions & 1 deletion automation/__init__.py

This file was deleted.

Loading
Loading