diff --git a/AGENTS.md b/AGENTS.md index 56ba68a..2708351 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,6 +9,19 @@ Create local symlinks if your editor expects the legacy paths: `ln -s .agents .cursor` and `ln -s .agents .claude` (both are gitignored). +### Two audiences, two skill trees + +| Directory | Audience | Purpose | +|-----------|----------|---------| +| **`.agents/skills/`** (`.claude/skills/`, `.cursor/skills/`) | Agents **developing** this repo | propose, plan-prompts, pr-open, pr-review | +| **`skills/`** (project root) | Agents **using** this tool on their own codebase | /callers, /routes, /explain-feature, /impact-of, etc. | + +`.agents/` skills are loaded by the agent working *on* java-codebase-rag source +code. `skills/` are shipped to consumers — they instruct an agent to call the +MCP tools (`search`, `find`, `describe`, `neighbors`, `resolve`) against an +indexed Java codebase. Do not mix the two: never import consumer skills into +`.agents/skills/` or vice versa. + This repo is a **self-contained stdio MCP server** that serves semantic + structural search over a Java codebase. It is a Python project (the indexer and server). It is **not** a Java project — the diff --git a/skills/README.md b/skills/README.md index fb1022e..4a4bc63 100644 --- a/skills/README.md +++ b/skills/README.md @@ -58,6 +58,18 @@ skills/ README.md ← this file ``` +## Skill structure + +Every SKILL.md follows this structure: + +1. **Frontmatter** — `name` and `description` (used by skill discovery) +2. **MCP required** — declares the MCP server dependency and enforces tool usage +3. **Argument contract** — what the skill accepts +4. **Steps** — imperative MCP call chain (each step names the tool to call) +5. **Worked example** — concrete walk-through +6. **Do not** — guardrails against bypassing MCP tools +7. **Out of scope** — boundaries for when to use a different skill + ## 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. diff --git a/skills/callees/SKILL.md b/skills/callees/SKILL.md index 6403eae..585ef91 100644 --- a/skills/callees/SKILL.md +++ b/skills/callees/SKILL.md @@ -5,6 +5,19 @@ description: Show what a method symbol calls (in-process CALLS). Use when the us # /callees — Show callees of a method symbol +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## 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")`. @@ -13,16 +26,9 @@ This skill is for **method symbols**. For inbound traffic to an HTTP route, use ## Steps -1. **Resolve.** If the argument starts with `sym:`, use it. Otherwise: - `resolve(identifier=, hint_kind="symbol")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `search(query=, limit=5)` and stop if still empty. -2. **In-process callees:** - `neighbors({ids: , 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: , direction: "out", edge_types: ["DECLARES_CLIENT"]})` - → for each client id: - `neighbors({ids: , direction: "out", edge_types: ["HTTP_CALLS"]})`. - (Async: `DECLARES_PRODUCER` → `ASYNC_CALLS` on producer ids.) +1. **Resolve.** If the argument starts with `sym:`, use it as the id. Otherwise, call `resolve(identifier=, hint_kind="symbol")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `search(query=, limit=5)` and stop if still empty. +2. **In-process callees.** Call `neighbors` with `ids=`, `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).** Call `neighbors` with `ids=`, `direction="out"`, `edge_types=["DECLARES_CLIENT"]`. For each client id, call `neighbors` with `ids=`, `direction="out"`, `edge_types=["HTTP_CALLS"]`. (Async: `DECLARES_PRODUCER` → `ASYNC_CALLS` on producer ids.) ## Worked example @@ -33,6 +39,13 @@ You: → resolve(identifier="ChatController#joinOperator", hint_kind="symbol") → returns CALLS edges to in-process service methods → (optional step 3) neighbors(out, ["DECLARES_CLIENT"]) on sym id, then HTTP_CALLS from client ids +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. + ## Out of scope - Recursive callees beyond depth 1 (use `/trace-request-flow` or `/mini-map`). diff --git a/skills/callers/SKILL.md b/skills/callers/SKILL.md index 11f89f9..4286121 100644 --- a/skills/callers/SKILL.md +++ b/skills/callers/SKILL.md @@ -5,6 +5,19 @@ description: Show who calls a method symbol (in-process CALLS). Use when the use # /callers — Show callers of a method symbol +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## 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")`. @@ -13,11 +26,8 @@ This skill is for **method symbols**. For inbound traffic to an HTTP route, use ## Steps -1. **Resolve.** If the argument starts with `sym:`, use it. Otherwise: - `resolve(identifier=, hint_kind="symbol")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `search(query=, limit=5)` and stop if still empty. -2. **In-process callers:** - `neighbors({ids: , direction: "in", edge_types: ["CALLS"]})`. - Render grouped by caller `fqn` + `microservice`. +1. **Resolve.** If the argument starts with `sym:`, use it as the id. Otherwise, call `resolve(identifier=, hint_kind="symbol")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `search(query=, limit=5)` and stop if still empty. +2. **In-process callers.** Call `neighbors` with `ids=`, `direction="in"`, `edge_types=["CALLS"]`. Render grouped by caller `fqn` + `microservice`. ## Worked example @@ -27,6 +37,13 @@ You: → resolve(identifier="ChatController#joinOperator", hint_kind="symbol") → neighbors({ids: "sym:...", direction: "in", edge_types: ["CALLS"]}) → returns CALLS edges from in-process callers +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. + ## Out of scope - Callers of routes (use `/who-hits-route`). diff --git a/skills/clients/SKILL.md b/skills/clients/SKILL.md index a5c872e..11de948 100644 --- a/skills/clients/SKILL.md +++ b/skills/clients/SKILL.md @@ -5,15 +5,26 @@ description: List outbound HTTP clients, optionally filtered by microservice. Us # /clients — List outbound HTTP clients +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Optional positional argument: microservice name. Omit to list all clients. ## Steps -1. **Find clients.** - - With microservice: `find(kind="client", filter={microservice: }, limit=100)`. - - Without microservice: `find(kind="client", filter={}, limit=100)`. +1. **Find clients.** Call `find(kind="client", filter={microservice: }, limit=100)` when a microservice is given, or `find(kind="client", filter={}, limit=100)` when listing all. 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. @@ -27,3 +38,10 @@ You: → find(kind="client", filter={microservice: "chat-core"}, limit=100) User: /clients You: → find(kind="client", filter={}, limit=100) → returns all outbound HTTP client nodes + +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. diff --git a/skills/controllers/SKILL.md b/skills/controllers/SKILL.md index 5b8090f..6345fea 100644 --- a/skills/controllers/SKILL.md +++ b/skills/controllers/SKILL.md @@ -5,15 +5,26 @@ description: List controller classes, optionally filtered by microservice. Use w # /controllers — List controllers +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## 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: })`. - - Without microservice: `find(kind="symbol", filter={role: "CONTROLLER"})`. +1. **Find controllers.** Call `find(kind="symbol", filter={role: "CONTROLLER", microservice: })` when a microservice is given, or `find(kind="symbol", filter={role: "CONTROLLER"})` when listing all. 2. **Render.** Show each result's `fqn`, `microservice`, and `id`. ## Worked example @@ -26,3 +37,10 @@ You: → find(kind="symbol", filter={role: "CONTROLLER", microservice: "chat-cor User: /controllers You: → find(kind="symbol", filter={role: "CONTROLLER"}) → returns all controller symbols across all microservices + +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. diff --git a/skills/explain-feature/SKILL.md b/skills/explain-feature/SKILL.md index 937a103..1bf6ec2 100644 --- a/skills/explain-feature/SKILL.md +++ b/skills/explain-feature/SKILL.md @@ -5,21 +5,31 @@ description: Understand how a feature works end-to-end by tracing from entry poi # /explain-feature — Understand a feature end-to-end +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Single positional argument: free-form text describing the feature or concept to explain. ## Steps -1. **Locate entry points.** - `search(query=, limit=8)` → pick top 1–3 hits with strong `symbol_id` fit (role, `symbol_kind` alignment). -2. **Inspect each hit.** - `describe(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. +1. **Locate entry points.** Call `search(query=, limit=8)`. Pick top 1–3 hits with strong `symbol_id` fit (role, `symbol_kind` alignment). +2. **Inspect each hit.** Call `describe(id=)` for each hit. Read `edge_summary` to understand the node's connectivity. +3. **Walk with bounded neighbors.** For each inspected node, call `neighbors` with **small** `edge_types` sets per step: + - Methods: call `neighbors` with `direction="out"`, `edge_types=["CALLS"]` for in-process flow. + - Boundaries: call `neighbors` for `EXPOSES` (route handlers), `DECLARES_CLIENT` → `HTTP_CALLS` (outbound HTTP), `DECLARES_PRODUCER` → `ASYNC_CALLS` (async). + - Type wiring: call `neighbors` for `IMPLEMENTS`, `INJECTS` when relevant. 4. **Render.** Synthesize findings into a narrative: entry points → key methods → data flow → cross-service boundaries. ## Stop conditions @@ -44,6 +54,13 @@ You: → search(query="operator assignment", limit=8) → synthesize: "OperatorAssignmentService is an interface with two implementations. The controller calls it via DI. It delegates to OperatorRepository for persistence..." +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. + ## Out of scope - Exact impact analysis (use `/impact-of`). diff --git a/skills/handlers/SKILL.md b/skills/handlers/SKILL.md index 652db14..06139f8 100644 --- a/skills/handlers/SKILL.md +++ b/skills/handlers/SKILL.md @@ -5,17 +5,27 @@ description: Show the method that handles an HTTP or messaging route. Use when t # /handlers — Show handler method for a route +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Single positional argument: a **route** id (`route:...` preferred) OR an identifier-shaped string (path, METHOD /path) → `resolve(identifier=..., hint_kind="route")`. ## Steps -1. **Resolve.** If the argument starts with `route:` or `r:`, use it. Otherwise: - `resolve(identifier=, hint_kind="route")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `find(kind="route", filter={path_prefix: })` and stop if still empty. -2. **Handler method:** - `neighbors({ids: , direction: "in", edge_types: ["EXPOSES"]})`. - Render the handler method `fqn` + `microservice`. +1. **Resolve.** If the argument starts with `route:` or `r:`, use it directly. Otherwise, call `resolve(identifier=, hint_kind="route")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `find(kind="route", filter={path_prefix: })` and stop if still empty. +2. **Handler method.** Call `neighbors` with `ids=`, `direction="in"`, `edge_types=["EXPOSES"]`. Render the handler method `fqn` + `microservice`. ## Worked example @@ -28,3 +38,10 @@ You: → resolve(identifier="POST /chat/join", hint_kind="route") → route:POST /chat/join → neighbors({ids: "route:...", direction: "in", edge_types: ["EXPOSES"]}) → returns handler method + +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate route ids — always obtain them from `resolve` or `find`. diff --git a/skills/impact-of/SKILL.md b/skills/impact-of/SKILL.md index 3ad5937..eba75ff 100644 --- a/skills/impact-of/SKILL.md +++ b/skills/impact-of/SKILL.md @@ -5,23 +5,31 @@ description: Analyze what breaks if a symbol changes. Use when the user asks "wh # /impact-of — What breaks if this changes +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Single positional argument: a Symbol id (`sym:...` preferred) OR an identifier-shaped string (FQN, simple name) → `resolve(identifier=..., hint_kind="symbol")`. ## Steps -1. **Resolve.** If the argument starts with `sym:`, use it. Otherwise: - `resolve(identifier=, hint_kind="symbol")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `search(query=, limit=5)` and stop if still empty. -2. **Inspect.** - `describe(id=)` → read `edge_summary` and `role` to understand the node's position. -3. **Recursive inbound walk** (depth ≤ 2): - `neighbors({ids: , direction: "in", edge_types: ["CALLS", "INJECTS", "IMPLEMENTS", "EXTENDS"]})`. - For each inbound neighbor that is a method symbol: - `neighbors({ids: , direction: "in", edge_types: ["CALLS", "INJECTS", "IMPLEMENTS", "EXTENDS"]})`. +1. **Resolve.** If the argument starts with `sym:`, use it as the id. Otherwise, call `resolve(identifier=, hint_kind="symbol")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `search(query=, limit=5)` and stop if still empty. +2. **Inspect.** Call `describe(id=)`. Read `edge_summary` and `role` to understand the node's position. +3. **Recursive inbound walk** (depth ≤ 2). Call `neighbors` with `ids=`, `direction="in"`, `edge_types=["CALLS", "INJECTS", "IMPLEMENTS", "EXTENDS"]`. For each inbound neighbor that is a method symbol, call `neighbors` again with `ids=`, `direction="in"`, `edge_types=["CALLS", "INJECTS", "IMPLEMENTS", "EXTENDS"]`. 4. **Route/client impact** (when applicable): - - If the symbol is a method with routes: `neighbors(out, ["EXPOSES"])` → then `neighbors(in, ["HTTP_CALLS", "ASYNC_CALLS"])` on route ids for callers outside the codebase. - - If the symbol declares clients: `neighbors(out, ["DECLARES_CLIENT"])` → `neighbors(out, ["HTTP_CALLS"])` for affected downstream services. + - If the symbol is a method with routes: call `neighbors` with `direction="out"`, `edge_types=["EXPOSES"]`, then call `neighbors` with `direction="in"`, `edge_types=["HTTP_CALLS", "ASYNC_CALLS"]` on route ids for callers outside the codebase. + - If the symbol declares clients: call `neighbors` with `direction="out"`, `edge_types=["DECLARES_CLIENT"]`, then call `neighbors` with `direction="out"`, `edge_types=["HTTP_CALLS"]` for affected downstream services. 5. **Render impact list.** Deduplicate results. Group by: - Direct callers/injectors (depth 1) - Transitive dependents (depth 2) @@ -51,6 +59,13 @@ You: → resolve(identifier="ChatRepository", hint_kind="symbol") → callers of ChatService: ChatController methods → impact: ChatRepository → ChatService → ChatController (depth 2) +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. + ## Out of scope - Exact line-level change impact (use `git diff` + source reading). diff --git a/skills/implements/SKILL.md b/skills/implements/SKILL.md index 7b8337d..c6cc2fb 100644 --- a/skills/implements/SKILL.md +++ b/skills/implements/SKILL.md @@ -5,17 +5,27 @@ description: Show concrete classes that implement an interface. Use when the use # /implements — Concrete implementors of an interface +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Single positional argument: a **type** Symbol id (`sym:...` preferred) OR an identifier-shaped string (FQN, simple name) → `resolve(identifier=..., hint_kind="symbol")`. ## Steps -1. **Resolve.** If the argument starts with `sym:`, use it. Otherwise: - `resolve(identifier=, hint_kind="symbol")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `search(query=, limit=5)` and stop if still empty. -2. **Implementors:** - `neighbors({ids: , direction: "in", edge_types: ["IMPLEMENTS"]})`. - Render each implementor's `fqn` + `microservice`. +1. **Resolve.** If the argument starts with `sym:`, use it as the id. Otherwise, call `resolve(identifier=, hint_kind="symbol")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `search(query=, limit=5)` and stop if still empty. +2. **Implementors.** Call `neighbors` with `ids=`, `direction="in"`, `edge_types=["IMPLEMENTS"]`. Render each implementor's `fqn` + `microservice`. ## Worked example @@ -24,3 +34,10 @@ You: → resolve(identifier="OperatorAssignmentService", hint_kind="symbol") → sym:com.bank.chat.assign.service.OperatorAssignmentService (interface) → neighbors({ids: "sym:...", direction: "in", edge_types: ["IMPLEMENTS"]}) → returns concrete classes implementing the interface + +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. diff --git a/skills/injects/SKILL.md b/skills/injects/SKILL.md index 4c62f8b..a0ad948 100644 --- a/skills/injects/SKILL.md +++ b/skills/injects/SKILL.md @@ -5,17 +5,27 @@ description: Show where a type is injected via dependency injection. Use when th # /injects — Where a type is injected +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Single positional argument: a **type** Symbol id (`sym:...` preferred) OR an identifier-shaped string (FQN, simple name) → `resolve(identifier=..., hint_kind="symbol")`. ## Steps -1. **Resolve.** If the argument starts with `sym:`, use it. Otherwise: - `resolve(identifier=, hint_kind="symbol")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `search(query=, limit=5)` and stop if still empty. -2. **Injection sites:** - `neighbors({ids: , direction: "in", edge_types: ["INJECTS"]})`. - Render each injection site's `fqn` + `microservice` + edge `attrs.mechanism` + `attrs.field_or_param`. +1. **Resolve.** If the argument starts with `sym:`, use it as the id. Otherwise, call `resolve(identifier=, hint_kind="symbol")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `search(query=, limit=5)` and stop if still empty. +2. **Injection sites.** Call `neighbors` with `ids=`, `direction="in"`, `edge_types=["INJECTS"]`. Render each injection site's `fqn` + `microservice` + edge `attrs.mechanism` + `attrs.field_or_param`. ## Worked example @@ -24,3 +34,10 @@ You: → resolve(identifier="OperatorAssignmentService", hint_kind="symbol") → sym:com.bank.chat.assign.service.OperatorAssignmentService → neighbors({ids: "sym:...", direction: "in", edge_types: ["INJECTS"]}) → returns types/methods that inject OperatorAssignmentService + +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. diff --git a/skills/mini-map/SKILL.md b/skills/mini-map/SKILL.md index df6aadf..9c1b873 100644 --- a/skills/mini-map/SKILL.md +++ b/skills/mini-map/SKILL.md @@ -5,6 +5,19 @@ description: Noise-filtered call map for a method. Shows delegation, persistence # /mini-map — Noise-filtered call map for a method +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract - Required: seed id — `sym:` id or identifier-shaped string → `resolve(identifier=..., hint_kind="symbol")`. @@ -15,23 +28,22 @@ description: Noise-filtered call map for a method. Shows delegation, persistence ### Step 1 — Resolve -If the argument starts with `sym:`, use it. Otherwise: -`resolve(identifier=, hint_kind="symbol")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `search(query=, limit=5)` and stop if still empty. +If the argument starts with `sym:`, use it as the id. Otherwise, call `resolve(identifier=, hint_kind="symbol")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `search(query=, limit=5)` and stop if still empty. ### Step 2 — Fetch ordered CALLS -`neighbors({ids: , direction: "out", edge_types: ["CALLS"]})`. +Call `neighbors` with `ids=`, `direction="out"`, `edge_types=["CALLS"]`. Rows are source-ordered (`call_site_line`, `call_site_byte`). After ontology 15, true receiver-failure sites are **not** on `CALLS` — they are `UnresolvedCallSite` nodes. `attrs.resolved=false` on remaining `CALLS` rows means known-receiver-external (JDK/Spring) callees, not receiver failure. ### Step 3 — Optional MCP pre-filter -When the raw CALLS set is large (e.g. > 30 rows), prefer MCP-side filtering over hand-rolled rules: +When the raw CALLS set is large (e.g. > 30 rows), prefer MCP-side filtering over hand-rolled rules. Call `neighbors` again with the appropriate `edge_filter`: -- **Skeleton pass** (delegation hops): `neighbors(out, ["CALLS"], edge_filter={callee_declaring_role: "SERVICE"})`. -- **Trim JDK/low-signal**: `neighbors(out, ["CALLS"], edge_filter={min_confidence: 0.5})` and/or `edge_filter={exclude_callee_declaring_roles: ["OTHER"]}` (blunt — also drops known-external rows; document in output). -- **Collapse identical callees**: `neighbors(out, ["CALLS"], dedup_calls=True)`. -- **Full transcript with unresolved sites**: `neighbors(out, ["CALLS"], include_unresolved=True)` **only when not using `edge_filter`** on the same call (mutual exclusivity). +- **Skeleton pass** (delegation hops): call `neighbors` with `direction="out"`, `edge_types=["CALLS"]`, `edge_filter={callee_declaring_role: "SERVICE"}`. +- **Trim JDK/low-signal**: call `neighbors` with `direction="out"`, `edge_types=["CALLS"]`, `edge_filter={min_confidence: 0.5}` and/or `edge_filter={exclude_callee_declaring_roles: ["OTHER"]}` (blunt — also drops known-external rows; document in output). +- **Collapse identical callees**: call `neighbors` with `direction="out"`, `edge_types=["CALLS"]`, `dedup_calls=True`. +- **Full transcript with unresolved sites**: call `neighbors` with `direction="out"`, `edge_types=["CALLS"]`, `include_unresolved=True` **only when not using `edge_filter`** on the same call (mutual exclusivity). ### Step 4 — Skill heuristics @@ -95,6 +107,13 @@ You: → resolve(identifier="ClientMessageProcessor#process", hint_kind="symbol" READS → …Repository#find… [filtered ~37 edges: ~22 accessors, ~10 JDK/OTHER, ~5 deduped] +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. + ## Out of scope - Cross-service tracing (use `/trace-request-flow`). diff --git a/skills/nl/SKILL.md b/skills/nl/SKILL.md index a0e5354..3fdb9c0 100644 --- a/skills/nl/SKILL.md +++ b/skills/nl/SKILL.md @@ -5,18 +5,28 @@ description: Natural-language search into the graph. Use when the user asks a fu # /nl — Natural-language to graph navigation +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Single positional argument: free-form text describing what to find. ## Steps -1. **Search.** - `search(query=, limit=8)` — review results for strong `symbol_id` fit (role, `symbol_kind`, `microservice` alignment). -2. **Inspect top hit.** - When a result has a `symbol_id`, call `describe(id=)` to get the full record and `edge_summary`. -3. **Stop or walk.** - If the describe answers the question, stop. Otherwise use `neighbors` with relevant `edge_types` from the `edge_summary`. +1. **Search.** Call `search(query=, limit=8)`. Review results for strong `symbol_id` fit (role, `symbol_kind`, `microservice` alignment). +2. **Inspect top hit.** When a result has a `symbol_id`, call `describe(id=)` to get the full record and `edge_summary`. +3. **Stop or walk.** If the describe answers the question, stop. Otherwise call `neighbors` with relevant `edge_types` from the `edge_summary`. ## Worked example @@ -27,6 +37,13 @@ You: → search(query="operator assignment", limit=8) → returns full record with edge_summary showing CALLS, INJECTS edges → agent can now walk with neighbors if needed +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. + ## Out of scope - Structured listing by role or kind (use `/controllers`, `/routes`, etc.). diff --git a/skills/producers/SKILL.md b/skills/producers/SKILL.md index cf601b1..a5fecee 100644 --- a/skills/producers/SKILL.md +++ b/skills/producers/SKILL.md @@ -5,15 +5,26 @@ description: List outbound async producers, optionally filtered by microservice. # /producers — List outbound async producers +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Optional positional argument: microservice name. Omit to list all producers. ## Steps -1. **Find producers.** - - With microservice: `find(kind="producer", filter={microservice: }, limit=100)`. - - Without microservice: `find(kind="producer", filter={}, limit=100)`. +1. **Find producers.** Call `find(kind="producer", filter={microservice: }, limit=100)` when a microservice is given, or `find(kind="producer", filter={}, limit=100)` when listing all. 2. **Render.** Show each result's `fqn`, `microservice`, `producer_kind`, `topic_prefix`, and `id`. ## Worked example @@ -26,3 +37,10 @@ You: → find(kind="producer", filter={microservice: "chat-core"}, limit=100) User: /producers You: → find(kind="producer", filter={}, limit=100) → returns all outbound async producer nodes + +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. diff --git a/skills/routes/SKILL.md b/skills/routes/SKILL.md index efd0cc1..113e0d6 100644 --- a/skills/routes/SKILL.md +++ b/skills/routes/SKILL.md @@ -5,15 +5,26 @@ description: List HTTP and messaging routes, optionally filtered by microservice # /routes — List HTTP and messaging routes +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Optional positional argument: microservice name. Omit to list all routes. ## Steps -1. **Find routes.** - - With microservice: `find(kind="route", filter={microservice: })`. - - Without microservice: `find(kind="route", filter={})`. +1. **Find routes.** Call `find(kind="route", filter={microservice: })` when a microservice is given, or `find(kind="route", filter={})` when listing all. 2. **Render.** Show each result's `fqn` (HTTP method + path), `microservice`, `framework`, and `id`. ## Worked example @@ -26,3 +37,10 @@ You: → find(kind="route", filter={microservice: "chat-assign"}) User: /routes You: → find(kind="route", filter={}) → returns all routes across all microservices + +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`. diff --git a/skills/trace-request-flow/SKILL.md b/skills/trace-request-flow/SKILL.md index 45bf424..cde9676 100644 --- a/skills/trace-request-flow/SKILL.md +++ b/skills/trace-request-flow/SKILL.md @@ -5,27 +5,31 @@ description: Follow a request from HTTP entry point through the call chain to pe # /trace-request-flow — Follow a request end-to-end +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Single positional argument: a route identifier — `route:` id, `METHOD /path` string, or path fragment → `resolve(identifier=..., hint_kind="route")` or `find(kind="route", filter={path_prefix: ...})`. ## Steps -1. **Resolve route.** - - If argument starts with `route:` or `r:`, use it directly. - - Otherwise: `resolve(identifier=, hint_kind="route")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `find(kind="route", filter={path_prefix: })` and stop if still empty. -2. **Handler method.** - `neighbors({ids: , direction: "in", edge_types: ["EXPOSES"]})` → handler method `sym:` id. -3. **Walk call chain** (depth ≤ 4 on methods): - `neighbors({ids: , direction: "out", edge_types: ["CALLS"]})`. - For each callee method: +1. **Resolve route.** If argument starts with `route:` or `r:`, use it directly. Otherwise, call `resolve(identifier=, hint_kind="route")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `find(kind="route", filter={path_prefix: })` and stop if still empty. +2. **Handler method.** Call `neighbors` with `ids=`, `direction="in"`, `edge_types=["EXPOSES"]` to get the handler method `sym:` id. +3. **Walk call chain** (depth ≤ 4 on methods). Call `neighbors` with `ids=`, `direction="out"`, `edge_types=["CALLS"]`. For each callee method: - If it is a SERVICE/COMPONENT method likely to delegate further, recurse one more hop. - If it is a REPOSITORY/MAPPER, classify as persistence and stop on that branch. -4. **Cross-service boundaries:** - At methods with outbound clients: `neighbors(out, ["DECLARES_CLIENT"])` on method id - → `neighbors(out, ["HTTP_CALLS"])` on each client id. - At methods with async producers: `neighbors(out, ["DECLARES_PRODUCER"])` on method id - → `neighbors(out, ["ASYNC_CALLS"])` on each producer id. +4. **Cross-service boundaries.** At methods with outbound clients: call `neighbors` with `direction="out"`, `edge_types=["DECLARES_CLIENT"]` on method id, then call `neighbors` with `direction="out"`, `edge_types=["HTTP_CALLS"]` on each client id. At methods with async producers: call `neighbors` with `direction="out"`, `edge_types=["DECLARES_PRODUCER"]` on method id, then call `neighbors` with `direction="out"`, `edge_types=["ASYNC_CALLS"]` on each producer id. 5. **Render ordered sequence.** Show the flow as: `Route → Handler → Service → ... → Repository / Client / Producer` with edge annotations at boundaries. @@ -53,6 +57,13 @@ You: → resolve(identifier="POST /chat/join", hint_kind="route") → (optional) neighbors(out, ["DECLARES_CLIENT"]) → client ids → Render: POST /chat/join → ChatController#joinOperator → ChatService#join → Repository#save +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate route/symbol ids — always obtain them from `resolve`, `find`, or `search`. + ## Out of scope - Full noise-filtered call map (use `/mini-map` for single-method deep dives). diff --git a/skills/who-hits-route/SKILL.md b/skills/who-hits-route/SKILL.md index 09cb1e6..9191486 100644 --- a/skills/who-hits-route/SKILL.md +++ b/skills/who-hits-route/SKILL.md @@ -5,17 +5,27 @@ description: Show all inbound paths to an HTTP or messaging route (HTTP_CALLS, A # /who-hits-route — All inbound paths to a route +## MCP required + +This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`). + +**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble: + +``` +Q-class: +Pick: Why: +``` + +For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`. + ## Argument contract Single positional argument: a **route** id (`route:...` preferred) OR an identifier-shaped string (path, METHOD /path) → `resolve(identifier=..., hint_kind="route")`. ## Steps -1. **Resolve.** If the argument starts with `route:` or `r:`, use it. Otherwise: - `resolve(identifier=, hint_kind="route")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `find(kind="route", filter={path_prefix: })` and stop if still empty. -2. **All inbound:** - `neighbors({ids: , direction: "in", edge_types: ["HTTP_CALLS", "ASYNC_CALLS", "EXPOSES"]})`. - Render grouped by edge type: +1. **Resolve.** If the argument starts with `route:` or `r:`, use it directly. Otherwise, call `resolve(identifier=, hint_kind="route")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `find(kind="route", filter={path_prefix: })` and stop if still empty. +2. **All inbound.** Call `neighbors` with `ids=`, `direction="in"`, `edge_types=["HTTP_CALLS", "ASYNC_CALLS", "EXPOSES"]`. Render grouped by edge type: - `EXPOSES` → handler method Symbol - `HTTP_CALLS` → Client nodes (with `attrs.match`, `attrs.confidence`) - `ASYNC_CALLS` → Producer nodes (with `attrs.match`, `attrs.confidence`) @@ -28,6 +38,13 @@ You: → resolve(identifier="POST /chat/join", hint_kind="route") → neighbors({ids: "route:...", direction: "in", edge_types: ["HTTP_CALLS", "ASYNC_CALLS", "EXPOSES"]}) → returns EXPOSES from handler method + HTTP_CALLS from clients + ASYNC_CALLS from producers +## Do not + +- Do not answer from training data or general Java knowledge. +- Do not read source files directly when MCP tools can provide the answer. +- Do not skip MCP calls and guess at results. +- Do not fabricate route ids — always obtain them from `resolve` or `find`. + ## Out of scope - In-process callers of a method (use `/callers`).