leankg 0.19.21

Lightweight Knowledge Graph for AI-Assisted Development
# LeanKG - AI Agent Context

## Project Overview

LeanKG is a lightweight knowledge graph for codebase understanding. It indexes code, builds dependency graphs, calculates impact radius, and exposes everything via MCP for AI tool integration.

**Tech Stack:** Rust + CozoDB + tree-sitter + MCP

## Quick Start

```bash
# Index a codebase
cargo run -- init
cargo run -- index ./src

# Calculate impact radius
cargo run -- impact src/main.rs 3

# Start MCP server
cargo run -- serve
```

## Development Workflow

**When implementing features, follow:** `docs/workflow-opencode-agent.md`

### Pattern: Update Docs → Implement → Test → Commit → Push → Bump Version → Tag

1. **Update docs first** - Consolidated PRD+HLD (`docs/prd.md`) → README as needed
2. **Implement** - Follow patterns in `docs/workflow-opencode-agent.md`
3. **Build & test** - `cargo build && cargo test`
4. **Commit** - `git commit -m "feat: description"` (one feature per commit)
5. **Push** - `git pull --rebase && git push`
6. **Bump version** - Update `version` in `Cargo.toml`
7. **Tag** - `git tag -a v<version> -m "Release v<version>" && git push origin v<version>` (after version bump)

### Commit Message Rules

- **NEVER** add `Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>` to commits
- **NEVER** add `🤖 Generated with Claude Code` or similar AI attribution
- **NEVER** add "Generated by" phrases in PR descriptions

## Key Commands

**IMPORTANT: Always use `--release` flag for builds. Debug builds are disabled.**

```bash
cargo build --release  # Build project (release)
cargo test             # Run tests
cargo run --release -- <cmd>  # Run CLI commands
```

## Important Files

| File | Purpose |
|------|---------|
| `src/lib.rs` | Module exports |
| `src/db/models.rs` | Data models (CodeElement, Relationship, BusinessLogic) |
| `src/graph/query.rs` | Graph query engine |
| `src/mcp/tools.rs` | MCP tool definitions |
| `src/mcp/handler.rs` | MCP tool handlers |
| `src/indexer/extractor.rs` | Code parsing with tree-sitter |

## Data Model

- **CodeElement** - Files, functions, classes with `qualified_name` (e.g., `src/main.rs::main`)
- **Relationship** - `imports`, `calls`, `tested_by`, `references`, `documented_by`
- **BusinessLogic** - Annotations linking code to business requirements

## MCP Tools

Core tools: `query_file`, `get_dependencies`, `get_dependents`, `get_impact_radius`, `get_review_context`, `find_function`, `get_call_graph`, `search_code`, `generate_doc`, `find_large_functions`, `get_tested_by`

Doc/Traceability tools: `get_files_for_doc`, `get_doc_structure`, `get_traceability`, `search_by_requirement`, `get_doc_tree`, `get_code_tree`, `find_related_docs`

**Doc↔code prefer-order (v3.7.13):** `search_by_requirement` / `get_traceability` for `FR-*` / `US-*` IDs → `get_files_for_doc` / `find_related_docs` (after `mcp_index_docs`, canonical `docs/…` paths) → `concept_search` / `kg_trace_workflow` → `semantic_search` → `search_code`.

## Verification Status

See `docs/implementation-feature-verification-2026-03-25.md` for test results.

---

## LeanKG Tools Usage

### Prefer-order (discover before connection verbs)

When MCP HTTP on `:9699` is healthy, for fuzzy / NL / “where is X?” questions **discover first** — do **not** open with `query_graph`:

`get_overview_context` → `mcp_status` → `concept_search` → **`search_knowledge`** → **`semantic_search`** → `search_code` / `find_function` → then connection verbs → `get_context` / impact / deps.

| Question type | First tools |
|---------------|-------------|
| Fuzzy / meaning / domain NL | `concept_search`**`search_knowledge`****`semantic_search`**`search_code` |
| Exact symbol / file name | `find_function` / `search_code` / `query_file` |
| How A↔B? (known endpoints) | `shortest_path` |
| What is this known symbol? | `explain_node` |
| Expand subgraph after seeds | `query_graph` (**after** semantic/concept hits) |

**BAN:** Do not call `query_graph` as the first NL discovery tool when embeddings/concepts may answer. Full catalog: [`docs/mcp-tools.md`](docs/mcp-tools.md).

**Dynamic ontology (agent memory):** Agents persist discoveries as `add_ontology_concept` (concept-level: bugs, design insights, domain logic) and `add_ontology_workflow` (procedural: fix sequences, debug procedures, release flows). These survive YAML re-syncs and appear in `concept_search` results. Use `add_knowledge` for free-form notes; `search_knowledge` matches both title and content. Delete only dynamic rows with `delete_ontology_concept`.

