weavatrix 0.1.3 → 0.2.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 (78) hide show
  1. package/README.md +168 -63
  2. package/SECURITY.md +25 -8
  3. package/package.json +2 -2
  4. package/skill/SKILL.md +108 -39
  5. package/src/analysis/architecture-contract.js +343 -0
  6. package/src/analysis/audit-debt.js +94 -0
  7. package/src/analysis/change-classification.js +509 -0
  8. package/src/analysis/cycle-route.js +14 -0
  9. package/src/analysis/dead-check.js +13 -6
  10. package/src/analysis/dead-code-review.js +245 -0
  11. package/src/analysis/dep-check-ecosystems.js +163 -0
  12. package/src/analysis/dep-check.js +69 -147
  13. package/src/analysis/dep-rules.js +47 -31
  14. package/src/analysis/duplicates.compute.js +47 -7
  15. package/src/analysis/endpoints-java.js +186 -0
  16. package/src/analysis/endpoints-rust.js +124 -0
  17. package/src/analysis/endpoints.js +18 -5
  18. package/src/analysis/findings.js +8 -1
  19. package/src/analysis/git-history.js +549 -0
  20. package/src/analysis/git-ref-graph.js +74 -0
  21. package/src/analysis/graph-analysis.aggregate.js +29 -28
  22. package/src/analysis/graph-analysis.edges.js +24 -0
  23. package/src/analysis/graph-analysis.js +1 -1
  24. package/src/analysis/graph-analysis.summaries.js +4 -1
  25. package/src/analysis/http-contracts.js +581 -0
  26. package/src/analysis/internal-audit.collect.js +43 -2
  27. package/src/analysis/internal-audit.reach.js +52 -1
  28. package/src/analysis/internal-audit.run.js +66 -13
  29. package/src/analysis/java-source.js +36 -0
  30. package/src/analysis/package-reachability.js +39 -0
  31. package/src/analysis/static-test-reachability.js +133 -0
  32. package/src/build-graph.js +72 -13
  33. package/src/graph/build-worker.js +3 -4
  34. package/src/graph/builder/lang-java.js +177 -14
  35. package/src/graph/builder/lang-js.js +71 -12
  36. package/src/graph/builder/lang-rust.js +129 -6
  37. package/src/graph/community.js +27 -0
  38. package/src/graph/file-lock.js +69 -0
  39. package/src/graph/freshness-probe.js +141 -0
  40. package/src/graph/graph-filter.js +28 -11
  41. package/src/graph/incremental-refresh.js +232 -0
  42. package/src/graph/internal-builder.barrels.js +169 -0
  43. package/src/graph/internal-builder.build.js +111 -16
  44. package/src/graph/internal-builder.java.js +33 -0
  45. package/src/graph/internal-builder.langs.js +2 -1
  46. package/src/graph/internal-builder.resolvers.js +109 -2
  47. package/src/graph/layout.js +21 -5
  48. package/src/graph/relations.js +4 -0
  49. package/src/graph/repo-registry.js +124 -0
  50. package/src/mcp/catalog.mjs +64 -21
  51. package/src/mcp/evidence-snapshot.architecture.mjs +80 -0
  52. package/src/mcp/evidence-snapshot.common.mjs +160 -0
  53. package/src/mcp/evidence-snapshot.duplicates.mjs +217 -0
  54. package/src/mcp/evidence-snapshot.health.mjs +95 -0
  55. package/src/mcp/evidence-snapshot.inventory.mjs +148 -0
  56. package/src/mcp/evidence-snapshot.mjs +50 -0
  57. package/src/mcp/evidence-snapshot.package-graph.mjs +249 -0
  58. package/src/mcp/evidence-snapshot.structure.mjs +81 -0
  59. package/src/mcp/graph-context.mjs +106 -181
  60. package/src/mcp/graph-diff.mjs +217 -0
  61. package/src/mcp/staleness-notice.mjs +20 -0
  62. package/src/mcp/sync-evidence.mjs +418 -0
  63. package/src/mcp/sync-payload.mjs +194 -8
  64. package/src/mcp/tool-result.mjs +51 -0
  65. package/src/mcp/tools-actions.mjs +114 -33
  66. package/src/mcp/tools-architecture.mjs +144 -0
  67. package/src/mcp/tools-company.mjs +273 -0
  68. package/src/mcp/tools-graph-hubs.mjs +58 -0
  69. package/src/mcp/tools-graph.mjs +36 -68
  70. package/src/mcp/tools-health.mjs +354 -20
  71. package/src/mcp/tools-history.mjs +22 -0
  72. package/src/mcp/tools-impact-change.mjs +261 -0
  73. package/src/mcp/tools-impact.mjs +35 -11
  74. package/src/mcp-server.mjs +100 -17
  75. package/src/mcp-source-tools.mjs +11 -3
  76. package/src/path-classification.js +201 -0
  77. package/src/path-ignore.js +69 -0
  78. package/src/security/typosquat.js +1 -1
