carto-md 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BENCHMARK_RESULTS.md +34 -0
- package/CONTRIBUTING.md +28 -2
- package/README.md +1 -0
- package/package.json +3 -2
- package/src/agents/formatter.js +3 -0
- package/src/agents/scan-structure.js +69 -0
- package/src/mcp/change-plan.js +737 -0
- package/src/mcp/server-v2.js +2 -86
- package/src/store/sync-v2.js +5 -3
- package/src/sync.js +1 -18
- package/acp-strategy.md +0 -480
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Carto V2 Benchmark Results
|
|
2
|
+
|
|
3
|
+
Generated: 2026-05-28T17:58:28.019Z
|
|
4
|
+
Platform: Node v20.20.1 · 8 CPUs · 8192.0 MB RAM · darwin arm64
|
|
5
|
+
|
|
6
|
+
| Repo | Source Files | Indexed | First Run | Second Run | DB Size | Routes | Import Edges |
|
|
7
|
+
|------|-------------|---------|-----------|------------|---------|--------|--------------|
|
|
8
|
+
| prisma | 3303 | 3303 | 1.6s | 178ms | 2.2 MB | 10 | 3590 |
|
|
9
|
+
| supabase | 6818 | 6746 | 4.9s | 725ms | 4.3 MB | 90 | 5754 |
|
|
10
|
+
| vscode | 10565 | 10565 | 9.7s | 1.2s | 10.6 MB | 11 | 19769 |
|
|
11
|
+
| zed | 1837 | 1837 | 2.7s | 83ms | 4.7 MB | 12 | 2176 |
|
|
12
|
+
|
|
13
|
+
## Domains Detected
|
|
14
|
+
|
|
15
|
+
**prisma:** DATABASE(1044) · CORE(752) · EVENTS(36) · AUTH(8)
|
|
16
|
+
**supabase:** CORE(4243) · AUTH(412) · DATABASE(387) · PAYMENTS(51) · EVENTS(17) · NOTIFICATIONS(12) · TRPC(3)
|
|
17
|
+
**vscode:** CORE(5330) · AUTH(850) · EVENTS(446) · DATABASE(419) · NOTIFICATIONS(5)
|
|
18
|
+
**zed:** CORE(1424) · DATABASE(110) · AUTH(75) · EVENTS(55) · PAYMENTS(53) · NOTIFICATIONS(10) · TRPC(2)
|
|
19
|
+
|
|
20
|
+
## MCP Query Latency
|
|
21
|
+
|
|
22
|
+
| Repo | get_structure | get_routes | get_domains_list |
|
|
23
|
+
|------|--------------|------------|-----------------|
|
|
24
|
+
| prisma | 0ms | 0ms | 1ms |
|
|
25
|
+
| supabase | 1ms | 0ms | 3ms |
|
|
26
|
+
| vscode | 1ms | 0ms | 3ms |
|
|
27
|
+
| zed | 0ms | 0ms | 1ms |
|
|
28
|
+
|
|
29
|
+
## Target Assessment
|
|
30
|
+
|
|
31
|
+
- **prisma**: ✅ All targets met
|
|
32
|
+
- **supabase**: ✅ All targets met
|
|
33
|
+
- **vscode**: ✅ All targets met
|
|
34
|
+
- **zed**: ✅ All targets met
|
package/CONTRIBUTING.md
CHANGED
|
@@ -215,13 +215,39 @@ cd carto
|
|
|
215
215
|
npm install
|
|
216
216
|
node src/cli/index.js init # test in any project
|
|
217
217
|
node src/cli/index.js serve # test MCP server
|
|
218
|
-
npm test # run test suite (
|
|
218
|
+
npm test # run test suite (35 tests)
|
|
219
219
|
node test/correctness.js # run correctness tests (31 tests)
|
|
220
220
|
node test/benchmark.js # run benchmarks against real repos
|
|
221
221
|
```
|
|
222
222
|
|
|
223
223
|
---
|
|
224
224
|
|
|
225
|
+
## CI
|
|
226
|
+
|
|
227
|
+
Every push and PR runs the test suite on a 3 OS × 3 Node matrix (macOS, Linux, Windows × Node 18, 20, 22) via `.github/workflows/test.yml`. A red cell blocks merge; one cell failing does not cancel the others, so you see the full picture.
|
|
228
|
+
|
|
229
|
+
There are three workflows:
|
|
230
|
+
|
|
231
|
+
| Workflow | Trigger | What it does |
|
|
232
|
+
|----------|---------|-------------|
|
|
233
|
+
| `test.yml` | push to `main`, PRs to `main` | `npm ci` + `npm test` on 9 cells |
|
|
234
|
+
| `bench.yml` | Sundays 04:00 UTC + manual | Self-bench (`test/bench-ci.js`) on `ubuntu-22.04`, compared against `test/bench-baseline.json` |
|
|
235
|
+
| `release-smoke.yml` | tags `v*`, PRs touching `package.json` / `package-lock.json` / `.npmignore` | `npm pack` + install tarball into a fresh dir + `carto --help` smoke on 3 OS × 2 Node |
|
|
236
|
+
|
|
237
|
+
**Local equivalents** before pushing:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
npm test # main suite (matches what test.yml runs)
|
|
241
|
+
npm run test:correctness # correctness suite — needs tmp-bench/<name> clones, NOT run in CI
|
|
242
|
+
npm run test:bench-ci # self-bench (matches what bench.yml runs)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**If a cell goes red:** click the failing job's "Details" link in the PR check section. Test failures show test names; install failures usually mean `package-lock.json` drifted from `package.json` — re-run `npm install` locally and commit the lockfile change.
|
|
246
|
+
|
|
247
|
+
**If `bench.yml` reports a regression:** the failure includes which metric exceeded its tolerance and by how much. The artifact `bench-output-<run-id>` keeps the raw output for 90 days. If the regression is intentional (e.g., you traded perf for correctness), update the baseline value in `test/bench-baseline.json` in the same PR and link the bench run id in the PR description.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
225
251
|
## PR checklist
|
|
226
252
|
|
|
227
253
|
- [ ] Tested on at least 2-3 real open-source projects
|
|
@@ -232,7 +258,7 @@ node test/benchmark.js # run benchmarks against real repos
|
|
|
232
258
|
- [ ] Extension added to `CODE_EXTS` and `detectLanguage()` in `sync-v2.js`
|
|
233
259
|
- [ ] No changes to merger logic (unless explicitly fixing a merger bug)
|
|
234
260
|
- [ ] No network calls added
|
|
235
|
-
- [ ] `npm test` passes (
|
|
261
|
+
- [ ] `npm test` passes (35/35)
|
|
236
262
|
- [ ] `node test/correctness.js` passes (31/31)
|
|
237
263
|
|
|
238
264
|
---
|
package/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# carto
|
|
2
2
|
|
|
3
|
+
[](https://github.com/theanshsonkar/carto/actions/workflows/test.yml)
|
|
3
4
|
[](https://www.npmjs.com/package/carto-md)
|
|
4
5
|
[](LICENSE)
|
|
5
6
|
[](https://www.npmjs.com/package/carto-md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "carto-md",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Structural intelligence layer for AI coding tools. Indexes your codebase into SQLite — routes, models, import graph, blast radius, domains — and exposes 16 MCP tools for Kiro, Cursor, and Claude.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"carto": "src/cli/index.js"
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "node test/test.js",
|
|
11
11
|
"test:correctness": "node test/correctness.js",
|
|
12
|
-
"test:benchmark": "node test/benchmark.js"
|
|
12
|
+
"test:benchmark": "node test/benchmark.js",
|
|
13
|
+
"test:bench-ci": "node test/bench-ci.js"
|
|
13
14
|
},
|
|
14
15
|
"dependencies": {
|
|
15
16
|
"@agentclientprotocol/sdk": "^0.22.1",
|
package/src/agents/formatter.js
CHANGED
|
@@ -16,6 +16,9 @@ function formatSections({ routes, models, frontend, structure, warnings, fileMap
|
|
|
16
16
|
sections.push(`- ${icon} ${entry.name}${suffix}`);
|
|
17
17
|
}
|
|
18
18
|
} else {
|
|
19
|
+
if (process.env.CARTO_DEBUG) {
|
|
20
|
+
console.warn('[CARTO] Warning: structure data was empty when formatting AGENTS.md');
|
|
21
|
+
}
|
|
19
22
|
sections.push('_No structure data available._');
|
|
20
23
|
}
|
|
21
24
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* IGNORE_DIRS — names skipped at the top level when listing project structure.
|
|
7
|
+
*
|
|
8
|
+
* This is intentionally a *small* set tuned for the "Project Structure (auto)"
|
|
9
|
+
* block in AGENTS.md. It is NOT the same as the recursive file-discovery
|
|
10
|
+
* ignore lists (e.g. JS_IGNORE / PYTHON_IGNORE in src/detector/files.js or
|
|
11
|
+
* IGNORE_DIRS in src/store/sync-v2.js) — those filter what gets indexed.
|
|
12
|
+
*
|
|
13
|
+
* Top-level structure should still surface things like `dist/`, `build/`,
|
|
14
|
+
* `coverage/` (so users see what their project actually contains), but it
|
|
15
|
+
* should hide noise (`node_modules`, `.git`, `.carto`, etc.) and the file
|
|
16
|
+
* the structure block is about to be merged into (`AGENTS.md`).
|
|
17
|
+
*
|
|
18
|
+
* Anchored on the original V1 set in src/sync.js so existing AGENTS.md
|
|
19
|
+
* outputs do not drift after the V1 → V2 cleanup.
|
|
20
|
+
*/
|
|
21
|
+
const IGNORE_DIRS = new Set([
|
|
22
|
+
'node_modules',
|
|
23
|
+
'.git',
|
|
24
|
+
'__pycache__',
|
|
25
|
+
'.venv',
|
|
26
|
+
'venv',
|
|
27
|
+
'.idea',
|
|
28
|
+
'.vscode',
|
|
29
|
+
'.carto',
|
|
30
|
+
'AGENTS.md'
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* scanStructure(basePath) → Array<{ name: string, type: 'dir' | 'file' }>
|
|
35
|
+
*
|
|
36
|
+
* Lists the immediate children of `basePath` (one level deep, no recursion).
|
|
37
|
+
* Filters out IGNORE_DIRS. Sorts: directories before files; alphabetical
|
|
38
|
+
* within each group.
|
|
39
|
+
*
|
|
40
|
+
* Symlinks are reported by Dirent as neither dir nor file → treated as 'file'.
|
|
41
|
+
* Failures (missing dir, EACCES, etc.) return an empty array silently — the
|
|
42
|
+
* formatter handles the empty case.
|
|
43
|
+
*/
|
|
44
|
+
async function scanStructure(basePath) {
|
|
45
|
+
const entries = [];
|
|
46
|
+
let items;
|
|
47
|
+
try {
|
|
48
|
+
items = await fs.promises.readdir(basePath, { withFileTypes: true });
|
|
49
|
+
} catch {
|
|
50
|
+
return entries;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for (const item of items) {
|
|
54
|
+
if (IGNORE_DIRS.has(item.name)) continue;
|
|
55
|
+
entries.push({
|
|
56
|
+
name: item.name,
|
|
57
|
+
type: item.isDirectory() ? 'dir' : 'file'
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
entries.sort((a, b) => {
|
|
62
|
+
if (a.type !== b.type) return a.type === 'dir' ? -1 : 1;
|
|
63
|
+
return a.name.localeCompare(b.name);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return entries;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { scanStructure, IGNORE_DIRS };
|