Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,13 @@ See [`mcp.json.example`](./mcp.json.example) for the same shape in `.mcp.json` (

### Driving the MCP from an agent

- **[`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md)** — standalone MCP operating manual (copy-paste into `QWEN.md` / `CLAUDE.md` / `AGENTS.md`): five tools, `NodeFilter`, edge taxonomy, required `neighbors` arguments, ontology glossary, recovery playbook, slash-style aliases.
- **[`skills/`](./skills/)** — user-facing navigation and workflow skills for java-codebase-rag consumers. Skills are `SKILL.md` files; agents discover them via slash-names (`/callees`, `/routes`, etc.). See [`propose/active/AGENT-SKILLS-AND-COMMANDS-PROPOSE.md`](./propose/active/AGENT-SKILLS-AND-COMMANDS-PROPOSE.md) for the full Tier 1 + Tier 2 skill set.
- **[`docs/MANUAL-VERIFICATION-CHECKLIST.md`](./docs/MANUAL-VERIFICATION-CHECKLIST.md)** — 7-phase agent-driven verification you run after indexing your real project.
Pick **one** of two options (not both — they cover the same navigation intents):

1. **[`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md)** (recommended for most) — standalone MCP operating manual. Copy-paste the `BEGIN`/`END` block into your project's `QWEN.md`, `CLAUDE.md`, or `AGENTS.md`. Contains: five-tool reference, `NodeFilter` / edge taxonomy, ontology glossary, recovery playbook, and inline slash-style aliases (`/callers`, `/callees`, `/routes`, etc.) as prompt templates. Self-contained — no external file dependencies.

2. **[`skills/`](./skills/)** (for hosts with skill discovery) — 15 shipped `SKILL.md` files. If your MCP host supports skill discovery (Claude Code, Qwen Code, Cursor), the same navigation intents are available as discoverable `/` commands. Tier 1 = deterministic MCP chains (`/callers`, `/callees`, `/routes`, `/controllers`, `/clients`, `/producers`, `/handlers`, `/who-hits-route`, `/implements`, `/injects`, `/nl`). Tier 2 = bounded workflows (`/explain-feature`, `/impact-of`, `/trace-request-flow`, `/mini-map`). See [`skills/README.md`](./skills/README.md) for the full index.

Also: **[`docs/MANUAL-VERIFICATION-CHECKLIST.md`](./docs/MANUAL-VERIFICATION-CHECKLIST.md)** — 7-phase agent-driven verification you run after indexing your real project.

---

Expand All @@ -115,6 +119,10 @@ See [`mcp.json.example`](./mcp.json.example) for the same shape in `.mcp.json` (

Full schemas, `NodeFilter` / `EdgeFilter` semantics, and the hints contract live in [`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md). Edge types and traversal directions are listed in [`docs/EDGE-NAVIGATION.md`](./docs/EDGE-NAVIGATION.md).

### Three-layer architecture

Layer 1 (storage) → Layer 2 (5 MCP tools) → Layer 3 (skills). Navigation skills in [`skills/`](./skills/) wrap the MCP tools into deterministic chains (Tier 1) and bounded workflows (Tier 2). See the [architecture diagram in `skills/README.md`](./skills/README.md#three-layer-architecture).

---

## Configuration
Expand Down Expand Up @@ -156,7 +164,7 @@ Run `java-codebase-rag --help` to list grouped subcommands. Operator playbook wi
| [`docs/CONFIGURATION.md`](./docs/CONFIGURATION.md) | Environment variables, project YAML, graph ontology, brownfield overrides, ignore patterns. |
| [`docs/JAVA-CODEBASE-RAG-CLI.md`](./docs/JAVA-CODEBASE-RAG-CLI.md) | CLI operator playbook: workflows, exit codes, env alignment. |
| [`docs/EDGE-NAVIGATION.md`](./docs/EDGE-NAVIGATION.md) | MCP-traversable edges, directions, dot-key composition. |
| [`skills/`](./skills/) | User-facing skills for java-codebase-rag consumers. Navigation and workflow skills (Tier 1 + Tier 2) planned — see [`propose/active/AGENT-SKILLS-AND-COMMANDS-PROPOSE.md`](./propose/active/AGENT-SKILLS-AND-COMMANDS-PROPOSE.md). |
| [`skills/`](./skills/) | 15 navigation and workflow skills for hosts with skill discovery (alternative to copy-pasting AGENT-GUIDE). See [`skills/README.md`](./skills/README.md). |
| [`docs/MANUAL-VERIFICATION-CHECKLIST.md`](./docs/MANUAL-VERIFICATION-CHECKLIST.md) | 7-phase agent-driven verification after indexing your project. |
| [`docs/CODEBASE_REQUIREMENTS.md`](./docs/CODEBASE_REQUIREMENTS.md) | Assumptions about your Java repo + per-file edit map for non-conforming codebases. |
| [`automation/cursor_propose_only/README.md`](./automation/cursor_propose_only/README.md) | Optional proposal orchestration workflow (single-command autopilot, planning bundles, automated execution/review loops). |
Expand Down
31 changes: 18 additions & 13 deletions docs/AGENT-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,19 +269,24 @@ Returns **edges** with `attrs` (`confidence`, `strategy`, `match`, … on cross-

After two failed attempts on the same intent, stop and report tool name, args, and response snippet.

### Slash-style aliases

- `/nl <text>` → `search({"query":"<text>","limit":8})` then `describe` on best `symbol_id`.
- `/controllers <ms>` → `find({"kind":"symbol","filter":{"microservice":"<ms>","role":"CONTROLLER"}})`.
- `/routes <ms>` → `find({"kind":"route","filter":{"microservice":"<ms>"}})`.
- `/clients <ms>` → `find({"kind":"client","filter":{"microservice":"<ms>"},"limit":100})`.
- `/producers <ms>` → `find({"kind":"producer","filter":{"microservice":"<ms>"},"limit":100})`.
- `/callers <sym_id>` → `neighbors({"ids":"<sym_id>","direction":"in","edge_types":["CALLS"]})`.
- `/callees <sym_id>` → `neighbors({"ids":"<sym_id>","direction":"out","edge_types":["CALLS"]})`.
- `/handlers <route_id>` → `neighbors({"ids":"<route_id>","direction":"in","edge_types":["EXPOSES"]})`.
- `/who-hits-route <route_id>` → `neighbors({"ids":"<route_id>","direction":"in","edge_types":["HTTP_CALLS","ASYNC_CALLS","EXPOSES"]})`.
- `/implements <type_sym_id>` → `neighbors({"ids":"<type_sym_id>","direction":"in","edge_types":["IMPLEMENTS"]})`.
- `/injects <type_sym_id>` → `neighbors({"ids":"<type_sym_id>","direction":"in","edge_types":["INJECTS"]})`.
### Common navigation patterns

These patterns combine the five tools above. Use the decision tree to pick the right starting tool.

| Intent | Tool chain |
| ------ | ---------- |
| Natural-language "find X" | `search(query=…, limit=8)` → `describe(top_hit.symbol_id)` |
| List controllers in service S | `find(kind="symbol", filter={microservice:"S", role:"CONTROLLER"})` |
| List routes in service S | `find(kind="route", filter={microservice:"S"})` |
| List clients in service S | `find(kind="client", filter={microservice:"S"}, limit=100)` |
| List producers in service S | `find(kind="producer", filter={microservice:"S"}, limit=100)` |
| Who calls method M | `resolve` → `neighbors(ids, "in", ["CALLS"])` |
| What does M call | `resolve` → `neighbors(ids, "out", ["CALLS"])` |
| Handler for route R | `neighbors(route_id, "in", ["EXPOSES"])` |
| All inbound to route R | `neighbors(route_id, "in", ["HTTP_CALLS","ASYNC_CALLS","EXPOSES"])` |
| Implementors of interface T | `neighbors(type_id, "in", ["IMPLEMENTS"])` |
| Where is T injected | `neighbors(type_id, "in", ["INJECTS"])` |
| Impact of changing X | `resolve` → `describe` → bounded `neighbors(in, ["CALLS","INJECTS","IMPLEMENTS","EXTENDS"])` depth ≤2 |

### Canonical workflow: "explain feature X"

Expand Down
67 changes: 67 additions & 0 deletions skills/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# skills/ — Layer 3 navigation and workflow skills

High-level intents over the 5-tool MCP (`search` / `find` / `describe` / `neighbors` / `resolve`). Skills are agent-side prompt scaffolding — they are NOT a second MCP API and NOT CLI subcommands.

## Three-layer architecture

```
┌──────────────────────────────────────────────────────────────┐
│ Layer 3 — High-level intents (what the user actually thinks) │
│ /trace-request-flow, /callees, /controllers, /routes, │
│ /impact-of, /mini-map │
│ ───────────────────────────────────────────────────────── │
│ Implementation: SKILL.md in skills/ at project root. │
│ Tier 1 = deterministic chains; Tier 2 = bounded workflows │
│ + /mini-map heuristics. │
├──────────────────────────────────────────────────────────────┤
│ Layer 2 — Composable primitives (the MCP API) │
│ search, find, describe, neighbors, resolve │
├──────────────────────────────────────────────────────────────┤
│ Layer 1 — Storage primitives │
│ Kuzu Cypher + LanceDB tables │
└──────────────────────────────────────────────────────────────┘
```

## Skill index

### Tier 1 — Navigation (deterministic MCP chains)

| Skill | Purpose |
| ----- | ------- |
| [`/nl`](nl/SKILL.md) | Natural-language search into the graph |
| [`/controllers`](controllers/SKILL.md) | List controller classes |
| [`/routes`](routes/SKILL.md) | List HTTP and messaging routes |
| [`/clients`](clients/SKILL.md) | List outbound HTTP clients |
| [`/producers`](producers/SKILL.md) | List outbound async producers |
| [`/callers`](callers/SKILL.md) | Who calls this method (in-process CALLS) |
| [`/callees`](callees/SKILL.md) | What this method calls (in-process CALLS) |
| [`/handlers`](handlers/SKILL.md) | Method that handles a route |
| [`/who-hits-route`](who-hits-route/SKILL.md) | All inbound paths to a route |
| [`/implements`](implements/SKILL.md) | Concrete classes implementing an interface |
| [`/injects`](injects/SKILL.md) | Where a type is injected |

### Tier 2 — Workflow (bounded multi-step)

| Skill | Purpose |
| ----- | ------- |
| [`/explain-feature`](explain-feature/SKILL.md) | Understand how a feature works end-to-end |
| [`/impact-of`](impact-of/SKILL.md) | What breaks if a symbol changes |
| [`/trace-request-flow`](trace-request-flow/SKILL.md) | Follow a request from entry to persistence |
| [`/mini-map`](mini-map/SKILL.md) | Noise-filtered call map for a method |

## Layout

```
skills/
<skill-name>/
SKILL.md ← frontmatter (name + description) + markdown body
README.md ← this file
```

## Relationship to developer skills

Developer workflow skills (propose, pr-review, etc.) live in `.agents/skills/` — they are for contributors working **on** java-codebase-rag. Skills in this directory are for **consumers** using java-codebase-rag to explore their own codebases.

## Versioning

Skills are versioned lockstep with the MCP. When `NodeFilter` keys, `edge_filter` axes, `edge_types`, or `kind` values change, skills are updated in the same PR.
40 changes: 40 additions & 0 deletions skills/callees/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
name: callees
description: Show what a method symbol calls (in-process CALLS). Use when the user asks "what does X call", "callees of X", or "what does X invoke". Argument is a sym: id, or an identifier resolved via resolve.
---

# /callees — Show callees of a method symbol

## Argument contract

Single positional argument: a method **symbol** id (`sym:...` preferred) OR an identifier-shaped string (FQN fragment, method signature) → `resolve(identifier=..., hint_kind="symbol")`.

This skill is for **method symbols**. For inbound traffic to an HTTP route, use `/who-hits-route`. For outbound Feign/HTTP from a method, see optional step 3 below.

## Steps

1. **Resolve.** If the argument starts with `sym:`, use it. Otherwise:
`resolve(identifier=<arg>, hint_kind="symbol")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `search(query=<arg>, limit=5)` and stop if still empty.
2. **In-process callees:**
`neighbors({ids: <sym_id>, direction: "out", edge_types: ["CALLS"]})`.
Render grouped by edge type; show callee `fqn` + `microservice`.
3. **Optional — outbound HTTP (only when user asks about cross-service calls):**
`neighbors({ids: <sym_id>, direction: "out", edge_types: ["DECLARES_CLIENT"]})`
→ for each client id:
`neighbors({ids: <client_id>, direction: "out", edge_types: ["HTTP_CALLS"]})`.
(Async: `DECLARES_PRODUCER` → `ASYNC_CALLS` on producer ids.)

## Worked example

User: /callees ChatController#joinOperator(JoinOperatorRequest)
You: → resolve(identifier="ChatController#joinOperator", hint_kind="symbol")
→ sym:com.bank.chat.core.api.ChatController#joinOperator(JoinOperatorRequest)
→ neighbors({ids: "sym:...", direction: "out", edge_types: ["CALLS"]})
→ returns CALLS edges to in-process service methods
→ (optional step 3) neighbors(out, ["DECLARES_CLIENT"]) on sym id, then HTTP_CALLS from client ids

## Out of scope

- Recursive callees beyond depth 1 (use `/trace-request-flow` or `/mini-map`).
- Noisy CALLS subgraphs on service methods (prefer `/mini-map`; fall back here if the map is too thin).
- Filtering by microservice (compose with `/controllers` if needed).
33 changes: 33 additions & 0 deletions skills/callers/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: callers
description: Show who calls a method symbol (in-process CALLS). Use when the user asks "who calls X", "callers of X", or "what invokes X". Argument is a sym: id or identifier resolved via resolve.
---

# /callers — Show callers of a method symbol

## Argument contract

Single positional argument: a method **symbol** id (`sym:...` preferred) OR an identifier-shaped string (FQN fragment, method signature) → `resolve(identifier=..., hint_kind="symbol")`.

This skill is for **method symbols**. For inbound traffic to an HTTP route, use `/who-hits-route`.

## Steps

1. **Resolve.** If the argument starts with `sym:`, use it. Otherwise:
`resolve(identifier=<arg>, hint_kind="symbol")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `search(query=<arg>, limit=5)` and stop if still empty.
2. **In-process callers:**
`neighbors({ids: <sym_id>, direction: "in", edge_types: ["CALLS"]})`.
Render grouped by caller `fqn` + `microservice`.

## Worked example

User: /callers ChatController#joinOperator(JoinOperatorRequest)
You: → resolve(identifier="ChatController#joinOperator", hint_kind="symbol")
→ sym:com.bank.chat.core.api.ChatController#joinOperator(JoinOperatorRequest)
→ neighbors({ids: "sym:...", direction: "in", edge_types: ["CALLS"]})
→ returns CALLS edges from in-process callers

## Out of scope

- Callers of routes (use `/who-hits-route`).
- Recursive callers beyond depth 1 (use `/impact-of`).
29 changes: 29 additions & 0 deletions skills/clients/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: clients
description: List outbound HTTP clients, optionally filtered by microservice. Use when the user asks "list clients", "show outbound HTTP calls", or "what Feign clients are in X".
---

# /clients — List outbound HTTP clients

## Argument contract

Optional positional argument: microservice name. Omit to list all clients.

## Steps

1. **Find clients.**
- With microservice: `find(kind="client", filter={microservice: <arg>}, limit=100)`.
- Without microservice: `find(kind="client", filter={}, limit=100)`.
2. **Render.** Show each result's `fqn`, `microservice`, `client_kind`, `target_service`, and `id`.
3. **Narrow if needed.** When results are broad, add `client_kind` or `target_service` to the filter.

## Worked example

User: /clients chat-core
You: → find(kind="client", filter={microservice: "chat-core"}, limit=100)
→ returns outbound HTTP client nodes in chat-core
→ e.g. client:ChatServiceClient (feign_method), target_service=chat-service

User: /clients
You: → find(kind="client", filter={}, limit=100)
→ returns all outbound HTTP client nodes
28 changes: 28 additions & 0 deletions skills/controllers/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: controllers
description: List controller classes, optionally filtered by microservice. Use when the user asks "list controllers", "show me controllers in X", or "what controllers are there".
---

# /controllers — List controllers

## Argument contract

Optional positional argument: microservice name. Omit to list all controllers.

## Steps

1. **Find controllers.**
- With microservice: `find(kind="symbol", filter={role: "CONTROLLER", microservice: <arg>})`.
- Without microservice: `find(kind="symbol", filter={role: "CONTROLLER"})`.
2. **Render.** Show each result's `fqn`, `microservice`, and `id`.

## Worked example

User: /controllers chat-core
You: → find(kind="symbol", filter={role: "CONTROLLER", microservice: "chat-core"})
→ returns controller symbols in chat-core microservice
→ e.g. sym:com.bank.chat.core.api.ChatController

User: /controllers
You: → find(kind="symbol", filter={role: "CONTROLLER"})
→ returns all controller symbols across all microservices
51 changes: 51 additions & 0 deletions skills/explain-feature/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: explain-feature
description: Understand how a feature works end-to-end by tracing from entry points through call chains. Use when the user asks "how does X work", "explain feature X", or "walk me through X". Argument is a free-form feature description.
---

# /explain-feature — Understand a feature end-to-end

## Argument contract

Single positional argument: free-form text describing the feature or concept to explain.

## Steps

1. **Locate entry points.**
`search(query=<arg>, limit=8)` → pick top 1–3 hits with strong `symbol_id` fit (role, `symbol_kind` alignment).
2. **Inspect each hit.**
`describe(id=<symbol_id>)` → read `edge_summary` to understand the node's connectivity.
3. **Walk with bounded neighbors.**
For each inspected node, use `neighbors` with **small** `edge_types` sets per step:
- Methods: `neighbors(out, ["CALLS"])` for in-process flow.
- Boundaries: `EXPOSES` for route handlers; `DECLARES_CLIENT` → `HTTP_CALLS` for outbound HTTP; `DECLARES_PRODUCER` → `ASYNC_CALLS` for async.
- Type wiring: `IMPLEMENTS`, `INJECTS` when relevant.
4. **Render.** Synthesize findings into a narrative: entry points → key methods → data flow → cross-service boundaries.

## Stop conditions

- Maximum 3 hops from any entry point.
- Stop when you can answer the user's question.
- Do not prefetch unrelated subgraphs.

## Recursion limit

- Depth ≤ 3 from each entry point.
- Maximum 10 `neighbors` calls total.

## Worked example

User: /explain-feature operator assignment
You: → search(query="operator assignment", limit=8)
→ hit: sym:com.bank.chat.assign.service.OperatorAssignmentService
→ describe(id="sym:...") → edge_summary shows CALLS, INJECTS
→ neighbors(out, ["CALLS"]) → shows delegation to repository and other services
→ neighbors(in, ["IMPLEMENTS"]) → shows concrete implementations
→ synthesize: "OperatorAssignmentService is an interface with two implementations.
The controller calls it via DI. It delegates to OperatorRepository for persistence..."

## Out of scope

- Exact impact analysis (use `/impact-of`).
- Full request flow tracing (use `/trace-request-flow`).
- Noise-filtered call maps (use `/mini-map`).
Loading
Loading