### MANDATORY: Docker MCP project paths (not host paths)

When Cursor's LeanKG MCP talks to the Docker HTTP server on `:9699`, RocksDB keys projects by **in-container** mount paths. Host Mac paths fail with "not initialized" even when the index exists.

| Repo / mount | Pass `project=` (container path) | Do NOT pass |
|--------------|-----------------------------------|-------------|
| This LeanKG repo | `/workspace` | `/Users/.../leankg` or `.../leankg/.leankg` |
| Side-by-side monorepo | `/workspace-other` (or whatever bind is in local `docker-compose.override.yml`) | the host path of that repo |
| freepeak polyrepo (if mounted) | `/workspace-freepeak` | `/Users/.../freepeak` |

**Every tool call** must include the container `project` argument, e.g.:

```
mcp_status(project="/workspace")
search_code(query="Handler", project="/workspace")
find_function(name="main", project="/workspace")
get_context(file="src/lib.rs", project="/workspace")
```

**Probe before assuming empty:**

1. `curl http://localhost:9699/health` — Docker MCP up?
2. `mcp_status(project="/workspace")` — this repo indexed?
3. Only if status fails for every known container mount, fall back to stdio/`mcp_init` on a local `.leankg` (non-Docker).

Local-only mount lists live in gitignored `.dockerfile` / `docker-compose.override.yml` (`LEANKG_PROJECT_DIRS`). Never paste personal host bind paths into commits or agent replies.

### MANDATORY: Use LeanKG First, Fallback to Raw Tools

**This is a MANDATORY workflow - not optional guidance.**

#### Step 1: Always Try LeanKG First
1. Call `mcp_status(project="/workspace")` to check if LeanKG is ready for this repo
2. If Docker MCP is down / not ready, try other mounts from `LEANKG_PROJECT_DIRS`, then local `mcp_init` only as last resort
3. **Session overview:** `get_overview_context(project="/workspace")` — not `load_layer(L0)` alone
4. Use appropriate LeanKG tools with `project="/workspace"`: `concept_search``semantic_search``search_code`, `find_function`, `query_file`, `get_impact_radius`, `get_dependencies`, `get_dependents`, `get_tested_by`, `get_context`
5. **Environment filter:** `env=` on search / `kg_*` (hard-removed: `search_by_environment`)

#### Prefer-order (canonical)

| Chain | Tools |
|-------|-------|
| Overview | `get_overview_context` → optional `load_layer``get_architecture` |
| Search | `concept_search``semantic_search``search_code` |
| Env | `env=` on search / `kg_*` |
| File context | `get_context` (default) |

Hard-removed: `mcp_hello`, `mcp_impact`, `get_doc_for_file`, `find_clones`, `wake_up`, `search_by_environment`

#### Step 2: Fallback Only If LeanKG Fails
- LeanKG returns empty results OR
- LeanKG returns error AND you need the data
- THEN you may use `Glob`, `Grep`, `Read` as fallback

#### Step 3: Never Skip LeanKG for Code Search
- NEVER say "I'll just use grep" without trying LeanKG first
- NEVER claim "LeanKG doesn't have this" without actually checking
- NEVER pass a Mac host path as `project` when Docker MCP on `:9699` is healthy

| Task | LeanKG First | Fallback |
|------|--------------|----------|
| Where is X? | `search_code("X", project="/workspace")` | `Grep("X")` |
| Find function | `find_function("name", project="/workspace")` | `Grep("fn name")` |
| What breaks? | `get_impact_radius(file, project="/workspace")` | Manual trace |
| What tests? | `get_tested_by(file, project="/workspace")` | `Grep("test.*file")` |
| Read content | `get_context(file, project="/workspace")` | `Read(file)` |

### Why This Matters
- LeanKG is 10-100x faster than raw grep on large codebases
- LeanKG understands code relationships (imports, calls, tests)
- Raw tools should be emergency fallback only
- Wrong `project` path looks like "LeanKG is broken" when the Docker index is fine

---

## MCP Server Management

### Known Issues
- **MCP HTTP stability**: Zombie processes and stale locks can accumulate on restart. See `docs/analysis/mcp-http-stability-analysis-2026-05-05.md`

### MCP HTTP Server Commands

```bash
# Check if running
lsof -i :9699 2>/dev/null | grep LISTEN

# Verify health
curl http://localhost:9699/health

# Verify SSE endpoint
curl -I http://localhost:9699/mcp/stream

# Clean restart (kill stale processes first)
lsof -ti :9699 | xargs kill -9 2>/dev/null; sleep 1
launchctl stop com.leankg.mcp-http 2>/dev/null; sleep 1
launchctl start com.leankg.mcp-http

# Watch for build changes
./scripts/watch-leankg-build.sh
```

---

*Last updated: 2026-07-17*