weavatrix 0.2.12 → 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 +25 -0
- package/docs/releases/v0.2.13.md +48 -0
- package/package.json +2 -2
- package/skill/SKILL.md +69 -23
- package/src/analysis/allowed-test-runner.js +20 -9
- package/src/mcp/catalog.mjs +2 -0
- package/src/mcp/tools-graph.mjs +1 -0
- package/src/mcp/tools-verified-change.mjs +12 -4
- package/src/mcp-server.mjs +17 -3
- package/docs/releases/v0.2.12.md +0 -45
package/README.md
CHANGED
|
@@ -194,6 +194,13 @@ Advanced registrations may still pass an exact comma-separated capability set:
|
|
|
194
194
|
a compatibility alias for `advisories,hosted`; new registrations should use the named profiles or
|
|
195
195
|
the narrower capability names.
|
|
196
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
|
+
|
|
197
204
|
Or clone it:
|
|
198
205
|
|
|
199
206
|
```sh
|
|
@@ -342,6 +349,24 @@ reconnect. Every MCP response also carries local, transient `_meta["weavatrix/me
|
|
|
342
349
|
time, output bytes/token estimate, graph freshness/revision/update and graph-cache status. These
|
|
343
350
|
metrics are not persisted or transmitted by Weavatrix.
|
|
344
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
|
+
|
|
345
370
|
### 0.2.9 correctness, signal, and consent patch
|
|
346
371
|
|
|
347
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.
|
|
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.
|
|
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
|
-
|
|
20
|
-
|
|
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
|
|
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
|
-
- **
|
|
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;
|
|
@@ -63,15 +70,17 @@ projection; expand only when the answer requires it.
|
|
|
63
70
|
a backend change may affect registered clients, and inspect each graph reconciliation state before
|
|
64
71
|
using the verdict.
|
|
65
72
|
- **Measure one symbol's transitive blast radius**: `get_dependents`.
|
|
66
|
-
- **Review the current branch, diff, or external patch**: `change_impact`;
|
|
67
|
-
|
|
68
|
-
|
|
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.
|
|
69
77
|
- **Compare structural graph revisions**: `graph_diff base_ref=<merge-base>` for module edges, cycles,
|
|
70
78
|
orphans and lost callers; without `base_ref`, compare the last rebuild snapshots.
|
|
71
79
|
- **Use behavioral history**: `git_history` for churn x connectivity, hidden co-change and expected
|
|
72
80
|
test/source coupling from bounded local Git numstat evidence.
|
|
73
|
-
- **Plan and verify a serious change or pre-commit gate**:
|
|
74
|
-
`verified_change phase=
|
|
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,
|
|
75
84
|
architecture, duplicate, optional API and test proof into one PASS/BLOCKED/UNKNOWN envelope. It is
|
|
76
85
|
a proof layer around an agent's edit, not a source editor or hidden auto-fix.
|
|
77
86
|
|
|
@@ -101,7 +110,8 @@ projection; expand only when the answer requires it.
|
|
|
101
110
|
- **Select rules before editing**: `prepare_change`; **enforce the ratchet after editing**:
|
|
102
111
|
`verify_architecture`.
|
|
103
112
|
- **Understand or request an exception**: `explain_architecture_violation` ->
|
|
104
|
-
`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.
|
|
105
115
|
- **Pull an owner-approved Hosted target**: `pull_architecture_contract` only in an explicitly enabled
|
|
106
116
|
Hosted profile.
|
|
107
117
|
- **Review exactly what Hosted sync would send**: `preview_sync`; only an approved
|
|
@@ -195,17 +205,19 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
|
|
|
195
205
|
|
|
196
206
|
## Recipes
|
|
197
207
|
|
|
198
|
-
- **Proof-carrying refactor**: `verified_change task
|
|
199
|
-
`verified_change task
|
|
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.
|
|
200
211
|
Add `run_tests:true` only when test execution was authorized. `BLOCKED` means an evidenced ratchet
|
|
201
212
|
or test failure; `UNKNOWN` means at least one required proof is incomplete.
|
|
202
213
|
|
|
203
214
|
- **Orient in the configured repo**: `module_map` → `list_communities` → `god_nodes`. Hub ranking
|
|
204
215
|
is production-only by default; use `include_classified:true` only when tests/generated/build
|
|
205
216
|
surfaces are deliberately part of the question.
|
|
206
|
-
- **Refactor safety for one symbol**: `
|
|
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` →
|
|
207
219
|
`coverage_map` (low coverage × many dependents ⇒ write tests first) → edit →
|
|
208
|
-
`verified_change phase=verify base_ref=<merge-base>`.
|
|
220
|
+
`verified_change task=<task> phase=verify base_ref=<merge-base>`.
|
|
209
221
|
- **Performance review**: `hot_path_review` → inspect its local evidence with `read_source` → use
|
|
210
222
|
`get_dependents` for change risk → confirm with the repository's profiler/benchmark before editing.
|
|
211
223
|
- **Pre-PR review of your current changes**: `change_impact` (auto merge-base; includes uncommitted
|
|
@@ -238,6 +250,10 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
|
|
|
238
250
|
- **API inventory**: `list_endpoints` (including mount provenance, Next.js App Router, Rust axum and
|
|
239
251
|
actix-web). When one exact route is known, use `trace_endpoint` for its composed mount chain,
|
|
240
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.
|
|
241
257
|
- **Cross-repository API impact**: ensure both repositories are in `list_known_repos`, then call
|
|
242
258
|
`trace_api_contract backend=<uuid-or-label> clients=[<uuid-or-label>]`; narrow with `method`, `path`,
|
|
243
259
|
or backend `changed_files`. `path` may be a segment-aligned fragment (`/query` can select
|
|
@@ -248,8 +264,9 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
|
|
|
248
264
|
confidence; only an unambiguously resolved handler node can suppress a dead-method candidate.
|
|
249
265
|
`POSSIBLE_EXTERNAL_USE`, `UNKNOWN`, and remaining unresolved/dynamic URLs are incomplete evidence,
|
|
250
266
|
never proof that a method is dead.
|
|
251
|
-
- **Release regression gate**: for a Weavatrix source checkout, use `npm test` for the
|
|
252
|
-
|
|
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
|
|
253
270
|
`full -> incremental -> none -> reconnect/none` lifecycle, bounded output and active-target checks.
|
|
254
271
|
Use `npm run benchmark:real` for available manifest repositories and
|
|
255
272
|
`npm run benchmark:real:release` only when all six source checkouts are present; `MISSING`,
|
|
@@ -259,16 +276,25 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
|
|
|
259
276
|
- **Target architecture before editing**: `get_architecture_contract` → `prepare_change` with the
|
|
260
277
|
intended files → edit and rebuild → `verify_architecture`. A missing contract returns a starter
|
|
261
278
|
proposal from `get_architecture_contract output_format:"json"`, not an automatically approved
|
|
262
|
-
architecture.
|
|
263
|
-
|
|
264
|
-
|
|
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.
|
|
265
289
|
- **Behavioral architecture**: `git_history` ranks churn × connectivity hotspots and hidden
|
|
266
290
|
co-change coupling from bounded local numstat history. Always set `top_n`; it is enforced across
|
|
267
291
|
every returned structured collection and JSON reports per-collection truncation. Use it as review
|
|
268
292
|
evidence, not proof that two files must be merged.
|
|
269
293
|
- **Machine output**: keep the default `output_format:"text"` for concise agent conversations; opt
|
|
270
294
|
into `output_format:"json"` only when a workflow consumes the full `weavatrix.tool.v1` envelope.
|
|
271
|
-
- **Find code**: `search_code` (regex + glob) →
|
|
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.
|
|
272
298
|
- **Another repo**: `list_known_repos` → `open_repo <path>`
|
|
273
299
|
(builds or upgrades the graph when needed; `build:false` probes without building).
|
|
274
300
|
|
|
@@ -276,9 +302,29 @@ TypeScript/JavaScript overlay. Java receiver-type call edges are parser-resolved
|
|
|
276
302
|
|
|
277
303
|
Weavatrix understands nearest workspace manifests, nested `tsconfig`/`jsconfig` aliases,
|
|
278
304
|
framework-owned runtime peers such as Next.js + `react-dom`, generated NAPI-RS platform loaders,
|
|
279
|
-
and Next.js App Router route exports.
|
|
280
|
-
|
|
281
|
-
|
|
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:
|
|
282
328
|
|
|
283
329
|
```json
|
|
284
330
|
{
|
|
@@ -19,29 +19,40 @@ function packageManager(repoRoot) {
|
|
|
19
19
|
return 'npm'
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
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
|
|
39
|
-
if (!
|
|
40
|
-
if (!
|
|
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:
|
|
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) {
|
package/src/mcp/catalog.mjs
CHANGED
|
@@ -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
|
}
|
package/src/mcp/tools-graph.mjs
CHANGED
|
@@ -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
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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'
|
package/src/mcp-server.mjs
CHANGED
|
@@ -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, {
|
|
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()
|
package/docs/releases/v0.2.12.md
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# Weavatrix 0.2.12
|
|
2
|
-
|
|
3
|
-
## Agent workflow routing and cross-repository API clarity
|
|
4
|
-
|
|
5
|
-
0.2.12 incorporates a second hands-on evaluation across Weavatrix, BranchPilot,
|
|
6
|
-
controller-rest-api and its registered clients. It does not reduce the product to a short list: the
|
|
7
|
-
skill still maps all 38 methods across application understanding, graph views, Health, dependencies,
|
|
8
|
-
dead code, duplicates, coverage, history, endpoints, impact, architecture and Hosted governance.
|
|
9
|
-
|
|
10
|
-
The skill now makes three high-leverage routing decisions explicit:
|
|
11
|
-
|
|
12
|
-
- prefer `trace_api_contract` over disconnected per-repository searches when a backend change can
|
|
13
|
-
affect registered clients;
|
|
14
|
-
- use `change_impact` as a diff-risk classifier that separates additive exports from
|
|
15
|
-
signature/body/removal risk, runtime/type-only radius and honest coverage evidence;
|
|
16
|
-
- treat `verified_change` as a proof layer around an agent's edit, never a hidden source editor or
|
|
17
|
-
auto-fix.
|
|
18
|
-
|
|
19
|
-
The one-symbol refactor workflow now carries exact context, dependents and coverage through the
|
|
20
|
-
post-edit `verified_change` ratchet. The public site also surfaces cross-repository API contract
|
|
21
|
-
tracing as a first-class graph capability rather than hiding it under generic multi-repository mode.
|
|
22
|
-
|
|
23
|
-
## Worked examples and public benchmark evidence
|
|
24
|
-
|
|
25
|
-
The README and public site now show four concrete dogfood scenarios instead of relying on feature
|
|
26
|
-
names alone: orienting inside a 1,076-file backend and tracing one of 462 observed routes; proving
|
|
27
|
-
external handler use across three registered repositories; classifying a BranchPilot change before
|
|
28
|
-
editing; and turning Health plus clone evidence into a bounded review queue. The examples preserve
|
|
29
|
-
uncertainty for dynamic URLs, advisory coverage and review-required findings.
|
|
30
|
-
|
|
31
|
-
The public benchmark section reports reproducible fixture and revision-pinned real-repository
|
|
32
|
-
regression gates with dates, environment, commands and explicit limits. It does not present these
|
|
33
|
-
machine-dependent local measurements as competitor benchmarks. A lightweight CSS motion sequence
|
|
34
|
-
illustrates the graph-to-verdict workflow and respects `prefers-reduced-motion`; no synthetic product
|
|
35
|
-
screenshots are used.
|
|
36
|
-
|
|
37
|
-
## Compatibility and verification
|
|
38
|
-
|
|
39
|
-
- Runtime implementation, tool names, schemas and result envelopes are unchanged from 0.2.11.
|
|
40
|
-
- Hosted sync payload v2/v3 and architecture-contract transport are unchanged.
|
|
41
|
-
- Skill inventory: all 38 current methods are routed; 0 missing.
|
|
42
|
-
- Full Node suite baseline: 506 tests, 503 passed, 3 platform skips, 0 failed.
|
|
43
|
-
- Six-language fixture, cross-repository and lifecycle benchmark: `PASS`.
|
|
44
|
-
- Six locally available revision-pinned real-repository baselines: `PASS`.
|
|
45
|
-
- Release metadata, 99-character MCP Registry description and MCPB validation: `PASS`.
|