Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions DELEGATE-PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# DELEGATE-PLAN — v0.5.7 QA green

**Repo:** `/Users/macbookair/Documents/Visual Studio Code/MCP/gate-mcp`
**Done when:** `npm test` exit 0 AND `node dist/main.js doctor --strict` pass
**No commit** unless user asks.

## Repro (2026-10-12)

| Command | Result |
|---------|--------|
| `npm test` | 47 passed, 2 failed |

### Failures

1. **Test 34 — AlgoTrading SMC** — `handleGraphQuery` with `projectRoot: algoSmc` while `GATE_PROJECT_ROOT` = gate-mcp → boundary error.
2. **Test 42 — cachePartition** — `mkdtemp` `/var/...` vs canonical `/private/var/...`.

## Tasks

| ID | Owner | Scope | Fix | Status |
|----|-------|-------|-----|--------|
| T1 | implementer (`b8ab98b6`) | `src/test.ts` | Temp set `GATE_PROJECT_ROOT=algoSmc` for Test 34, restore in `finally` | [x] verified |
| T2 | implementer (`b8ab98b6`) | `src/test.ts`, `scripts/qa-multi-repo-proof.mjs` | Compare `cachePartition` to `canonicalizePath` / `realpathSync.native`; qa assert added as regression guard | [x] verified |
| T3 | parent (orchestrator) | — | `npm run build`, `npm run test:unit`, `npm test`, `doctor --strict` | [x] verified |

## Verification (orchestrator, 2026-10-12 08:12, Node 22.21.1)

| Command | Exit | Result |
|---------|------|--------|
| `npm run build` | 0 | tsc clean |
| `npm run test:unit` | 0 | 49 passed, 0 failed |
| `npm test` | 0 | unit 49/0 + qa-multi-repo pass + adversarial `failedCount: 0` |
| `node dist/main.js doctor --strict` | 0 | 10/10 PASS, `ok: true` |

Re-verified after moving fixes onto branch `fix/qa-057` from `origin/main` (8547e2e): build 0, `npm test` 0, same counts.

Review notes: Test 34 fix is test-side (product boundary refusal is intended security behavior). Test 34 only runs on machines with the AlgoTrading SMC checkout; skips elsewhere.

## Acceptance

```bash
npm run build
npm run test:unit
npm test
node dist/main.js doctor --strict
```

## Out of scope

- graphify node-count drift warnings
- EPIPE on MCP stdio after test suite (non-failing noise)

---

# Next — end-user docs (done) + React demo (plan only)

Constraints: Gate stays standalone; graphify is a separate tool, no bundling.
Ask the user before any graphify integration or caveman-in-code change.

## D1 — README end-user docs [x]

- `What Gate compresses — and what it does not` (tool results only; not prompts, built-in Read, or model output; meaning of `Savings: n/a`).
- `Reading gate_session_stats` — persistent-cache fields vs process-wide fields, `measurement_scope`, `billingScope`, honest example.
- `Pin Node in mcp.json` — absolute `node` + `dist/main.js` paths; `NODE_MODULE_VERSION` symptom; verify with `doctor --strict`.
- Known limitations: code generation, native SQLite rows.

## P1 — React demo script: full read vs compress (PLAN ONLY — do not build until user says)

Goal: reproducible, honest before/after numbers for marketing, from one command.

| Step | Detail |
|------|--------|
| Fixture | Pin a public React repo at a fixed commit (e.g. a mid-size Vite + React app), cloned to a temp dir — not vendored |
| Task | Fixed "work loop": 8–12 files a real agent touches for one feature (component, hook, context, API client, test) |
| Baseline | Raw file bytes + BPE tokens (same counter as `tokenCounter.ts`) for each file |
| Gate | Spawn `dist/main.js` over MCP stdio; call `gate_compress_file` `signature` per file, then a second pass to show dedup hits; finish with `gate_session_stats` |
| Output | `demo/react-demo-result.json` + Markdown table: file, raw tokens, Gate tokens, %, `expanded` flag |
| Honesty | Label `billingScope: tool_payload_only`; include files where Gate expands or saves ~0; show that edits still need a `full` read |

Files: `scripts/demo-react-compare.mjs` (new), `package.json` script `demo:react`, README "Benchmarks" link.
Acceptance: deterministic numbers on two runs; no network after clone; runs on Node 20 and 22.
Risks: picking a repo that flatters Gate — choose before seeing numbers; signature-only views are not enough to edit code, so the demo must say so.
143 changes: 134 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,31 @@ Architecture detail: [`ARCHITECTURE.md`](ARCHITECTURE.md).

