# Contributing to lean-ctx

Thanks for your interest in lean-ctx — contributions are welcome.

## Spec-driven workflow (non-trivial changes)

lean-ctx develops non-trivial features **spec-anchored** (review-gated SDD):

```text
spec → plan → tasks → implement (impact-first) → verify → evidence
```

1. **Spec** — `specs/NNN-<slug>/spec.md` (copy `specs/_template/`); `NNN` = tracking
   issue iid, acceptance criteria in EARS. One feature = one dir.
2. **Plan** — draft in your agent's plan mode (e.g. Cursor Plan Mode `Shift+Tab`),
   then distill the approved approach into `specs/NNN-<slug>/plan.md`.
   Review before coding.
3. **Tasks** — `specs/NNN-<slug>/tasks.md`: atomic, individually testable.
4. **Implement** — impact-first: run `ctx_impact` (or `lean-ctx graph impact <file>`)
   before editing `rust/src/**` and verify the affected tests.
5. **Verify** — `scripts/preflight.sh fast` + the affected tests.
6. **Evidence** — cite the spec in commits (`refs specs/NNN-<slug>`), link issue #NNN.

Skip the full loop for trivial fixes; use it for features, contracts, and anything
touching the tool/CLI surface. See `specs/README.md`.

## Quick start (core Rust binary)

### Prerequisites

