carto-md 2.0.8 → 2.1.0

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.
Files changed (182) hide show
  1. package/CONTRIBUTING.md +19 -15
  2. package/README.md +203 -286
  3. package/docs/anci/v0.1-DRAFT.md +420 -0
  4. package/docs/api/README.md +99 -0
  5. package/docs/api/did_we_discuss_this.md +34 -0
  6. package/docs/api/dismiss_suggestion.md +34 -0
  7. package/docs/api/explain_change_in_natural_language.md +33 -0
  8. package/docs/api/find_consumers_of_api.md +34 -0
  9. package/docs/api/get_action_patterns.md +32 -0
  10. package/docs/api/get_active_drift.md +32 -0
  11. package/docs/api/get_active_suggestions.md +25 -0
  12. package/docs/api/get_ai_cost_attribution.md +32 -0
  13. package/docs/api/get_arch_events.md +42 -0
  14. package/docs/api/get_architectural_drift.md +37 -0
  15. package/docs/api/get_architecture.md +25 -0
  16. package/docs/api/get_blast_radius.md +34 -0
  17. package/docs/api/get_canonical_pattern.md +39 -0
  18. package/docs/api/get_change_plan.md +34 -0
  19. package/docs/api/get_change_velocity.md +32 -0
  20. package/docs/api/get_churn_vs_blast_radius.md +32 -0
  21. package/docs/api/get_complexity_trend.md +39 -0
  22. package/docs/api/get_context.md +34 -0
  23. package/docs/api/get_conventions.md +32 -0
  24. package/docs/api/get_cross_domain.md +25 -0
  25. package/docs/api/get_cross_language_call_graph.md +25 -0
  26. package/docs/api/get_cross_repo_blast_radius.md +34 -0
  27. package/docs/api/get_cross_team_coupling.md +25 -0
  28. package/docs/api/get_data_flow.md +33 -0
  29. package/docs/api/get_dead_code_with_confidence.md +32 -0
  30. package/docs/api/get_decision_log.md +32 -0
  31. package/docs/api/get_dependency_surface.md +25 -0
  32. package/docs/api/get_domain.md +34 -0
  33. package/docs/api/get_domain_evolution.md +39 -0
  34. package/docs/api/get_domain_health.md +32 -0
  35. package/docs/api/get_domains_list.md +25 -0
  36. package/docs/api/get_drift_digest.md +32 -0
  37. package/docs/api/get_env_vars.md +32 -0
  38. package/docs/api/get_evolution_delta.md +36 -0
  39. package/docs/api/get_file_ownership.md +33 -0
  40. package/docs/api/get_file_summary.md +34 -0
  41. package/docs/api/get_high_impact_files.md +32 -0
  42. package/docs/api/get_hot_in_prod_no_tests.md +34 -0
  43. package/docs/api/get_hotspot_files.md +37 -0
  44. package/docs/api/get_iac_resources.md +25 -0
  45. package/docs/api/get_interface_contract.md +33 -0
  46. package/docs/api/get_intervention_history.md +32 -0
  47. package/docs/api/get_invariants.md +37 -0
  48. package/docs/api/get_llm_enrichment.md +33 -0
  49. package/docs/api/get_microservice_cut_points.md +32 -0
  50. package/docs/api/get_microservices_migration_cut_points.md +25 -0
  51. package/docs/api/get_minimal_context_for_intent.md +39 -0
  52. package/docs/api/get_models.md +32 -0
  53. package/docs/api/get_neighbors.md +39 -0
  54. package/docs/api/get_org_architecture.md +25 -0
  55. package/docs/api/get_org_domain_mapping.md +25 -0
  56. package/docs/api/get_pending_decisions.md +32 -0
  57. package/docs/api/get_predictive_risk.md +32 -0
  58. package/docs/api/get_progressive_disclosure_tree.md +25 -0
  59. package/docs/api/get_recent_decisions.md +37 -0
  60. package/docs/api/get_risk_weighted_blast_radius.md +32 -0
  61. package/docs/api/get_routes.md +25 -0
  62. package/docs/api/get_safety_checklist.md +33 -0
  63. package/docs/api/get_semantic_diff.md +34 -0
  64. package/docs/api/get_service_boundary_violations.md +25 -0
  65. package/docs/api/get_service_dependency_graph.md +25 -0
  66. package/docs/api/get_session_context.md +32 -0
  67. package/docs/api/get_similar_patterns.md +39 -0
  68. package/docs/api/get_stale_docs.md +25 -0
  69. package/docs/api/get_structure.md +25 -0
  70. package/docs/api/get_temporal_context.md +34 -0
  71. package/docs/api/get_test_coverage_map.md +25 -0
  72. package/docs/api/get_token_budget_report.md +36 -0
  73. package/docs/api/get_upgrade_risk.md +25 -0
  74. package/docs/api/get_working_memory.md +25 -0
  75. package/docs/api/ingest_otlp_traces.md +34 -0
  76. package/docs/api/scaffold_for_intent.md +34 -0
  77. package/docs/api/search_routes.md +34 -0
  78. package/docs/api/simulate_change_impact.md +37 -0
  79. package/docs/api/validate_change.md +39 -0
  80. package/docs/api/validate_diff.md +39 -0
  81. package/docs/concepts/anci.md +87 -0
  82. package/docs/concepts/blast-radius.md +66 -0
  83. package/docs/concepts/domains.md +91 -0
  84. package/docs/concepts/import-graph.md +102 -0
  85. package/docs/concepts/mcp-integration.md +148 -0
  86. package/docs/guides/adding-feature-safely.md +101 -0
  87. package/docs/guides/ci-integration.md +175 -0
  88. package/docs/guides/monorepo-setup.md +121 -0
  89. package/docs/guides/onboarding-new-engineer.md +121 -0
  90. package/docs/guides/pre-merge-review.md +139 -0
  91. package/docs/migration/v1-to-v2.md +110 -0
  92. package/docs/quickstart.md +95 -0
  93. package/docs/scale.md +129 -0
  94. package/docs/troubleshooting.md +180 -0
  95. package/package.json +12 -5
  96. package/scripts/gen-api-docs.js +170 -0
  97. package/scripts/postinstall.js +391 -24
  98. package/src/acp/agent.js +83 -11
  99. package/src/acp/config.js +64 -0
  100. package/src/acp/persistence.js +146 -0
  101. package/src/acp/providers/anthropic.js +179 -27
  102. package/src/acp/providers/index.js +15 -2
  103. package/src/acp/providers/openai.js +164 -38
  104. package/src/acp/providers/sse.js +82 -0
  105. package/src/acp/safety.js +128 -0
  106. package/src/acp/session.js +73 -0
  107. package/src/adjacent/call-graph.js +170 -0
  108. package/src/adjacent/iac.js +167 -0
  109. package/src/adjacent/llm-enrich.js +35 -0
  110. package/src/adjacent/runtime.js +216 -0
  111. package/src/adjacent/semantic-diff.js +143 -0
  112. package/src/agents/leiden.js +4 -4
  113. package/src/agents/scan-structure.js +2 -2
  114. package/src/ai/context-builder.js +215 -0
  115. package/src/ai/retrieval/lexical.js +122 -0
  116. package/src/ai/retrieval/rrf.js +121 -0
  117. package/src/ai/retrieval/semantic.js +35 -0
  118. package/src/ai/retrieval/structural.js +82 -0
  119. package/src/ai/tools.js +423 -0
  120. package/src/anci/consumer.js +305 -0
  121. package/src/anci/deserialize.js +160 -0
  122. package/src/anci/emit.js +85 -0
  123. package/src/anci/serialize.js +264 -0
  124. package/src/anci/yaml.js +401 -0
  125. package/src/bitmap/index.js +1 -1
  126. package/src/bitmap/tools.js +2 -2
  127. package/src/brain/conventions/index.js +185 -0
  128. package/src/brain/index.js +31 -0
  129. package/src/brain/invariants/index.js +252 -0
  130. package/src/brain/procedural/index.js +181 -0
  131. package/src/brain/suggestions/index.js +153 -0
  132. package/src/brain/working/index.js +170 -0
  133. package/src/cli/anci.js +237 -0
  134. package/src/cli/check.js +47 -1
  135. package/src/cli/diff.js +83 -0
  136. package/src/cli/doctor.js +270 -0
  137. package/src/cli/explain.js +61 -0
  138. package/src/cli/index.js +115 -0
  139. package/src/cli/init.js +144 -6
  140. package/src/cli/inspect.js +1 -1
  141. package/src/cli/org.js +172 -0
  142. package/src/cli/pr-impact.js +554 -0
  143. package/src/cli/serve.js +1 -1
  144. package/src/cli/status.js +211 -0
  145. package/src/cli/sync.js +2 -2
  146. package/src/cli/temporal.js +188 -0
  147. package/src/cli/validate.js +201 -0
  148. package/src/cli/watch.js +4 -4
  149. package/src/cli/why.js +101 -0
  150. package/src/extractors/frameworks.js +236 -0
  151. package/src/extractors/languages/dart.js +138 -0
  152. package/src/extractors/languages/go.js +11 -1
  153. package/src/extractors/languages/javascript.js +16 -6
  154. package/src/extractors/languages/kotlin.js +169 -0
  155. package/src/extractors/languages/php.js +195 -0
  156. package/src/extractors/languages/python.js +12 -1
  157. package/src/extractors/languages/swift.js +140 -0
  158. package/src/extractors/languages/typescript.js +15 -2
  159. package/src/extractors/plugin-api.js +102 -0
  160. package/src/mcp/change-plan.js +8 -8
  161. package/src/mcp/files-without-tests.js +285 -0
  162. package/src/mcp/middleware/index.js +451 -0
  163. package/src/mcp/server.js +2292 -0
  164. package/src/mcp/validate.js +1 -1
  165. package/src/org/detect.js +262 -0
  166. package/src/org/queries.js +144 -0
  167. package/src/org/store.js +173 -0
  168. package/src/org/sync.js +106 -0
  169. package/src/predictive/cut-points.js +83 -0
  170. package/src/predictive/drift-digest.js +88 -0
  171. package/src/predictive/ownership.js +145 -0
  172. package/src/predictive/risk-score.js +121 -0
  173. package/src/predictive/validate-change.js +55 -0
  174. package/src/store/store-adapter.js +3 -3
  175. package/src/store/{sync-v2.js → sync.js} +105 -16
  176. package/src/temporal/backfill.js +211 -0
  177. package/src/temporal/delta.js +85 -0
  178. package/src/temporal/events.js +180 -0
  179. package/src/temporal/queries.js +358 -0
  180. package/src/temporal/snapshot.js +151 -0
  181. package/src/temporal/store.js +400 -0
  182. package/src/mcp/server-v2.js +0 -986