`gate_help` with `tool: "recommended_stack"` is the agent-facing playbook.

<a id="what-gate-compresses"></a>

### What Gate compresses — and what it does not

Gate only shrinks **results of Gate tool calls**. It is a tool your agent
chooses to call, not a filter on the whole conversation.

| Gate reduces | Gate does **not** touch |
|---|---|
| `tools/list` schema size (catalog mode) | Your prompts and chat history |
| File views returned by `gate_compress_file` | The editor's built-in `Read` / `Grep` / terminal output |
| Graph answers from `gate_graph_query` | Rules, system prompt, attached files |
| Re-reads of unchanged files (SQLite dedup) | Model output — generated code and replies |
| JSON passed to `gate_clean_response` | Other MCP servers (unless routed through the opt-in proxy) |
| Images passed to `gate_optimize_image` | Your provider bill — see `billingScope` below |

What this means in practice:

- If the agent never calls a Gate tool, savings are **zero**. Add a rule
telling your agent to use `gate_compress_file` before full reads.
- An agent footer such as `Savings: n/a` means no Gate compression ran that
turn. It does not mean Gate is broken. Run `gate_init` to confirm health.
- Gate cannot shrink code generation. Smaller input context leaves more room
for output, but the output itself is the model's.

---

<a id="get-started-60-seconds"></a>
Expand All @@ -157,10 +182,10 @@ npm exec --yes --strict-allow-scripts \
--package=@gatemcp/cli -- gatemcp
```

Package: `@gatemcp/cli` · binary: `gatemcp` · current: **0.5.7**.
Package: `@gatemcp/cli` · binary: `gatemcp` · current: **0.5.8**.

Then wire your IDE (Cursor snippet below). Run **`gate_init`** once per workspace.
Doctor: `npx --package=@gatemcp/cli@0.5.7 gatemcp doctor /abs/path/to/repo --strict`.
Doctor: `npx --package=@gatemcp/cli@0.5.8 gatemcp doctor /abs/path/to/repo --strict`.

<details>
<summary><strong>Install from source</strong></summary>
Expand Down Expand Up @@ -201,6 +226,54 @@ narrow (never widen).

</details>

<a id="pin-node-for-sqlite"></a>

<details>
<summary><strong>Pin Node in <code>mcp.json</code></strong> — fixes SQLite <code>NODE_MODULE_VERSION</code> errors</summary>

`better-sqlite3` is a native module. It is compiled for the Node version that
ran `npm install`. Your IDE may launch MCP servers with a **different** Node
(nvm, Homebrew, Volta, or a GUI app `PATH` without your shell profile).

Symptoms:

- Server fails to start, or `gate_init` / `gate_session_stats` shows `persistentCache: false`
- Log line like `was compiled against a different Node.js version using NODE_MODULE_VERSION 127. This version of Node.js requires NODE_MODULE_VERSION 137`

Fix: point the IDE at the **same** Node binary that installed Gate. In the
terminal where you installed it:

```bash
which node # e.g. /Users/you/.nvm/versions/node/v22.21.1/bin/node
echo "$(npm root -g)/@gatemcp/cli/dist/main.js"
```

Then use both absolute paths:

```json
{
"mcpServers": {
"gatemcp": {
"command": "/Users/you/.nvm/versions/node/v22.21.1/bin/node",
"args": ["/Users/you/.nvm/versions/node/v22.21.1/lib/node_modules/@gatemcp/cli/dist/main.js"],
"env": {
"GATE_PROJECT_ROOT": "/absolute/path/to/your/repo"
}
}
}
}
```

Verify with the same Node:
`/path/to/node /path/to/dist/main.js doctor /absolute/path/to/your/repo --strict` —
`cache_access` must say `SQLite write/reopen probe passed`.

If you switch Node versions later, reinstall Gate under the new version (or
keep the pin). Avoid `GATE_ALLOW_MEMORY_CACHE=1` as a fix — it hides the
problem and turns off persistent dedup.

</details>

<details>
<summary><strong>Claude Code / Windsurf / Antigravity / VS Code / Codex</strong></summary>

Expand All @@ -218,7 +291,7 @@ narrow (never widen).
codex plugin marketplace add Dukeabaddon/Gate-MCP && codex plugin add gatemcp@dukeabaddon-gate-mcp
```

Restart the thread after install. Plugin pins `@gatemcp/cli@0.5.7`.
Restart the thread after install. Plugin pins `@gatemcp/cli@0.5.8`.

</details>

Expand Down Expand Up @@ -257,12 +330,46 @@ savings stay `0`.
| `billingScope` | `"tool_payload_only"` — **not** Cursor billed tokens |
| `expanded: true` | Output grew; `savingsPercent` forced to `0` |

