diff --git a/.claude/agents/implementer.md b/.claude/agents/implementer.md new file mode 100644 index 0000000..cbcaca8 --- /dev/null +++ b/.claude/agents/implementer.md @@ -0,0 +1,32 @@ +--- +name: implementer +description: Implements one PR section from plans/CURSOR-PROMPTS-*.md with strict scope, sentinels, and venv-only Python. +tools: Read, Edit, Write, Grep, Glob, Bash +--- + +You implement a single PR from this repository's plan handoffs. + +## Before coding + +1. Read the assigned PR section in `plans/CURSOR-PROMPTS-*.md` (fenced **Prompt** block). +2. Read the matching section in `plans/PLAN-*.md` when referenced. +3. Respect **Out of scope (do NOT touch)** — if you need a forbidden file, stop and ask. +4. Use only `.venv/bin/python`, `.venv/bin/ruff`, `.venv/bin/pip` (see `.claude/rules/python-venv-only.md`). + +## While implementing + +- Deliverables in listed order; no scope creep or drive-by lint in unrelated files. +- Match named `test_*` from the prompt/plan; update prompt text if you change tests. +- Run the prompt's **`## Tests to run (iteration loop)`** subset during iteration. +- Run sentinel `rg` checks from the prompt; they must be zero on `git diff master..HEAD`. +- MCP handlers must not write to stdout (`server.py` is stdio MCP). + +## Evidence to leave for review + +- Paste the exact pytest subset command and exit code. +- Run manual evidence commands from the prompt when required. +- Do not `git push` unless the user asked. + +## Repo rules + +See @.claude/rules/agent-workflow.md and @.claude/rules/breaking-changes.md. diff --git a/.claude/agents/reviewer.md b/.claude/agents/reviewer.md new file mode 100644 index 0000000..6a64775 --- /dev/null +++ b/.claude/agents/reviewer.md @@ -0,0 +1,34 @@ +--- +name: reviewer +description: Reviews PRs against plan scope; requires pasted pytest subset evidence and green CI; uses [CRITICAL]..[TRIVIAL] / APPROVED format. +tools: Read, Grep, Glob, Bash +--- + +You review pull requests for this repository using the **`pr-review`** skill contract. + +## Checklist (mandatory) + +1. **Scope** — diff matches stated scope; no plan **Out of scope** leaks. +2. **Sentinels** — if the task prompt listed `rg` patterns, confirm zero hits on `git diff master..HEAD`. +3. **Iteration subset** — PR thread must paste the **exact** pytest command from **`## Tests to run (iteration loop)`** plus exit code or pass summary. Reject checkbox-only claims. +4. **CI merge gate** — link to a **green** `test` workflow run on the PR commit (full `pytest tests` when code changed; docs-only may skip pytest but job must be green). +5. **Manual evidence** — reproduce plan-required commands when listed. + +## Finding format + +Use severity prefixes so automation can parse reviews: + +- `[CRITICAL] ...` +- `[HIGH] ...` +- `[MEDIUM] ...` +- `[LOW] ...` +- `[TRIVIAL] ...` + +When no actionable issues remain, respond with **`APPROVED`** on its own line (optionally after a short summary). + +## References + +- Skill: @.claude/skills/pr-review/SKILL.md +- Workflow: @.claude/rules/agent-workflow.md + +Do not run `gh auth status`. Do not approve merge without both subset evidence (when applicable) and green CI. diff --git a/.claude/rules/agent-workflow.md b/.claude/rules/agent-workflow.md new file mode 100644 index 0000000..d3c0b90 --- /dev/null +++ b/.claude/rules/agent-workflow.md @@ -0,0 +1,143 @@ +# Agent workflow + +## Investigate before editing + +For any non-trivial change, read the relevant doc first instead of +inferring from code: + +- Behaviour / public surface → `README.md`. +- Brownfield assumptions, role/capability tuning → `CODEBASE_REQUIREMENTS.md`. +- In-flight design proposes → **`propose/*.md` at the root of `propose/`** + (not under `propose/completed/`). **List or search** for current names. +- Why current design exists → `propose/completed/` and `plans/completed/`. +- Testing philosophy → `tests/README.md`. +- In-flight multi-PR scope → **`plans/*.md` at the root of `plans/`** + (not under `plans/completed/`). Rule files are not a live catalog; **list + or search `plans/`** for active `PLAN-*.md` / `CURSOR-PROMPTS-*.md`. + Finished plans and prompt templates → `plans/completed/`. + +## Propose-then-implement culture + +The repo has a strong "propose then implement" culture +(`propose/`, `plans/`). For non-trivial features: + +1. Drop a short markdown propose under `propose/` describing scope, + schema impact, reindex requirement, and tests touched. +2. For multi-PR efforts, add a matching `plans/PLAN-.md` with + per-PR sections, then `plans/CURSOR-PROMPTS-.md` with the + per-PR agent execution prompts (Cursor and Claude Code). +3. Reference the propose / plan from the PR description. +4. Move propose into `propose/completed/` (or plan into + `plans/completed/`) once the *whole* effort is landed — not after + each PR. + +Skip this for clearly-bounded fixes (one-file bugs, doc edits, test +loosening). Use judgement. + +## Per-PR task contract (agent handoffs) + +When you're given a per-PR task prompt from `plans/CURSOR-PROMPTS-*.md`: + +- **Scope is binding.** The "Out of scope (do NOT touch)" list is a + hard constraint, not a guideline. Sentinel grep patterns the prompt + lists must return zero on `git diff master..HEAD`. +- **Implement in the listed order.** Do not reshape the PR or roll + multiple PRs together. +- **Match named tests verbatim.** When the plan §4 table lists + `test__`, that is the exact name to use. If you + add, drop, or rename tests, update the plan/prompt text in the same + change so reviewers are not chasing a stale list. +- **No drive-by lint fixes.** Removing an unused `import` in a file + the PR doesn't otherwise touch is still a scope leak. If a file + isn't in the deliverables list, don't touch it. +- **PR description must include**: scope statement, manual evidence + (with the exact command from the prompt), and any intentional design + divergences from sibling PRs called out explicitly so the reviewer + doesn't flag them as bugs. + +## Editing rules + +- Respect `.claude/rules/breaking-changes.md`: no compatibility + shims, no deprecation cycles. +- One source of truth for ontology values lives in + `java_ontology.py`. Don't sprinkle role / capability / client-kind / + strategy / match string literals across other modules. +- Schema changes that affect the Lance index or Kuzu graph need a + matching update to the README "Re-index required" callout. Bump + `ontology_version` when enrichment semantics change. The current + version is **14**. +- Brownfield is a first-class surface: any new auto-detection + (route, role, capability, http client, async producer) must + compose with the matching `BrownfieldOverrides` layer. Last writer + wins (outermost layer overrides earlier ones), with one explicit + exception: caller-side `HTTP_CALLS` / `ASYNC_CALLS` use option-(b) + *replacement* rather than union when any brownfield layer fires + on a method (single network packet → single edge). See + `plans/completed/PLAN-TIER1B-COMPLETION.md` § "Caller-side composition + divergence". +- Kuzu's Python binder rejects `dict` for `MAP` columns. Store all + map-shaped graph_meta data (`routes_by_framework`, + `routes_by_layer`, `http_calls_by_strategy`, + `async_calls_by_strategy`, etc.) as `STRING` JSON blobs and decode + in `kuzu_queries.meta()`. +- `server.py` is a stdio MCP server: anything reachable from a tool + handler must not write to **stdout** (that's the JSON-RPC + transport). Diagnostics go to stderr. +- Tool `description=` strings and `_INSTRUCTIONS` in `server.py` are + read by LLM clients to choose tools — treat them as part of the + contract, not freeform docs. + +## Validate + +- `.venv/bin/ruff check .` — fix or justify warnings. +- `.venv/bin/python -m pytest tests -v` — must pass without `JAVA_CODEBASE_RAG_RUN_HEAVY`. + Expect skips only where tests document env gating (see `tests/README.md`). + Each plan may add tests; match the active plan if it cites a count. +- Exception for isolated automation workflow changes: if edits are limited to + `automation/cursor_propose_only/**` (plus optional docs references to that + workflow), targeted validation is enough: + - `.venv/bin/ruff check .` + - `.venv/bin/python -m pytest automation/cursor_propose_only/tests -q` +- For schema or ranking work, also run with + `JAVA_CODEBASE_RAG_RUN_HEAVY=1` locally (slow; downloads models). +- For graph builder changes, also rebuild a fixture and inspect + `java-codebase-rag meta` (or `GraphMetaOutput` from the same helper) to confirm new counters wire up: + ```bash + rm -rf /tmp/check && .venv/bin/python build_ast_graph.py \ + --source-root tests/bank-chat-system --kuzu-path /tmp/check --verbose + ``` + +## Commit and PR + +- Commit messages: present tense, imperative, lowercase first word, + matching existing style (e.g. `fixed call graph review D6`, + `applied fixes for call graph layer`). +- One logical change per commit when feasible. +- Branch names: + - `cursor/` — Cursor-agent work + - `feat/` — landed-feature work (e.g. `feat/b2b-http-async-edges`) + - `plan/` — in-progress plan / propose drafts + - `chore/` — repo hygiene (docs, tooling, deps) +- PR body should reference any propose / plan it implements, list + user-visible behaviour changes, and call out reindex / env-var / + ontology bumps explicitly. +- Never push directly to `master`. + +## Don't + +- Don't run `gh auth status` or otherwise inspect credentials. +- Don't widen the public surface "just in case" — every new tool, + env var, or schema column adds a re-index burden on users. +- Don't special-case the `tests/bank-chat-system/` fixture in + production code. If a test needs it, the test is wrong (see + `tests/README.md`). +- Don't tighten loose test assertions (`>= 1`, `len(...) >= N`, + `key in result`) into exact counts to chase a number — they are + intentionally loose. +- Don't add a hard dependency on `cocoindex` outside + `java_index_flow_lancedb.py` / the `java-codebase-rag` lifecycle (`init` / + `increment` / `reprocess` / `erase`) path. +- Don't introduce a parallel `*Overrides` class when extending + brownfield support. `BrownfieldOverrides` already holds route, + role, capability, http client, and async producer dicts — extend + it in place. diff --git a/.claude/rules/breaking-changes.md b/.claude/rules/breaking-changes.md new file mode 100644 index 0000000..83657b1 --- /dev/null +++ b/.claude/rules/breaking-changes.md @@ -0,0 +1,5 @@ +# Breaking changes and compatibility + +- **Breaking changes are always allowed.** Do not keep compatibility with prior versions, external consumers, or hypothetical "users" of this repo unless the current task explicitly asks for a compatibility layer. + +- Prefer straightforward removals and schema or API updates over deprecation periods, dual code paths, shims, or version branching unless there is a clear, stated need in the task at hand. diff --git a/.claude/rules/project-overview.md b/.claude/rules/project-overview.md new file mode 100644 index 0000000..0454cd3 --- /dev/null +++ b/.claude/rules/project-overview.md @@ -0,0 +1,72 @@ +# Project overview + +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 `tests/bank-chat-system/` tree is fixture data, not code to +modify. + +Treat README and the markdown docs as the source of truth for +behaviour, schemas, env vars, ranking, edges, tool defaults, and +ontology. **Do not copy that content into rules** — read it directly +when needed. + +## Where to look + +- `README.md` — feature surface, env vars, ranking, capabilities, + MCP tools (`search` / `find` / `describe` / `neighbors` / `resolve`; response + `hints` + pagination echo on locate tools — see README), `java-codebase-rag` CLI, + "Re-index required" callouts. The current + `ontology_version` is **14** (`EDGE_SCHEMA` in `java_ontology.py`; material `OVERRIDES` Symbol→Symbol edges: subtype + instance method → supertype declaration with matching `signature`, one + `IMPLEMENTS`/`EXTENDS` hop; valid `neighbors` `EdgeType`). Builds on v12 + (`@CodebaseHttpClient` rename + shared `CodebaseHttpMethod` enum; inbound + `@CodebaseHttpRoute` replaces same-method built-in HTTP rows; still + `@CodebaseAsyncRoute` wins over same-method `@KafkaListener`; `Client` nodes, + `DECLARES_CLIENT`, `find(kind="client")`, HTTP_CALLS / ASYNC_CALLS caller edges, + brownfield composition from earlier bumps). Earlier ontology bumps are described + inline in the README's callouts list. +- `CODEBASE_REQUIREMENTS.md` — Java-repo assumptions and per-file + map of what to edit when a target tree doesn't match defaults. +- `tests/README.md` — testing philosophy. +- `propose/` — design proposes. **In-flight** proposes are **`*.md` + at the root of `propose/`** (not under `propose/completed/`). + **`propose/completed/`** — landed work and rationale for current code. + **List or search this tree** for current filenames; do not rely on + enumerated copies in rules. +- `plans/` — longer-form multi-PR plans (`PLAN-*.md`) and + **`CURSOR-PROMPTS-*.md`** for per-PR agent handoffs (Cursor and Claude Code). + Top-level `*.md` here are active or in-progress efforts. **`plans/completed/`** — + finished plans and completed prompt sets (templates). Same rule: **open + the directory**, don't cache a mental file list from here. +- `.claude/rules/breaking-changes.md` — the no-back-compat policy. + +## File map (top of repo) + +| File | Role | +|------|------| +| `server.py` | MCP stdio server. Every `@mcp.tool` lives here. | +| `search_lancedb.py` | Vector / hybrid / graph-expanded search; ranking. | +| `build_ast_graph.py` | Tree-sitter → Kuzu graph builder (full rebuild). Owns `pass1`–`pass6` (`pass5` emits `HTTP_CALLS` / `ASYNC_CALLS` caller edges; `pass6_match_edges` resolves cross-service / intra-service / ambiguous / phantom / unresolved match outcomes — ontology 7). | +| `kuzu_queries.py` | Read-only Cypher helpers used by the server. Includes `meta()` decoder for the Kuzu MAP-as-STRING JSON-blob columns. | +| `ast_java.py` | Tree-sitter Java parsing, role/capability inference, `_string_value_atoms` helper (shared by route/client/producer extractors), `_collect_outgoing_calls` for caller-side detection. | +| `graph_enrich.py` | `module` / `microservice` resolution, `BrownfieldOverrides` (route + role + capability + http client + async producer), meta-annotation walk, `resolve_routes_for_method` / `resolve_http_client_for_method` / `resolve_async_producer_for_method`. | +| `java_ontology.py` | Source of truth for `VALID_ROLES`, `VALID_CAPABILITIES`, `VALID_CLIENT_KINDS`, `VALID_HTTP_CALL_STRATEGIES`, `VALID_ASYNC_CALL_STRATEGIES`, `VALID_HTTP_CALL_MATCHES`. | +| `chunk_heuristics.py` | Query-time chunk hints (no AST / no re-index). | +| `mcp_hints.py` | MCP v2 road-sign `hints` catalog (`generate_hints`; locked v1 templates in `propose/completed/HINTS-ROAD-SIGNS-PROPOSE.md`). | +| `index_common.py` | Embedding config (no CocoIndex dep). | +| `java_index_flow_lancedb.py` | CocoIndex flow (used by `java-codebase-rag init` / `increment` / `reprocess` / `erase`). | +| `java_index_v1_common.py` | Shared file walker / exclude patterns. | +| `path_filtering.py` | Layered ignore patterns (`.gitignore`-style; PR-C / B5). Reused by indexer + graph build. | +| `pr_analysis.py` | `java-codebase-rag analyze-pr` helpers (PR-B / B4) — diff parsing, hunk-to-symbol mapping. | +| `mcp.json.example` | Template for `.mcp.json`. | + +## Test layout + +- `tests/conftest.py` — session-scoped Kuzu graph fixture. +- `tests/bank-chat-system/` — deterministic Java corpus (fixture, not production model). +- `tests/fixtures/call_graph_smoke/` — mini Maven tree calibrated against the call-graph resolver. +- `tests/fixtures/brownfield_route_stubs/` — `@CodebaseRoute` / `@CodebaseRoutes` source stubs (PR-A3). +- `tests/fixtures/brownfield_client_stubs/` — `@CodebaseHttpClient` / `@CodebaseHttpClients` / `@CodebaseProducer` / `@CodebaseProducers` source stubs (PR-D2). +- `tests/fixtures/http_caller_smoke/` — Feign + RestTemplate + KafkaTemplate + WebClient + StreamBridge fixture for caller-side detection (PR-D1). +- Heavy e2e tests gated behind `JAVA_CODEBASE_RAG_RUN_HEAVY=1`. diff --git a/.claude/rules/python-venv-only.md b/.claude/rules/python-venv-only.md new file mode 100644 index 0000000..2889e8d --- /dev/null +++ b/.claude/rules/python-venv-only.md @@ -0,0 +1,10 @@ +# Python Environment Rule + +- Use only the repository `.venv/bin/python` for Python commands (repo root). +- Use only `.venv/bin/pip` for package install and dependency commands. +- Do not use system `python`, `python3`, `pip`, or `pip3` for this repo unless you have explicitly activated `.venv` and that is what those resolve to. +- When running tests, linters, or scripts, invoke the `.venv/bin` executables directly. +- Examples: + - `.venv/bin/python -m pytest tests -q` + - `.venv/bin/ruff check .` + - `.venv/bin/pip install -r requirements.txt` diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..ec46029 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json.schemastore.org/claude-code-settings.json", + "permissions": { + "allow": [ + "Bash(.venv/bin/python *)", + "Bash(.venv/bin/ruff *)", + "Bash(.venv/bin/pip *)", + "Bash(gh *)", + "Read(./**)", + "Edit(./**)" + ], + "deny": [ + "Bash(git push *)", + "Read(./.env)", + "Read(./.env.*)" + ] + } +} diff --git a/.claude/skills/java-codebase-explore/SKILL.md b/.claude/skills/java-codebase-explore/SKILL.md new file mode 100644 index 0000000..e5a0843 --- /dev/null +++ b/.claude/skills/java-codebase-explore/SKILL.md @@ -0,0 +1,16 @@ +--- +name: java-codebase-explore +description: >- + Explore an unfamiliar Java microservices codebase indexed by java-codebase-rag MCP. + Use for "explore this codebase", "map the call graph", "onboard onto this code", + "plan a change to service", "write a propose doc for redesign". Strategy guide only; + pair with docs/AGENT-GUIDE.md for exact MCP tool shapes. Not for routine PR review + (use pr-review skill). +disable-model-invocation: false +--- + +# java-codebase-explore + +Canonical exploration strategy lives in the shared doc below. Read it when this skill activates. + +@docs/skills/java-codebase-explore.md diff --git a/.claude/skills/plan-project-scope/SKILL.md b/.claude/skills/plan-project-scope/SKILL.md new file mode 100644 index 0000000..c5a4b4b --- /dev/null +++ b/.claude/skills/plan-project-scope/SKILL.md @@ -0,0 +1,165 @@ +--- +name: plan-project-scope +description: Write high-quality implementation plans for this repository using the merged plan format. Use when creating, updating, or reviewing files under `plans/`, splitting work into multiple PRs, or generating per-PR execution contracts. +disable-model-invocation: true +--- + +# Plan Skill + +Author implementation plans that match this repo's merged style (`PLAN-*`) and stay execution-ready for agent handoff. + +## When to use + +Use this skill when: +- the user asks for a new plan file in `plans/` +- an existing plan needs restructuring or deeper execution detail +- a proposal is approved and now needs a multi-PR delivery split +- the user asks to create per-PR execution prompts/contracts + +Do not use this skill for one-file fixes, tiny docs edits, or direct implementation requests with no planning phase. + +## Input contract + +Before drafting a plan, confirm: +1. The proposal or problem statement this plan implements. +2. Whether this is a single PR or multi-PR rollout. +3. Any fixed constraints (out-of-scope, required tests, branch strategy). + +If the user already provided these, proceed without extra questions. + +## Required repo context + +Read before writing: +1. `README.md` (public surface, env vars, ontology/reindex impact) +2. `CODEBASE_REQUIREMENTS.md` (brownfield and source assumptions) +3. Relevant active/completed docs under `plans/` and `propose/` +4. Target implementation files only as needed + +## Quality bar from merged plan PRs + +Strong plans in this repo consistently include: +- upfront **Status** and dependency context (`Depends on`, if applicable) +- a clear **Goal** section with concrete expected outcomes +- explicit **Principles (do not relitigate in review)** to freeze key decisions +- a **PR breakdown overview table** (scope, ontology bump, areas of concern, tests, dependency order) +- **Areas of concern column:** short **risk/review lens** (what to double-check or where coupling is likely). **Not** a module allowlist, **not** exhaustive, and **not** a substitute for the per-PR **File-by-file changes** section (that section remains the touch-scope contract) +- per-PR sections with: + - file-by-file changes + - named tests (verbatim test function names where possible) + - definition of done + - implementation step checklist +- explicit **Cross-PR risks and mitigations** +- explicit **Out of scope** +- whole-plan done definition and optional landing tracking + +## Default plan structure + +Use this structure unless the user requests a different format: + +```markdown +# Plan: + +Status: **active (planning)**. This plan implements +[`propose/-PROPOSE.md`](../propose/-PROPOSE.md). + +Depends on: . + +## Goal +- +- + +## Principles (do not relitigate in review) +- +- + +## PR breakdown - overview +| PR | Scope | Ontology bump | Areas of concern | Test buckets | Independent of | +| --- | --- | --- | --- | --- | --- | +| PR-X1 | ... | ... | ... | ... | ... | + +Landing order: **X1 -> X2 -> X3**. + +## Resolved design decisions +| Topic | Decision | +| --- | --- | +| ... | ... | + +--- + +# PR-X1 - +## File-by-file changes +### 1. `path/to/file.py` +- <changes> + +## Tests for PR-X1 +1. `test_name_1` +2. `test_name_2` + +## Definition of done (PR-X1) +- <checklist> + +## Implementation step list +| # | Step | File(s) | Done when | +| - | - | - | - | +| 1 | ... | ... | ... | + +--- + +# Cross-PR risks and mitigations +| # | Risk | Severity | Mitigation | +| --- | --- | --- | --- | +| 1 | ... | ... | ... | + +# Out of scope +- <non-goals> + +# Whole-plan done definition +1. <condition> +2. <condition> + +# Tracking +- `PR-X1`: _pending_ +- `PR-X2`: _pending_ +``` + +## Rules while authoring + +- Prefer concrete, testable statements over high-level intentions. +- Keep PR scopes independent when possible; state landing order explicitly. +- Name tests exactly when feasible; avoid vague "add tests". +- Call out ontology bump and re-index impact for schema/enrichment changes. +- Keep "Out of scope" strict; use it to prevent scope creep during implementation. +- Treat **Areas of concern** as **heads-up text for reviewers** (coupling, regression risk, semantic hotspots). Do **not** phrase it as “only these modules” — honest implementation may touch adjacent files; when that happens, update the **File-by-file changes** list and **Out of scope** so the contract stays clear. +- Do not add compatibility shims unless explicitly requested. + +## Per-PR execution prompt option + +If the user wants agent-ready per-PR prompts, add a companion file: +- `plans/CURSOR-PROMPTS-<TOPIC>.md` + +Each PR prompt should include: +- branch/base +- in-scope deliverables +- out-of-scope guardrails +- pytest commands and evidence expectations (avoid hard totals that go stale) +- definition of done and PR title convention + +Use **any** completed **`plans/completed/CURSOR-PROMPTS-*.md`** as the structural reference (pick one that matches the effort’s shape). + +## Naming and placement + +- Plan files live in `plans/` as `PLAN-<TOPIC>.md` (uppercase topic). +- Move completed plans to `plans/completed/` after full rollout lands. + +## Final checklist + +- [ ] Plan has status, goal, principles, PR breakdown, risks, out-of-scope, done definition +- [ ] Every PR section has file-level scope and tests +- [ ] Ontology/reindex implications are explicit when relevant +- [ ] Implementation order is explicit and dependency-safe +- [ ] Plan is execution-ready without re-deriving design + +## Additional resources + +- See [reference.md](reference.md) for style rules distilled from merged PRs. +- See [examples.md](examples.md) for reusable section snippets. diff --git a/.claude/skills/plan-project-scope/examples.md b/.claude/skills/plan-project-scope/examples.md new file mode 100644 index 0000000..7c036bd --- /dev/null +++ b/.claude/skills/plan-project-scope/examples.md @@ -0,0 +1,71 @@ +# Plan Snippets + +Use these snippets as copy-ready scaffolding. + +## 1) Status header + +```markdown +Status: **active (planning)**. This plan implements +[`propose/TOPIC-PROPOSE.md`](../propose/TOPIC-PROPOSE.md) +as a multi-PR sequence. This file is plan-only and does not implement code. +``` + +## 2) PR overview table + +```markdown +## PR breakdown - overview + +| PR | Scope | Ontology bump | Areas of concern | Test buckets | Independent of | +| --- | --- | --- | --- | --- | --- | +| PR-X1 | schema + extraction | 9 -> 10 | graph DDL vs writer drift; extraction edge cases | extraction + schema | prerequisite only | +| PR-X2 | matcher integration | none | ambiguous matches; query-layer churn | regression + continuity | PR-X1 | +| PR-X3 | MCP tool + docs | none | tool contract vs docs drift; operator confusion | tool filters + docs | PR-X1 | + +Landing order: **X1 -> X2 -> X3**. +``` + +The **Areas of concern** cells are **review hints** (risks, coupling), not a filename allowlist and not the authority on what may be edited — use the per-PR **File-by-file changes** section for that. + +## 3) Per-PR section skeleton + +```markdown +# PR-X1 - <title> + +## File-by-file changes + +### 1. `build_ast_graph.py` +- Add schema DDL for new node/edge table. +- Wire create/drop lifecycle. + +### 2. `tests/test_topic.py` +- Add targeted tests for extraction semantics. + +## Tests for PR-X1 +1. `test_case_one` +2. `test_case_two` + +## Definition of done (PR-X1) +- Schema persists and is queryable. +- New tests pass with full suite. +``` + +## 4) Risk table + +```markdown +# Cross-PR risks and mitigations + +| # | Risk | Severity | Mitigation | +| --- | --- | --- | --- | +| 1 | Extraction/matcher drift | high | lock with parity regression tests | +| 2 | Tool contract drift | medium | explicit filter tests and DTO checks | +``` + +## 5) Out-of-scope contract + +```markdown +# Out of scope + +- Companion tools not required for this rollout. +- Adjacent schema redesign not required by this proposal. +- Runtime integrations outside current static-analysis scope. +``` diff --git a/.claude/skills/plan-project-scope/reference.md b/.claude/skills/plan-project-scope/reference.md new file mode 100644 index 0000000..a9aab7a --- /dev/null +++ b/.claude/skills/plan-project-scope/reference.md @@ -0,0 +1,45 @@ +# Plan Style Reference (Repo-grounded) + +This reference distills patterns from **merged multi-PR plans** in this repo. **Do not cache example filenames from here** — open **`plans/completed/`** (and root **`plans/`** for in-flight work) for current `PLAN-*.md` / `CURSOR-PROMPTS-*.md` examples; match their section depth and tables, not a particular PR number. + +## Non-negotiables + +1. **Plan-only clarity** + - State when a PR is docs/planning only. +2. **Execution-ready detail** + - A contributor should implement without re-deriving architecture. +3. **Scope control** + - Out-of-scope section must be explicit and enforceable. +4. **Test contract** + - Provide named tests and expected validation commands. +5. **Dependency clarity** + - State prerequisites and PR landing order. + +## Recommended section order + +1. Status + proposal link + dependencies +2. Goal +3. Principles (frozen decisions) +4. PR overview table +5. Resolved design decisions +6. Per-PR sections (files/tests/DoD/steps) +7. Cross-PR risks + mitigations +8. Out of scope +9. Whole-plan done definition +10. Tracking + +## Writing patterns that work well + +- Use "do not relitigate in review" for locked design constraints. +- Use per-PR test names to avoid ambiguity during implementation. +- Use "Definition of done" per PR plus overall done definition. +- Use small "implementation step list" tables for deterministic execution. +- Include explicit non-goals for adjacent tempting work. + +## Anti-patterns + +- "Add tests" without naming concrete test cases. +- Mixing multiple PR scopes into one section. +- Omitting dependency order for multi-PR plans. +- Vague risk sections with no mitigation actions. +- Missing ontology/reindex notes when schema changes are planned. diff --git a/.claude/skills/plan-prompts/SKILL.md b/.claude/skills/plan-prompts/SKILL.md new file mode 100644 index 0000000..5ad5414 --- /dev/null +++ b/.claude/skills/plan-prompts/SKILL.md @@ -0,0 +1,148 @@ +--- +name: plan-prompts +description: Generate per-PR agent execution prompts in `plans/CURSOR-PROMPTS-*.md` from an existing `plans/PLAN-*.md`. Each prompt must include `## Tests to run (iteration loop)` (pytest file subset + rationales) between Deliverables and Tests per the iteration convention in `tests/README.md`. Use when the user asks to split implementation into PR prompts for Cursor or Claude Code with strict in-scope/out-of-scope guardrails. +disable-model-invocation: true +--- + +# Plan Prompts Skill + +Create execution-ready agent prompts for each PR defined in a plan (Cursor and Claude Code). + +## When to use + +Use this skill when: +- the user asks for `plans/CURSOR-PROMPTS-*.md` +- a `PLAN-*.md` exists and needs per-PR executable prompts +- implementation should be delegated PR-by-PR with tight scope control + +Do not use this skill if there is no plan yet. Write/update the plan first. + +## Required inputs + +Before writing prompts, confirm: +1. Source plan file path (for example `plans/PLAN-XYZ.md`). +2. PR list and landing order from the plan. +3. Any fixed constraints (branch naming, files or areas not to touch). + +If already present in the plan, do not ask again. + +## Source references to read + +Always read: +1. **One** structural template from **`plans/completed/CURSOR-PROMPTS-*.md`** (pick a completed handoff similar in size or topic; if unsure, open the directory and choose any full example). +2. The target **`plans/PLAN-*.md`** +3. **`tests/README.md`** for merge gate + iteration-loop expectations +4. **`README.md`** for current public contract terms when prompts mention tooling/schema + +## Output file contract + +Write one file: +- `plans/CURSOR-PROMPTS-<TOPIC>.md` + +Include: +- status line +- one section per PR in plan landing order +- `Branch`, `Base`, `Plan section` +- `@-files` list for context attachment +- copy-paste `Prompt` block with strict scope contract + +## Per-PR prompt requirements + +Each PR prompt must include all of: +- **Scope** with concrete deliverables mapped to plan section +- **Out of scope (do NOT touch)** list mirroring plan boundaries +- **Deliverables** numbered and testable +- **`## Tests to run (iteration loop)`** — pytest **file** subset for fast local iteration (see below); must appear **after Deliverables and before the full Tests section** +- **Tests** command and expected signals (pass/fail, skips, fixtures); avoid hard totals that go stale across branches +- **Sentinel checks** (`rg` patterns) where scope enforcement is critical +- **Manual evidence** commands when plan requires runtime proof +- **Definition of Done** checklist with PR title + branch convention + +### Tests to run (iteration loop) — required subsection + +Per **`tests/README.md`** (iteration subset + where the `## Tests to run (iteration loop)` block lives). Background design history for the fast loop lives under **`propose/completed/`** and **`plans/completed/`** — search basenames for `TEST-SUITE` if you need the original PR wording. + +- Add a markdown section with the **exact heading** `## Tests to run (iteration loop)` inside the fenced **Prompt** block, **immediately after** `## Deliverables` and **before** `## Tests`. +- Content: bullet list of `tests/test_*.py` paths, each with a **one-line rationale** tied to the PR’s code paths. +- **Merge gate:** state that CI enforces a green `test` check on every PR; code changes run the full default suite (`pytest tests`, `JAVA_CODEBASE_RAG_RUN_HEAVY` unset or `0`), docs-only PRs skip pytest but still need a green `test` job; the iteration list is for speed only. +- **Docs-only (UC15):** if the PR is documentation-only with no test signal, use an explicit empty pattern, e.g. a single bullet `*(none — docs-only change; CI test job passes but pytest is skipped.)*` — do not invent a fake file list. + +This heading must stay verbatim so reviewers (and the repo **`pr-review`** skill in `.claude/skills/pr-review/`) can grep for it. + +## Style rules + +- Keep prompts self-contained; an agent should not re-derive design. +- Keep wording imperative and unambiguous. +- Preserve plan decisions; do not invent architecture changes in prompt text. +- Prefer exact symbol/file names from the plan. +- Use explicit stop conditions: "If you need to touch X, stop and ask." + +## Prompt scaffold + +```markdown +## PR-XX — <title> + +**Branch:** `feat/<topic>` off `<base>`. +**Base:** `<base branch or predecessor PR branch>`. +**Plan section:** `plans/PLAN-<TOPIC>.md` § <section>. + +**Attach (`@-files`):** +- `@plans/PLAN-<TOPIC>.md` +- `@<key implementation files>` + +**Prompt:** + +```` +You are implementing PR-XX from `plans/PLAN-<TOPIC>.md`. + +Read the PR-XX section first. The plan is the source of truth. + +## Scope +- <exact implementation scope> + +## Out of scope (do NOT touch) +- <hard constraints> + +## Deliverables +1. <deliverable> +2. <deliverable> + +## Tests to run (iteration loop) + +Run only these files during local iteration; CI `test` on PR + `master` is the merge gate (full pytest when code changes). + +- `tests/test_<file>.py` — <one-line rationale> +- `tests/test_<other>.py` — <one-line rationale> + +Docs-only PRs (UC15): use a single bullet such as *(none — docs-only change; CI test job passes but pytest is skipped.)* instead of inventing paths. + +## Tests +Run: `<command>` +Expected: <pass/fail, skips, key fixtures — not a brittle total count> + +## Sentinel checks +- `<rg command>` + +## Manual evidence +<commands and expected signal> + +## Definition of Done +- [ ] <item> +- [ ] PR title: `<title format>` +- [ ] Branch: `<branch>` +```` +``` + +## Final checklist + +- [ ] Prompt file covers every PR from the plan in order +- [ ] Each prompt has explicit scope and out-of-scope +- [ ] Deliverables are numbered and verifiable +- [ ] Each generated prompt includes **`## Tests to run (iteration loop)`** between Deliverables and Tests (or the UC15 docs-only line) +- [ ] Tests and sentinel checks are present where needed +- [ ] No scope drift from plan decisions + +## Additional resources + +- See [reference.md](reference.md) for quality rules. +- See [examples.md](examples.md) for compact copy-ready snippets. diff --git a/.claude/skills/plan-prompts/examples.md b/.claude/skills/plan-prompts/examples.md new file mode 100644 index 0000000..9870b3d --- /dev/null +++ b/.claude/skills/plan-prompts/examples.md @@ -0,0 +1,58 @@ +# Plan Prompts Examples + +## Example status header + +```markdown +# Cursor task prompts — <topic> (PR-X1 -> PR-X3) + +Status: **active**. One prompt per PR; each prompt is self-contained. +``` + +## Example PR section skeleton + +```markdown +## PR-X1 — schema + extraction + +**Branch:** `feat/topic-x1` off `master`. +**Base:** `master`. +**Plan section:** `plans/PLAN-TOPIC.md` § PR-X1. + +**Attach (`@-files`):** +- `@plans/PLAN-TOPIC.md` +- `@build_ast_graph.py` +- `@tests/test_topic.py` +``` + +## Example hard guardrail block + +```markdown +## Out of scope (do NOT touch) +- Any MCP tool work (belongs to PR-X3). +- Any brownfield override logic (belongs to PR-X2). +- Any ontology bump beyond what PR-X1 declares. + +If you need to touch these areas, stop and ask. +``` + +## Example deliverables + iteration subset + tests + +```markdown +## Deliverables +1. Add schema DDL for `Client` + relation table. +2. Wire create/drop lifecycle. +3. Add extraction tests for declared client rows. + +## Tests to run (iteration loop) + +Run only these files during local iteration; full suite is the merge gate (CI on PR + `master`). + +- `tests/test_client_node_extraction.py` — exercises new `Client` rows and extraction. +- `tests/test_ast_graph_build.py` — schema and graph build paths touched by DDL wiring. + +## Tests +Run: `.venv/bin/python -m pytest tests/test_client_node_extraction.py tests/test_ast_graph_build.py -v` +Expected: all tests pass. + +## Sentinel checks +- `rg "list_clients|find_client_callers" server.py` should return no new matches in PR-X1. +``` diff --git a/.claude/skills/plan-prompts/reference.md b/.claude/skills/plan-prompts/reference.md new file mode 100644 index 0000000..8372353 --- /dev/null +++ b/.claude/skills/plan-prompts/reference.md @@ -0,0 +1,30 @@ +# Plan Prompts Reference + +Use this when converting `PLAN-*` into `CURSOR-PROMPTS-*`. + +## Core quality bar + +1. Prompt is self-contained and executable by another agent. +2. Scope stays within one PR section only. +3. Out-of-scope is explicit and enforceable. +4. Deliverables are concrete and numbered. +5. **Iteration subset** (`## Tests to run (iteration loop)`) lists `tests/test_*.py` bullets with one-line rationales (or UC15 docs-only line) between Deliverables and Tests. +6. Tests + evidence are specific, not generic. + +## Mapping rule (plan -> prompt) + +- Plan PR section title -> Prompt PR section title +- Plan file-by-file changes -> Prompt "Scope" + "Deliverables" +- Plan tests list -> Prompt "Tests" (full / plan-required command) +- Fast iteration subset -> Prompt **`## Tests to run (iteration loop)`** (between Deliverables and Tests; see `plan-prompts` skill) +- Plan done definition -> Prompt "Definition of Done" +- Plan risks/out-of-scope -> Prompt "Out of scope" + sentinel checks + +## Common failure modes + +- Mixing two PR scopes into one prompt +- Dropping out-of-scope items from the plan +- Vague tests ("run tests") without commands +- Missing **`## Tests to run (iteration loop)`** between Deliverables and Tests (unless the PR is docs-only per UC15) +- Missing branch/base/title conventions +- Adding new architecture decisions not present in the plan diff --git a/.claude/skills/pr-open/SKILL.md b/.claude/skills/pr-open/SKILL.md new file mode 100644 index 0000000..112bfab --- /dev/null +++ b/.claude/skills/pr-open/SKILL.md @@ -0,0 +1,150 @@ +--- +name: pr-open +description: Open a pull request to `master` with a comprehensive, review-ready description using this repo's plan-driven format. Use when the user asks to create/open a PR, especially from `plans/PLAN-*.md` or `plans/CURSOR-PROMPTS-*.md`, and include a Definition of Done checklist in the PR body. +disable-model-invocation: true +--- + +# PR Open Skill + +Create PRs to `master` with complete context, validation evidence, and a +Definition of Done checklist that matches this repository's plan-prompt style. + +## When to use + +Use this skill when: +- the user asks to open/create a PR +- the branch already contains implementation and needs a full PR description +- the work follows a plan/prompt contract and needs checklist-backed evidence + +Do not use this skill for propose-only docs PRs unless the user explicitly asks +for the full implementation-style PR template. + +## Required inputs + +Before opening a PR, collect: +1. PR scope source (`plans/PLAN-*.md` section, prompt file, or user text) +2. Branch and base (`master` unless user says otherwise) +3. Test command(s) and results +4. Manual evidence command(s) and outcomes (if required by plan) +5. Out-of-scope items that must be explicitly confirmed + +If any are missing, infer from repository context or ask the user. + +## Preparation workflow + +1. Inspect git state: + - `git status --short --branch` + - `git diff --stat master...HEAD` + - `git log --oneline master..HEAD` +2. Ensure branch is pushed: + - if no upstream, run `git push -u origin HEAD` +3. Gather evidence: + - run lint/tests requested by plan or user + - run manual evidence commands listed by plan/prompt (if any) +4. Build PR body using the template below. +5. Open PR with: + - `gh pr create --base master --title "<title>" --body "<heredoc body>"` + +## Utility script (one command) + +Use the included script to generate the full PR body from structured input and +open the PR in one step: + +1. Copy and fill `.claude/skills/pr-open/pr-input.example.json`. +2. Preview body: + - `.venv/bin/python .claude/skills/pr-open/create_pr.py --input /path/to/pr-input.json --print-only` +3. Open PR: + - `.venv/bin/python .claude/skills/pr-open/create_pr.py --input /path/to/pr-input.json --create` + +Script behavior: +- enforces required sections/fields +- outputs sections in canonical order +- includes Definition of Done checklist +- defaults base branch to `master` + +## PR title convention + +- Prefer: `feat: <scope> (<plan-pr-id>)` for feature PRs. +- Prefer: `fix: <scope>` for bug-fix PRs. +- Keep title aligned with plan/prompt naming when provided. + +## PR body template (comprehensive) + +Use this exact section order: + +```markdown +## Scope +<What this PR implements and which plan/prompt section it maps to.> + +## What Changed +- <Concrete code changes, grouped by module/behavior> +- <...> + +## Semantics / Non-Goals +- <Behavior intentionally unchanged> +- <Explicit non-goals> + +## Validation +### Lint +- `<command>` ✅/❌ + +### Tests +- `<command>` ✅/❌ +- Result: `<counts or summary>` + +### Additional checks +- `<command>` ✅/❌ + +## Sentinel checks +- `<rg command>` -> <result> + +## Manual evidence +- `<command>` +- Observed: <key output summary> + +## Out of Scope Confirmed +Did not implement: +- <item> +- <item> + +## Definition of Done +- [ ] All listed deliverables for this PR are shipped. +- [ ] Required lint/tests pass locally with recorded command output. +- [ ] Sentinel checks produce expected results. +- [ ] Only in-scope files are modified. +- [ ] PR description includes scope, validation, and manual evidence. +- [ ] PR targets `master` with agreed title and branch naming. +``` + +## Plan-prompt mapping rule + +When working from `plans/CURSOR-PROMPTS-*.md`, map sections directly: +- Prompt `Scope` -> PR `Scope` +- Prompt `Deliverables` -> PR `What Changed` +- Prompt `Tests` -> PR `Validation` +- Prompt `Manual evidence` -> PR `Manual evidence` +- Prompt `Out of scope` -> PR `Out of Scope Confirmed` +- Prompt `Definition of Done` -> PR `Definition of Done` + +## Example anchor + +Mirror the structure used in PR #42: +- clear `Scope` mapped to plan PR id +- explicit `Semantics / Non-Goals` +- command-level `Validation` +- `Sentinel checks` and `Manual evidence` +- explicit `Out of Scope Confirmed` + +## Final checklist + +- [ ] Base branch is `master` +- [ ] Branch is pushed and tracks remote +- [ ] PR body includes all template sections +- [ ] Definition of Done checklist is present +- [ ] PR URL is returned to the user + +## Additional resources + +- See [reference.md](reference.md) for section quality rules. +- See [examples.md](examples.md) for copy-ready PR body examples. +- Use [pr-input.example.json](pr-input.example.json) as the fillable input shape. diff --git a/.claude/skills/pr-open/create_pr.py b/.claude/skills/pr-open/create_pr.py new file mode 100644 index 0000000..3a2ca4a --- /dev/null +++ b/.claude/skills/pr-open/create_pr.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 +""" +Generate a comprehensive PR body and optionally open a PR. + +Usage: + .venv/bin/python .claude/skills/pr-open/create_pr.py --input .claude/skills/pr-open/pr-input.example.json --print-only + .venv/bin/python .claude/skills/pr-open/create_pr.py --input /path/to/pr-input.json --create +""" + +from __future__ import annotations + +import argparse +import json +import subprocess +import sys +from pathlib import Path + + +REQUIRED_TOP_LEVEL_KEYS = { + "title", + "scope", + "what_changed", + "semantics_non_goals", + "validation", + "sentinel_checks", + "manual_evidence", + "out_of_scope_confirmed", +} + + +DEFAULT_DOD = [ + "All listed deliverables for this PR are shipped.", + "Required lint/tests pass locally with recorded command output.", + "Sentinel checks produce expected results.", + "Only in-scope files are modified.", + "PR description includes scope, validation, and manual evidence.", + "PR targets `master` with agreed title and branch naming.", +] + + +def _as_list(value: object, key: str) -> list[str]: + if not isinstance(value, list) or not all(isinstance(x, str) and x.strip() for x in value): + raise ValueError(f"Field '{key}' must be a non-empty list of non-empty strings.") + return value + + +def _validate_validation_block(payload: dict) -> dict: + validation = payload.get("validation") + if not isinstance(validation, dict): + raise ValueError("Field 'validation' must be an object.") + + lint = _as_list(validation.get("lint"), "validation.lint") + tests = _as_list(validation.get("tests"), "validation.tests") + additional = validation.get("additional_checks", []) + if additional: + additional = _as_list(additional, "validation.additional_checks") + else: + additional = [] + return {"lint": lint, "tests": tests, "additional_checks": additional} + + +def _load_payload(path: Path) -> dict: + data = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(data, dict): + raise ValueError("Input JSON must be an object.") + + missing = sorted(REQUIRED_TOP_LEVEL_KEYS - set(data.keys())) + if missing: + raise ValueError(f"Missing required key(s): {', '.join(missing)}") + + for key in ("title", "scope"): + if not isinstance(data.get(key), str) or not data[key].strip(): + raise ValueError(f"Field '{key}' must be a non-empty string.") + + data["what_changed"] = _as_list(data.get("what_changed"), "what_changed") + data["semantics_non_goals"] = _as_list(data.get("semantics_non_goals"), "semantics_non_goals") + data["validation"] = _validate_validation_block(data) + data["sentinel_checks"] = _as_list(data.get("sentinel_checks"), "sentinel_checks") + data["manual_evidence"] = _as_list(data.get("manual_evidence"), "manual_evidence") + data["out_of_scope_confirmed"] = _as_list( + data.get("out_of_scope_confirmed"), "out_of_scope_confirmed" + ) + + dod = data.get("definition_of_done", DEFAULT_DOD) + data["definition_of_done"] = _as_list(dod, "definition_of_done") + base = data.get("base", "master") + if not isinstance(base, str) or not base.strip(): + raise ValueError("Field 'base' must be a non-empty string when provided.") + data["base"] = base.strip() + data["draft"] = bool(data.get("draft", False)) + return data + + +def _bullet_lines(items: list[str]) -> list[str]: + return [f"- {item}" for item in items] + + +def _build_body(data: dict) -> str: + lines: list[str] = [] + lines.append("## Scope") + lines.append(data["scope"].strip()) + lines.append("") + + lines.append("## What Changed") + lines.extend(_bullet_lines(data["what_changed"])) + lines.append("") + + lines.append("## Semantics / Non-Goals") + lines.extend(_bullet_lines(data["semantics_non_goals"])) + lines.append("") + + lines.append("## Validation") + lines.append("### Lint") + lines.extend(_bullet_lines(data["validation"]["lint"])) + lines.append("") + lines.append("### Tests") + lines.extend(_bullet_lines(data["validation"]["tests"])) + if data["validation"]["additional_checks"]: + lines.append("") + lines.append("### Additional checks") + lines.extend(_bullet_lines(data["validation"]["additional_checks"])) + lines.append("") + + lines.append("## Sentinel checks") + lines.extend(_bullet_lines(data["sentinel_checks"])) + lines.append("") + + lines.append("## Manual evidence") + lines.extend(_bullet_lines(data["manual_evidence"])) + lines.append("") + + lines.append("## Out of Scope Confirmed") + lines.append("Did not implement:") + lines.extend(_bullet_lines(data["out_of_scope_confirmed"])) + lines.append("") + + lines.append("## Definition of Done") + lines.extend([f"- [ ] {item}" for item in data["definition_of_done"]]) + lines.append("") + + return "\n".join(lines).rstrip() + "\n" + + +def _open_pr(title: str, body: str, base: str, draft: bool) -> None: + cmd = ["gh", "pr", "create", "--base", base, "--title", title, "--body", body] + if draft: + cmd.append("--draft") + subprocess.run(cmd, check=True) + + +def main() -> int: + parser = argparse.ArgumentParser(description="Generate and open a comprehensive PR body.") + parser.add_argument("--input", required=True, help="Path to JSON input payload.") + parser.add_argument("--print-only", action="store_true", help="Print generated body only.") + parser.add_argument("--create", action="store_true", help="Create PR with gh after generation.") + args = parser.parse_args() + + if not args.print_only and not args.create: + parser.error("Choose at least one action: --print-only and/or --create.") + + if args.print_only and args.create: + parser.error("Use either --print-only or --create, not both.") + + try: + payload = _load_payload(Path(args.input)) + except Exception as exc: # pragma: no cover - CLI error path + print(f"Error: {exc}", file=sys.stderr) + return 2 + + body = _build_body(payload) + if args.print_only: + print(body) + return 0 + + try: + _open_pr(payload["title"], body, payload["base"], payload["draft"]) + except subprocess.CalledProcessError as exc: # pragma: no cover - CLI error path + print(f"Failed to create PR (exit {exc.returncode}).", file=sys.stderr) + return exc.returncode + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.claude/skills/pr-open/examples.md b/.claude/skills/pr-open/examples.md new file mode 100644 index 0000000..6e2e4a7 --- /dev/null +++ b/.claude/skills/pr-open/examples.md @@ -0,0 +1,44 @@ +# PR Open Examples + +## Example section skeleton + +```markdown +## Scope +Implements PR-XX from `plans/PLAN-TOPIC.md` by delivering <short scope>. + +## What Changed +- Updated `module_a.py` to <behavior change>. +- Added `tests/test_topic.py` with focused regressions for <cases>. + +## Semantics / Non-Goals +- Existing <behavior> matching semantics remain unchanged. +- No new MCP tools or schema columns in this PR. +``` + +## Example validation block + +```markdown +## Validation +### Lint +- `ruff check .` ✅ + +### Tests +- `pytest tests/test_topic.py -v` ✅ +- Result: 6 passed + +### Additional checks +- `pytest tests -q` ✅ +- Result: 302 passed, 4 skipped +``` + +## Example Definition of Done block + +```markdown +## Definition of Done +- [ ] All deliverables 1-6 are shipped. +- [ ] `ruff check .` passes. +- [ ] `pytest tests/test_topic.py -v` passes. +- [ ] Sentinel checks return expected results. +- [ ] Only in-scope files are modified. +- [ ] PR is opened against `master` with agreed title and branch. +``` diff --git a/.claude/skills/pr-open/pr-input.example.json b/.claude/skills/pr-open/pr-input.example.json new file mode 100644 index 0000000..29105fe --- /dev/null +++ b/.claude/skills/pr-open/pr-input.example.json @@ -0,0 +1,42 @@ +{ + "title": "feat: <short scope> (PR-Xn)", + "base": "master", + "draft": false, + "scope": "Implements PR-Xn from `plans/PLAN-<TOPIC>.md` (or `plans/completed/PLAN-<TOPIC>.md` if the plan landed) by <one-sentence outcome>.", + "what_changed": [ + "Example bullet: primary code path touched.", + "Example bullet: tests or fixtures added." + ], + "semantics_non_goals": [ + "Explicitly out-of-scope follow-ups for this PR." + ], + "validation": { + "lint": [ + "`ruff check .` ✅" + ], + "tests": [ + "`pytest tests/test_<area>.py -v` ✅", + "`pytest tests -v` ✅" + ], + "additional_checks": [ + "Optional focused pytest or `rg` spot-checks from the plan prompt." + ] + }, + "sentinel_checks": [ + "`rg '<scope pattern>' <paths>` -> expected matches or silence ✅" + ], + "manual_evidence": [ + "Commands from the plan prompt, with expected stdout/stderr signals." + ], + "out_of_scope_confirmed": [ + "Items the plan marks out of scope for this PR." + ], + "definition_of_done": [ + "All listed deliverables for this PR are shipped.", + "Required lint/tests pass locally with recorded command output.", + "Sentinel checks produce expected results.", + "Only in-scope files are modified.", + "PR description includes scope, validation, and manual evidence.", + "PR targets `master` with agreed title and branch naming." + ] +} diff --git a/.claude/skills/pr-open/reference.md b/.claude/skills/pr-open/reference.md new file mode 100644 index 0000000..87e9158 --- /dev/null +++ b/.claude/skills/pr-open/reference.md @@ -0,0 +1,30 @@ +# PR Open Reference + +Use this reference to keep PR descriptions consistent and review-ready. + +## Quality bar + +1. Scope names the exact plan/prompt section implemented. +2. Changes are grouped by behavior, not just file names. +3. Validation includes command + pass/fail + result summary. +4. Out-of-scope is explicit to prevent review ambiguity. +5. Definition of Done is checklist-form and verifiable. + +## Definition of Done checklist guidance + +A strong DoD checklist should verify: +- deliverables complete +- test/lint evidence recorded +- sentinel checks verified +- file scope respected +- PR metadata correct (base/title/branch) + +Avoid vague items like "looks good" or "reviewed code". + +## Common failure modes + +- Missing "Out of Scope Confirmed" section +- Listing tests without result counts +- No manual evidence for plan-required runtime checks +- DoD present but not tied to measurable outcomes +- PR body copied from template but not filled with concrete details diff --git a/.claude/skills/pr-review/SKILL.md b/.claude/skills/pr-review/SKILL.md new file mode 100644 index 0000000..94d3b0a --- /dev/null +++ b/.claude/skills/pr-review/SKILL.md @@ -0,0 +1,60 @@ +--- +name: pr-review +description: >- + Reviews pull requests against plan scope, requires pasted pytest subset + evidence plus green full-suite CI, and rejects checkbox-only test claims. + Use when reviewing a PR, approving a merge, or checking an agent handoff. +disable-model-invocation: true +--- + +# PR review + +Use this checklist when reviewing a PR that was driven by a written plan or a **`plan-prompts`** / `CURSOR-PROMPTS-*` agent task handoff. + +## 1. Scope and diff hygiene + +- [ ] Diff matches stated scope; no drive-by refactors or scope leaks from the plan’s **Out of scope** list. +- [ ] If the task prompt listed sentinel `git grep` patterns, they are **absent** from `git diff master..HEAD` (when that contract applies). + +## 2. Test evidence — iteration subset (mandatory) + +The PR body or thread must include **pasteable proof** that the author ran the files declared under **`## Tests to run (iteration loop)`** in the task prompt. + +**Acceptable** + +- The **exact** command line (e.g. `.venv/bin/python -m pytest tests/test_foo.py tests/test_bar.py -v` or equivalent). +- The **exit code** or explicit pass summary tied to that command (e.g. `exit 0`, or pytest’s final `N passed` line immediately after the command). + +**Not acceptable (reject the review)** + +- Only a checkbox such as `- [x] subset ran` or “tests passed” **without** the command and outcome above. +- A vague “ran pytest” with no file list and no exit code. +- Substituting a different file list than the prompt declared, without explanation. + +If the task prompt declared **docs-only** (empty iteration list per UC15), subset evidence is: state that no test files were required for iteration, and still require a **green `test` CI** run below (pytest may be skipped when only documentation paths changed). + +**Subset green does not replace the merge gate:** If the required `test` CI check is red (or missing), the PR is not merge-ready even when the declared subset passed locally. + +## 3. Test evidence — full suite / CI (mandatory when repo CI exists) + +When this repository has a required GitHub Actions workflow (`.github/workflows/test.yml`): + +- [ ] The PR description or review comment includes a **link** to a **green** `test` Actions run on **this PR** at the **same commit** being reviewed (or the tip the reviewer approves). For code changes, the run must include `pytest tests` with `JAVA_CODEBASE_RAG_RUN_HEAVY` unset or `0`. For docs-only PRs, a green run with pytest skipped is sufficient. + +If CI is not yet enabled for the repo, note that in the review; once the workflow exists, **withhold approval** until both §2 and §3 are satisfied. + +## 4. Plan and docs + +- [ ] PR body references the plan/propose when the work was plan-driven. +- [ ] `tests/README.md` or other operator docs changes remain consistent with repo conventions. + +## 5. Manual / product evidence + +Reproduce or spot-check any plan-required manual command **after** §2–§3 are satisfied (or in parallel if independent). + +--- + +## Self-check (dry-run) + +- **Fail:** Review comment says “subset verified [x]” with no pytest command → **does not meet §2**. +- **Pass:** Pasted command, pytest summary / `exit 0`, and link to green full-suite run on the PR commit. diff --git a/.claude/skills/propose/SKILL.md b/.claude/skills/propose/SKILL.md new file mode 100644 index 0000000..0f02f0f --- /dev/null +++ b/.claude/skills/propose/SKILL.md @@ -0,0 +1,134 @@ +--- +name: propose +description: Write high-quality proposal docs for this repository using the established propose style. Use when the user asks to create, update, or review files under `propose/`, or requests a "proposal/propose" before implementation. +disable-model-invocation: true +--- + +# Propose Skill + +Create proposal docs that match this repository's accepted style and workflow. + +## When to use + +Use this skill when: +- the user asks for a new proposal in `propose/` +- the user asks to refine an existing proposal +- work is non-trivial and should be proposed before implementation + +Do not use this skill for small one-file bug fixes or purely mechanical edits. + +## Handoff to `plan-project-scope` + +If the work is expected to ship as multiple implementation PRs, create/update +the proposal here first, then hand off plan authoring to +`../plan-project-scope/SKILL.md` for the execution split and per-PR delivery contract. + +## Required repo context + +Before drafting, read: +1. `README.md` (public surface, env vars, ontology/reindex implications) +2. `CODEBASE_REQUIREMENTS.md` (brownfield assumptions and source mapping) +3. Relevant active plan/propose docs under `plans/` and `propose/` +4. The target area's implementation files (only as needed) + +## Proposal quality bar (based on merged PR patterns) + +Strong proposals in this repo consistently do the following: +- state **Status** up front (proposal only, not implementation) +- define a crisp **Problem Statement** with concrete failure modes +- include a concrete **Proposed Solution** with explicit scope boundaries +- call out **Schema / ontology / re-index impact** explicitly +- include **Open questions** with `[TBD]` items and recommended defaults +- include **Out of scope** to avoid accidental scope creep +- include **Sequencing** and dependencies when multi-PR work is expected +- include a lightweight **test/validation strategy** even for docs-only PRs + +## Standard propose structure + +Use this structure by default (adapt section names only when needed): + +```markdown +# <TOPIC TITLE> + +## Status +Proposal — not yet implemented. + +## Problem Statement +<What is broken/missing, and why it matters now. Include concrete examples.> + +## Proposed Solution +<Core design, API/schema behavior, decision points.> + +## Scope +<What this proposal changes.> + +## Schema / Ontology / Re-index impact +- Ontology bump: <required or not required> +- Re-index required: <yes/no and why> +- Config/tool surface changes: <list or "none"> + +## Tests / Validation +<How correctness will be validated once implemented.> + +## Open Questions ([TBD]) +1. <Question> — Recommended: <option> +2. <Question> — Recommended: <option> + +## Out of scope +- <Explicit non-goals> + +## Sequencing / Follow-ups +<PR split, dependencies, or "single PR".> +``` + +## Writing rules + +- Prefer explicit, testable statements over aspirational language. +- Keep terminology consistent with `java_ontology.py` and README terms. +- If behavior changes user-facing tools, mention exact tool names and fields. +- If semantics change, state ontology bump and re-index requirement plainly. +- If this is a design-only PR, clearly say no production code changed. +- Never propose compatibility shims unless explicitly requested. + +## PR body template for propose-only changes + +When opening the PR, use this compact shape: + +```markdown +## What +<Added/updated proposal file(s).> + +## Why now +<Urgency and context.> + +## Highlights +- <3-6 key points> + +## Tests +Docs-only; baseline unchanged. + +## Out of scope +- <Implementation deferred> +``` + +## File naming + +- Use uppercase kebab-style topic names ending in `-PROPOSE.md`. +- Keep names specific to the decision, e.g.: + - `FEATURE-NAME-PROPOSE.md` + - `TOOL-NAME-PROPOSE.md` + - `ARCHITECTURE-CHANGE-PROPOSE.md` + +## Final checklist + +- [ ] Proposal file lives under `propose/` +- [ ] Problem statement includes concrete examples +- [ ] Schema/ontology/re-index impact is explicit +- [ ] Open questions include `[TBD]` with recommendations +- [ ] Out-of-scope section is present +- [ ] Sequencing/follow-up path is clear + +## Additional resources + +- See practical examples in [reference.md](reference.md). +- See a repo-grounded golden sample in [examples.md](examples.md). diff --git a/.claude/skills/propose/examples.md b/.claude/skills/propose/examples.md new file mode 100644 index 0000000..e58ebfd --- /dev/null +++ b/.claude/skills/propose/examples.md @@ -0,0 +1,105 @@ +# Propose Examples + +This file contains a repo-grounded example shaped after merged propose PRs in this workspace. + +## Golden sample: outbound HTTP client listing tool + +```markdown +# LIST-CLIENTS-MCP-TOOL-PROPOSE + +## Status +Proposal — depends on brownfield annotations v2 landing first. Design-only; no implementation in this PR. + +## Problem Statement +After the annotation-direction cleanup, outbound HTTP declarations (Feign and annotated imperative clients) are no longer represented as inbound routes. + +That leaves a practical gap: +> "Show every outbound HTTP call this service declares, which service it targets, and what client kind it uses." + +`list_routes` is the wrong surface for this question: +1. It is inbound-oriented. +2. It misses some outbound imperative declarations. +3. Post-v2, Feign declarations are no longer expected in route rows. + +## Proposed Solution +Add a first-class outbound declaration surface: + +1. New `Client` node table (one row per outbound client declaration). +2. New `DECLARES_CLIENT` edge (`Symbol -> Client`) mirroring `EXPOSES(Symbol -> Route)`. +3. New MCP tool `list_clients` with filters: + - `microservice` + - `client_kind` + - `target_service` + - `path_prefix` + - `method` + - `limit` + +`HTTP_CALLS(Symbol -> Route)` remains the call-edge truth for caller-to-callee resolution outcomes. +`Client` is caller-side declaration metadata, not a replacement for matched call edges. + +## Scope +- graph schema additions for `Client` and `DECLARES_CLIENT` +- extraction + enrichment emission for outbound client declarations +- query helper + DTO + `list_clients` tool surface in server layer +- README tool list + usage notes update + +## Schema / Ontology / Re-index impact +- Ontology bump: required (additive graph schema change) +- Re-index required: yes (new tables need population) +- Config/tool surface changes: one new MCP tool (`list_clients`) + +## Tests / Validation +- schema smoke: `Client` and `DECLARES_CLIENT` exist after rebuild +- extraction tests: deterministic client IDs and expected field values +- query tests: each filter behaves independently and in combination +- tool tests: response DTO shape and limit bounds +- regression checks: existing route/call tools remain unchanged + +## Open Questions ([TBD]) +1. Should `target_service` be a plain string or foreign-key relation in v1? + - Recommended: string in v1 (keeps schema simple, avoids lifecycle coupling). +2. Should unresolved declarations be excluded by default? + - Recommended: no; include with `resolved` field so users can debug. +3. Should tool be named `list_clients` or `list_http_clients`? + - Recommended: `list_clients` (concise, aligns with current naming style). + +## Out of scope +- `get_client_by_path` +- `find_client_callers` +- `find_client_target_route` +- async outbound parity tooling (`Producer` + `list_async_producers`) + +## Sequencing / Follow-ups +- Depends on annotation-shape v2 proposal implementation. +- Suggested split: + - PR-1: schema + emission + tests + - PR-2: MCP tool + docs + follow-up tests + +## PR body (proposal-only) template +## What +Adds `propose/completed/<TOPIC>-PROPOSE.md` (this sample used the list-clients topic) describing outbound client declarations and a new MCP tool surface. + +## Why now +Outbound declaration discovery needs a first-class tool after direction-honest annotation reshaping. + +## Highlights +- Introduces `Client` node and `DECLARES_CLIENT` relation. +- Keeps `HTTP_CALLS` as the matching truth surface. +- Defines `list_clients` filters and DTO behavior. +- Explicitly scopes follow-up tools out of v1. + +## Tests +Docs-only; baseline unchanged. + +## Out of scope +- Implementation and follow-up outbound helper tools. +``` + +## Notes on why this is "golden" + +- Starts with status and dependency context. +- Uses concrete user workflow language in the problem statement. +- Separates declaration metadata from call-edge semantics clearly. +- Calls out ontology/re-index impact explicitly. +- Includes clear `[TBD]` questions with recommendations. +- Constrains scope and outlines practical sequencing. diff --git a/.claude/skills/propose/reference.md b/.claude/skills/propose/reference.md new file mode 100644 index 0000000..9605290 --- /dev/null +++ b/.claude/skills/propose/reference.md @@ -0,0 +1,159 @@ +# Propose References + +Use these examples as shape guides. Replace topic-specific details with the target feature/tool. + +## Example A: Small propose (single PR, no schema change) + +```markdown +# ROUTE-MATCH-LOGGING-PROPOSE + +## Status +Proposal — not yet implemented. + +## Problem Statement +Route matching failures are hard to diagnose because users only see final `unresolved` outcomes without compact reason details. + +Current behavior forces manual graph inspection and slows iteration on brownfield overrides. + +## Proposed Solution +Add structured debug metadata for matcher outcomes: +- emit a compact `reason_code` for each unresolved/ambiguous edge +- include per-run reason counters in `graph_meta` +- keep default tool responses unchanged unless debug mode is requested + +## Scope +- matcher instrumentation in pass6 +- read-path plumbing for counters +- docs update for debug fields + +## Schema / Ontology / Re-index impact +- Ontology bump: not required +- Re-index required: yes (new `graph_meta` fields emitted during rebuild) +- Config/tool surface changes: optional debug flag on one tool + +## Tests / Validation +- unit tests for reason-code assignment +- regression test for existing match labels unchanged +- fixture run verifying counter keys present + +## Open Questions ([TBD]) +1. Should reason details be persisted per-edge or only aggregated? — Recommended: aggregated only (v1). +2. Should debug payload be included by default in tool outputs? — Recommended: no, opt-in flag. + +## Out of scope +- changing match algorithm ranking +- adding new call-edge types + +## Sequencing / Follow-ups +Single implementation PR. +``` + +## Example B: Medium propose (ontology bump + additive schema) + +```markdown +# LIST-PRODUCERS-MCP-TOOL-PROPOSE + +## Status +Proposal — depends on outbound producer extraction already present. + +## Problem Statement +Users can list inbound async listeners but cannot list outbound producer declarations in a first-class way. + +This creates asymmetric discovery: outbound async intent is searchable only indirectly through edge traversal. + +## Proposed Solution +Introduce: +1. `Producer` graph node table for outbound producer declarations +2. `DECLARES_PRODUCER(Symbol -> Producer)` relation +3. new MCP tool `list_producers` with filters (`microservice`, `producer_kind`, `topic_prefix`) + +## Scope +- additive graph schema (new node + rel table) +- extraction emission for producer declarations +- query helper + server DTO + MCP tool +- README tool surface update + +## Schema / Ontology / Re-index impact +- Ontology bump: required (additive schema expansion) +- Re-index required: yes (new tables populated on rebuild) +- Config/tool surface changes: one new MCP tool + +## Tests / Validation +- schema smoke asserting new tables exist +- extraction tests for deterministic producer IDs +- MCP tool tests for filter behavior and limits +- no-regression tests for existing async route tools + +## Open Questions ([TBD]) +1. Should `Producer` include delivery semantics fields in v1? — Recommended: no, keep minimal. +2. Should `list_producers` include unresolved rows by default? — Recommended: yes, with `resolved` flag. +3. Should tool name be `list_producers` or `list_async_producers`? — Recommended: `list_producers`. + +## Out of scope +- reverse traversal tools (`find_producer_callers`) +- producer-to-consumer match visualization tool + +## Sequencing / Follow-ups +- PR-1: schema + extraction +- PR-2: tool + docs + test expansion +``` + +## Example C: Large propose (multi-PR program) + +```markdown +# INCREMENTAL-GRAPH-REBUILD-PROPOSE + +## Status +Proposal — design approved required before implementation plan. + +## Problem Statement +Full graph rebuild runs on every change and dominates edit-query iteration latency on medium/large codebases. + +## Proposed Solution +Add incremental rebuild mode with safe fallback: +- dirty-file detection from changed paths +- dependency closure expansion +- selective delete/re-emit for affected rows +- global final reconciliation pass for cross-service outcomes + +## Scope +- incremental orchestrator and dependency index +- pass-level selective delete helpers +- determinism/equivalence test harness +- CLI wiring for full vs incremental mode selection + +## Schema / Ontology / Re-index impact +- Ontology bump: not required (behavioral/runtime strategy change only) +- Re-index required: no one-time migration; normal rebuild still supported +- Config/tool surface changes: optional mode controls + +## Tests / Validation +- mandatory equivalence: incremental(state) == full(state) +- determinism across repeated incremental runs +- fallback-path tests for unsafe change scenarios +- benchmark capture on fixture + one larger corpus + +## Open Questions ([TBD]) +1. Storage location for dependency index? — Recommended: sidecar file. +2. Should renamed files always force full rebuild? — Recommended: yes (v1 safety). +3. Is partial pass6 allowed? — Recommended: no, keep pass6 global in v1. + +## Out of scope +- watch mode daemon +- multi-writer concurrency support +- distributed indexing + +## Sequencing / Follow-ups +- PR-T1: dependency index + baseline tests +- PR-T2: selective delete helpers +- PR-T3: incremental orchestrator + equivalence checks +- PR-T4: mode decision engine integration +- PR-T5: optional brownfield closure refinements +``` + +## Quick adaptation checklist + +- Keep section order stable unless there is a strong reason to change it. +- Use exact tool/symbol names when describing API surface. +- Call out ontology bump/reindex implications explicitly every time. +- For docs-only proposal PRs, state test baseline unchanged. diff --git a/.cursor/skills/propose/SKILL.md b/.cursor/skills/propose/SKILL.md index 92d2c4f..0f02f0f 100644 --- a/.cursor/skills/propose/SKILL.md +++ b/.cursor/skills/propose/SKILL.md @@ -17,11 +17,11 @@ Use this skill when: Do not use this skill for small one-file bug fixes or purely mechanical edits. -## Handoff to `plan` +## Handoff to `plan-project-scope` If the work is expected to ship as multiple implementation PRs, create/update the proposal here first, then hand off plan authoring to -`../plan/SKILL.md` for the execution split and per-PR delivery contract. +`../plan-project-scope/SKILL.md` for the execution split and per-PR delivery contract. ## Required repo context diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c6a1a06..5d2c2eb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,6 +25,8 @@ jobs: - 'plans/**' - 'reports/**' - '.cursor/**' + - '.claude/**' + - 'CLAUDE.md' - 'AGENTS.md' - 'README.md' - 'CODEBASE_REQUIREMENTS.md' diff --git a/AGENTS.md b/AGENTS.md index be877c6..973545d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,17 +1,21 @@ # AGENTS.md -Entry point for Cursor CLI agents (and other agentic tools) working -on this repo. Detailed guidance lives in `.cursor/rules/*.mdc` — -those files are auto-loaded by Cursor. This file is a flat summary -for tools that don't read `.cursor/rules/`. +Entry point for **agentic tools** working on this repo (Cursor CLI, Claude Code, and others). + +| Host | Primary entry | Rules | Skills | +|------|---------------|-------|--------| +| **Claude Code** | [`CLAUDE.md`](CLAUDE.md) | [`.claude/rules/`](.claude/rules/) | [`.claude/skills/`](.claude/skills/) (canonical) | +| **Cursor** | This file | [`.cursor/rules/*.mdc`](.cursor/rules/) | [`.cursor/skills/`](.cursor/skills/) (mirror; copy to `~/.cursor/skills/` if needed) | + +Detailed guidance for Cursor also lives in `.cursor/rules/*.mdc` (auto-loaded by Cursor). Claude Code loads `CLAUDE.md`, `.claude/rules/`, and `.claude/skills/` automatically. **Canonical skill prose** is under `.claude/skills/`; keep `.cursor/skills/` in sync when editing workflow skills. ## Where to look - `README.md` — feature surface, env vars, ranking, capabilities, - MCP tool list (`search` / `find` / `describe` / `neighbors` / `resolve`; - response `hints` + pagination echo — see README), - CLI ops (`java-codebase-rag --help`), and "Re-index required" callouts. - **`ontology_version` is currently 14** (`EDGE_SCHEMA` in `java_ontology.py`; v14 re-index required; HTTP/ASYNC caller-side endpoint flips ship in SCHEMA-V2 PR-B/C — see README graph section and `docs/EDGE-NAVIGATION.md`). + MCP tool list (`search` / `find` / `describe` / `neighbors` / `resolve`; + response `hints` + pagination echo — see README), + CLI ops (`java-codebase-rag --help`), and "Re-index required" callouts. + **`ontology_version` is currently 14** (`EDGE_SCHEMA` in `java_ontology.py`; v14 re-index required; HTTP/ASYNC caller-side endpoint flips ship in SCHEMA-V2 PR-B/C — see README graph section and `docs/EDGE-NAVIGATION.md`). - [`docs/JAVA-CODEBASE-RAG-CLI.md`](./docs/JAVA-CODEBASE-RAG-CLI.md) — operator guide for the `java-codebase-rag` CLI (`init` / `increment` / `reprocess` / `erase`, `meta`, `tables`, `diagnose-ignore`, `analyze-pr`; hidden `refresh` alias → `reprocess` — see that doc). - `CODEBASE_REQUIREMENTS.md` — Java-repo assumptions and tuning map. - **`propose/`** — design proposes. **In-flight** work is **`propose/*.md`** @@ -19,10 +23,10 @@ for tools that don't read `.cursor/rules/`. **`propose/completed/`** — landed proposes and rationale. **List or search** the tree for current filenames; entrypoint docs are not maintained as a catalog. -- **`plans/`** — multi-PR plans (`PLAN-*.md`) and per-PR Cursor prompts - (`CURSOR-PROMPTS-*.md`). Top-level files here are active or staged - multi-PR efforts; **`plans/completed/`** holds finished plans and - completed prompt sets (reference templates for future work). +- **`plans/`** — multi-PR plans (`PLAN-*.md`) and per-PR agent execution prompts + (`CURSOR-PROMPTS-*.md` — used by Cursor and Claude Code). Top-level files here + are active or staged multi-PR efforts; **`plans/completed/`** holds finished plans + and completed prompt sets (reference templates for future work). - `tests/README.md` — testing philosophy. Read these directly. Don't rely on rule files to mirror them. @@ -30,8 +34,8 @@ Read these directly. Don't rely on rule files to mirror them. ## Hard rules 1. **No backward-compatibility obligation** — - `.cursor/rules/breaking-changes.mdc`. Prefer removals and schema - updates over shims. + `.claude/rules/breaking-changes.md` (Cursor: `.cursor/rules/breaking-changes.mdc`). + Prefer removals and schema updates over shims. 2. **Propose-then-implement** for non-trivial features. Drop a short markdown propose under `propose/`, reference it from the PR, move it to `propose/completed/` once landed. @@ -79,22 +83,22 @@ When adding or editing Cypher run against Kuzu (for example in ## Workflow -- Branch from `master`. Branch names: `cursor/<topic>` (CLI work), +- Branch from `master`. Branch names: `cursor/<topic>` (Cursor-agent work), `plan/<name>` (in-progress propose), `feat/<topic>` and `chore/<topic>` for landed-feature work. - Commit messages: present tense, imperative, lowercase first word. - Always open a PR; never push to `master`. - Run `.venv/bin/ruff check .` and `.venv/bin/python -m pytest tests -v` before pushing. - Exception for isolated automation-only changes: if edits are limited to - `automation/cursor_propose_only/**` (plus optional references to that workflow - in docs), full `tests -v` is not required. Run: + `automation/cursor_propose_only/**` (plus optional docs references to that + workflow), full `tests -v` is not required. Run: - `.venv/bin/ruff check .` - `.venv/bin/python -m pytest automation/cursor_propose_only/tests -q` - Heavy indexer tests: `JAVA_CODEBASE_RAG_RUN_HEAVY=1` (see `tests/README.md`). -## Per-PR Cursor task contract +## Per-PR agent task contract -When picking up a per-PR Cursor task prompt (from `plans/` or +When picking up a per-PR task prompt (from `plans/` or `plans/completed/`, files matching `CURSOR-PROMPTS-*.md`; use any completed prompt file in `plans/completed/` as a structural template when you need one): @@ -111,28 +115,20 @@ when you need one): unrelated files). They violate the per-PR scope contract even when they look harmless. -## Cursor Cloud specific instructions +## Environment This is a self-contained Python project — no external services (no Postgres, Kafka, Docker) are needed. All storage (Kuzu, LanceDB, CocoIndex state) is embedded/file-based. -### Environment +### Setup -- Python 3.11+ with `.venv` at repo root. The update script creates - the venv and installs deps if missing. -- `.venv/bin` must be on `PATH` for CLI tests - (`test_java_codebase_rag_cli.py` uses - `shutil.which("java-codebase-rag")`). The update script handles - this via `~/.bashrc`. -- The package must be installed in **editable mode** - (`pip install -e .`) so the `java-codebase-rag` CLI entry point - is registered. The update script handles this. +- Python 3.11+ with `.venv` at repo root. +- Use only `.venv/bin/python`, `.venv/bin/pip`, `.venv/bin/ruff`. +- Install editable: `pip install -e .` so `java-codebase-rag` is on `PATH`. ### Running checks -Standard commands per `README.md` § 1 and `AGENTS.md` § Workflow: - ```bash .venv/bin/ruff check . .venv/bin/python -m pytest tests -v @@ -156,4 +152,4 @@ rm -rf /tmp/check && .venv/bin/python build_ast_graph.py \ The MCP server (`server.py`) is stdio-based and is not started as a long-running dev server — it is invoked by MCP hosts (Claude Desktop, -Claude Code) directly. +Claude Code, Cursor) directly. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..7915f13 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,90 @@ +# CLAUDE.md + +Entry point for **Claude Code** (and other tools that read this file) working +on this repo. Cursor agents should use [`AGENTS.md`](AGENTS.md) (which also +summarizes both hosts). Detailed modular rules live under `.claude/rules/`. + +## Modular rules + +See @.claude/rules/project-overview.md for the project map and file roles. + +See @.claude/rules/agent-workflow.md for investigate → propose → implement → validate workflow. + +See @.claude/rules/breaking-changes.md for the no-back-compat policy. + +See @.claude/rules/python-venv-only.md for the `.venv/bin` requirement. + +## Where to look + +- `README.md` — feature surface, env vars, ranking, capabilities, + MCP tool list (`search` / `find` / `describe` / `neighbors` / `resolve`; + response `hints` + pagination echo — see README), + CLI ops (`java-codebase-rag --help`), and "Re-index required" callouts. + **`ontology_version` is currently 14** (`EDGE_SCHEMA` in `java_ontology.py`). +- [`docs/JAVA-CODEBASE-RAG-CLI.md`](./docs/JAVA-CODEBASE-RAG-CLI.md) — operator guide for the CLI. +- `CODEBASE_REQUIREMENTS.md` — Java-repo assumptions and tuning map. +- **`propose/`** — in-flight work is **`propose/*.md`** at the root (not under `completed/`). + **`propose/completed/`** — landed proposes. **List or search** the tree; no catalog here. +- **`plans/`** — `PLAN-*.md` and per-PR **`CURSOR-PROMPTS-*.md`** (agent execution prompts for + Cursor and Claude Code). Top-level files are active efforts; **`plans/completed/`** holds templates. +- **`tests/README.md`** — testing philosophy, CI merge gate, iteration subset convention. +- **`.claude/skills/`** — maintainer skills (`propose`, `plan-project-scope`, `plan-prompts`, + `pr-review`, `pr-open`, `java-codebase-explore`). Canonical copies; Cursor mirrors under `.cursor/skills/`. + +Read README and docs directly. Do not rely on this file to mirror them. + +## Hard rules + +1. **No backward-compatibility obligation** — `.claude/rules/breaking-changes.md`. +2. **Propose-then-implement** for non-trivial features (`propose/`, `plans/`). +3. **Don't overfit to `tests/bank-chat-system/`** — assert invariants, not exact counts. +4. **`server.py` is stdio MCP** — no stdout from tool handlers; diagnostics to stderr. +5. **Ontology literals** — single source in `java_ontology.py` (`VALID_*` sets). +6. **Brownfield overrides are first-class** — compose with `BrownfieldOverrides`; see + `plans/completed/PLAN-TIER1B-COMPLETION.md` for caller-side HTTP/ASYNC replacement rule. +7. **Schema changes require reindex** — README callout + `ontology_version` bump when semantics change. + +## Kuzu Cypher pitfalls + +When adding or editing Cypher run against Kuzu (`kuzu_queries.py`, `mcp_v2.py`, etc.): + +- **Do not filter relationship types with** `label(e) IN $list` **in** `WHERE`. Prefer + **OR of scalar equalities** (`label(e) = $p OR label(e) = $q …`) with bound parameters. +- **Typed union patterns** like `-[e:CALLS|HTTP_CALLS]->` are only safe if every column you + `RETURN` from `e` exists on **all** relationship types in the schema. Otherwise use untyped + `[e]` plus explicit label filtering, or split queries. + +## Workflow + +- Branch from `master`. Names: `feat/<topic>`, `plan/<name>`, `chore/<topic>`, `cursor/<topic>`. +- Commit messages: present tense, imperative, lowercase first word. +- Open a PR; never push to `master`. +- Run `.venv/bin/ruff check .` and `.venv/bin/python -m pytest tests -v` before pushing. +- Automation-only changes under `automation/cursor_propose_only/**`: targeted pytest on that package is enough. +- Heavy tests: `JAVA_CODEBASE_RAG_RUN_HEAVY=1` (see `tests/README.md`). + +## Per-PR agent task contract + +When executing a section from `plans/CURSOR-PROMPTS-*.md`: + +- Treat **Out of scope** as binding; sentinel `rg` patterns must be zero on `git diff master..HEAD`. +- Implement deliverables in order; match named `test_*` when listed. +- Include manual evidence and iteration pytest subset per the prompt; reviewers use the **`pr-review`** skill. + +## Environment (Claude Code) + +- Python 3.11+ with `.venv` at repo root; use **only** `.venv/bin/python`, `.venv/bin/pip`, `.venv/bin/ruff`. +- Install editable: `pip install -e .` so `java-codebase-rag` is on `PATH`. +- MCP: copy `mcp.json.example` to `.mcp.json` or `claude mcp add` per README §3. + +### Hello-world verification + +```bash +rm -rf /tmp/check && .venv/bin/python build_ast_graph.py \ + --source-root tests/bank-chat-system \ + --kuzu-path /tmp/check/code_graph.kuzu --verbose +.venv/bin/java-codebase-rag meta \ + --source-root tests/bank-chat-system --index-dir /tmp/check +``` + +The MCP server is stdio-based — invoked by Claude Code / Claude Desktop, not as a long-running dev server. diff --git a/README.md b/README.md index d498fac..7b757bf 100644 --- a/README.md +++ b/README.md @@ -223,6 +223,17 @@ claude mcp add --transport stdio java-codebase-rag -- \ Set env vars (`JAVA_CODEBASE_RAG_INDEX_DIR`, `JAVA_CODEBASE_RAG_SOURCE_ROOT`, `SBERT_MODEL`, …) in `.mcp.json` or your shell profile. Official docs: [Claude Code settings](https://docs.anthropic.com/en/docs/claude-code/settings). +#### Claude Code (maintaining this repo) + +When you work **on** `java-codebase-rag` itself (not a downstream Java project), Claude Code loads: + +- [`CLAUDE.md`](./CLAUDE.md) — entrypoint and hard rules +- [`.claude/rules/`](./.claude/rules/) — modular always-on instructions +- [`.claude/skills/`](./.claude/skills/) — `propose`, `plan-project-scope`, `plan-prompts`, `pr-review`, `pr-open`, `java-codebase-explore` +- [`.claude/settings.json`](./.claude/settings.json) — allowlisted `.venv/bin/python`, `ruff`, `pytest`, `gh` + +Cursor contributors use the same workflow via [`AGENTS.md`](./AGENTS.md) and [`.cursor/skills/`](./.cursor/skills/) (mirrors of `.claude/skills/`). Per-PR implementation handoffs live in [`plans/CURSOR-PROMPTS-*.md`](./plans/) (host-neutral prompt bodies). + ### Claude Desktop Edit `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`) and add an entry under `mcpServers` with the same `command`, `args`, and `env` as in `mcp.json.example`. diff --git a/automation/cursor_propose_only/README.md b/automation/cursor_propose_only/README.md index 316da41..2a65b7f 100644 --- a/automation/cursor_propose_only/README.md +++ b/automation/cursor_propose_only/README.md @@ -1,9 +1,13 @@ -# Cursor propose-only automation +# Propose-only automation (Cursor and Claude Code) This workflow is intentionally isolated under `automation/cursor_propose_only/` so orchestration sources are not mixed with production runtime code, main docs, or the primary test suite. +Command templates are **host-specific** (`cursor-agent` vs `claude -p`). The Python +orchestration (`prepare`, `evaluate`, `execute`, `autopilot`) is host-agnostic; +only the `--*-command` strings change. + ## Commands From repository root: @@ -92,6 +96,33 @@ tasks as `ready_to_merge` / `merged`. --run ``` +### Claude Code equivalents + +Use non-interactive Claude Code with the staged prompt files (from repo root; requires +[`.claude/settings.json`](../../.claude/settings.json) or your user permissions): + +```bash +.venv/bin/python automation/cursor_propose_only/execute.py \ + --repo-root . \ + --workflow reports/propose_automation/workflow.json \ + --rounds 3 \ + --min-severity medium \ + --implementation-command 'claude -p "$(cat {task_prompt_file})" --output-format json' \ + --review-command 'claude -p "$(cat {review_prompt_file})" --output-format json' \ + --merge-command 'gh pr merge {pr_url} --squash --delete-branch' \ + --run +``` + +Planning / autopilot: substitute the same pattern for `{planner_prompt_file}`, +`{review_prompt_file}`, and `{task_prompt_file}` on `autopilot.py` (`--planner-command`, +`--planning-review-command`, `--implementation-command`, `--implementation-review-command`). + +Example planner line: + +```bash +--planner-command 'claude -p "$(cat {planner_prompt_file})" --output-format json' +``` + Notes: - without `--run`, `execute.py` performs a dry-run and only stages prompts/state diff --git a/propose/CLAUDE-CODE-PARITY-PROPOSE.md b/propose/CLAUDE-CODE-PARITY-PROPOSE.md new file mode 100644 index 0000000..2302e14 --- /dev/null +++ b/propose/CLAUDE-CODE-PARITY-PROPOSE.md @@ -0,0 +1,81 @@ +# CLAUDE-CODE-PARITY — first-class Claude Code maintainer agent config + +**Status**: implemented (this propose documents the landed work). + +**Author**: Agent (feat/claude-code-migration) + +**Date**: 2026-05-20 + +--- + +## Problem Statement + +The java-codebase-rag **MCP product** is host-agnostic (README documents Claude Code MCP setup), but **maintainer ergonomics** are Cursor-only: + +- Always-on rules live under `.cursor/rules/*.mdc` (Cursor frontmatter). +- Workflow skills live under `.cursor/skills/` (propose, plan, review, PR open). +- `AGENTS.md` points exclusively at Cursor. +- Per-PR handoffs (`plans/CURSOR-PROMPTS-*.md`) work in Claude prompts but nothing tells Claude Code to load repo conventions. +- Optional automation (`automation/cursor_propose_only/`) documents `cursor-agent` only. + +Contributors using Claude Code get README + raw plans without the same guardrails Cursor agents receive. + +## Proposed Solution + +Add a **dual-host** layout: + +| Layer | Cursor | Claude Code (canonical for shared prose) | +|-------|--------|------------------------------------------| +| Entry | `AGENTS.md` | `CLAUDE.md` + `AGENTS.md` (dual-host) | +| Rules | `.cursor/rules/*.mdc` | `.claude/rules/*.md` | +| Skills | `.cursor/skills/*` (optional copy to `~/.cursor/skills/`) | `.claude/skills/*` | +| Settings | (IDE defaults) | `.claude/settings.json` | +| Per-PR prompts | `plans/CURSOR-PROMPTS-*.md` | Same files (host-neutral bodies; `@` attachments work) | +| Subagents | — | `.claude/agents/implementer.md`, `reviewer.md` | +| Exploration | `docs/skills/java-codebase-explore.md` | `.claude/skills/java-codebase-explore/SKILL.md` (`@` import) | + +**Naming:** Keep `CURSOR-PROMPTS-*` filenames in v1; skills/docs say "agent execution prompts" for both hosts. + +**No sync script** in v1 — accept short-term duplication between `.cursor/` and `.claude/` with cross-links in `AGENTS.md` / `CLAUDE.md`. + +## Scope + +- `CLAUDE.md` at repo root +- `.claude/rules/` (four files ported from `.cursor/rules/`) +- `.claude/settings.json` (venv, ruff, pytest, gh allowlist) +- `.claude/skills/` (five maintainer skills + java-codebase-explore wrapper) +- `.claude/agents/` (implementer, reviewer) +- `AGENTS.md`, `README.md`, `tests/README.md` dual-host wording +- `.github/workflows/test.yml` — `.claude/**` in docs-only path filter +- `automation/cursor_propose_only/README.md` — example `claude -p` invocations + +## Schema / Ontology / Re-index impact + +- Ontology bump: **not required** +- Re-index required: **no** +- MCP / tool surface: **unchanged** + +## Tests / Validation + +- Docs-only PRs: CI `test` job green (pytest skipped). +- No production `*.py` changes except copying `create_pr.py` under `.claude/skills/pr-open/`. +- Manual smoke: open repo in Claude Code; confirm skills; run one `plans/CURSOR-PROMPTS-*` PR block. + +## Out of scope + +- Deleting or replacing `.cursor/` +- Renaming `CURSOR-PROMPTS-*` → `AGENT-PROMPTS-*` +- Perplexity `.zip` repackaging of `java-codebase-explore` +- Renaming `automation/cursor_propose_only/` package +- MCP server or indexer behavior changes + +## Sequencing + +| PR | Deliverables | +|----|----------------| +| PR-1 | `CLAUDE.md`, `.claude/rules/`, `.claude/settings.json`, `AGENTS.md`, README | +| PR-2 | `.claude/skills/*` (5 skills), `tests/README.md`, CI path filter | +| PR-3 | `java-codebase-explore` skill, `.claude/agents/*` | +| PR-4 | Automation README `claude -p` examples | + +Land as one branch (`feat/claude-code-migration`) or split per table; move this file to `propose/completed/` when merged. diff --git a/tests/README.md b/tests/README.md index c9e86e5..4fd8913 100644 --- a/tests/README.md +++ b/tests/README.md @@ -33,9 +33,9 @@ cd /path/to/java-codebase-rag ## CI merge gate and fixture tiers -**Merge gate (mechanical):** [`.github/workflows/test.yml`](../.github/workflows/test.yml) always runs the `test` job on every pull request and on every push to `master`. When any **source** path changes (Python, deps, `pytest.ini`, `mcp.json.example`, `.gitignore`, workflows, non-markdown under `tests/` or `automation/`), it runs `pytest tests` with `JAVA_CODEBASE_RAG_RUN_HEAVY=0`. Documentation-only changes (`propose/`, `plans/`, `reports/`, `.cursor/`, `docs/`, `**/*.md`, etc.) still produce a green `test` check but skip pytest. Branch protection on `master` requires the `test` status check to pass before merge and disables force-push. Break-glass policy: `enforce_admins: false` so the sole maintainer can bypass for emergency hotfixes — explain the bypass in the merge commit. +**Merge gate (mechanical):** [`.github/workflows/test.yml`](../.github/workflows/test.yml) always runs the `test` job on every pull request and on every push to `master`. When any **source** path changes (Python, deps, `pytest.ini`, `mcp.json.example`, `.gitignore`, workflows, non-markdown under `tests/` or `automation/`), it runs `pytest tests` with `JAVA_CODEBASE_RAG_RUN_HEAVY=0`. Documentation-only changes (`propose/`, `plans/`, `reports/`, `.cursor/`, `.claude/`, `docs/`, `**/*.md`, etc.) still produce a green `test` check but skip pytest. Branch protection on `master` requires the `test` status check to pass before merge and disables force-push. Break-glass policy: `enforce_admins: false` so the sole maintainer can bypass for emergency hotfixes — explain the bypass in the merge commit. -**Iteration subset (convention):** During implementation, authors name a `pytest` file subset inside each per-PR execution prompt (for example in `plans/CURSOR-PROMPTS-*.md`). The repo **[`plan-prompts`](../.cursor/skills/plan-prompts/SKILL.md)** skill (`.cursor/skills/plan-prompts/`) requires a **`## Tests to run (iteration loop)`** section in that scaffold, placed **after Deliverables and before Tests**. Reviewers follow the repo **[`pr-review`](../.cursor/skills/pr-review/SKILL.md)** skill (`.cursor/skills/pr-review/`): pasted subset command + exit code, plus a green `test` CI link from the merge gate documented above (full pytest for code changes; pytest skipped for docs-only PRs). Canonical skill sources live under `.cursor/skills/`; you may copy them into `~/.cursor/skills/` if your Cursor setup loads personal skills only. See [`propose/completed/TEST-SUITE-FAST-LOOP-PROPOSE.md`](../propose/completed/TEST-SUITE-FAST-LOOP-PROPOSE.md) and [`plans/completed/PLAN-TEST-SUITE-FAST-LOOP.md`](../plans/completed/PLAN-TEST-SUITE-FAST-LOOP.md). +**Iteration subset (convention):** During implementation, authors name a `pytest` file subset inside each per-PR execution prompt (for example in `plans/CURSOR-PROMPTS-*.md`). The repo **`plan-prompts`** skill requires a **`## Tests to run (iteration loop)`** section in that scaffold, placed **after Deliverables and before Tests**. Canonical copies: [`.claude/skills/plan-prompts/SKILL.md`](../.claude/skills/plan-prompts/SKILL.md) (Claude Code); [`.cursor/skills/plan-prompts/SKILL.md`](../.cursor/skills/plan-prompts/SKILL.md) (Cursor — may copy to `~/.cursor/skills/`). Reviewers follow **`pr-review`**: [`.claude/skills/pr-review/`](../.claude/skills/pr-review/) / [`.cursor/skills/pr-review/`](../.cursor/skills/pr-review/) — pasted subset command + exit code, plus a green `test` CI link from the merge gate documented above (full pytest for code changes; pytest skipped for docs-only PRs). See [`propose/completed/TEST-SUITE-FAST-LOOP-PROPOSE.md`](../propose/completed/TEST-SUITE-FAST-LOOP-PROPOSE.md) and [`plans/completed/PLAN-TEST-SUITE-FAST-LOOP.md`](../plans/completed/PLAN-TEST-SUITE-FAST-LOOP.md). **Fixture tiers (PR-1):**