@@ -0,0 +1,139 @@
1
+ # Guide: Pre-merge review
2
+
3
+ > Architecture review at PR time, automatically. The reviewer sees structural impact alongside the diff.
4
+
5
+ ## What the GitHub Action does
6
+
7
+ On every pull request:
8
+
9
+ 1. Checks out the PR head
10
+ 2. Restores `.carto/` from `actions/cache` (or runs `carto init` cold)
11
+ 3. Runs `carto pr-impact --base $BASE --head $HEAD --format markdown`
12
+ 4. Posts the result as a sticky comment on the PR (one comment per PR, updated in place on every push)
13
+
14
+ The whole flow runs in 30–120 seconds on a warm cache, 1–3 minutes cold.
15
+
16
+ ## Setup
17
+
18
+ In `.github/workflows/carto.yml`:
19
+
20
+ ```yaml
21
+ name: Carto Impact Report
22
+ on:
23
+ pull_request:
24
+ branches: [main]
25
+ permissions:
26
+ contents: read
27
+ pull-requests: write
28
+ jobs:
29
+ carto:
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+ with: { fetch-depth: 0 } # full history — pr-impact needs the base ref
34
+ - uses: theanshsonkar/carto@v2.0.9
35
+ ```
36
+
37
+ That's the entire config. The action handles npm install, cache restore, sync, pr-impact, and the comment.
38
+
39
+ ## What the comment looks like
40
+
41
+ ```markdown
42
+ ## 🗺️ Carto Impact Report
43
+
44
+ This PR touches **AUTH** and **DATABASE** domains.
45
+
46
+ | Metric | Value |
47
+ |--------|-------|
48
+ | Risk | 🔴 HIGH |
49
+ | Blast radius (union) | 47 files |
50
+ | Files changed | 6 |
51
+ | Cross-domain violations introduced | 2 |
52
+ | Files without tests in blast radius | 5 of 31 |
53
+ | High-impact file changed | src/auth/session.ts (8 direct dependents) |
54
+
55
+ <details>
56
+ <summary>Affected routes (4)</summary>
57
+
58
+ - POST /auth/login — risk: HIGH
59
+ - GET /auth/me — risk: HIGH
60
+ - POST /auth/register — risk: MEDIUM
61
+ - POST /api/users — risk: LOW
62
+
63
+ </details>
64
+
65
+ <details>
66
+ <summary>Cross-domain violations (2)</summary>
67
+
68
+ - auth/login.ts now imports from payments/billing.ts (AUTH→PAYMENTS)
69
+ - database/user-repo.ts now imports from auth/jwt.ts (DATABASE→AUTH)
70
+
71
+ </details>
72
+
73
+ <details>
74
+ <summary>Files without tests in blast radius (5)</summary>
75
+
76
+ - src/auth/middleware.ts
77
+ - src/auth/jwt-helpers.ts
78
+ - …
79
+ </details>
80
+ ```
81
+
82
+ ## What a reviewer does with this
83
+
84
+ Look at the four signals in order:
85
+
86
+ 1. **Risk badge.** HIGH / MEDIUM / LOW / SAFE. If it's SAFE or LOW, you can mostly skip the structural review and focus on the code itself. If it's HIGH, look more carefully.
87
+
88
+ 2. **Cross-domain violations.** Each one is a new dependency between domains. Sometimes correct (a refactor moving shared logic), sometimes a smell (auth pulling from payments). Reviewer applies judgment.
89
+
90
+ 3. **Files without tests.** Files in the blast radius that don't have a sibling test file. Lower confidence in the change because there's no automated check. Suggest the author add tests, or document why not.
91
+
92
+ 4. **High-impact file changed.** Anything modifying a >20-dependent file deserves an extra read-through. Subtle changes to a widely-used utility have outsized blast.
93
+
94
+ ## Failing the build on risk
95
+
96
+ For repos that want a harder gate, set `fail-on` in the workflow:
97
+
98
+ ```yaml
99
+ - uses: theanshsonkar/carto@v2.0.9
100
+ with:
101
+ fail-on: HIGH
102
+ ```
103
+
104
+ Now the build fails when the risk is HIGH. PRs need to lower the risk (split, add tests, refactor) before they can merge.
105
+
106
+ Use sparingly. HIGH-risk changes are sometimes correct and *necessary* — the right reviewer call is "look more carefully", not "block automatically".
107
+
108
+ ## Inputs reference
109
+
110
+ | Input | Default | What it does |
111
+ |---------------|-------------|--------------|
112
+ | `carto-version` | `latest` | Pin in production for reproducibility. |
113
+ | `base` | auto | Git ref the PR branched from. Auto-detected from `origin/$GITHUB_BASE_REF`. |
114
+ | `head` | auto | Git ref of the PR head. Auto-detected from `$GITHUB_SHA`. |
115
+ | `fail-on` | _(empty)_ | Fail when risk ≥ this severity. `HIGH`, `MEDIUM`, or `LOW`. |
116
+ | `comment-mode`| `sticky` | `sticky` updates existing comment, `new` posts a new one every push, `none` skips the comment (renders to stdout). |
117
+ | `node-version`| `20` | Node version on the runner. |
118
+
119
+ ## Outputs
120
+
121
+ | Output | Description |
122
+ |--------------|-------------|
123
+ | `risk` | `SAFE` / `LOW` / `MEDIUM` / `HIGH` — gate downstream steps on it. |
124
+ | `comment-url`| URL of the posted comment. |
125
+
126
+ ## Running it locally (mirror the CI)
127
+
128
+ ```bash
129
+ carto pr-impact --base origin/main --head HEAD
130
+ carto pr-impact --base origin/main --head HEAD --format json
131
+ carto pr-impact --base origin/main --head HEAD --fail-on HIGH
132
+ ```
133
+
134
+ Same engine, same output. Useful for testing changes before pushing.
135
+
136
+ ## Related
137
+
138
+ - [`docs/guides/ci-integration.md`](./ci-integration.md) — broader CI patterns
139
+ - [`docs/concepts/blast-radius.md`](../concepts/blast-radius.md) — the math behind the metric
@@ -0,0 +1,110 @@
1
+ # Migration: V1 → V2
2
+
3
+ > Notes for anyone who installed `carto-md` pre-2.0.6.
4
+
5
+ ## What V2 changed
6
+
7
+ V1 stored the index as JSON files at `.carto/cache/graph-cache.json` and `.carto/cache/hashes.json`. V2 stores it as SQLite at `.carto/carto.db` with a derived bitmap sidecar at `.carto/bitmap.bin`.
8
+
9
+ Why: SQLite handles 100K-file repos cleanly where the JSON approach started getting slow at ~10K files. The bitmap layer makes graph queries 100–10,000× faster than SQL at scale (see [`docs/scale.md`](../scale.md)).
10
+
11
+ V1 has been fully deleted from the tree as of carto-md@2.0.6.
12
+
13
+ ## What you need to do
14
+
15
+ In most cases — nothing. `carto init` (or any `carto` command that touches the index) detects the old V1 cache files and migrates them transparently on first run.
16
+
17
+ Specifically, the migration:
18
+
19
+ 1. Reads `.carto/cache/graph-cache.json` if present (V1 metadata)
20
+ 2. Notices it's incompatible with the V2 schema
21
+ 3. Runs a fresh `carto sync` to repopulate `.carto/carto.db` from source
22
+ 4. Leaves the V1 files in place (they're harmless dead bytes)
23
+
24
+ The Spec 7 test suite explicitly covers this case: *"carto init migrates leftover V1 graph-cache.json cleanly (no errors)"*.
25
+
26
+ ## Manual cleanup (optional)
27
+
28
+ After the first V2 sync succeeds, the V1 files are no longer read. Reclaim a bit of disk:
29
+
30
+ ```bash
31
+ rm -f .carto/cache/graph-cache.json
32
+ rm -f .carto/cache/hashes.json
33
+ rmdir .carto/cache # if empty
34
+ ```
35
+
36
+ Or just `carto remove && carto init` for a clean slate.
37
+
38
+ ## MCP wiring changes
39
+
40
+ V1 exposed 12 MCP tools. V2 ships ~75, organized into 8 categories (core graph, episodic memory, temporal, brain, predictive, AI-native retrieval, adjacent, org-wide).
41
+
42
+ The highest-impact additions from V1:
43
+
44
+ - `get_architecture()` — the "use this first" tool
45
+ - `get_file_summary(file)` — surfaces what `carto why` shows
46
+ - `get_change_plan(intent)` — real graph traversal (V1 was keyword grep — Spec 2 rewrite)
47
+ - `get_similar_patterns(file)` — Jaccard-similarity over import sets
48
+ - `validate_diff(diff)` — sub-15ms pre-write governance, writes every call into the episodic log
49
+ - `did_we_discuss_this(topic)` — six-week recall over the decision log
50
+ - `get_predictive_risk(file?)` — P(file causes the next incident) score
51
+ - `get_minimal_context_for_intent(intent, budget)` — token-budgeted hybrid retrieval (structural + lexical + semantic with RRF fusion)
52
+ - `simulate_change_impact(files)` — bitmap-backed multi-file blast radius
53
+
54
+ Plus the temporal trio (`get_architectural_drift`, `get_domain_evolution`, `get_hotspot_files`), the brain stack (`get_invariants`, `get_conventions`, `get_action_patterns`, `scaffold_for_intent`), and the org/cross-repo set (`get_org_architecture`, `get_service_dependency_graph`, `find_consumers_of_api`).
55
+
56
+ Full reference: [`docs/api/`](../api/).
57
+
58
+ If your AI tool was configured against V1 and you're seeing tool-not-found errors, restart the tool to pick up the V2 server's new `tools/list` response. The wire protocol is the same.
59
+
60
+ ## ACP agent
61
+
62
+ V1's ACP agent (in Zed / JetBrains / VS Code via `carto agent`) used its own in-memory index. V2's ACP agent shares the SQLite index with the MCP server (Spec 5). Re-running `carto init` in your project ensures both ACP and MCP see the same data.
63
+
64
+ ## `.cartoignore` defaults
65
+
66
+ V2 expanded the default exclusion list from 12 patterns to 39 (Spec 8: SSH keys, AWS/GCP creds, `.netrc`, kubeconfig, etc.). If your project had a custom `.cartoignore`, it's preserved — Carto only writes a default when none exists. To pick up the new defaults, delete your `.cartoignore` and run `carto init` to regenerate.
67
+
68
+ ## Git hooks
69
+
70
+ V1 didn't install git hooks. V2 (Spec 9) installs four:
71
+
72
+ - `pre-commit`
73
+ - `post-checkout`
74
+ - `post-merge`
75
+ - `post-rewrite`
76
+
77
+ Each runs `carto sync >/dev/null 2>&1 || true` — never blocks git, never errors loudly. If you already have hooks for other purposes, Carto appends to them non-destructively. Run `carto doctor` to confirm the hooks installed.
78
+
79
+ ## Behavior changes worth flagging
80
+
81
+ | Behavior | V1 | V2 |
82
+ |----------|----|----|
83
+ | File-discovery cap | hard cap at ~50K files | uncapped |
84
+ | Index format | JSON | SQLite + bitmap |
85
+ | Re-parse on edit | only via `carto watch` | lazy at MCP query time + git hooks |
86
+ | `get_change_plan` | keyword grep | real graph traversal |
87
+ | Cross-domain detection | path-based | graph-clustered |
88
+ | ACP / MCP share index | no | yes |
89
+ | Read-only MCP DB | no | yes |
90
+ | Default `.cartoignore` | 12 patterns | 39 patterns |
91
+
92
+ If you depended on a V1-specific behavior that's no longer accurate, file an issue — we may have broken something we shouldn't have.
93
+
94
+ ## Pinned-version recommendation
95
+
96
+ If you're upgrading in CI, pin a known-good Carto version:
97
+
98
+ ```yaml
99
+ # .github/workflows/carto.yml
100
+ - uses: theanshsonkar/carto@v2.0.9
101
+ with:
102
+ carto-version: '2.0.9' # pin instead of `latest`
103
+ ```
104
+
105
+ This way the action's output (and the PR-comment shape) stays stable across CI runs even when newer Carto versions ship.
106
+
107
+ ## Related
108
+
109
+ - [`docs/troubleshooting.md`](../troubleshooting.md) — what to do when migration goes sideways
110
+ - [Spec 6](../../Progress/working.md) in `Progress/working.md` — the deletion that removed V1
@@ -0,0 +1,95 @@
1
+ # Quickstart — 10 minutes from install to first MCP query
2
+
3
+ Get carto wired into your AI tool and answering questions about your codebase in under ten minutes.
4
+
5
+ ## 1. Install (30 seconds)
6
+
7
+ ```bash
8
+ npm install -g carto-md
9
+ ```
10
+
11
+ Carto ships prebuilt native binaries for macOS arm64/x64, Linux x64 (glibc + musl), and Windows x64. If you're on a platform without prebuilds you'll fall back to compiling from source — see [troubleshooting.md](./troubleshooting.md#native-build-fails) if that breaks.
12
+
13
+ Verify the install:
14
+
15
+ ```bash
16
+ carto --version
17
+ ```
18
+
19
+ ## 2. Index your project (1 minute)
20
+
21
+ ```bash
22
+ cd ~/your-project
23
+ carto init
24
+ ```
25
+
26
+ You'll see something like:
27
+
28
+ ```
29
+ [CARTO] Detecting project...
30
+ [CARTO] Detected: nextjs (typescript)
31
+ [CARTO] Found 847 JS/TS files (847 total)
32
+ [CARTO] Discovered 847 source files
33
+ [CARTO] Computing reverse dependencies...
34
+ [CARTO] Indexed 847 files in 1.8s
35
+ [CARTO] MCP auto-wired into: Cursor, Claude Code, Kiro
36
+ [CARTO] AGENTS.md generated.
37
+
38
+ ┌─ Carto · indexed ─────────────────────────────────────────
39
+ │ 847 files · 5 domains · 23 routes · 1,204 import edges
40
+
41
+ │ Top domains:
42
+ │ CORE (677 files)
43
+ │ AUTH (42 files)
44
+ │ PAYMENTS (38 files)
45
+ │ DATABASE (67 files)
46
+
47
+ │ 💡 Highest-risk file: src/lib/db.ts
48
+ │ (34 files depend on it — try `carto why src/lib/db.ts`)
49
+ └───────────────────────────────────────────────────────────
50
+ ```
51
+
52
+ What just happened:
53
+
54
+ - Carto walked the project, parsed every source file with tree-sitter
55
+ - Built an import graph, clustered files into domains (Leiden+CPM), extracted routes + models
56
+ - Wrote `.carto/` containing the SQLite index, the bitmap sidecar, the per-domain context files
57
+ - Wrote `AGENTS.md` at the project root
58
+ - Installed 4 git hooks so the index re-syncs on commit/checkout/merge/rebase
59
+ - Detected your installed AI tools and wrote MCP config files for each
60
+
61
+ ## 3. Restart your AI tool
62
+
63
+ The MCP wiring lands when the AI tool starts fresh. Kill it and reopen, then verify carto loaded — most tools log MCP server connections.
64
+
65
+ ## 4. Ask your first question
66
+
67
+ Open any prompt your AI tool exposes and try one of:
68
+
69
+ > *"What's the blast radius of `src/lib/db.ts`?"*
70
+
71
+ > *"Show me the architecture overview."*
72
+
73
+ > *"What files would I need to change to add rate limiting to /api/users?"*
74
+
75
+ The AI calls Carto's MCP tools (`get_blast_radius`, `get_architecture`, `get_change_plan`) and answers with structural facts instead of grepping.
76
+
77
+ ## 5. Try the CLI too
78
+
79
+ While you're here:
80
+
81
+ ```bash
82
+ carto status # one-screen health view
83
+ carto why src/lib/db.ts # 3-line summary of a file
84
+ carto explain "add rate limiting" # natural-language → plan
85
+ carto check # cross-domain violations
86
+ carto doctor # diagnose any setup issues
87
+ ```
88
+
89
+ ## What's next
90
+
91
+ - [`docs/concepts/blast-radius.md`](./concepts/blast-radius.md) — what "blast radius" means and how it's computed
92
+ - [`docs/concepts/domains.md`](./concepts/domains.md) — how the Leiden clusterer infers AUTH/PAYMENTS/etc. without config
93
+ - [`docs/concepts/mcp-integration.md`](./concepts/mcp-integration.md) — every MCP tool with an example call
94
+ - [`docs/guides/adding-feature-safely.md`](./guides/adding-feature-safely.md) — the workflow this whole thing enables
95
+ - [`docs/guides/ci-integration.md`](./guides/ci-integration.md) — drop the GitHub Action onto every PR
package/docs/scale.md ADDED
@@ -0,0 +1,129 @@
1
+ # Carto at scale
2
+
3
+ > Empirical scale data for the bitmap engine — synthetic stress sweep + every real-world repo in the Carto corpus. Reproducer commands at the bottom.
4
+
5
+ The bitmap-backed graph engine is designed to handle 100K-1M files cleanly. This page is the empirical receipt. It captures both the **dense-synth stress sweep** (deterministic worst-case fan-out distribution) and the **real-world corpus** (4 of the 7 larger repos, the largest open-source codebases under MIT/permissive licenses we routinely test against).
6
+
7
+ ## What's measured
8
+
9
+ For each run we capture:
10
+
11
+ - **Init time** — full `runSync` from a wiped `.carto/` directory.
12
+ - **Sync time** — second `runSync` immediately after, no files changed (mtime+hash skip path).
13
+ - **DB size** — `.carto/carto.db` bytes on disk.
14
+ - **bitmap.bin size** — the sidecar bytes on disk.
15
+ - **Sidecar (RAM)** — sum of all bitmap word-array byte lengths held in memory.
16
+ - **Peak RSS** — process resident memory after init and during query workloads.
17
+ - **MCP query p50 / p99** — 1000 calls each (50-call warmup) for the 5 production bitmap tools (`blastRadius`, `crossDomain`, `highImpactFiles`, `similarPatterns`) plus `simulate_change_impact`. Random query inputs are seeded so identical `--seed` produces identical workloads.
18
+
19
+ The query stage opens SQLite **read-only** — invariant honored. The bitmap-as-derived-disposable invariant is also honored: the runner only reads from `bitmap.bin`, never writes.
20
+
21
+ All numbers below were captured on the maintainer dev box: Apple silicon, Node 20.20, macOS, NVMe SSD. Recapture via the commands at the bottom.
22
+
23
+ ## Synthetic stress sweep (dense fan-out)
24
+
25
+ Source: `bench/scale-test/`. Generates a deterministic-for-seed TypeScript repo with a worst-case-shaped import graph: 5 domain-like top-level dirs (`auth`/`payments`/`database`/`events`/`core`), Pareto(α=2) fan-out clipped to [1,8], 75% same-domain / 25% cross-domain, hotspot-biased targets so the first ~10% of file ids accumulate most in-edges. Imports always reference an earlier file id (acyclic).
26
+
27
+ Edge density ≈ 1.5 per file. **This is denser than every real-world repo in the corpus** — real codebases have many leaf files with zero imports, so the synth deliberately exercises the worst case for the bitmap layer.
28
+
29
+ | Files | Edges | Init | Sync | DB | bitmap.bin | Sidecar (RAM) | Peak RSS |
30
+ |------:|------:|-----:|-----:|---:|-----------:|--------------:|---------:|
31
+ | 1,000 | 1,392 | 533ms | 70ms | 756 KB | 222 KB | 186 KB | 149 MB |
32
+ | 10,000 | 14,876 | 3.28s | 627ms | 6.5 MB | 17.0 MB | 18.1 MB | 350 MB |
33
+ | 50,000 | 76,145 | 1.1m | 5.14s | 36.9 MB | 414.9 MB | 488.4 MB | 1.35 GB |
34
+
35
+ | Files | blastRadius p50/p99 | crossDomain p50/p99 | highImpactFiles p50/p99 | similarPatterns p50/p99 | simulate_change_impact p50/p99 |
36
+ |------:|---------------------|---------------------|------------------------|------------------------|--------------------------------|
37
+ | 1,000 | 1.6µs / 24.4µs | 19.5µs / 25.0µs | 709ns / 4.3µs | 276µs / 484µs | 7.0µs / 78.8µs |
38
+ | 10,000 | 6.6µs / 67.7µs | 705µs / 914µs | 750ns / 1.4µs | 17.0ms / 19.3ms | 11.6µs / 113µs |
39
+ | 50,000 | 22.4µs / 472µs | 28.1ms / 28.9ms | 750ns / 1.3µs | 462ms / 798ms | 49.9µs / 455µs |
40
+
41
+ ### What 50K reveals
42
+
43
+ Three distinct failure modes show up at the dense-synth 50K row, **all of them addressable by a Roaring-bitmap upgrade on the roadmap**:
44
+
45
+ 1. **Storage scales linearly with N** — every file gets its own forward + reverse bitmap of size ~`N/8` bytes. At N=50K bitmap.bin is 415 MB; at N=100K linear extrapolation puts it at ~1.7 GB. The current pure-Node `Uint32Array` bitset (`src/bitmap/bitset.js`) trades storage efficiency for raw query speed and zero native deps. Roaring would cut this 5-50× depending on density.
46
+ 2. **`crossDomain` p50 hits 28 ms** — linear sweep over the `crossForward` Map. Fixable with a precomputed cross-domain edge bitmap that's OR-aggregated once at build time, not iterated per query.
47
+ 3. **`similarPatterns` p50 hits 462 ms** — Jaccard over import sets at scale costs O(candidates × set-intersection). The MCP layer calls this with `top_k=5` so user-facing latency is well under the raw bench number, but the absolute cost is real.
48
+
49
+ Three things stay healthy at 50K: `blastRadius` p50 22µs, `highImpactFiles` p50 750ns (popcount index is O(1) array slice), `simulate_change_impact` p50 50µs.
50
+
51
+ ### Pending (not yet captured on this box)
52
+
53
+ | Files | Notes |
54
+ |------:|-------|
55
+ | 100,000 | Stress-test for the dense-bitset implementation. ~3-5 min walltime expected. Worth running before any Roaring work to lock in the regression baseline. |
56
+ | 500,000 | Practical ceiling for the dense-bitset; expect bitmap.bin > 4 GB, possibly hitting OOM on 16 GB-RAM dev boxes. |
57
+ | 1,000,000 | Roaring-bitmap upgrade target. Expect dense-bitset OOM. |
58
+
59
+ Reproducible via `npm run bench:scale -- --size 100000 --keep --out /tmp/carto-100k`.
60
+
61
+ ## Real-world corpus
62
+
63
+ These are the 4 largest repos in `~/carto-test-repos`, all already indexed by `~/carto-test-repos/run-bench.sh` (the bench harness baseline). The query latency below was measured against those existing indexes via `--queries-only` so this measurement does not perturb the indexes used by `node test/accuracy-corpus.js`.
64
+
65
+ | Repo | Indexed files | Edges | DB | bitmap.bin | Sidecar (RAM) |
66
+ |------|--------------:|------:|---:|-----------:|--------------:|
67
+ | [cal.com](https://github.com/calcom/cal.com) | 4,351 | 3,478 | 3.1 MB | 1.9 MB | 2.0 MB |
68
+ | [nextjs](https://github.com/vercel/next.js) | 6,193 | 7,930 | 15.0 MB | 4.4 MB | 4.3 MB |
69
+ | [supabase](https://github.com/supabase/supabase) | 6,330 | 5,189 | 4.8 MB | 4.4 MB | 4.4 MB |
70
+ | [vscode](https://github.com/microsoft/vscode) | 7,567 | 13,335 | 14.3 MB | 4.1 MB | 4.5 MB |
71
+
72
+ | Repo | blastRadius p50/p99 | crossDomain p50/p99 | highImpactFiles p50/p99 | similarPatterns p50/p99 | simulate_change_impact p50/p99 |
73
+ |------|---------------------|---------------------|------------------------|------------------------|--------------------------------|
74
+ | cal.com | 4.3µs / 51µs | 148µs / 279µs | 667ns / 1.0µs | 1.0µs / 1.99ms | 10.3µs / 71.0µs |
75
+ | nextjs | 5.0µs / 155µs | 196µs / 284µs | 750ns / 1.3µs | 1.2µs / 3.01ms | 28.9µs / 211µs |
76
+ | supabase | 5.5µs / 47.9µs | 201µs / 260µs | 708ns / 1.0µs | 1.5µs / 3.19ms | 10.8µs / 65.9µs |
77
+ | vscode | 2.7µs / 428µs | 1.23ms / 1.47ms | 750ns / 1.7µs | 834ns / 4.03ms | 19.3µs / 637µs |
78
+
79
+ ### Real-world vs dense-synth
80
+
81
+ The 7,567-file vscode row vs the 10,000-file synth row tells the most important story:
82
+
83
+ - vscode `similarPatterns` p50 is **834ns**; synth-10K is **17ms**. Real codebases have far sparser per-file import sets — most files import 0-3 things, a handful import many. Synth is a deliberate worst case (Pareto fan-out always ≥1, often 4-8). Real Jaccard-over-import-sets fits in cache; synth doesn't.
84
+ - vscode `crossDomain` p50 is **1.23ms**; synth-10K is **704µs**. Cross-domain edges scale with edge density; synth is denser. Both are sub-2ms at any sensible scale.
85
+ - vscode `bitmap.bin` is **4.1 MB** at 7,567 files; synth-10K is **17 MB** at 10,000 files. ~4× density difference, reflected directly in storage.
86
+
87
+ The takeaway: **dense-synth identifies the failure modes; real-world data sets the actual user expectations.** Both are needed.
88
+
89
+ ## Linux kernel and Chromium
90
+
91
+ Block 1.B in PEAK §10 explicitly calls out the Linux kernel and Chromium as scale targets. Neither is in `~/carto-test-repos` today (multi-GB clones, gated on the maintainer's disk budget). The `bench/scale-test/real-world.js` driver lands here so capturing those rows is one command once a clone exists:
92
+
93
+ ```bash
94
+ git clone --depth=1 https://github.com/torvalds/linux ~/clones/linux
95
+ node bench/scale-test/real-world.js --repo ~/clones/linux --name linux-kernel
96
+ ```
97
+
98
+ ```bash
99
+ # Chromium follows the official `fetch` flow; expect a 30+ GB clone.
100
+ node bench/scale-test/real-world.js --repo ~/clones/chromium/src --name chromium
101
+ ```
102
+
103
+ These rows are intentionally not yet captured. The 50K dense-synth + 7,567-file vscode + 6,330-file supabase rows above already establish the scaling profile of the current implementation; whether kernel/Chromium clear or fail is *known* in the bitmap-storage sense (linear in N, hits the GB scale at 100K+ files in the worst case). Capturing them on the maintainer box is a confirm-the-known activity, not a discover-the-unknown one.
104
+
105
+ ## Reproducing this page
106
+
107
+ Every number above is mechanically reproducible. The exact commands:
108
+
109
+ ```bash
110
+ # Synth sweep (deterministic, dense-fan-out worst case)
111
+ npm run bench:scale -- --size 1000
112
+ npm run bench:scale -- --size 10000
113
+ npm run bench:scale -- --size 50000
114
+
115
+ # Real-world corpus (uses existing indexes; doesn't re-index)
116
+ node bench/scale-test/real-world.js --repo ~/carto-test-repos/tier-b/vscode --name vscode --queries-only
117
+ node bench/scale-test/real-world.js --repo ~/carto-test-repos/tier-b/supabase --name supabase --queries-only
118
+ node bench/scale-test/real-world.js --repo ~/carto-test-repos/tier-b/nextjs --name nextjs --queries-only
119
+ node bench/scale-test/real-world.js --repo ~/carto-test-repos/tier-b/cal.com --name cal.com --queries-only
120
+
121
+ # Larger (maintainer-machine work)
122
+ npm run bench:scale -- --size 100000 --keep --out /tmp/carto-100k
123
+ ```
124
+
125
+ Each run writes `bench/scale-test/results/<tag>-<ISO-timestamp>.json` and refreshes `bench/scale-test/REPORT.md`. The aggregator keeps the latest run per (kind, label) so re-running a row replaces the old number.
126
+
127
+ ---
128
+
129
+ _See `bench/scale-test/README.md` for full harness documentation._
@@ -0,0 +1,180 @@
1
+ # Troubleshooting
2
+
3
+ > Real failure modes, with fixes.
4
+
5
+ ## Install / native modules
6
+
7
+ ### `node-gyp rebuild` fails on install
8
+
9
+ Symptom: `npm install -g carto-md` exits with C++ errors mentioning `tree-sitter` or `better-sqlite3`.
10
+
11
+ Why: no prebuilt binary for your platform → falling back to compile-from-source → no C++ toolchain present.
12
+
13
+ Fix: install build tools, then retry.
14
+
15
+ | OS | Command |
16
+ |---|---|
17
+ | macOS | `xcode-select --install` |
18
+ | Ubuntu / Debian | `sudo apt-get install build-essential python3` |
19
+ | RHEL / Fedora | `sudo dnf groupinstall "Development Tools"` |
20
+ | Windows | `npm install --global windows-build-tools` (run from elevated PowerShell) |
21
+ | Alpine | `apk add --no-cache python3 make g++` |
22
+
23
+ If you're on a supported platform (macOS arm64/x64, Linux x64 glibc + musl, Windows x64), you *shouldn't* be hitting this. Run `carto doctor` — the output will tell you which native module is the problem.
24
+
25
+ ### Node version refused at install time
26
+
27
+ ```
28
+ [CARTO] Node v16.x.x is too old. carto-md requires Node ≥ v18.
29
+ ```
30
+
31
+ Upgrade Node. https://nodejs.org/ — even-numbered LTS releases (18, 20, 22) are best.
32
+
33
+ ### Missing optional grammars
34
+
35
+ ```
36
+ ⚠ Tree-sitter grammars (2 of 8 missing: tree-sitter-rust, tree-sitter-java)
37
+ ```
38
+
39
+ The optional language grammars failed to prebuild on your platform. Files in those languages still get indexed — Carto falls back to regex extraction (less accurate but functional).
40
+
41
+ To force a grammar to install:
42
+
43
+ ```bash
44
+ npm install -g tree-sitter-rust
45
+ ```
46
+
47
+ If that fails too, the platform doesn't have a prebuild and won't compile. That's fine — regex fallback works.
48
+
49
+ ## Index / sync
50
+
51
+ ### `carto sync` says "0 files re-parsed" but I changed files
52
+
53
+ Cache hit. Carto stats each file's mtime+size and skips ones that haven't changed. If you genuinely changed a file but mtime didn't move (rare — usually copying a same-content file), force a re-parse:
54
+
55
+ ```bash
56
+ touch src/the/file.ts
57
+ carto sync
58
+ ```
59
+
60
+ For a full rebuild from scratch:
61
+
62
+ ```bash
63
+ carto remove
64
+ carto init
65
+ ```
66
+
67
+ ### `carto check` claims unstable clustering
68
+
69
+ ```
70
+ [CARTO] Warning: 8.2% of files changed domain since last sync — clustering unstable.
71
+ ```
72
+
73
+ The Leiden+CPM clusterer can be sensitive when the codebase is borderline between two stable partitions. If this happens repeatedly:
74
+
75
+ 1. Pin the important files with `anchor` in `carto.config.json`. See [`docs/concepts/domains.md`](./concepts/domains.md).
76
+ 2. If a domain is genuinely splitting (a refactor in progress), this is informational — accept the drift.
77
+ 3. If you don't care about exact domain names but want stability, set keyword hints in `carto.config.json` so the names are forced.
78
+
79
+ ### Index is huge
80
+
81
+ A 100K-file repo produces a 160 MB `carto.db` and 20 MB `bitmap.bin`. Larger than expected? Most likely you're indexing `node_modules/`, a `vendor/` dir, or a generated `dist/`. Run:
82
+
83
+ ```bash
84
+ carto inspect | head -20
85
+ ```
86
+
87
+ That shows the file count. If it's way bigger than your source tree, edit `.cartoignore` to exclude the offender:
88
+
89
+ ```
90
+ node_modules/
91
+ vendor/
92
+ **/__generated__/
93
+ build/
94
+ dist/
95
+ out/
96
+ ```
97
+
98
+ ## MCP / AI tool integration
99
+
100
+ ### AI tool doesn't see Carto's tools
101
+
102
+ 1. Restart the AI tool (it loads MCP config at startup).
103
+ 2. Run `carto doctor` — it surfaces whether config files exist for the tools you have installed.
104
+ 3. If `doctor` says "MCP configuration: no MCP config files found", re-run `carto init` (it auto-wires).
105
+ 4. If `init` doesn't detect your tool, see the README's manual config snippets in the [Manual MCP wiring](../README.md) section (collapsed `<details>` block right after the install snippet).
106
+
107
+ ### MCP server crashes
108
+
109
+ Pre-2.0.7 the MCP server could crash on tool errors and the AI tool would see `-32000 Failed to reconnect`. Fixed in 2.0.7. If you're seeing it on a newer version, set `CARTO_DEBUG=1` before launching the AI tool to capture stderr.
110
+
111
+ ### "Lazy re-parse" doesn't fire on stale files
112
+
113
+ The MCP server stats the file on every file-aware query and re-parses if mtime is newer than the DB row. If a query returns stale data:
114
+
115
+ 1. Check the file's mtime: `stat src/the/file.ts`
116
+ 2. Compare against the DB row: `carto inspect | grep "last full sync"`
117
+ 3. If mtime is older, sync was after edit and the data isn't stale.
118
+ 4. If mtime is newer but the data is stale, file a bug — that's the regression test target.
119
+
120
+ ## Validation API / PR Action
121
+
122
+ ### `carto pr-impact` says "No carto index"
123
+
124
+ The action's cache restored an empty `.carto/`. Either:
125
+
126
+ - Cache key isn't invalidating. Check `hashFiles` glob in the workflow.
127
+ - First run on this branch — let it run `carto init` cold once.
128
+ - Index was removed; run `carto init` manually inside the workflow before pr-impact.
129
+
130
+ ### Sticky comment isn't sticky
131
+
132
+ The action looks for the `<!-- carto-impact-report -->` marker in existing PR comments and updates the first match. If multiple comments have the marker (somehow), the action updates the first. If you see duplicate comments, check that the workflow isn't running twice (e.g. matrix builds, multiple triggers).
133
+
134
+ ### `--fail-on HIGH` trips too often
135
+
136
+ Lower the threshold to `MEDIUM` for a softer gate, or use `--fail-on` only on `main`-bound PRs and not feature-branch PRs. Or accept that HIGH-risk PRs deserve careful review and let the gate work as intended.
137
+
138
+ ## SWE-bench harness
139
+
140
+ ### `bench/swe-bench/run.sh --task-set verified` says "dataset not found"
141
+
142
+ Download the SWE-bench-Verified dataset from Hugging Face:
143
+
144
+ ```bash
145
+ pip install huggingface_hub
146
+ huggingface-cli download princeton-nlp/SWE-bench_Verified \
147
+ --repo-type dataset --local-dir ~/swe-bench-verified
148
+ ```
149
+
150
+ Or set `CARTO_SWE_VERIFIED_PATH=/path/to/test.jsonl`.
151
+
152
+ ### AnthropicAgent throws on `--arm carto`
153
+
154
+ You ran `--task-set verified` without `ANTHROPIC_API_KEY`. Set the key, or stick to `--task-set sample` which uses the deterministic StubAgent.
155
+
156
+ ### Cost runaway during a real-API run
157
+
158
+ Set an Anthropic spend limit on your account dashboard *before* a long run. The harness emits per-task token counts to the JSONL output — tail it during the run to spot anomalies early:
159
+
160
+ ```bash
161
+ tail -f bench/swe-bench/results/<run-id>.jsonl | jq .tokensInput
162
+ ```
163
+
164
+ ## General
165
+
166
+ ### `carto doctor` is the right starting point
167
+
168
+ For any "something is broken" report, run `carto doctor` first. It checks Node, native modules, the index, git hooks, MCP config, .cartoignore. The output points at the broken component with a `Fix:` line.
169
+
170
+ ### Found a real bug
171
+
172
+ Open an issue with:
173
+
174
+ - `node --version`
175
+ - `carto --version`
176
+ - Output of `carto doctor`
177
+ - Output of `carto inspect | head -30`
178
+ - Steps to reproduce
179
+
180
+ The maintainer triage is fast on real bugs with reproducible info. The triage is slow on vague "carto doesn't work" reports.