package/README.md CHANGED
@@ -5,8 +5,8 @@
5
5
  Grep sees text. Weavatrix sees structure. It builds a dependency graph of any local repository —
6
6
  files, symbols, and the imports/calls/inheritance connecting them — and serves it to Claude Code,
7
7
  Codex, or any MCP client: change impact, transitive dependents, health audit, clone detection,
8
- coverage mapping. **23 tools available; 21 offline tools enabled by default, including one-call
9
- repository switching. Local-first: with the defaults, no repository data leaves your machine.**
8
+ coverage mapping. **32 tools available; 29 enabled by the default offline profile. Local-first: with
9
+ the defaults, no repository data leaves your machine.**
10
10
 
11
11
  - Website: [weavatrix.com](https://weavatrix.com)
12
12
  - Source: [github.com/sergii-ziborov/weavatrix](https://github.com/sergii-ziborov/weavatrix)
@@ -23,16 +23,16 @@ answers grep can't produce:
23
23
  out before you ship.
24
24
  - *"Who calls this function?"* → `get_dependents` walks reverse edges transitively: every caller,
25
25
  importer and subclass that can feel the refactor, ranked by proximity × connectivity.
26
- - *"Did my refactor actually decouple anything?"* → `rebuild_graph` + `graph_diff` report the
27
- structural delta: new module dependencies, broken or introduced import cycles, symbols that lost
28
- their last caller.
26
+ - *"Did my refactor actually decouple anything?"* → `graph_diff base_ref=HEAD~1` builds an immutable
27
+ baseline graph without checking it out, then reports the structural delta: new module
28
+ dependencies, broken or introduced import cycles, and symbols that lost their last caller.
29
29
 
30
30
  ## Quick start
31
31
 
32
32
  Requires Node ≥ 18. One command:
33
33
 
34
34
  ```sh
35
- # Claude Code — offline default; open_repo can switch local repositories:
35
+ # Claude Code — offline default; local repository switching is available explicitly:
36
36
  claude mcp add -s user weavatrix -- npx -y weavatrix <repoRoot>
37
37
  ```
38
38
 
@@ -51,20 +51,33 @@ startup_timeout_sec = 20
51
51
  tool_timeout_sec = 60
52
52
  ```
53
53
 
54
- The default includes offline repository switching but excludes every network tool. Pass a final
55
- comma-separated capability list only to restrict or extend it:
54
+ The package has one binary and several explicit security profiles. The omitted profile is `offline`:
55
+ all local analysis plus `open_repo`, with every HTTP tool absent. Pass one profile as the final
56
+ argument when a stricter repository boundary or a network feature is wanted:
57
+
58
+ | Profile | Local repository switching | Cross-repo graph reads | OSV requests | Hosted sync / contract pull |
59
+ |---|---:|---:|---:|---:|
60
+ | `offline` (default) | Yes, only through `open_repo` | Yes, only through `trace_api_contract` | No | No |
61
+ | `pinned` | No | No | No | No |
62
+ | `osv` | Yes | Yes, only when called | Only when `refresh_advisories` is called | No |
63
+ | `hosted` / `full` | Yes | Yes, only when called | Only when called | Only when `sync_graph` or `pull_architecture_contract` is called |
56
64
 
57
65
  ```sh
58
- # Pin the registration to one repository (hide open_repo/list_known_repos):
59
- claude mcp add -s user weavatrix -- npx -y weavatrix <repoRoot> graph,search,source,health,build
66
+ # Hard-pin one repository and expose no network tools:
67
+ claude mcp add -s user weavatrix -- npx -y weavatrix <repoRoot> pinned
60
68
 
61
- # Add network tools while pinning one repository:
62
- claude mcp add -s user weavatrix -- npx -y weavatrix <repoRoot> graph,search,source,health,build,online
69
+ # Add only explicit OSV refresh:
70
+ claude mcp add -s user weavatrix -- npx -y weavatrix <repoRoot> osv
63
71
 
64
- # Add network tools and keep the default repository switching:
65
- claude mcp add -s user weavatrix -- npx -y weavatrix <repoRoot> graph,search,source,health,build,retarget,online
72
+ # Enable the owner-authenticated hosted workflow:
73
+ claude mcp add -s user weavatrix -- npx -y weavatrix <repoRoot> hosted
66
74
  ```
67
75
 
76
+ Advanced registrations may still pass an exact comma-separated capability set:
77
+ `graph,search,source,health,build,retarget,crossrepo,advisories,hosted`. The former `online` capability remains
78
+ a compatibility alias for `advisories,hosted`; new registrations should use the named profiles or
79
+ the narrower capability names.
80
+
68
81
  Or clone it:
69
82
 
70
83
  ```sh
@@ -73,16 +86,18 @@ cd weavatrix && npm install
73
86
  claude mcp add -s user weavatrix -- node <path-to>/weavatrix/bin/weavatrix-mcp.mjs <repoRoot>
74
87
  ```
75
88
 
76
- - `<repoRoot>` — the repository to start with; the graph location is derived automatically
77
- (`<repoRoot-parent>/weavatrix-graphs/<repoName>/graph.json`). Pass an explicit
89
+ - `<repoRoot>` — the repository to start with; the graph location is derived automatically in the
90
+ per-user registry (`~/.weavatrix/graphs/<repository-storage-key>/graph.json`; its stable UUID is
91
+ stored beside it in `.repository-id`). Pass an explicit
78
92
  `<graph.json> <repoRoot>` pair instead if you keep graphs elsewhere.
79
93
 
80
94
  No graph yet? Ask the agent to call `rebuild_graph`; it builds the missing graph locally.
81
- `open_repo` can change the active repository and builds a missing graph automatically. A normal
82
- `open_repo` call also upgrades graphs created before `0.1.3` to typed import edges; `build:false`
95
+ With the default `offline` profile (or an explicit capability set containing `retarget`),
96
+ `open_repo` can change the active repository
97
+ and builds a missing graph automatically. A normal
98
+ `open_repo` call also upgrades graphs created before `0.1.4` to edge metadata v2; `build:false`
83
99
  probes without building and refuses a legacy graph. Retargeting is offline but intentionally changes
84
- the filesystem boundary for subsequent tools; omit `retarget` from an explicit capability list when
85
- a registration must stay pinned to one repository.
100
+ the filesystem boundary for subsequent tools; select `pinned` when that boundary must not move.
86
101
 
87
102
  An agent skill with recipes ships in [skill/SKILL.md](skill/SKILL.md) — install as
88
103
  `~/.claude/skills/weavatrix/SKILL.md`.
@@ -91,49 +106,115 @@ An agent skill with recipes ships in [skill/SKILL.md](skill/SKILL.md) — instal
91
106
 
92
107
  **graph** — `graph_stats`, `get_node`, `get_neighbors`, `query_graph`, `god_nodes`,
93
108
  `shortest_path`, `get_community`, `list_communities`, `module_map`, `get_dependents`,
94
- `change_impact`, `graph_diff`. Runtime dependencies and TypeScript type-only coupling are reported
95
- separately where that distinction changes the result.
109
+ `change_impact`, `git_history`, `graph_diff`, `get_architecture_contract`,
110
+ `prepare_change`. Runtime dependencies, TypeScript type-only coupling and language
111
+ compile-only edges (Rust module/use, Java imports) are reported separately where that distinction
112
+ changes the result.
96
113
 
97
114
  **search / source** — `search_code` (ripgrep-backed, pure-Node fallback), `read_source` (a
98
115
  symbol's actual code in one hop), `list_endpoints` (HTTP route inventory:
99
- Express/Fastify/Nest/Flask/FastAPI/Go mux …)
100
-
101
- **health** — `run_audit` (dead code, unused exports, missing/unused npm/Go/Python deps, runtime
102
- cycles, type-only coupling, orphans, boundary rules, offline OSV vulnerabilities + typosquat +
103
- lockfile drift), `find_duplicates` (MOSS winnowing over method bodies — catches copy-paste even
116
+ Express/Fastify/Nest/Flask/FastAPI/Go mux/Rust axum and actix-web …)
117
+
118
+ **health** — `find_dead_code` (bounded review queue for statically unreferenced files, functions,
119
+ methods, and symbols, with confidence/evidence and explicit public/framework/dynamic caveats),
120
+ `run_audit` (unused files/exports/dependencies, missing npm/Go/Python deps, runtime
121
+ cycles, type-only/compile-only coupling, orphans, boundary rules, offline OSV vulnerabilities + typosquat +
122
+ lockfile drift; accepts an immutable `base_ref`, `changed_files`, and `debt: new|existing|all` for
123
+ review-scoped results), `find_duplicates` (MOSS winnowing over method bodies — catches copy-paste even
104
124
  after renames), `coverage_map` (existing coverage reports mapped onto the graph; untested hotspots
105
- ranked by connectivity — tests are never executed)
125
+ ranked by connectivity — tests are never executed), `verify_architecture`,
126
+ `explain_architecture_violation`, `propose_architecture_exception`
106
127
 
107
128
  **build** — `rebuild_graph` (reports the structural delta, keeps the prior state as
108
129
  `graph.prev.json`)
109
130
 
110
- **retarget** *(enabled by default, offline, explicit tool call)* `open_repo`, `list_known_repos`;
111
- changes the active repository boundary
131
+ For dead functions/methods/symbols, call `find_dead_code` first. Its default production-only queue
132
+ shows high/medium-confidence candidates and excludes tests, generated code, mocks, stories and docs;
133
+ use `kinds:["method"]` or a `path` prefix to narrow it. `min_confidence:"low"` explicitly includes
134
+ public APIs and framework/dynamic/reflection-sensitive candidates with their warnings. For repository
135
+ maintenance or branch debt, pair it with `run_audit category=unused debt=all` (or add an immutable
136
+ `base_ref` with `debt=new`) to cover unused files, exports and dependencies. Neither tool authorizes
137
+ deletion: inspect `read_source`, `get_dependents`, exact search, manifests/configuration and tests first.
138
+
139
+ `graph_diff` accepts `base_ref` (`HEAD~1`, `main`, `origin/main`, or another local Git ref) for a
140
+ fresh baseline comparison. Without it, the tool compares against `graph.prev.json` saved by the last
141
+ full rebuild. Either mode can be narrowed with `path`.
142
+
143
+ Graph and health calls reconcile the working graph before answering. Safe JS/TS body-only changes
144
+ reparse only the changed files plus bounded reverse importers; add/delete, export-surface, barrel,
145
+ manifest, alias, ignore/config, non-JS/TS, or unsafe merge cases deliberately fall back to a full
146
+ rebuild. The result says whether freshness was `none`, `incremental`, or `full`. Graph artifacts stay
147
+ in the per-user cache and never need to be committed to Git.
148
+
149
+ **retarget** *(included in `offline`; absent from `pinned`; every switch is an explicit local call)* —
150
+ `open_repo`, `list_known_repos`; changes the active repository boundary
151
+
152
+ **crossrepo** *(included in `offline`; absent from `pinned`; reads only registered local graphs)* —
153
+ `trace_api_contract`; reconciles the selected backend/client graphs and joins routes to client callsites
154
+
155
+ `query_graph` accepts optional `seed_files` when an architectural question must start from exact
156
+ entry points. Resolved explicit seeds are exclusive by default; set `augment_seeds:true` only when
157
+ fuzzy question-derived seeds are also wanted. Broad bootstrap/routing/authentication questions
158
+ without explicit seeds rank conventional entry points and high-level modules ahead of incidental matches.
159
+
160
+ **advisories** *(network, explicit opt-in)* — `refresh_advisories`
112
161
 
113
- **online** *(explicit opt-in — see Privacy)* — `refresh_advisories`, `sync_graph`
162
+ **hosted** *(network, explicit opt-in)* — `pull_architecture_contract`, `sync_graph`
114
163
 
115
- Quality of life: graph tools self-report staleness vs the repo HEAD; ambiguous name lookups are
116
- disclosed instead of silently guessed; and the server **hot-reloads its own tool code** when the
117
- files under `src/mcp/` change — no reconnect needed.
164
+ Quality of life: graph/health reads auto-reconcile and expose `none` / `incremental` / `full`
165
+ freshness, with a short clean-read debounce to avoid rescanning the repository for every tool call;
166
+ ambiguous name lookups are
167
+ disclosed instead of silently guessed; and the server **hot-reloads its watched MCP tool entry
168
+ modules and catalog** when those files change — other MCP helpers and analysis engines require a
169
+ reconnect.
118
170
 
119
171
  ## Signal quality and repository configuration
120
172
 
121
- Weavatrix `0.1.3` reduces the most common sources of static-analysis noise:
173
+ Weavatrix `0.2.0` reduces the most common sources of static-analysis noise while deepening Rust and
174
+ Java graphs:
122
175
 
123
176
  - In Git repositories, graph and clone scans use tracked plus non-ignored untracked files, so
124
177
  `.gitignore`-excluded build outputs such as packaged applications do not dominate findings.
178
+ - Add a repository-root `.weavatrixignore` for analysis-only exclusions that should remain tracked
179
+ in Git. It supports `*`, `**`, `?`, root-anchored `/patterns`, directory suffixes and ordered `!`
180
+ re-includes. The same file universe is used by graph building, audits and clone scanning.
181
+ - `mode: "no-tests"` and `find_duplicates(include_tests:false)` classify `test-e2e`, Cypress,
182
+ Playwright, acceptance and integration roots as tests, not only `*.test`/`*.spec` filenames.
183
+ - `benchmarks/**` and any `**/__temp/**` root are classified as non-production review surfaces and
184
+ suppressed from dead-code/clone/audit queues by default. If a benchmark is deliberate production
185
+ source, opt its narrow path back in with `.weavatrix.json` `classify.product` patterns.
125
186
  - TypeScript `import type` and type-only re-exports remain visible as compile-time coupling but do
126
187
  not inflate runtime-cycle severity. `module_map`, `change_impact` and structural diffs preserve
127
188
  that distinction. `god_nodes` ranks unique neighbors with runtime connectivity first and reports
128
189
  repeated occurrences separately.
190
+ - Rust `mod`, `use` and `pub use` paths now resolve between files and modules. They are marked
191
+ compile-only, so they enrich `module_map` and compile-time coupling without inventing runtime
192
+ initialization cycles or promoting compile-time coupling to runtime impact. Axum and actix-web
193
+ routes are included in `list_endpoints`.
194
+ - Java class/interface/enum/record/annotation declarations retain their symbol kind; methods and
195
+ constructors are linked to their declaring type with visibility metadata. Internal
196
+ `extends`/`implements` relationships and resolvable type references link to real declarations.
197
+ Imports are compile-only; call/reference/heritage edges contribute impact. Maven/Gradle Java
198
+ trees use package-aware communities instead of one giant `src` bucket. External or synthetic
199
+ placeholder types are not created merely to inflate graph counts.
129
200
  - Dependency checks resolve the nearest workspace manifest and `tsconfig`/`jsconfig` aliases,
130
201
  account for framework-owned runtime peers such as Next.js + `react-dom`, and recognize Next.js
131
202
  App Router route exports as endpoints.
203
+ - Generated NAPI-RS platform loaders and declared template/example catalogs no longer create
204
+ phantom runtime dependency, orphan or unused-export findings. Conventional template roots are
205
+ inferred conservatively; custom roots can be declared explicitly.
132
206
  - `coverage_map` reports coverage as **unavailable** when no supported report exists. That means
133
207
  “no data”, not zero coverage.
134
208
  - Duplicate output is a review queue, not a verdict: near-identical bodies are clone candidates;
135
209
  same-name/different-body pairs are divergence candidates. Read both sources and confirm the
136
210
  shared contract before consolidating code.
211
+ - `run_audit base_ref=... debt=new` compares stable finding fingerprints against a graph rebuilt
212
+ from that immutable commit. Existing debt and fixed findings are counted separately. Supplying
213
+ only `changed_files` is honestly labeled changed scope—it is never presented as proof that a
214
+ finding is new.
215
+ - `find_dead_code` exposes the symbol-level liveness evidence already used by the audit as a bounded
216
+ agent review queue. Public/exported methods, framework entries, decorators, dynamic loading and
217
+ reflection lower confidence; the result always says `REVIEW_REQUIRED` and `autoDelete:false`.
137
218
 
138
219
  `run_audit` makes incomplete security coverage explicit. OSV state is `OK` only after every
139
220
  supported pinned package/version for this repository was queried successfully. `PARTIAL` means
@@ -149,6 +230,7 @@ repository root:
149
230
  ```json
150
231
  {
151
232
  "entrypoints": ["scripts/publish-release.mjs"],
233
+ "nonRuntimeRoots": ["library", "catalogs/examples"],
152
234
  "python": {
153
235
  "managedDependencies": ["numpy", "openvino-genai"],
154
236
  "ignoreDependencies": ["vendor-sdk"]
@@ -157,6 +239,9 @@ repository root:
157
239
  ```
158
240
 
159
241
  `entrypoints` protects framework/script entry files from dead-code classification.
242
+ `nonRuntimeRoots` (alias: `templateRoots`) marks reusable examples/templates that are not deployed
243
+ as one application. It suppresses orphan/dead/unused-export noise and missing/unresolved dependency
244
+ findings when every use is inside those roots. Import edges, cycles and boundary checks remain visible.
160
245
  `managedDependencies` declares Python modules supplied by an external runtime;
161
246
  `ignoreDependencies` suppresses intentionally unresolved Python packages. Keep the lists narrow:
162
247
  they change audit interpretation, not the repository or its dependency installation.
@@ -164,29 +249,48 @@ they change audit interpretation, not the repository or its dependency installat
164
249
  ## Privacy: local-first, offline by design
165
250
 
166
251
  Graph queries, audits, clone scans and repository switching run locally. The default capability set
167
- is `graph,search,source,health,build,retarget`: no Weavatrix HTTP requests. `open_repo` changes the
168
- active local boundary only when called. Weavatrix itself initiates outbound HTTP only from two
169
- tools; both require the explicit `online` group and a tool call:
252
+ is `graph,search,source,health,build,retarget,crossrepo`: no Weavatrix HTTP requests. `open_repo`
253
+ changes the active local boundary only when called. Select `pinned` to remove repository switching,
254
+ global repository listing, and cross-repository graph tracing too.
255
+ Weavatrix itself initiates outbound HTTP only from three tools; all are absent from `offline` and
256
+ `pinned`, and none runs merely because a profile is enabled:
170
257
 
171
258
  - `refresh_advisories` — queries [OSV.dev](https://osv.dev) with your lockfile's package
172
259
  **names + versions** (that is what an OSV query is; never source code) and caches the advisories
173
260
  in `~/.weavatrix/advisories.json`. `run_audit` then matches against that store fully offline.
174
- - `sync_graph` — constructs a versioned, allowlisted payload from `graph.json`: relative paths,
175
- symbol names and line ranges, import/dependency identifiers, edges and numeric metrics. Unknown
176
- fields are discarded; source file bodies are never read for sync or included in the payload. The
177
- endpoint is **yours**, configured via `WEAVATRIX_SYNC_URL` / `WEAVATRIX_SYNC_TOKEN`. Off by default.
178
- Sync payload v2 preserves type-only edge metadata. Graphs built before `0.1.3` must be rebuilt
179
- once before syncing; a normal `open_repo` call performs that upgrade automatically.
180
-
181
- If `refresh_advisories` is not listed by the MCP client, that is the expected default: the
182
- registration does not include `online`. Only with the user's approval, add `online` to the final
183
- capability list (for example `graph,search,source,health,build,retarget,online`), restart/reconnect
184
- the MCP server, and then invoke `refresh_advisories`. Enabling the group does not trigger a request
185
- by itself.
186
-
187
- Capability groups (`graph`, `search`, `source`, `health`, `build`, `retarget`, `online`) are
188
- selectable through the final positional argument. Omitted caps use the safe default above; an
189
- explicit list exposes exactly the named groups.
261
+ - `pull_architecture_contract` — sends the active repository's opaque stable UUID with bearer
262
+ authentication, downloads the owner-approved target-architecture contract, validates it, and
263
+ stores the contract in the local graph cache. It sends no source, symbol, or repository path.
264
+ - `sync_graph` builds a bounded evidence snapshot locally, then sends payload v3: the v2 graph
265
+ allowlist plus module dependencies, runtime/compile-time cycles, declared boundary violations,
266
+ health findings, complexity-threshold breaches, stack identifiers, a bounded direct/transitive
267
+ dependency graph, direct package usage, and bounded clone/divergence review candidates. Local
268
+ analyzers may read repository source and manifests to derive those
269
+ facts. The wire contract has no fields for file bodies, snippets, absolute host paths, environment
270
+ values or Git remotes; unknown fields are discarded and unsafe optional path metadata is omitted.
271
+ The request also carries the normalized repository display name used by the
272
+ hosted list. The endpoint is **yours**, configured through `WEAVATRIX_SYNC_URL` and the optional
273
+ `WEAVATRIX_SYNC_TOKEN`; the feature is off by default. Pass `payload_version: 2` only for an
274
+ intentional graph-only compatibility sync—there is no silent downgrade that discards evidence.
275
+ Graphs built before `0.1.4` must be rebuilt once before syncing; V3 also refuses a stale graph so
276
+ source-derived evidence cannot be mixed with old topology.
277
+
278
+ Evidence sections carry independent `state` (`COMPLETE`, `PARTIAL`, `NOT_CHECKED`,
279
+ `NOT_APPLICABLE`, `ERROR`) and `verdict` (`PASS`, `FAIL`, `UNKNOWN`) fields plus exact
280
+ `total/returned/truncated` counts. An incomplete check is never converted into a clean zero. V3 is
281
+ deterministic: volatile timestamps are excluded and the allowlisted snapshot has a canonical SHA-256
282
+ fingerprint, so identical evidence does not manufacture a hosted revision. The client mirrors the
283
+ hosted 8 MiB / 25,000-node / 100,000-edge / 50,000-external-import safety limits before networking.
284
+
285
+ If a network tool is not listed by the MCP client, that is the expected offline default. With the
286
+ user's approval, select `osv` for advisory refresh only or `hosted` for the hosted workflow,
287
+ restart/reconnect the MCP server, and then invoke the intended tool. Enabling a profile does not
288
+ trigger a request by itself.
289
+
290
+ Profiles (`offline`, `pinned`, `osv`, `hosted`, `full`) or exact capability groups (`graph`,
291
+ `search`, `source`, `health`, `build`, `retarget`, `crossrepo`, `advisories`, `hosted`) are selectable through
292
+ the final positional argument. Omitted caps use `offline`; an explicit capability list exposes
293
+ exactly the named groups. Legacy `online` expands to `advisories,hosted` for compatibility.
190
294
 
191
295
  ## Security model
192
296
 
@@ -195,12 +299,12 @@ vulnerability findings. This is where each capability comes from and how it is c
195
299
 
196
300
  | Capability alert | Why it exists | Activation and boundary |
197
301
  |---|---|---|
198
- | Network access | `refresh_advisories` sends pinned package names and versions to OSV; `sync_graph` sends a versioned allowlist of graph metadata (relative paths, symbols and line ranges, import/dependency identifiers, edges and numeric metrics). It discards unknown graph fields and does not read source file bodies | `online` is disabled by default; each request requires a tool call, and sync additionally requires `WEAVATRIX_SYNC_URL` |
302
+ | Network access | `refresh_advisories` sends pinned package names and versions to OSV; `pull_architecture_contract` sends an opaque repository UUID and receives an owner-approved contract; `sync_graph` sends a normalized repository label plus an allowlisted graph/evidence payload. Evidence is derived locally from source and manifests, but source bodies, snippets, absolute paths, environment values, credentials and Git remotes are excluded | `offline` and `pinned` expose no network tools. `osv` exposes only advisory refresh. `hosted`/`full` expose all three; every request still requires an explicit tool call, and hosted calls require `WEAVATRIX_SYNC_URL` |
199
303
  | Shell access | Local `git` powers staleness/change impact; `rg` accelerates search; timed-out Windows child processes may be terminated | Used only by the corresponding local operation; it does not imply network access |
200
- | Debug / dynamic loading | Cache-busted `import()` hot-reloads local MCP tool modules; `createRequire` loads package metadata and parser dependencies | Loads files from the installed package; no `eval` |
201
- | Environment access | Reads `WEAVATRIX_*` configuration; local child processes inherit the normal host environment | `WEAVATRIX_SYNC_TOKEN` is removed from every child-process and worker environment and read only by `sync_graph` |
202
- | Filesystem access | Reads the active repository, graph, lockfiles and coverage reports; writes derived graphs and advisory cache | Realpath containment blocks traversal and symlink/junction escapes. `open_repo` is an explicit offline call that changes the active boundary; omit `retarget` in a custom capability list to pin one repository. The optional malware dependency scan may inspect installed dependency caches such as GOPATH |
203
- | URL strings | Fixed OSV/documentation URLs plus a user-configured sync URL | A URL string causes no request by itself; only the two `online` tools perform requests |
304
+ | Debug / dynamic loading | Cache-busted `import()` hot-reloads watched MCP tool entry modules; `createRequire` loads package metadata and parser dependencies | Loads files from the installed package; no `eval` |
305
+ | Environment access | Reads `WEAVATRIX_*` configuration; local child processes inherit the normal host environment | `WEAVATRIX_SYNC_TOKEN` is removed from every child-process and worker environment and read only by `sync_graph` / `pull_architecture_contract` |
306
+ | Filesystem access | Reads the active repository, graph, lockfiles and coverage reports; writes derived graphs and advisory/architecture caches | Realpath containment blocks traversal and symlink/junction escapes. The `pinned` profile removes `open_repo`; the default `offline` profile permits only explicit local switching. The optional malware dependency scan may inspect installed dependency caches such as GOPATH |
307
+ | URL strings | Fixed OSV/documentation URLs plus a user-configured sync URL | A URL string causes no request by itself; only the three network-profile tools perform requests |
204
308
 
205
309
  `read_source` accepts repo-relative regular files only, caps a read at 2 MB, and refuses lexical or
206
310
  realpath escapes. Graph-derived paths pass through the same boundary before analysis tools read
@@ -214,8 +318,9 @@ native compilation.
214
318
 
215
319
  ## On-disk layout
216
320
 
217
- Graphs are derived data and never live inside your repo: they go to a `weavatrix-graphs/` folder
218
- **next to** it (one folder per repo, holding `graph.json` + `graph.prev.json`).
321
+ Graphs are derived data and never live inside your repo: the global per-user registry stores them at
322
+ `~/.weavatrix/graphs/<repository-storage-key>/` (including `.repository-id`, `graph.json`, and
323
+ `graph.prev.json`).
219
324
 
220
325
  ## Development
221
326
 
@@ -226,8 +331,8 @@ npm test # node --test
226
331
 
227
332
  Design rule: **no source file exceeds 300 lines.** Larger concerns split into dotted-suffix modules
228
333
  behind a slim facade (`foo.js` re-exports `foo.parse.js`, `foo.report.js`, …); the MCP layer lives
229
- in `src/mcp/` (graph context, four tool modules, catalog + hot-reload loader) behind the thin stdio
230
- entry `src/mcp-server.mjs`.
334
+ in `src/mcp/` (graph context, tool entry modules, focused helpers, and the catalog/hot-reload
335
+ loader) behind the thin stdio entry `src/mcp-server.mjs`.
231
336
 
232
337
  ## Roadmap
233
338
 
package/SECURITY.md CHANGED
@@ -21,11 +21,28 @@ mitigation is available so users have a reasonable opportunity to update.
21
21
 
22
22
  ## Security boundaries
23
23
 
24
- The default MCP registration is offline. Every standard source, manifest, configuration and coverage
25
- read is canonical-path-contained within the active repository and rejects traversal plus symlink or
26
- junction escapes. The optional malware dependency scan may inspect installed dependency caches such
27
- as GOPATH. The default `retarget` capability exposes `open_repo`, an explicit offline tool call that
28
- intentionally changes the active repository; omit that group in a custom capability list to pin one
29
- boundary. The optional `online` capability contains Weavatrix's HTTP tools; `sync_graph`
30
- additionally requires a user-configured endpoint and sends only a versioned metadata allowlist,
31
- discarding unknown fields from the local graph cache.
24
+ The default `offline` MCP profile exposes no HTTP tools. Every standard source, manifest,
25
+ configuration and coverage read is canonical-path-contained within the active repository and rejects
26
+ traversal plus symlink or junction escapes. The optional malware dependency scan may inspect installed
27
+ dependency caches such as GOPATH. `offline` permits repository switching only through an explicit
28
+ local `open_repo` call; select `pinned` to remove that tool, the global repository listing, and
29
+ cross-repository API tracing, holding a hard startup-repository boundary.
30
+
31
+ Network capabilities are split by purpose. `osv` adds only `refresh_advisories`, which sends pinned
32
+ package names and versions to OSV.dev when called. `hosted` / `full` also expose `sync_graph` and
33
+ `pull_architecture_contract`; both require a user-configured endpoint, and contract pull requires
34
+ bearer authentication. The legacy `online` capability remains an alias for advisory plus hosted
35
+ networking so existing registrations do not break.
36
+
37
+ Payload v3 runs bounded local analyzers over the active repository, then sends only a strict
38
+ graph/evidence allowlist plus a normalized repository display name. That evidence can include a
39
+ bounded direct/transitive lockfile dependency graph and stable clone/divergence candidates. The
40
+ contract has no source-body,
41
+ snippet, absolute-host-path, environment, credential, Git-remote or analyzer-error fields; unknown
42
+ fields are discarded and unsafe optional path metadata is omitted. V3 rejects stale graphs,
43
+ duplicate node IDs, dangling edges and oversized payloads before any request. Graph-only payload v2
44
+ remains an explicit compatibility option and is never selected as a silent fallback.
45
+
46
+ `pull_architecture_contract` sends only the active repository's opaque stable UUID, receives an
47
+ owner-approved target contract, validates it, and caches it locally. It never sends source, symbols,
48
+ file paths, or Git metadata.
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "weavatrix",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "Weavatrix — code graph & blast-radius MCP server for AI coding agents: change impact, transitive dependents, health audit, duplicate detection, and coverage mapping over any local repository.",
6
- "author": "Sergii Ziborov <sergii@edgehawk.io>",
6
+ "author": "Sergii Ziborov <sergii.ziborov@gmail.com>",
7
7
  "license": "MIT",
8
8
  "homepage": "https://weavatrix.com",
9
9
  "repository": {