weavatrix 0.2.11 → 0.2.13

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/README.md CHANGED
@@ -49,6 +49,100 @@ Weavatrix answers questions a text index cannot:
49
49
  impact, bounded call-argument flow, Git graph drift, architecture/duplicate/API ratchets, and
50
50
  affected-test evidence.
51
51
 
52
+ ## Worked examples
53
+
54
+ These are representative sequences from local dogfooding, not fabricated chat transcripts. Counts
55
+ describe the observed repository snapshots and will move with the code.
56
+
57
+ ### Understand an unfamiliar backend without reading it linearly
58
+
59
+ ```text
60
+ Question: Where does an attack-mitigation request go?
61
+
62
+ module_map
63
+ -> production territories and strongest module dependencies
64
+ list_endpoints
65
+ -> 462 routes observed in a 1,076-file backend snapshot
66
+ trace_endpoint
67
+ -> composed router mount -> controller -> service -> task/messaging
68
+ -> bounded call-site excerpts around decisive edges
69
+ ```
70
+
71
+ Use `module_map` for the initial application shape, then switch to the exact endpoint or symbol. Do
72
+ not lead with a broad natural-language `query_graph` when the route or identifier is already known.
73
+
74
+ ### Check whether a backend handler is used by another repository
75
+
76
+ ```text
77
+ Question: Can this handler be removed?
78
+
79
+ list_known_repos -> trace_api_contract
80
+ backend endpoints observed: 163
81
+ client callsites joined: 267 across two registered clients
82
+ handler liveness: NOT_DEAD_EXTERNAL_USE
83
+ unresolved dynamic URLs: POSSIBLE_EXTERNAL_USE / UNKNOWN
84
+ ```
85
+
86
+ This joins separately cached local graphs; it does not upload source. Medium/high-confidence
87
+ external use can keep a handler out of the dead-code queue, while dynamic or ambiguous calls remain
88
+ explicitly incomplete evidence.
89
+
90
+ ### Change one method with an evidence trail
91
+
92
+ ```text
93
+ inspect_symbol -> context_bundle -> get_dependents -> coverage_map
94
+ -> edit the bounded workset
95
+ -> verified_change phase=verify base_ref=<merge-base>
96
+ ```
97
+
98
+ On an observed BranchPilot diff, `change_impact` separated removed methods/signatures from additive
99
+ exports and ranked a 98-node radius without collapsing runtime and type-only coupling. If measured
100
+ coverage, the architecture contract, or requested tests are missing, the final state is `UNKNOWN`,
101
+ not a cosmetic pass.
102
+
103
+ ### Review Health and clone debt without auto-deleting code
104
+
105
+ ```text
106
+ run_audit category=dependencies debt=all
107
+ -> missing direct dependency (observed: mongodb)
108
+ -> lockfile drift and unresolved imports
109
+ run_audit debt=all
110
+ -> runtime cycles separated from compile/type-only coupling
111
+ find_duplicates
112
+ -> clone families and same-name divergence
113
+ -> homogeneous router boilerplate suppressed by default
114
+ ```
115
+
116
+ Every dead-code, orphan, dependency and duplicate item remains review evidence. Confirm framework
117
+ conventions and source use before editing; Weavatrix does not auto-delete or merge findings.
118
+
119
+ ## Benchmarks
120
+
121
+ Two different gates ship in the repository:
122
+
123
+ - `npm run benchmark` is a reproducible golden suite for TypeScript, JavaScript, Python, Go, Java
124
+ and Rust, plus cross-repository HTTP matching, framework conventions and the MCP graph lifecycle.
125
+ - `npm run benchmark:real` compares revision-pinned local application snapshots with the checked-in
126
+ 0.2.1 relation baseline. It fails on unexplained signal loss; `MISSING`, `STALE` and `UNBASELINED`
127
+ remain incomplete, not green.
128
+
129
+ Latest local release run (Windows x64, Node 24.15.0, July 18, 2026):
130
+
131
+ | Gate | Result | Selected evidence |
132
+ |---|---:|---|
133
+ | Six language fixtures | 6/6 PASS | exact symbols/edges and complete edge provenance |
134
+ | Cross-repo fixture | PASS, 431.79 ms cold | endpoint match, typed wrapper, external use, affected screen |
135
+ | Lifecycle | PASS | `full -> incremental -> none -> reconnect/none`; 1,376-byte text response |
136
+ | Total fixture cold build | 1.31 s | all six language graphs; 6.4 KB bounded report |
137
+ | Real-repository baseline | 6/6 PASS | TS, JS, Python, Go, Java and Rust snapshots |
138
+
139
+ Real snapshots ranged from 473 nodes / 1,165 edges in 0.22 s (Go) to 8,192 nodes / 21,814 edges
140
+ in 9.44 s (TypeScript). The Java snapshot built 7,143 nodes / 23,708 edges in 2.61 s, including
141
+ receiver-aware cross-file calls. These are regression measurements on one machine, not competitor
142
+ benchmarks or universal latency claims. See [benchmark/cases.mjs](benchmark/cases.mjs),
143
+ [benchmark/real-repositories.json](benchmark/real-repositories.json), and run the commands above to
144
+ reproduce them on your own repositories.
145
+
52
146
  ## Quick start