- Rust (stable) via [rustup](https://rustup.rs/)
- Git
- A C toolchain (`cc`, plus `cmake` for `aws-lc`) — several dependencies
  (jemalloc, `aws-lc`, …) build from source

### Setup

```bash
git clone https://github.com/yvgude/lean-ctx.git
cd lean-ctx/rust

cargo build
cargo test
```

### Quality bar (required)

```bash
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features
cargo test --release
```

### Pre-push gate (CI parity)

`make setup-hooks` wires a pre-push hook that runs `scripts/preflight.sh fast` —
the deterministic CI jobs (fmt, clippy, rustdoc, generated-docs drift, Windows
cross-compile) mirrored locally so you catch them in seconds, not after a 50-min
matrix. It is **change-aware**: a docs-only push (README, CHANGELOG, `*.md`,
website, …) skips the Rust gates entirely, while CI still runs every job as the
source of truth. Run the full gate (everything + `cargo test --lib`, ignoring the
diff) with `make preflight`. Bypass once with `SKIP_PREFLIGHT=1 git push`.

A change to contract code (`proxy/`, `tools/`, `config/schema/`) that ships no
test signal triggers a **no-test advisory**; export
`LEAN_CTX_PREFLIGHT_STRICT_TESTS=1` to make it blocking.

## Building across worktrees & disk usage

lean-ctx pulls in a **heavy native-dependency tree** (jemalloc, an `aws-lc`
crypto build, tree-sitter grammars, …), so a debug build is larger than the Rust
source alone suggests. A couple of things worth knowing so it doesn't surprise
your disk:

- **Each `git worktree` gets its own `target/`.** Keep several PR checkouts open
  and Cargo compiles the full native tree *per worktree*, sharing nothing
  between them.
- **`target/debug` never garbage-collects.** Stale incremental units and old
  dependency versions accumulate, so one heavily-rebuilt `target/` can reach
  **tens of GB** (vs. ~2 GB for a clean build).

### A shared compilation cache (recommended)

[`sccache`](https://github.com/mozilla/sccache) deduplicates dependency compiles
across worktrees and branches, without the build-lock contention a shared
`CARGO_TARGET_DIR` introduces:

```bash
cargo install sccache
export RUSTC_WRAPPER=sccache   # add to your shell profile
```

> A single shared `CARGO_TARGET_DIR` also dedups, but Cargo holds a per-target
> build lock, so concurrent builds across worktrees **serialize**.

### Prune stale artifacts

[`cargo-sweep`](https://github.com/holmgr/cargo-sweep) drops build artifacts past
a cutoff so `target/` can't grow without bound:

```bash
cargo install cargo-sweep
cargo sweep --time 7      # remove artifacts unused for > 7 days
```

### Reclaim space fast

`target/` is always safe to delete — it's pure build output and regenerates on
the next build:

```bash
cargo clean               # this checkout's target/
du -sh target             # check current size
```

Debug info is the bulk of that size: this repo sets
`[profile.dev] debug = "line-tables-only"`, which keeps `file:line` in panics and
backtraces while dropping full variable-level data. Set `debug = 2` in a local
profile override if you need to step-debug.

## Cookbook / SDK / extensions (optional)

If you contribute to `cookbook/` or `packages/`, you’ll also need:

- Node.js (>= 22.12.0)
- npm

```bash
cd cookbook
npm ci
npm test
```

## Repo structure

```text
lean-ctx/
├─ rust/                 # core binary (CLI + MCP server + shell hook)
│  ├─ src/
│  │  ├─ main.rs         # CLI entry point
│  │  ├─ lib.rs          # library entry point (shared core)
│  │  ├─ mcp_stdio.rs    # MCP stdio transport
│  │  ├─ server/         # MCP server state + dispatch
│  │  ├─ tools/          # MCP tool handlers (ctx_read, ctx_shell, ...)
│  │  ├─ core/           # cache, compression, patterns/, memory, graphs, ...
│  │  ├─ cli/            # CLI subcommands (setup, init, read, ...)
│  │  └─ hooks/          # editor/agent installers (Cursor, Claude Code, ...)
│  └─ tests/             # integration/e2e/adversarial tests
├─ cookbook/             # real examples + lean-ctx-client
├─ packages/             # editor integrations (VSCode, Chrome, JetBrains, ...)
├─ docs/                 # repo docs (developer-facing)
└─ website/generated/    # generated schemas (tool + TDD schema)
```

## Common contribution types

### Add a shell compression pattern

1. Add a new module in `rust/src/core/patterns/<tool>.rs`
2. Implement:

```rust
pub fn compress(command: &str, output: &str) -> Option<String>
```

3. Register the module + routing in `rust/src/core/patterns/mod.rs` (`try_specific_pattern`)
4. Add tests (unit tests in the module or integration tests in `rust/tests/`)
5. Run the quality checks above

Tip: open a ticket via the [New Compression Pattern](.github/ISSUE_TEMPLATE/compression_pattern.md) template and include raw output + expected compressed output.

### Add or update an MCP tool

- Core handler logic lives in `rust/src/tools/ctx_*.rs` — keep it pure and
  deterministic (#498). See `ctx_explore.rs` for the citation-returning
  exploration pattern (BM25 + static graph + AST, bounded turns, no session writes).
- The MCP adapter (implements `McpTool`) lives in `rust/src/tools/registered/ctx_*.rs`:
  schema via `tool_def`, arg parsing, `ToolOutput`. Register it in
  `rust/src/server/registry.rs` and bump the count SSOT in `rust/src/server/mod.rs`
  (`test_registry_tool_count_ssot`).
- For a CLI surface, add `rust/src/cli/<name>_cmd.rs` and route it in
  `rust/src/cli/dispatch/mod.rs` (+ `dispatch/help.rs`).
- Regenerate and commit the SSOT artifacts:
  `cargo run --example gen_mcp_manifest --features dev-tools` and
  `cargo run --example gen_docs --features dev-tools`.
- If you change the public tool surface, also update `LEANCTX_FEATURE_CATALOG.md`
  (SSOT snapshot). The `entrypoints_wired`, `mcp_manifest_up_to_date` and
  `reference_docs_drift` tests gate the wiring end to end.

### Add an addon to the registry

An addon entry in `rust/data/addon_registry.json` ships **executable trust** to
every user (a `stdio` addon runs code on their machine; an `http` addon receives
their context). Registry submissions are therefore reviewed like a security
change, not a docs change. See the
[addon manifest contract](docs/contracts/addon-manifest-v1.md#security-model).

**Your submission must:**

1. Use a unique slug `[a-z0-9-]` and fill `author`, `homepage`, `license`,
   `description` (the CI validator rejects installable entries that don't).
2. **Pin the upstream.** No `latest`, no `npx/uvx`-without-a-version. The exact
   command + version must be reproducible.
3. Not shell out (`sh -c`, `bash -c`), fetch-and-exec (`curl`, `wget`), or use a
   non-HTTPS `url`. The validator flags all of these.
4. Point `homepage` at **public, inspectable source** for the MCP server.
5. Default to the **community** tier (`verified` stays `false`) — verification is
   conferred by review, never self-asserted.

Run the validator locally — it runs in CI on every change to the registry:

```bash
cd rust && cargo test --lib addons::registry
```

**Maintainer review checklist (binding):**

- [ ] Source is public and the MCP server's behaviour matches its description.
- [ ] Command/args/url are pinned and reproducible; no shell/fetch primitives.
- [ ] `env` / `headers` carry no embedded secrets; any required secret is the
      user's to supply, documented on the homepage.
- [ ] License is a real SPDX id and compatible with redistribution of the entry.
- [ ] `verified = true` requires **two** maintainer approvals **and** a clean
      run with **no** `warn`/`danger` finding. Otherwise it stays community-tier.
- [ ] When in doubt, merge as a **listed** entry (no `[mcp]` block) first.

### Docs & examples

- Prefer real, runnable examples (no mock data)
- If you add a new example app, add it under `cookbook/examples/` and ensure it talks to a real `lean-ctx serve` instance

## Issues

- If your issue was closed but the problem persists, comment `/reopen` on it — as the original author, this reopens the issue automatically (GitHub itself does not let authors reopen maintainer-closed issues). The command is matched anywhere in your comment, so "Please `/reopen`" works too; issues closed as *not planned* stay a maintainer call
- Issues closed as *not planned* are maintainer decisions and are not reopened automatically; a comment is still welcome

## Pull requests

- Keep PRs focused (one theme per PR)
- Include a short test plan (commands you ran)
- If relevant, include a small “before/after” token-savings snippet

## Contributor License Agreement (CLA)

Before your first pull request can be merged, you need to sign our
[Contributor License Agreement](CLA.md). It is a one-time, automated step: the
CLA Assistant bot comments on your PR, and you sign by replying:

> I have read the CLA Document and I hereby sign the CLA

The CLA keeps lean-ctx Apache-2.0 for everyone while allowing the maintainer to
relicense (e.g. for the hosted/commercial offering). The free, open-source
runtime for individual developers stays free — that commitment is written into
the CLA itself (§8).

## License

lean-ctx is distributed under the Apache License 2.0; by contributing, your
contributions are licensed to the public under the same terms (see the [CLA](CLA.md)
for the full grant).