`gate_session_stats` mixes path-filtered persistent cache totals with
process-wide counters for the MCP instance. See prior release notes for the
exact field split.

</details>

<a id="reading-gate-session-stats"></a>

### Reading `gate_session_stats`

The result has two groups of numbers with **different scopes**. Do not add
them together.

**Persistent cache** — stored in SQLite, survives IDE restarts, filtered by `projectRoot`:

| Field | Meaning |
|---|---|
| `persistentCache` | `true` = SQLite. `false` = in-memory fallback; run `gatemcp doctor --strict` (often a [Node pin](#pin-node-for-sqlite) issue) |
| `cachePartition` | Canonical `GATE_PROJECT_ROOT` the DB belongs to (macOS shows `/private/var` for `/var`) |
| `projectRoot` | Path filter applied to the totals below |
| `totalEntries` | Files cached under that path |
| `totalHits` | Times an unchanged file was served from cache |
| `totalTokensSaved` | Cumulative raw-file tokens minus cached-view tokens on those hits |
| `topEntries` | Top 10 files by activity |

**This MCP process** — reset when the server restarts, counts every repo the process served:

| Field | Meaning |
|---|---|
| `files_considered` / `files_compressed` | Files Gate read / returned a smaller view for |
| `input_bytes` / `output_bytes` | Raw file bytes in vs tool-result bytes out |
| `estimated_tokens_before` / `estimated_tokens_after` | Same, as BPE token estimates |
| `cache_hits` | Dedup hits in this process |
| `elapsed_ms` / `session_elapsed_ms` | Gate processing time / server uptime |

Labels on every result:

- `measurement_scope: "serialized_tool_result_excluding_mcp_envelope"` — what was measured.
- `billingScope: "tool_payload_only"` — **not** your Cursor / provider bill. Your bill also includes prompts, history, rules, other tools, and model output.

Example from one real session: `estimated_tokens_before: 6622`,
`estimated_tokens_after: 666` → Gate tool results were ~90% smaller than the
raw files. That is the honest claim; it is not "90% off your bill".

<details>
<summary><strong>Multi-repo / one global MCP</strong></summary>

Expand Down Expand Up @@ -385,7 +492,7 @@ With gatemcp (agent actually calls Gate):

## By the numbers

- **`@gatemcp/cli@0.5.7`** on npm — binary `gatemcp`
- **`@gatemcp/cli@0.5.8`** on npm — binary `gatemcp`
- **Catalog-first** tool surface (schema anti-bloat)
- **12** tools (6 hot-path in catalog + long tail via `gate_invoke`)
- **20+** languages via tree-sitter / regex fallback
Expand Down Expand Up @@ -454,7 +561,9 @@ Codex: remove the plugin from the Codex UI / plugin list. Source installs: `npm

| Area | Behavior |
|------|----------|
| **Opt-in only** | Zero savings if the agent never calls Gate |
| **Opt-in only** | Zero savings if the agent never calls Gate — see [what Gate compresses](#what-gate-compresses) |
| **Code generation** | Model output is never compressed; Gate only shrinks tool results |
| **Native SQLite** | IDE must run the same Node that installed Gate — see [Pin Node](#pin-node-for-sqlite) |
| **gate graph vs graphify** | Different graphs; use `graphify_*` for communities |
| **Graph savings %** | Symbol queries use a modeled baseline; `graphify_map` baselines the report file |
| **Cursor MCP name** | May appear as `user-gatemcp` |
Expand Down Expand Up @@ -491,6 +600,22 @@ Node **20** and **22–26** (Node 21 unsupported by required better-sqlite3).
## Changelog

<details open>
<summary><strong>v0.5.8</strong> — dependency security fixes, end-user docs</summary>

**Security.** `sharp` 0.35.3 → 0.35.5 (libheif / librsvg advisories). Lockfile
refresh clears transitive advisories in `proxy-addr`, `ip-address`, `fast-uri`,
`hono`, and `qs`. `npm audit --omit=dev` reports 0.

**Docs.** [What Gate compresses](#what-gate-compresses),
[reading `gate_session_stats`](#reading-gate-session-stats), and
[pinning Node for SQLite](#pin-node-for-sqlite).

**QA.** macOS `/var` vs `/private/var` canonical-path fixes in test scripts.
No tool behavior changes.

</details>

<details>
<summary><strong>v0.5.7</strong> — catalog mode, required SQLite, symbol HTML</summary>

**Schema budget.** Default `GATE_TOOL_MODE=catalog` lists six core tools plus
Expand Down
Loading
Loading