53
147
 
54
148
  Requires Node ≥ 18. One command:
@@ -100,6 +194,13 @@ Advanced registrations may still pass an exact comma-separated capability set:
100
194
  a compatibility alias for `advisories,hosted`; new registrations should use the named profiles or
101
195
  the narrower capability names.
102
196
 
197
+ After an upgrade, reconnect the MCP server or start a new agent task before checking its tool list:
198
+ many clients snapshot `tools/list` and input schemas for the lifetime of one connection. The expected
199
+ counts are 31 for `pinned`, 34 for `offline`, 35 for `osv`, and all 38 for `hosted` / `full`. A custom
200
+ capability list must include `crossrepo` to expose `trace_api_contract`; `online` alone adds only the
201
+ legacy advisory/Hosted groups. `graph_stats` reports the running package version, enabled capabilities
202
+ and registered-tool count so a cached process can be distinguished from the installed package.
203
+
103
204
  Or clone it:
104
205
 
105
206
  ```sh
@@ -248,6 +349,24 @@ reconnect. Every MCP response also carries local, transient `_meta["weavatrix/me
248
349
  time, output bytes/token estimate, graph freshness/revision/update and graph-cache status. These
249
350
  metrics are not persisted or transmitted by Weavatrix.
250
351
 
352
+ ### 0.2.13 runtime-integrity and cross-language verification patch
353
+
354
+ - `verified_change` no longer requires `package.json` when no package tests can run. Python, Go,
355
+ Java, Rust and other non-Node repositories now receive `NOT_REQUESTED` or `DISABLED` test evidence
356
+ instead of a false `BLOCKED`; actual package-script execution keeps the same double opt-in and
357
+ allowlist.
358
+ - Release verification starts the packed npm artifact and portable MCPB stage over stdio. It asserts
359
+ the exact profile counts and required 38-tool `full` surface, including `trace_endpoint`,
360
+ `trace_api_contract` and `preview_sync`, so source/package drift cannot publish silently.
361
+ - Runtime diagnostics expose the package version, selected capability groups and registered tool
362
+ count. The documentation now distinguishes an old client connection from an intentional profile
363
+ omission and explains that custom capabilities need `crossrepo` for contract tracing.
364
+ - The bundled skill documents practical CLI/worker/event flows, local target-architecture adoption,
365
+ repository classification, undirected path semantics and the correct release and proof-carrying
366
+ change recipes without reducing Weavatrix to text search.
367
+
368
+ Full patch notes: [docs/releases/v0.2.13.md](docs/releases/v0.2.13.md).
369
+
251
370
  ### 0.2.9 correctness, signal, and consent patch
252
371
 
253
372
  - Express endpoint inventory composes nested imported `router.use(...)` mounts, so a local route such
@@ -0,0 +1,48 @@
1
+ # Weavatrix 0.2.13
2
+
3
+ ## Runtime-integrity and cross-language verification patch
4
+
5
+ 0.2.13 closes two failures found by dogfooding the live MCP on real JavaScript and Python
6
+ applications. A live client could keep an older tool/schema snapshot after the checkout had advanced,
7
+ and `verified_change` treated the absence of a Node manifest as a blocker even when no package test
8
+ was requested. Neither failure is converted into a cosmetic pass: incomplete architecture, coverage,
9
+ API or test evidence still produces `UNKNOWN` where appropriate.
10
+
11
+ ### Cross-language `verified_change`
12
+
13
+ - An empty test request returns `NOT_REQUESTED` before looking for `package.json`.
14
+ - Requested package tests with `run_tests:false` return `DISABLED` without pretending that they ran
15
+ or blocking a Python/Go/Java/Rust repository for lacking an npm manifest.
16
+ - Actual execution still requires both `run_tests:true` and `WEAVATRIX_ALLOW_TEST_RUNS=1`, accepts
17
+ only existing test/check/verify package scripts and rejects shell-sensitive arguments.
18
+ - Regression coverage exercises both plan and verify phases against a Python-only repository.
19
+
20
+ ### Packed-runtime and live-tool integrity
21
+
22
+ - Release verification runs the packed npm artifact and portable MCPB stage as real stdio servers.
23
+ - The smoke gate asserts 34 tools for the offline profile and all 38 for `hosted` / `full`, including
24
+ `trace_endpoint`, `trace_api_contract` and the local-only `preview_sync` approval step.
25
+ - `graph_stats` and initialization diagnostics identify the running package version, enabled
26
+ capabilities and registered tool count. This separates an old client connection from a deliberately
27
+ restricted profile.
28
+ - Existing security boundaries are unchanged: `offline` remains the no-HTTP default; `online` stays
29
+ a compatibility alias for `advisories,hosted`; `crossrepo` is not silently added to a custom list;
30
+ and no network tool is made available by default.
31
+
32
+ MCP clients commonly snapshot `tools/list` for one connection. After upgrading, reconnect or start a
33
+ new task. Expected counts are 31 (`pinned`), 34 (`offline`), 35 (`osv`) and 38 (`hosted` / `full`).
34
+
35
+ ### Skill and architecture workflow
36
+
37
+ The bundled skill now covers non-HTTP entrypoints (CLI, worker, queue, cron and events), explains how
38
+ to review and save a local starter contract, establish an explicit ratchet baseline, apply a reviewed
39
+ exception, and classify generated/test/resource trees through `.weavatrix.json`. It also labels
40
+ `shortest_path` as undirected connectivity rather than directional call proof, uses the correct
41
+ `change_impact base` parameter, and avoids redundant symbol-context calls.
42
+
43
+ ## Compatibility
44
+
45
+ - The 38 tool names, input schemas and `weavatrix.tool.v1` result envelope remain compatible.
46
+ - Hosted sync payload v2/v3, confirmation-token consent and architecture-contract transport are
47
+ unchanged; no hosted application change is required.
48
+ - The public MIT license and local-first network boundary are unchanged.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "weavatrix",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "type": "module",
5
5
  "description": "Local repository intelligence MCP for AI coding agents: reusable architecture graph for fast application understanding, Health, dead code, clones, history, blast radius and architecture safeguards.",
6
6
  "author": "Sergii Ziborov <sergii.ziborov@gmail.com>",
@@ -26,7 +26,7 @@
26
26
  "skill",
27
27
  "scripts/run-agent-task-benchmark.mjs",
28
28
  "docs/agent-task-benchmark.md",
29
- "docs/releases/v0.2.11.md",
29
+ "docs/releases/v0.2.13.md",
30
30
  "README.md",
31
31
  "SECURITY.md",
32
32
  "LICENSE"
package/skill/SKILL.md CHANGED
@@ -16,15 +16,20 @@ Tools are named `mcp__weavatrix__…`. If none are available, ask the user to re
16
16
  (`claude mcp add -s user weavatrix -- npx -y weavatrix <repoRoot>`; Codex:
17
17
  `codex mcp add weavatrix -- npx -y weavatrix <repoRoot>`), then retry.
18
18
 
19
- If `refresh_advisories`, `preview_sync`, `pull_architecture_contract`, or `sync_graph` is missing, do not diagnose a
20
- broken installation: network tools are intentionally absent from `offline` and `pinned`.
19
+ First compare the selected profile with the `graph_stats` runtime line. Expected catalogs are 31
20
+ tools for `pinned`, 34 for `offline`, 35 for `osv`, and 38 for `hosted` / `full`. If the running
21
+ version/count differs from the installed package, or local tools such as `trace_endpoint` are missing,
22
+ reconnect/start a new agent task because clients commonly cache `tools/list` for one connection. A
23
+ custom capability list needs `crossrepo` for `trace_api_contract`; legacy `online` adds only
24
+ `advisories,hosted`. Missing HTTP tools are intentional only when the selected profile excludes them.
21
25
 
22
26
  Profiles use the same npm package and binary:
23
27
 
24
28
  - `offline` (default): all local analysis and explicit `open_repo`; no HTTP tools.
25
29
  - `pinned`: local analysis with no `open_repo`, no global/cross-repository graph access, and no HTTP tools.
26
30
  - `osv`: `offline` plus explicit `refresh_advisories`.
27
- - `hosted` / `full`: `osv` plus local-only `preview_sync`, `pull_architecture_contract` and `sync_graph`.
31
+ - `hosted` / `full`: `osv` plus local-only `preview_sync` and the explicitly invoked network tools
32
+ `pull_architecture_contract` and confirmed `sync_graph`.
28
33
 
29
34
  The legacy `online` capability remains a compatibility alias for `advisories,hosted`; prefer the
30
35
  named profiles for new registrations.
@@ -45,7 +50,9 @@ projection; expand only when the answer requires it.
45
50
  - **Find high-coupling hubs**: `god_nodes`; repeated call sites do not inflate unique connectivity.
46
51
  - **Inspect one graph entity**: `get_node`; pass an exact node ID when labels are ambiguous.
47
52
  - **Inspect direct one-hop relations**: `get_neighbors`; do not confuse it with transitive impact.
48
- - **Prove a path between two concepts**: `shortest_path`.
53
+ - **Find a connectivity path between two concepts**: `shortest_path`. It traverses the graph as
54
+ undirected reachability, so it is not proof of call/dependency direction; confirm direction with
55
+ `get_neighbors` and `read_source`.
49
56
  - **Explore an unknown entry point or architectural question**: `query_graph`; pin `seed_files` when
50
57
  known, and keep its broad result as orientation evidence.
51
58
  - **Inspect one exact symbol deeply**: `context_bundle` for the bounded edit workset;
@@ -59,16 +66,23 @@ projection; expand only when the answer requires it.
59
66
  - **Trace one endpoint through the application**: `trace_endpoint` for route -> handler -> bounded
60
67
  downstream call flow with edge-centered excerpts.
61
68
  - **Trace an API contract across repositories**: `list_known_repos` -> `trace_api_contract` with an
62
- explicit backend/client set; inspect each graph reconciliation state before using the verdict.
69
+ explicit backend/client set; prefer this over separate per-repository endpoint/search passes when
70
+ a backend change may affect registered clients, and inspect each graph reconciliation state before
71
+ using the verdict.
63
72
  - **Measure one symbol's transitive blast radius**: `get_dependents`.
64
- - **Review the current branch, diff, or external patch**: `change_impact`.
73
+ - **Review the current branch, diff, or external patch**: `change_impact`; its explicit baseline
74
+ parameter is `base`, not the `base_ref` used by audit/diff/verification tools. It distinguishes
75
+ additive exports from signature/body/removal risk and separates runtime/type-only radius plus
76
+ available measured coverage or explicitly static reachability.
65
77
  - **Compare structural graph revisions**: `graph_diff base_ref=<merge-base>` for module edges, cycles,
66
78
  orphans and lost callers; without `base_ref`, compare the last rebuild snapshots.
67
79
  - **Use behavioral history**: `git_history` for churn x connectivity, hidden co-change and expected
68
80
  test/source coupling from bounded local Git numstat evidence.
69
- - **Plan and verify a serious change or pre-commit gate**: `verified_change phase=plan` -> edit ->
70
- `verified_change phase=verify base_ref=<same-ref>`. It composes exact context, impact, graph,
71
- architecture, duplicate, optional API and test proof into one PASS/BLOCKED/UNKNOWN envelope.
81
+ - **Plan and verify a serious change or pre-commit gate**:
82
+ `verified_change task=<same-task> phase=plan base_ref=<merge-base>` -> edit ->
83
+ `verified_change task=<same-task> phase=verify base_ref=<same-ref>`. It composes exact context, impact, graph,
84
+ architecture, duplicate, optional API and test proof into one PASS/BLOCKED/UNKNOWN envelope. It is
85
+ a proof layer around an agent's edit, not a source editor or hidden auto-fix.
72
86
 
73
87
  ### Health, debt and testing scenarios
74
88
 
@@ -96,7 +110,8 @@ projection; expand only when the answer requires it.
96
110
  - **Select rules before editing**: `prepare_change`; **enforce the ratchet after editing**:
97
111
  `verify_architecture`.
98
112
  - **Understand or request an exception**: `explain_architecture_violation` ->
99
- `propose_architecture_exception`; proposals never mutate policy automatically.
113
+ `propose_architecture_exception`; proposals never mutate policy automatically. After human approval,
114
+ the owner must add the returned proposal to the local contract's `exceptions` or approve it in Hosted.
100
115
  - **Pull an owner-approved Hosted target**: `pull_architecture_contract` only in an explicitly enabled
101
116
  Hosted profile.
102
117
  - **Review exactly what Hosted sync would send**: `preview_sync`; only an approved
@@ -110,6 +125,9 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
110
125
 
111
126
  ## Ground rules
112
127
 
128
+ - **No hidden source mutation**: Weavatrix builds derived graph/cache artifacts and can run explicitly
129
+ authorized tests, but it does not edit repository source, auto-delete debt, merge clones, or rewrite
130
+ architecture policy. The coding agent remains responsible for the change and its tests.
113
131
  - **Evidence, not verdicts**: treat audit, hub, orphan and duplicate output as hypotheses. Confirm a
114
132
  finding in source and check framework/runtime conventions before deleting, merging or redesigning
115
133
  code. A same-name/different-body pair is a divergence candidate, not proof of duplication.
@@ -187,16 +205,19 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
187
205
 
188
206
  ## Recipes
189
207
 
190
- - **Proof-carrying refactor**: `verified_change task="..." phase=plan base_ref=<merge-base>` -> edit ->
191
- `verified_change task="..." phase=verify base_ref=<same-ref> tests=[{"script":"test","args":[...]}]`.
208
+ - **Proof-carrying refactor**: `verified_change task=<same-task> phase=plan base_ref=<merge-base>` -> edit ->
209
+ `verified_change task=<same-task> phase=verify base_ref=<same-ref> tests=[{"script":"test","args":[...]}]`.
210
+ Repeat `task` on both calls; it is required and is not retained between invocations.
192
211
  Add `run_tests:true` only when test execution was authorized. `BLOCKED` means an evidenced ratchet
193
212
  or test failure; `UNKNOWN` means at least one required proof is incomplete.
194
213
 
195
214
  - **Orient in the configured repo**: `module_map` → `list_communities` → `god_nodes`. Hub ranking
196
215
  is production-only by default; use `include_classified:true` only when tests/generated/build
197
216
  surfaces are deliberately part of the question.
198
- - **Refactor safety for one symbol**: `inspect_symbol` → `get_dependents` `coverage_map` (low coverage × many
199
- dependents write tests first) → `read_source`.
217
+ - **Refactor safety for one symbol**: `context_bundle` → optional `inspect_symbol` when raw LSP
218
+ occurrences, ambiguity details or the larger source window are needed → `get_dependents` →
219
+ `coverage_map` (low coverage × many dependents ⇒ write tests first) → edit →
220
+ `verified_change task=<task> phase=verify base_ref=<merge-base>`.
200
221
  - **Performance review**: `hot_path_review` → inspect its local evidence with `read_source` → use
201
222
  `get_dependents` for change risk → confirm with the repository's profiler/benchmark before editing.
202
223
  - **Pre-PR review of your current changes**: `change_impact` (auto merge-base; includes uncommitted
@@ -229,6 +250,10 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
229
250
  - **API inventory**: `list_endpoints` (including mount provenance, Next.js App Router, Rust axum and
230
251
  actix-web). When one exact route is known, use `trace_endpoint` for its composed mount chain,
231
252
  handler and bounded production call graph instead of broad natural-language traversal.
253
+ - **CLI, worker, queue, cron or event flow**: locate the manifest/registration literal with
254
+ `search_code`, then pin the discovered entry file with `query_graph seed_files=[...]`; use
255
+ `context_bundle` on its exact handler plus `get_neighbors` / `get_dependents`, and confirm the
256
+ registration and call sites with `read_source`. Do not force a non-HTTP flow through endpoint tools.
232
257
  - **Cross-repository API impact**: ensure both repositories are in `list_known_repos`, then call
233
258
  `trace_api_contract backend=<uuid-or-label> clients=[<uuid-or-label>]`; narrow with `method`, `path`,
234
259
  or backend `changed_files`. `path` may be a segment-aligned fragment (`/query` can select
@@ -239,8 +264,9 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
239
264
  confidence; only an unambiguously resolved handler node can suppress a dead-method candidate.
240
265
  `POSSIBLE_EXTERNAL_USE`, `UNKNOWN`, and remaining unresolved/dynamic URLs are incomplete evidence,
241
266
  never proof that a method is dead.
242
- - **Release regression gate**: for a Weavatrix source checkout, use `npm test` for the quick
243
- six-language golden corpus and `npm run benchmark` before release for the real MCP
267
+ - **Release regression gate**: for a Weavatrix source checkout, use `npm test` for the full
268
+ unit/integration suite, `npm run benchmark:quick` for the quick six-language golden corpus, and
269
+ `npm run benchmark` before release for the golden corpus plus the real MCP
244
270
  `full -> incremental -> none -> reconnect/none` lifecycle, bounded output and active-target checks.
245
271
  Use `npm run benchmark:real` for available manifest repositories and
246
272
  `npm run benchmark:real:release` only when all six source checkouts are present; `MISSING`,
@@ -250,16 +276,25 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
250
276
  - **Target architecture before editing**: `get_architecture_contract` → `prepare_change` with the
251
277
  intended files → edit and rebuild → `verify_architecture`. A missing contract returns a starter
252
278
  proposal from `get_architecture_contract output_format:"json"`, not an automatically approved
253
- architecture. Without a contract, `prepare_change` still returns provisional no-regression
254
- budgets, but they are guidance rather than enforceable policy. Pull an owner-approved hosted
255
- contract only when the user selected `hosted` and explicitly asks for it.
279
+ architecture. For offline adoption, have the owner review/edit `starterContract`, save it as
280
+ `.weavatrix/architecture.json`, and rerun the lookup. To establish a ratchet over accepted current
281
+ debt, run `verify_architecture output_format:"json"`; only after explicit owner approval, copy the
282
+ accepted `verification.new[*].fingerprint` values into `ratchet.baseline.fingerprints`, save, and
283
+ verify again so accepted debt is `existing` while later debt is `new`. The v1 verifier classifies
284
+ ratchet debt by fingerprints; `ratchet.baseline.metrics` is metadata, not a replacement. An approved local exception
285
+ is applied by adding the exact returned `proposal` to `exceptions`; rerun verification afterward.
286
+ Without a contract, `prepare_change` still returns provisional no-regression budgets, but they are
287
+ guidance rather than enforceable policy. Pull an owner-approved hosted contract only when the user
288
+ selected `hosted` and explicitly asks for it. No Weavatrix tool silently writes either policy.
256
289
  - **Behavioral architecture**: `git_history` ranks churn × connectivity hotspots and hidden
257
290
  co-change coupling from bounded local numstat history. Always set `top_n`; it is enforced across
258
291
  every returned structured collection and JSON reports per-collection truncation. Use it as review
259
292
  evidence, not proof that two files must be merged.
260
293
  - **Machine output**: keep the default `output_format:"text"` for concise agent conversations; opt
261
294
  into `output_format:"json"` only when a workflow consumes the full `weavatrix.tool.v1` envelope.
262
- - **Find code**: `search_code` (regex + glob) → `get_node` → `read_source`.
295
+ - **Find code**: `search_code` (regex + glob) →
296
+ `read_source path=<match-path> start_line=<match-line>`; add `get_node` / `get_neighbors` only after
297
+ identifying an exact graph symbol.
263
298
  - **Another repo**: `list_known_repos` → `open_repo <path>`
264
299
  (builds or upgrades the graph when needed; `build:false` probes without building).
265
300
 
@@ -267,9 +302,29 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
267
302
 
268
303
  Weavatrix understands nearest workspace manifests, nested `tsconfig`/`jsconfig` aliases,
269
304
  framework-owned runtime peers such as Next.js + `react-dom`, generated NAPI-RS platform loaders,
270
- and Next.js App Router route exports. For project-specific entry points, reusable template catalogs,
271
- or Python dependencies supplied by an external runtime, add `.weavatrix-deps.json` at the repository
272
- root:
305
+ and Next.js App Router route exports. Use repository-root `.weavatrix.json` to correct ambiguous
306
+ production classification without deleting graph evidence:
307
+
308
+ ```json
309
+ {
310
+ "classify": {
311
+ "generated": ["src/generated/**"],
312
+ "test": ["qa/**"],
313
+ "product": ["benchmarks/core/**"]
314
+ },
315
+ "exclude": ["resources/snapshots/**"]
316
+ }
317
+ ```
318
+
319
+ Use `generated` / `test` (or `e2e`, `mock`, `story`, `docs`, `benchmark`, `temp`) for non-production
320
+ code, top-level `exclude` for resource/catalog roots that should stay visible in the graph but not
321
+ drive production-first Health/query ranking, and `product` only to opt a verified benchmark/temp path
322
+ back into production review. `product` does not override an explicit generated/test classification or
323
+ `exclude`. Use `.weavatrixignore` instead only when a path must be removed consistently from graph,
324
+ audit and duplicate scans.
325
+
326
+ For project-specific entry points, reusable template catalogs, or Python dependencies supplied by an
327
+ external runtime, add `.weavatrix-deps.json` at the repository root:
273
328
 
274
329
  ```json
275
330
  {
@@ -19,29 +19,40 @@ function packageManager(repoRoot) {
19
19
  return 'npm'
20
20
  }
21
21
 
22
- export function validateTestRequests(repoRoot, requests = []) {
23
- const manifest = manifestAt(repoRoot)
24
- if (!manifest) return {ok: false, reason: 'package.json is missing or unreadable', tests: []}
22
+ function normalizeTestRequests(requests = []) {
25
23
  const tests = []
26
- for (const request of requests.slice(0, 5)) {
24
+ for (const request of (Array.isArray(requests) ? requests : []).slice(0, 5)) {
27
25
  const script = String(request?.script || '')
28
26
  const args = Array.isArray(request?.args) ? request.args.slice(0, 40).map(String) : []
29
27
  if (!SAFE_SCRIPT.test(script)) return {ok: false, reason: `script ${script || '(missing)'} is outside the test/check/verify allowlist`, tests}
30
- if (!Object.hasOwn(manifest.scripts || {}, script)) return {ok: false, reason: `package.json has no script named ${script}`, tests}
31
28
  if (args.some((arg) => arg.length > 300 || UNSAFE_SHELL_ARG.test(arg))) return {ok: false, reason: `script ${script} has an invalid or shell-sensitive argument`, tests}
32
29
  tests.push({script, args})
33
30
  }
31
+ return {ok: true, tests}
32
+ }
33
+
34
+ export function validateTestRequests(repoRoot, requests = []) {
35
+ const normalized = normalizeTestRequests(requests)
36
+ if (!normalized.ok || !normalized.tests.length) return normalized
37
+ const manifest = manifestAt(repoRoot)
38
+ if (!manifest) return {ok: false, reason: 'package.json is missing or unreadable', tests: []}
39
+ for (const test of normalized.tests) {
40
+ if (!Object.hasOwn(manifest.scripts || {}, test.script)) return {ok: false, reason: `package.json has no script named ${test.script}`, tests: []}
41
+ }
42
+ const tests = normalized.tests
34
43
  return {ok: true, tests, packageManager: packageManager(repoRoot)}
35
44
  }
36
45
 
37
46
  export async function runAllowedTests(repoRoot, requests = [], {enabled = false, timeoutMs = 60_000} = {}) {
38
- const checked = validateTestRequests(repoRoot, requests)
39
- if (!checked.ok) return {state: 'BLOCKED', reason: checked.reason, results: []}
40
- if (!checked.tests.length) return {state: 'NOT_REQUESTED', reason: 'no package scripts were requested', results: []}
47
+ const normalized = normalizeTestRequests(requests)
48
+ if (!normalized.ok) return {state: 'BLOCKED', reason: normalized.reason, results: []}
49
+ if (!normalized.tests.length) return {state: 'NOT_REQUESTED', reason: 'no package scripts were requested', plan: [], results: []}
41
50
  if (!enabled || process.env.WEAVATRIX_ALLOW_TEST_RUNS !== '1') return {
42
51
  state: 'DISABLED', reason: 'set WEAVATRIX_ALLOW_TEST_RUNS=1 and pass run_tests:true to execute allowlisted package scripts',
43
- plan: checked.tests, results: [],
52
+ plan: normalized.tests, results: [],
44
53
  }
54
+ const checked = validateTestRequests(repoRoot, normalized.tests)
55
+ if (!checked.ok) return {state: 'BLOCKED', reason: checked.reason, results: []}
45
56
  const results = []
46
57
  const timeout = Math.max(1000, Math.min(300_000, Number(timeoutMs) || 60_000))
47
58
  for (const test of checked.tests) {
@@ -169,6 +169,7 @@ export async function loadHotApi(version, capsArg) {
169
169
  import(new URL(`./tools-verified-change.mjs${v}`, import.meta.url).href),
170
170
  ])
171
171
  const raw = capsArg == null ? 'offline' : String(capsArg).trim()
172
+ const profile = Object.hasOwn(PROFILE_CAPS, raw) ? raw : 'custom'
172
173
  const selected = PROFILE_CAPS[raw] || raw.split(',').map((s) => s.trim()).filter(Boolean)
173
174
  .flatMap((cap) => cap === 'online' ? ['advisories', 'hosted'] : [cap])
174
175
  const caps = new Set(selected)
@@ -178,6 +179,7 @@ export async function loadHotApi(version, capsArg) {
178
179
  tools,
179
180
  byName: new Map(tools.map((t) => [t.name, t])),
180
181
  caps,
182
+ profile,
181
183
  stalenessLine,
182
184
  resetStalenessCache,
183
185
  }
@@ -40,6 +40,7 @@ export function tGraphStats(g, ctx) {
40
40
  const precision = g.precision || {state: 'UNAVAILABLE', verifiedEdges: 0, candidates: 0, queried: 0, reason: 'no revision-matched precision overlay'}
41
41
  return [
42
42
  `Graph summary`,
43
+ ctx?.runtime ? `- Weavatrix runtime: v${ctx.runtime.version}; profile ${ctx.runtime.profile}; ${ctx.runtime.toolCount} registered tools; capabilities: ${ctx.runtime.capabilities.join(',') || '(none)'}` : null,
43
44
  ctx?.repoRoot ? `- Repo: ${ctx.repoRoot}` : null,
44
45
  ctx?.graphPath ? `- Graph: ${ctx.graphPath}` : null,
45
46
  `- Build mode: ${g.graphBuildMode || 'full'}`,
@@ -126,10 +126,18 @@ export async function tVerifiedChange(g, args = {}, ctx = {}, tools = {}, permis
126
126
  })
127
127
  : {model: 'bounded call-argument-to-parameter evidence (not CFG or taint analysis)', status: 'UNAVAILABLE', reason: 'source capability is not enabled', edges: [], unsupportedEdges: 0, capped: false}
128
128
  const suggestedTests = targetTests(impact)
129
- const checkedTests = validateTestRequests(ctx.repoRoot, args.tests || [])
130
- const testProof = phase === 'verify'
131
- ? await runAllowedTests(ctx.repoRoot, args.tests || [], {enabled: args.run_tests === true, timeoutMs: args.test_timeout_ms})
132
- : {state: checkedTests.ok ? 'PLANNED' : 'BLOCKED', reason: checkedTests.reason, plan: checkedTests.tests || [], results: []}
129
+ const requestedTests = Array.isArray(args.tests) ? args.tests : []
130
+ let testProof
131
+ if (!requestedTests.length) {
132
+ testProof = {state: 'NOT_REQUESTED', reason: 'no package scripts were requested', plan: [], results: []}
133
+ } else if (args.run_tests !== true) {
134
+ testProof = await runAllowedTests(ctx.repoRoot, requestedTests, {enabled: false, timeoutMs: args.test_timeout_ms})
135
+ } else if (phase === 'verify') {
136
+ testProof = await runAllowedTests(ctx.repoRoot, requestedTests, {enabled: true, timeoutMs: args.test_timeout_ms})
137
+ } else {
138
+ const checkedTests = validateTestRequests(ctx.repoRoot, requestedTests)
139
+ testProof = {state: checkedTests.ok ? 'PLANNED' : 'BLOCKED', reason: checkedTests.reason, plan: checkedTests.tests || [], results: []}
140
+ }
133
141
  const testCoverageState = testCoverage(testProof, args.tests || [], suggestedTests)
134
142
 
135
143
  const architectureValue = phase === 'verify'
@@ -85,11 +85,21 @@ function hotVersion(hotFiles) {
85
85
  async function main() {
86
86
  let catalog = await loadCatalog()
87
87
  let api = await catalog.loadHotApi(0, CAPS_ARG)
88
+ const runtimeInfo = () => ({
89
+ version: PKG_VERSION,
90
+ profile: api.profile || 'custom',
91
+ capabilities: [...api.caps],
92
+ toolCount: api.tools.length,
93
+ })
94
+ const runtimeInstructions = () => {
95
+ const runtime = runtimeInfo()
96
+ return `Weavatrix ${runtime.version}; profile=${runtime.profile}; tools=${runtime.toolCount}; capabilities=${runtime.capabilities.join(',') || '(none)'}. If this differs from the client-visible tool list, reconnect the MCP client to discard its cached schema.`
97
+ }
88
98
  let graph = null
89
99
  let graphError = null
90
100
  // ctx owns the CURRENT target: rebuild_graph reloads it, open_repo retargets graphPath/repoRoot
91
101
  // at runtime. loadInto always reads ctx.graphPath so both paths share one loader.
92
- const ctx = {graphPath: GRAPH_PATH, repoRoot: REPO_ROOT, reload: null}
102
+ const ctx = {graphPath: GRAPH_PATH, repoRoot: REPO_ROOT, reload: null, runtime: runtimeInfo()}
93
103
  const loadInto = () => { graph = loadGraph(ctx.graphPath, {repoRoot: ctx.repoRoot}); graphError = null; return graph }
94
104
  ctx.reload = () => { api.resetStalenessCache(); try { return loadInto() } catch (e) { graphError = e.message; return null } }
95
105
  try {
@@ -229,6 +239,7 @@ async function main() {
229
239
  const nextApi = await nextCatalog.loadHotApi(v, CAPS_ARG)
230
240
  catalog = nextCatalog
231
241
  api = nextApi
242
+ ctx.runtime = runtimeInfo()
232
243
  loadedVersion = v
233
244
  log(`hot-reloaded tool implementations from changed source (${api.tools.length} tools)`)
234
245
  send({jsonrpc: '2.0', method: 'notifications/tools/list_changed'})
@@ -247,14 +258,17 @@ async function main() {
247
258
  }
248
259
  if (method === 'initialize') {
249
260
  if (params?.protocolVersion) protocolVersion = String(params.protocolVersion)
250
- return reply(id, {protocolVersion, capabilities: {tools: {listChanged: true}}, serverInfo: SERVER_INFO})
261
+ return reply(id, {protocolVersion, capabilities: {tools: {listChanged: true}}, serverInfo: SERVER_INFO, instructions: runtimeInstructions()})
251
262
  }
252
263
  if (method === 'notifications/initialized' || method === 'initialized') return
253
264
  if (method === 'ping') return reply(id, {})
254
265
  if (method === 'tools/list') {
255
266
  await maybeHotReload()
256
267
  if (shuttingDown) return
257
- return reply(id, {tools: api.tools.map(({name, description, inputSchema, outputSchema}) => ({name, description, inputSchema, outputSchema}))})
268
+ return reply(id, {
269
+ tools: api.tools.map(({name, description, inputSchema, outputSchema}) => ({name, description, inputSchema, outputSchema})),
270
+ _meta: {'weavatrix/runtime': runtimeInfo()},
271
+ })
258
272
  }
259
273
  if (method === 'tools/call') {
260
274
  await maybeHotReload()
@@ -1,23 +0,0 @@
1
- # Weavatrix 0.2.11
2
-
3
- ## MCP Registry publication hotfix
4
-
5
- 0.2.11 is the immutable follow-up to 0.2.10. The 0.2.10 npm package published successfully, but
6
- the official MCP Registry rejected its expanded server description because that field exceeded the
7
- Registry's 100-character limit. This patch shortens only the Registry summary while preserving the
8
- broad product positioning across the package, MCPB, skill, README and public site. The release
9
- verifier now enforces the same 1-100 character boundary before a tag can publish.
10
-
11
- The runtime is otherwise the verified 0.2.10 release: 38 graph-backed methods for fast application
12
- understanding, Health, dependencies, dead-code and duplicate review, history, endpoint and impact
13
- tracing, proof-carrying changes, target-architecture ratchets and explicit Hosted governance. Its
14
- Java receiver-aware call resolver and product-code-only architecture starter are unchanged.
15
-
16
- ## Compatibility and verification
17
-
18
- - Tool names, input schemas, result envelopes and Hosted sync payload v2/v3 remain unchanged.
19
- - Full Node suite: 506 tests, 503 passed, 3 platform skips, 0 failed.
20
- - Six-language, cross-repository, framework and MCP lifecycle benchmark: `PASS`.
21
- - Six available real-repository baselines: 6/6 `PASS`.
22
- - Repo Lens portable analyzer parity: 21/21 methods present in the default offline profile.
23
- - Release metadata, MCP Registry description length and MCPB manifest validation: `PASS`.