weavatrix 0.3.14 → 1.0.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 (305) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +231 -199
  3. package/bin/native/darwin-arm64/weavatrix +0 -0
  4. package/bin/native/darwin-x64/weavatrix +0 -0
  5. package/bin/native/linux-arm64/weavatrix +0 -0
  6. package/bin/native/linux-x64/weavatrix +0 -0
  7. package/bin/native/win32-arm64/weavatrix.exe +0 -0
  8. package/bin/native/win32-x64/weavatrix.exe +0 -0
  9. package/bin/resolve-binary.mjs +73 -0
  10. package/bin/run-native.mjs +26 -0
  11. package/bin/weavatrix-mcp.mjs +7 -6
  12. package/bin/weavatrix.mjs +5 -0
  13. package/package.json +8 -66
  14. package/skill/SKILL.md +62 -374
  15. package/skill/agents/openai.yaml +4 -0
  16. package/skill/references/tool-routing.md +45 -0
  17. package/SECURITY.md +0 -101
  18. package/docs/adr/0001-v0.3-offline-online-split.md +0 -60
  19. package/docs/agent-task-benchmark.md +0 -58
  20. package/docs/releases/v0.2.19.md +0 -33
  21. package/docs/releases/v0.3.0.md +0 -43
  22. package/docs/releases/v0.3.1.md +0 -30
  23. package/docs/releases/v0.3.10.md +0 -76
  24. package/docs/releases/v0.3.11.md +0 -55
  25. package/docs/releases/v0.3.12.md +0 -44
  26. package/docs/releases/v0.3.13.md +0 -34
  27. package/docs/releases/v0.3.14.md +0 -37
  28. package/docs/releases/v0.3.2.md +0 -15
  29. package/docs/releases/v0.3.3.md +0 -25
  30. package/docs/releases/v0.3.4.md +0 -40
  31. package/docs/releases/v0.3.5.md +0 -50
  32. package/docs/releases/v0.3.6.md +0 -44
  33. package/docs/releases/v0.3.7.md +0 -37
  34. package/docs/releases/v0.3.8.md +0 -21
  35. package/docs/releases/v0.3.9.md +0 -36
  36. package/scripts/run-agent-task-benchmark.mjs +0 -118
  37. package/src/analysis/allowed-test-runner.js +0 -70
  38. package/src/analysis/architecture/contract-graph.js +0 -119
  39. package/src/analysis/architecture/contract-schema.js +0 -110
  40. package/src/analysis/architecture/contract-storage.js +0 -35
  41. package/src/analysis/architecture/contract-verification.js +0 -168
  42. package/src/analysis/architecture-contract.js +0 -16
  43. package/src/analysis/audit-debt.js +0 -94
  44. package/src/analysis/audit-extensions.js +0 -60
  45. package/src/analysis/cargo-dependency-evidence.js +0 -108
  46. package/src/analysis/cargo-manifests.js +0 -81
  47. package/src/analysis/change-classification/diff-parser.js +0 -103
  48. package/src/analysis/change-classification/options.js +0 -40
  49. package/src/analysis/change-classification/symbol-classifier.js +0 -177
  50. package/src/analysis/change-classification.js +0 -188
  51. package/src/analysis/coverage-reports-tarpaulin.js +0 -112
  52. package/src/analysis/coverage-reports.js +0 -246
  53. package/src/analysis/cycle-route.js +0 -14
  54. package/src/analysis/data-flow-evidence.js +0 -114
  55. package/src/analysis/dead-check.js +0 -300
  56. package/src/analysis/dead-code-review/candidates.js +0 -194
  57. package/src/analysis/dead-code-review/policy.js +0 -23
  58. package/src/analysis/dead-code-review.js +0 -119
  59. package/src/analysis/dep-check-ecosystems.js +0 -205
  60. package/src/analysis/dep-check.js +0 -290
  61. package/src/analysis/dep-rules.js +0 -10
  62. package/src/analysis/dependency/conventions.js +0 -16
  63. package/src/analysis/dependency/scoped-dependencies.js +0 -51
  64. package/src/analysis/dependency/source-references.js +0 -21
  65. package/src/analysis/duplicate-groups.js +0 -104
  66. package/src/analysis/duplicates-worker.js +0 -11
  67. package/src/analysis/duplicates.compute.js +0 -269
  68. package/src/analysis/duplicates.js +0 -15
  69. package/src/analysis/duplicates.run.js +0 -52
  70. package/src/analysis/duplicates.tokenize.js +0 -199
  71. package/src/analysis/endpoints/common.js +0 -79
  72. package/src/analysis/endpoints/extract.js +0 -120
  73. package/src/analysis/endpoints/inventory.js +0 -84
  74. package/src/analysis/endpoints/mounts.js +0 -129
  75. package/src/analysis/endpoints-java.js +0 -260
  76. package/src/analysis/endpoints-rust.js +0 -124
  77. package/src/analysis/endpoints.js +0 -3
  78. package/src/analysis/findings.js +0 -70
  79. package/src/analysis/git-history/analytics.js +0 -177
  80. package/src/analysis/git-history/collector.js +0 -67
  81. package/src/analysis/git-history/options.js +0 -66
  82. package/src/analysis/git-history.js +0 -143
  83. package/src/analysis/git-ref-graph.js +0 -76
  84. package/src/analysis/go-dependency-evidence.js +0 -62
  85. package/src/analysis/graph-analysis.aggregate.js +0 -296
  86. package/src/analysis/graph-analysis.edges.js +0 -24
  87. package/src/analysis/graph-analysis.js +0 -7
  88. package/src/analysis/graph-analysis.refs.js +0 -202
  89. package/src/analysis/graph-analysis.summaries.js +0 -65
  90. package/src/analysis/health-capabilities.js +0 -83
  91. package/src/analysis/hot-path-review.js +0 -266
  92. package/src/analysis/http-contract-wrappers.js +0 -241
  93. package/src/analysis/http-contracts/analysis.js +0 -179
  94. package/src/analysis/http-contracts/client-call-detection.js +0 -82
  95. package/src/analysis/http-contracts/client-call-parser.js +0 -273
  96. package/src/analysis/http-contracts/graph-context.js +0 -143
  97. package/src/analysis/http-contracts/matching.js +0 -61
  98. package/src/analysis/http-contracts/shared.js +0 -85
  99. package/src/analysis/http-contracts.js +0 -6
  100. package/src/analysis/internal-audit/dependency-health.js +0 -113
  101. package/src/analysis/internal-audit/python-manifests.js +0 -78
  102. package/src/analysis/internal-audit/repo-files.js +0 -50
  103. package/src/analysis/internal-audit/supply-chain.js +0 -149
  104. package/src/analysis/internal-audit.collect.js +0 -213
  105. package/src/analysis/internal-audit.js +0 -9
  106. package/src/analysis/internal-audit.reach.js +0 -201
  107. package/src/analysis/internal-audit.run.js +0 -256
  108. package/src/analysis/java-source.js +0 -36
  109. package/src/analysis/jvm-artifact-index.js +0 -87
  110. package/src/analysis/jvm-dependency-evidence.js +0 -138
  111. package/src/analysis/jvm-manifests.js +0 -114
  112. package/src/analysis/manifests.js +0 -123
  113. package/src/analysis/package-reachability.js +0 -39
  114. package/src/analysis/source-complexity.ast.js +0 -97
  115. package/src/analysis/source-complexity.constants.js +0 -55
  116. package/src/analysis/source-complexity.js +0 -14
  117. package/src/analysis/source-complexity.report.js +0 -81
  118. package/src/analysis/source-complexity.walk.js +0 -228
  119. package/src/analysis/source-correctness/retry-patterns.js +0 -93
  120. package/src/analysis/source-correctness.js +0 -222
  121. package/src/analysis/static-test-reachability.js +0 -150
  122. package/src/analysis/structure/dependency-graph.js +0 -151
  123. package/src/analysis/structure/findings.js +0 -162
  124. package/src/analysis/task-retrieval.js +0 -107
  125. package/src/analysis/transport-contracts.js +0 -224
  126. package/src/analysis/transport-runtime-evidence.js +0 -155
  127. package/src/analysis-kit.mjs +0 -17
  128. package/src/bounds.js +0 -4
  129. package/src/build-graph.js +0 -209
  130. package/src/child-env.js +0 -7
  131. package/src/config.js +0 -5
  132. package/src/extension/local-services.mjs +0 -75
  133. package/src/git-exec.js +0 -67
  134. package/src/graph/build-worker.js +0 -49
  135. package/src/graph/builder/go-receiver-resolution.js +0 -112
  136. package/src/graph/builder/js/dynamic-import.js +0 -26
  137. package/src/graph/builder/js/queries.js +0 -48
  138. package/src/graph/builder/lang-csharp.js +0 -40
  139. package/src/graph/builder/lang-css.js +0 -29
  140. package/src/graph/builder/lang-go.js +0 -140
  141. package/src/graph/builder/lang-html.js +0 -29
  142. package/src/graph/builder/lang-java-calls.js +0 -142
  143. package/src/graph/builder/lang-java.js +0 -215
  144. package/src/graph/builder/lang-js.js +0 -291
  145. package/src/graph/builder/lang-python.js +0 -235
  146. package/src/graph/builder/lang-rust-calls.js +0 -63
  147. package/src/graph/builder/lang-rust.js +0 -299
  148. package/src/graph/builder/lang-solidity.js +0 -126
  149. package/src/graph/builder/lang-sql.js +0 -263
  150. package/src/graph/builder/pass2-resolution.js +0 -81
  151. package/src/graph/builder/spec-pkg.js +0 -87
  152. package/src/graph/community.js +0 -27
  153. package/src/graph/edge-provenance.js +0 -31
  154. package/src/graph/file-lock.js +0 -69
  155. package/src/graph/freshness-probe.js +0 -142
  156. package/src/graph/graph-filter.js +0 -63
  157. package/src/graph/incremental-refresh.js +0 -235
  158. package/src/graph/internal-builder.barrels.js +0 -235
  159. package/src/graph/internal-builder.build.js +0 -300
  160. package/src/graph/internal-builder.java.js +0 -33
  161. package/src/graph/internal-builder.js +0 -12
  162. package/src/graph/internal-builder.langs.js +0 -157
  163. package/src/graph/internal-builder.pass2.js +0 -163
  164. package/src/graph/internal-builder.resolvers.js +0 -286
  165. package/src/graph/layout.js +0 -51
  166. package/src/graph/node-id.js +0 -7
  167. package/src/graph/parser-artifact-boundary.js +0 -55
  168. package/src/graph/relations.js +0 -4
  169. package/src/graph/repo-registry.js +0 -124
  170. package/src/graph/resolvers/rust.js +0 -117
  171. package/src/infra/infra-items.js +0 -255
  172. package/src/infra/infra-registry.js +0 -184
  173. package/src/infra/infra.detect.js +0 -119
  174. package/src/infra/infra.js +0 -38
  175. package/src/infra/infra.match.js +0 -102
  176. package/src/infra/infra.scan.js +0 -93
  177. package/src/mcp/actions/graph-lifecycle.mjs +0 -148
  178. package/src/mcp/architecture-bootstrap.mjs +0 -168
  179. package/src/mcp/architecture-starter.mjs +0 -234
  180. package/src/mcp/catalog.mjs +0 -233
  181. package/src/mcp/company-contract-page.mjs +0 -142
  182. package/src/mcp/company-contract-reconcile.mjs +0 -87
  183. package/src/mcp/company-contract-verdict.mjs +0 -42
  184. package/src/mcp/evidence/bun-lock-graph.mjs +0 -209
  185. package/src/mcp/evidence/duplicate-member-order.mjs +0 -8
  186. package/src/mcp/evidence/package-graph-common.mjs +0 -115
  187. package/src/mcp/evidence/package-lock-graph.mjs +0 -92
  188. package/src/mcp/evidence-snapshot.architecture.mjs +0 -80
  189. package/src/mcp/evidence-snapshot.common.mjs +0 -158
  190. package/src/mcp/evidence-snapshot.duplicates.mjs +0 -213
  191. package/src/mcp/evidence-snapshot.health.mjs +0 -102
  192. package/src/mcp/evidence-snapshot.inventory.mjs +0 -148
  193. package/src/mcp/evidence-snapshot.mjs +0 -50
  194. package/src/mcp/evidence-snapshot.package-graph.mjs +0 -34
  195. package/src/mcp/evidence-snapshot.structure.mjs +0 -84
  196. package/src/mcp/extension-api.mjs +0 -77
  197. package/src/mcp/git-output.mjs +0 -7
  198. package/src/mcp/graph/context-core.mjs +0 -111
  199. package/src/mcp/graph/context-seeds.mjs +0 -207
  200. package/src/mcp/graph/context-state.mjs +0 -85
  201. package/src/mcp/graph/reverse-reach.mjs +0 -42
  202. package/src/mcp/graph/tools-core.mjs +0 -143
  203. package/src/mcp/graph/tools-query.mjs +0 -276
  204. package/src/mcp/graph-context.mjs +0 -5
  205. package/src/mcp/graph-diff.mjs +0 -218
  206. package/src/mcp/health/audit-format.mjs +0 -199
  207. package/src/mcp/health/audit.mjs +0 -199
  208. package/src/mcp/health/dead-code.mjs +0 -110
  209. package/src/mcp/health/duplicates.mjs +0 -121
  210. package/src/mcp/health/endpoints.mjs +0 -71
  211. package/src/mcp/health/structure.mjs +0 -220
  212. package/src/mcp/runtime-version.mjs +0 -31
  213. package/src/mcp/server/auto-refresh.mjs +0 -66
  214. package/src/mcp/server/runtime-config.mjs +0 -43
  215. package/src/mcp/server/shutdown.mjs +0 -40
  216. package/src/mcp/staleness-notice.mjs +0 -20
  217. package/src/mcp/sync/evidence-architecture.mjs +0 -54
  218. package/src/mcp/sync/evidence-common.mjs +0 -88
  219. package/src/mcp/sync/evidence-duplicates.mjs +0 -97
  220. package/src/mcp/sync/evidence-health.mjs +0 -56
  221. package/src/mcp/sync/evidence-packages.mjs +0 -95
  222. package/src/mcp/sync/payload-common.mjs +0 -97
  223. package/src/mcp/sync/payload-v2.mjs +0 -54
  224. package/src/mcp/sync/payload-v3.mjs +0 -79
  225. package/src/mcp/sync-evidence.mjs +0 -23
  226. package/src/mcp/sync-payload.mjs +0 -70
  227. package/src/mcp/tool-result.mjs +0 -54
  228. package/src/mcp/tools-actions.mjs +0 -11
  229. package/src/mcp/tools-architecture.mjs +0 -177
  230. package/src/mcp/tools-company.mjs +0 -251
  231. package/src/mcp/tools-context.mjs +0 -222
  232. package/src/mcp/tools-endpoints.mjs +0 -207
  233. package/src/mcp/tools-graph-hubs.mjs +0 -78
  234. package/src/mcp/tools-graph.mjs +0 -17
  235. package/src/mcp/tools-health.mjs +0 -24
  236. package/src/mcp/tools-history.mjs +0 -28
  237. package/src/mcp/tools-impact-change.mjs +0 -220
  238. package/src/mcp/tools-impact-precision.mjs +0 -89
  239. package/src/mcp/tools-impact.mjs +0 -169
  240. package/src/mcp/tools-source.mjs +0 -238
  241. package/src/mcp/tools-verified-change.mjs +0 -200
  242. package/src/mcp-rg.mjs +0 -50
  243. package/src/mcp-runtime.mjs +0 -2
  244. package/src/mcp-server.mjs +0 -298
  245. package/src/mcp-source-tools.mjs +0 -163
  246. package/src/path-classification.js +0 -226
  247. package/src/path-ignore.js +0 -69
  248. package/src/precision/lsp-client/constants.js +0 -12
  249. package/src/precision/lsp-client/environment.js +0 -20
  250. package/src/precision/lsp-client/errors.js +0 -15
  251. package/src/precision/lsp-client/lifecycle.js +0 -114
  252. package/src/precision/lsp-client/message-parser.js +0 -81
  253. package/src/precision/lsp-client/protocol.js +0 -212
  254. package/src/precision/lsp-client/registry.js +0 -59
  255. package/src/precision/lsp-client/repo-uri.js +0 -60
  256. package/src/precision/lsp-client/stdio-client.js +0 -140
  257. package/src/precision/lsp-client.js +0 -10
  258. package/src/precision/lsp-overlay/budget-policy.js +0 -78
  259. package/src/precision/lsp-overlay/build.js +0 -261
  260. package/src/precision/lsp-overlay/contract.js +0 -61
  261. package/src/precision/lsp-overlay/reference-results.js +0 -108
  262. package/src/precision/lsp-overlay/semantic-inputs.js +0 -62
  263. package/src/precision/lsp-overlay/source-session.js +0 -142
  264. package/src/precision/lsp-overlay/store.js +0 -150
  265. package/src/precision/lsp-overlay/target-index.js +0 -152
  266. package/src/precision/lsp-overlay/target-query.js +0 -55
  267. package/src/precision/lsp-overlay.js +0 -11
  268. package/src/precision/symbol-query.js +0 -224
  269. package/src/precision/typescript-lsp-provider.js +0 -12
  270. package/src/precision/typescript-provider/client.js +0 -89
  271. package/src/precision/typescript-provider/discovery.js +0 -124
  272. package/src/precision/typescript-provider/isolated-runtime.js +0 -39
  273. package/src/precision/typescript-provider/project-host.js +0 -254
  274. package/src/precision/typescript-provider/project-safety.js +0 -166
  275. package/src/precision/typescript-provider/reference-usage.js +0 -53
  276. package/src/process.js +0 -95
  277. package/src/repo-path.js +0 -53
  278. package/src/scan/discover.inventory.js +0 -78
  279. package/src/scan/discover.js +0 -5
  280. package/src/scan/discover.list.js +0 -79
  281. package/src/scan/discover.stack.js +0 -227
  282. package/src/scan/search.core.js +0 -24
  283. package/src/scan/search.git.js +0 -102
  284. package/src/scan/search.js +0 -9
  285. package/src/scan/search.node.js +0 -83
  286. package/src/scan/search.preview.js +0 -49
  287. package/src/scan/search.rg.js +0 -145
  288. package/src/security/advisory-store.js +0 -172
  289. package/src/security/installed-jvm-rust.js +0 -46
  290. package/src/security/installed.js +0 -280
  291. package/src/security/malware-file-heuristics.js +0 -121
  292. package/src/security/malware-heuristics.exclusions.js +0 -134
  293. package/src/security/malware-heuristics.js +0 -15
  294. package/src/security/malware-heuristics.roots.js +0 -145
  295. package/src/security/malware-heuristics.scan.js +0 -89
  296. package/src/security/malware-heuristics.sweep.js +0 -122
  297. package/src/security/malware-scoring.js +0 -105
  298. package/src/security/match.js +0 -85
  299. package/src/security/registry-sig.classify.js +0 -137
  300. package/src/security/registry-sig.js +0 -18
  301. package/src/security/registry-sig.rules.js +0 -192
  302. package/src/security/rust-advisory-report.js +0 -60
  303. package/src/security/typosquat.js +0 -81
  304. package/src/util.js +0 -40
  305. package/src/version.js +0 -7
@@ -1,143 +0,0 @@
1
- import { folderModuleOf } from "../graph-analysis.edges.js";
2
- import { isStructuralRelation } from "../../graph/relations.js";
3
- import { endpointId, normalizeContractFile } from "./shared.js";
4
-
5
- export function reverseRuntimeImports(graph = {}) {
6
- const byId = new Map();
7
- const files = new Set();
8
- for (const node of graph.nodes || []) {
9
- const file = normalizeContractFile(node?.source_file);
10
- if (!file) continue;
11
- byId.set(String(node.id), file);
12
- files.add(file);
13
- }
14
- const reverse = new Map([...files].map((file) => [file, new Set()]));
15
- for (const link of graph.links || []) {
16
- if (isStructuralRelation(link?.relation) || !["imports", "re_exports"].includes(link?.relation) || link?.typeOnly === true || link?.compileOnly === true || link?.barrelProxy === true) continue;
17
- const importer = byId.get(String(endpointId(link.source)));
18
- const imported = byId.get(String(endpointId(link.target)));
19
- if (!importer || !imported || importer === imported) continue;
20
- reverse.get(imported)?.add(importer);
21
- }
22
- return reverse;
23
- }
24
-
25
- export function wrapperScopeFiles(sourceFile, graph) {
26
- const source = normalizeContractFile(sourceFile);
27
- if (!source || !Array.isArray(graph?.nodes)) return null;
28
- const reverse = reverseRuntimeImports(graph);
29
- const allowed = new Set([source]);
30
- const queue = [{ file: source, depth: 0 }];
31
- while (queue.length && allowed.size < 2_000) {
32
- const current = queue.shift();
33
- if (current.depth >= 4) continue;
34
- for (const importer of [...(reverse.get(current.file) || [])].sort()) {
35
- if (allowed.has(importer)) continue;
36
- allowed.add(importer);
37
- queue.push({ file: importer, depth: current.depth + 1 });
38
- }
39
- }
40
- return allowed;
41
- }
42
-
43
- function isScreen(file) {
44
- const path = normalizeContractFile(file);
45
- const base = path.split("/").at(-1) || "";
46
- return /(^|\/)(pages?|screens?|views?|routes?)(\/|$)/i.test(path)
47
- || /(^|\/)(?:page|layout)\.[cm]?[jt]sx?$/i.test(path)
48
- || /^(?:App|Root)\.[cm]?[jt]sx?$/i.test(base);
49
- }
50
-
51
- export function affectedForEndpoint(callsites, clientContexts, limits) {
52
- const collected = new Map();
53
- let traversalTruncated = false;
54
- for (const context of clientContexts) {
55
- const seeds = callsites.filter((call) => call.clientRepo === context.id).map((call) => call.file).sort();
56
- if (!seeds.length) continue;
57
- const queue = [];
58
- const distance = new Map();
59
- for (const seed of seeds) if (!distance.has(seed)) { distance.set(seed, 0); queue.push(seed); }
60
- while (queue.length) {
61
- const file = queue.shift();
62
- const depth = distance.get(file);
63
- const key = `${context.id}\0${file}`;
64
- const previous = collected.get(key);
65
- if (!previous || depth < previous.distance) collected.set(key, { client: context.id, file, distance: depth });
66
- if (depth >= limits.maxImpactDepth) continue;
67
- for (const importer of [...(context.reverse.get(file) || [])].sort()) {
68
- if (distance.has(importer)) continue;
69
- if (distance.size >= limits.maxAffectedFiles * 2) { traversalTruncated = true; continue; }
70
- distance.set(importer, depth + 1);
71
- queue.push(importer);
72
- }
73
- }
74
- }
75
- const allFiles = [...collected.values()].sort((left, right) => left.distance - right.distance || left.client.localeCompare(right.client) || left.file.localeCompare(right.file));
76
- const filesTruncated = allFiles.length > limits.maxAffectedFiles;
77
- const files = allFiles.slice(0, limits.maxAffectedFiles);
78
- const allScreens = files.filter((entry) => isScreen(entry.file));
79
- const screensTruncated = allScreens.length > limits.maxScreens;
80
- const screens = allScreens.slice(0, limits.maxScreens);
81
- const moduleMap = new Map();
82
- for (const entry of files) {
83
- const module = folderModuleOf(entry.file);
84
- const key = `${entry.client}\0${module}`;
85
- const item = moduleMap.get(key) || { client: entry.client, module, files: 0, nearestDistance: entry.distance };
86
- item.files++;
87
- item.nearestDistance = Math.min(item.nearestDistance, entry.distance);
88
- moduleMap.set(key, item);
89
- }
90
- const allModules = [...moduleMap.values()].sort((left, right) => left.nearestDistance - right.nearestDistance || right.files - left.files || left.client.localeCompare(right.client) || left.module.localeCompare(right.module));
91
- const modulesTruncated = allModules.length > limits.maxModules;
92
- return {
93
- complete: !(traversalTruncated || filesTruncated || screensTruncated || modulesTruncated),
94
- files,
95
- screens,
96
- modules: allModules.slice(0, limits.maxModules),
97
- truncated: { traversal: traversalTruncated, files: filesTruncated, screens: screensTruncated, modules: modulesTruncated },
98
- };
99
- }
100
- const bareGraphLabel = (value) => String(value || "").replace(/\s*\(.*$/, "").replace(/[()]/g, "").trim();
101
-
102
- export function handlerNodeEvidence(endpoint, graph) {
103
- const handler = /^[A-Za-z_$][\w$]{0,127}$/.test(String(endpoint?.handler || "")) ? String(endpoint.handler) : null;
104
- if (!handler) return { handler: null, handlerNodeId: null, handlerResolution: "inline-or-unresolved" };
105
- const nodes = graph?.nodes || [];
106
- const matches = nodes.filter((node) => normalizeContractFile(node?.source_file) && bareGraphLabel(node?.label) === handler && String(node?.id || "") !== normalizeContractFile(node?.source_file));
107
- const endpointFile = normalizeContractFile(endpoint.file);
108
- const sameFile = matches.filter((node) => normalizeContractFile(node?.source_file) === endpointFile);
109
- const byId = new Map(nodes.map((node) => [endpointId(node?.id), node]));
110
- const linkFile = (value) => {
111
- const id = endpointId(value);
112
- return normalizeContractFile(byId.get(id)?.source_file || String(id || "").split("#")[0]);
113
- };
114
- const directlyImportedFiles = new Set((graph?.links || [])
115
- .filter((link) => ["imports", "re_exports"].includes(link?.relation) && linkFile(link?.source) === endpointFile)
116
- .map((link) => linkFile(link?.target)).filter(Boolean));
117
- const imported = matches.filter((node) => directlyImportedFiles.has(normalizeContractFile(node?.source_file)));
118
- const resolved = sameFile.length === 1 ? sameFile[0] : imported.length === 1 ? imported[0] : matches.length === 1 ? matches[0] : null;
119
- return {
120
- handler,
121
- handlerNodeId: resolved ? String(resolved.id) : null,
122
- handlerResolution: resolved ? "resolved" : matches.length > 1 ? "ambiguous" : "unresolved",
123
- };
124
- }
125
-
126
- export function externalUseLiveness(callsites, handlerEvidence) {
127
- const proven = callsites.filter((call) => call.match?.confidence === "high" || call.match?.confidence === "medium");
128
- const possible = callsites.filter((call) => call.match?.confidence === "low");
129
- const status = proven.length ? "NOT_DEAD_EXTERNAL_USE" : possible.length ? "POSSIBLE_EXTERNAL_USE" : "UNKNOWN";
130
- const evidence = proven.length ? proven : possible;
131
- return {
132
- status,
133
- subject: handlerEvidence.handlerNodeId ? "handler-node" : handlerEvidence.handler ? "endpoint-handler" : "endpoint",
134
- canSuppressDeadCandidate: proven.length > 0 && Boolean(handlerEvidence.handlerNodeId),
135
- staticEvidence: evidence.length,
136
- consumerRepositories: [...new Set(evidence.map((call) => call.clientRepo))].sort(),
137
- reason: proven.length
138
- ? "At least one selected external repository has a medium/high-confidence static HTTP contract match."
139
- : possible.length
140
- ? "Only low-confidence external HTTP contract matches were found; review before suppressing a dead-code candidate."
141
- : "No selected external repository proved a static caller; absence of evidence is not a dead-code verdict.",
142
- };
143
- }
@@ -1,61 +0,0 @@
1
- import { normalizeHttpContractPath } from "./shared.js";
2
-
3
- export const pathSegments = (path) => String(path || "").split("/").filter(Boolean);
4
- const parameter = (segment) => segment === ":param";
5
- const wildcard = (segment) => segment === "*";
6
-
7
- export function routeShapeMatches(endpointSegments, callSegments) {
8
- const catchAll = wildcard(endpointSegments.at(-1));
9
- if (catchAll ? callSegments.length < endpointSegments.length - 1 : endpointSegments.length !== callSegments.length) return false;
10
- const compared = catchAll ? endpointSegments.length - 1 : endpointSegments.length;
11
- for (let index = 0; index < compared; index++) {
12
- const expected = endpointSegments[index], actual = callSegments[index];
13
- if (parameter(expected)) continue;
14
- if (parameter(actual) || wildcard(actual) || expected !== actual) return false;
15
- }
16
- return true;
17
- }
18
-
19
- export function suffixShapeMatch(endpointSegments, callSegments) {
20
- if (endpointSegments.length === callSegments.length || Math.min(endpointSegments.length, callSegments.length) < 2) return false;
21
- if (endpointSegments.length < callSegments.length) return routeShapeMatches(endpointSegments, callSegments.slice(callSegments.length - endpointSegments.length));
22
- return routeShapeMatches(endpointSegments.slice(endpointSegments.length - callSegments.length), callSegments);
23
- }
24
-
25
- export function routeShapeContains(endpointSegments, requestedSegments) {
26
- if (!requestedSegments.length || requestedSegments.length > endpointSegments.length) return false;
27
- for (let start = 0; start <= endpointSegments.length - requestedSegments.length; start++) {
28
- if (routeShapeMatches(endpointSegments.slice(start, start + requestedSegments.length), requestedSegments)) return true;
29
- }
30
- return false;
31
- }
32
-
33
- export function methodMatches(endpointMethod, callMethod) {
34
- return endpointMethod === "ANY" || endpointMethod === "ALL" || endpointMethod === callMethod;
35
- }
36
-
37
- export function matchHttpContract(endpoint, call) {
38
- if (!call?.path || !methodMatches(String(endpoint?.method || "").toUpperCase(), call.method)) return null;
39
- const expected = pathSegments(normalizeHttpContractPath(endpoint.path));
40
- const actual = pathSegments(call.path);
41
- if (routeShapeMatches(expected, actual)) {
42
- if (call.unknownPrefix || call.partialDynamic) return { kind: "exact-dynamic", confidence: "medium", score: 0.78, reason: "method and normalized route shape match, but the client URL retains a dynamic component" };
43
- const concreteParameter = expected.some((segment, index) => parameter(segment) && !parameter(actual[index]));
44
- return {
45
- kind: "exact",
46
- confidence: "high",
47
- score: concreteParameter ? 0.96 : 1,
48
- reason: concreteParameter ? "method matches and a backend parameter accepts the concrete client segment" : "method and normalized route shape match exactly",
49
- };
50
- }
51
- if (suffixShapeMatch(expected, actual)) {
52
- const dynamic = call.dynamic || call.unknownPrefix || call.partialDynamic;
53
- return {
54
- kind: "suffix",
55
- confidence: dynamic ? "low" : "medium",
56
- score: dynamic ? 0.55 : 0.72,
57
- reason: dynamic ? "method matches and at least two trailing route segments match; the client prefix is dynamic" : "method matches and at least two trailing route segments match after a client/backend base-path difference",
58
- };
59
- }
60
- return null;
61
- }
@@ -1,85 +0,0 @@
1
- import { boundedInteger } from "../../util.js";
2
-
3
- export const HTTP_CONTRACTS_V = 2;
4
- export const HTTP_CONTRACT_METHODS = new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
5
-
6
- export const HTTP_CONTRACT_DEFAULTS = Object.freeze({
7
- maxBackendFiles: 3_000,
8
- maxClientFiles: 3_000,
9
- maxEndpoints: 250,
10
- maxCallsPerClient: 2_000,
11
- maxMatches: 1_000,
12
- maxCallsitesPerEndpoint: 100,
13
- maxUncertain: 200,
14
- maxImpactDepth: 2,
15
- maxAffectedFiles: 100,
16
- maxScreens: 50,
17
- maxModules: 50,
18
- });
19
-
20
- export const HTTP_CONTRACT_HARD_LIMITS = Object.freeze({
21
- maxBackendFiles: 3_000,
22
- maxClientFiles: 10_000,
23
- maxEndpoints: 500,
24
- maxCallsPerClient: 5_000,
25
- maxMatches: 5_000,
26
- maxCallsitesPerEndpoint: 500,
27
- maxUncertain: 1_000,
28
- maxImpactDepth: 5,
29
- maxAffectedFiles: 500,
30
- maxScreens: 200,
31
- maxModules: 200,
32
- });
33
-
34
- export const endpointId = (value) => value && typeof value === "object" ? value.id : value;
35
-
36
- export function normalizeContractFile(value) {
37
- const raw = String(value || "").replace(/\\/g, "/");
38
- if (!raw || raw.startsWith("/") || /^[a-z]:\//i.test(raw) || /[\x00-\x1f\x7f]/.test(raw)) return "";
39
- const normalized = raw.replace(/^\.\//, "");
40
- return normalized.split("/").some((part) => !part || part === "." || part === "..") ? "" : normalized;
41
- }
42
-
43
- export { boundedInteger };
44
-
45
- export function safeContractName(value, fallback) {
46
- const text = String(value || "").trim();
47
- return /^[a-z0-9][a-z0-9._-]{0,79}$/i.test(text) ? text : fallback;
48
- }
49
-
50
- export function contractLineAt(text, index) {
51
- let line = 1;
52
- for (let cursor = 0; cursor < index; cursor++) if (text.charCodeAt(cursor) === 10) line++;
53
- return line;
54
- }
55
-
56
- export function normalizeHttpContractLimits(input = {}) {
57
- const result = {};
58
- for (const key of Object.keys(HTTP_CONTRACT_DEFAULTS)) {
59
- result[key] = boundedInteger(input[key], HTTP_CONTRACT_DEFAULTS[key], key === "maxImpactDepth" ? 0 : 1, HTTP_CONTRACT_HARD_LIMITS[key]);
60
- }
61
- return result;
62
- }
63
-
64
- export function normalizeHttpContractPath(value) {
65
- let path = String(value || "").trim();
66
- if (!path || path.length > 2_048) return null;
67
- try {
68
- if (/^https?:\/\//i.test(path)) path = new URL(path).pathname;
69
- else if (/^\/\//.test(path)) path = new URL(`http:${path}`).pathname;
70
- } catch { return null; }
71
- const queryAt = path.search(/[?#]/);
72
- if (queryAt >= 0) path = path.slice(0, queryAt);
73
- path = path.replace(/\\/g, "/").replace(/\/+/g, "/");
74
- if (!path.startsWith("/")) path = `/${path}`;
75
- path = path.replace(/\/\{[^/}]+\}/g, "/:param")
76
- .replace(/\/:([A-Za-z_$][\w$-]*)(?:\?)?/g, "/:param")
77
- .replace(/\/\*[^/]*/g, "/*")
78
- .replace(/\[(?:\.\.\.)?[^\]]+\]/g, "/:param")
79
- .replace(/\/+$/g, "") || "/";
80
- return /[\x00-\x1f\x7f]/.test(path) || path.includes("..") ? null : path;
81
- }
82
-
83
- export function filesFromGraph(graph) {
84
- return [...new Set((graph?.nodes || []).map((node) => normalizeContractFile(node?.source_file)).filter(Boolean))].sort();
85
- }
@@ -1,6 +0,0 @@
1
- // Stable public facade for cross-repository HTTP contract evidence.
2
- export { HTTP_CONTRACTS_V, normalizeHttpContractPath } from "./http-contracts/shared.js";
3
- export { extractHttpClientCallsFromText } from "./http-contracts/client-call-parser.js";
4
- export { detectHttpClientCalls } from "./http-contracts/client-call-detection.js";
5
- export { matchHttpContract } from "./http-contracts/matching.js";
6
- export { analyzeHttpContracts } from "./http-contracts/analysis.js";
@@ -1,113 +0,0 @@
1
- import { readCoverageForRepo } from "../coverage-reports.js";
2
- import { buildHealthCapabilityMatrix } from "../health-capabilities.js";
3
-
4
- export function buildDependencyHealth({
5
- repoPath,
6
- graph,
7
- repoFiles,
8
- pyManifest,
9
- dep,
10
- goDep,
11
- pyDep,
12
- jvmDependencies,
13
- cargoDep,
14
- externalImports,
15
- findings,
16
- packageScopes,
17
- sourceFiles,
18
- correctnessCoverage,
19
- checks,
20
- }) {
21
- const dependencyFindings = findings.filter((finding) => ["unused-dep", "missing-dep", "duplicate-dep"].includes(finding.rule));
22
- const graphComplete = !((graph.graphBuildMode && graph.graphBuildMode !== "full") || graph.graphBuildScope);
23
- const npmManifests = repoFiles.filter((file) => /(^|\/)package\.json$/i.test(file));
24
- const pythonManifests = [...new Set((pyManifest.scopes || []).flatMap((scope) => scope.manifests || []))];
25
- const publicEvidence = ({ findings: _findings, ...item }) => item;
26
- const ecosystems = {
27
- npm: {
28
- ecosystem: "npm",
29
- present: npmManifests.length > 0,
30
- status: npmManifests.length ? "CHECKED" : "NOT_PRESENT",
31
- completeness: graphComplete ? "COMPLETE" : "PARTIAL",
32
- manifests: npmManifests,
33
- declared: dep.declared.size,
34
- reason: npmManifests.length
35
- ? "package.json declarations were compared with indexed JavaScript/TypeScript imports, including per-finding manifest/source/config evidence."
36
- : "No package.json was discovered.",
37
- },
38
- go: {
39
- ecosystem: "go",
40
- present: goDep.present,
41
- status: goDep.status,
42
- completeness: graphComplete && goDep.completeness === "COMPLETE" ? "COMPLETE" : goDep.completeness,
43
- manifests: goDep.manifests,
44
- declared: goDep.declared.size,
45
- reason: goDep.reason,
46
- },
47
- python: {
48
- ecosystem: "python",
49
- present: pyManifest.present,
50
- status: pyManifest.present ? "CHECKED" : "NOT_PRESENT",
51
- completeness: pyManifest.present ? (graphComplete && pyManifest.completeness === "COMPLETE" ? "COMPLETE" : "PARTIAL") : "NOT_APPLICABLE",
52
- manifests: pythonManifests,
53
- declared: pyDep.declared.size,
54
- reason: pyManifest.present
55
- ? pyManifest.reasons?.length
56
- ? `Python declarations were compared with indexed imports, but ${pyManifest.reasons.join("; ")}.`
57
- : "Every discovered supported Python manifest scope was compared with indexed imports. Environment markers and extras are normalized as declarations; runtime-computed imports remain outside static proof."
58
- : "No supported Python dependency manifest was discovered.",
59
- },
60
- maven: { ecosystem: "maven", ...publicEvidence(jvmDependencies.maven), completeness: jvmDependencies.maven.present && !graphComplete ? "PARTIAL" : jvmDependencies.maven.completeness },
61
- gradle: { ecosystem: "gradle", ...publicEvidence(jvmDependencies.gradle), completeness: jvmDependencies.gradle.present && !graphComplete ? "PARTIAL" : jvmDependencies.gradle.completeness },
62
- rust: { ecosystem: "rust", ...publicEvidence(cargoDep), declared: cargoDep.declared.size, completeness: cargoDep.present && !graphComplete ? "PARTIAL" : cargoDep.completeness },
63
- };
64
- const present = Object.values(ecosystems).filter((item) => item.present);
65
- const status = present.length === 0
66
- ? "NOT_CHECKED"
67
- : graphComplete && present.every((item) => item.status === "CHECKED" && item.completeness === "COMPLETE")
68
- ? "COMPLETE"
69
- : "PARTIAL";
70
- const importedPackages = new Set(externalImports
71
- .filter((entry) => entry?.pkg && !entry.builtin && !entry.unresolved)
72
- .map((entry) => `${entry.ecosystem || (/\.java$/i.test(entry.file || "") ? "maven-unresolved" : "npm")}:${entry.pkg}`));
73
- const supportedDeclared = dep.declared.size + goDep.declared.size + pyDep.declared.size + cargoDep.declared.size;
74
- const jvmDeclared = jvmDependencies.maven.declared + jvmDependencies.gradle.declared;
75
- const measuredCoverage = readCoverageForRepo(repoPath, sourceFiles);
76
- const healthCapabilities = buildHealthCapabilityMatrix({
77
- graphComplete,
78
- dependencyStatus: status,
79
- dependencyEcosystems: ecosystems,
80
- checks,
81
- sourceFiles,
82
- correctnessCoverage,
83
- measuredCoverageFiles: measuredCoverage.size,
84
- });
85
- return {
86
- manifestDeps: supportedDeclared + jvmDeclared,
87
- healthCapabilities,
88
- dependencyReport: {
89
- status,
90
- evidenceModel: "MANIFEST_PLUS_INDEXED_SOURCE",
91
- perFindingVerification: present.some((item) => item.status === "CHECKED")
92
- && dependencyFindings.every((finding) => finding.verification != null),
93
- verificationCoverage: Object.fromEntries(present.map((item) => [item.ecosystem, `${item.status}/${item.completeness}`])),
94
- ecosystems,
95
- declared: supportedDeclared + jvmDeclared,
96
- importedPackages: importedPackages.size,
97
- importRecords: externalImports.length,
98
- unused: dependencyFindings.filter((finding) => finding.rule === "unused-dep").length,
99
- missing: dependencyFindings.filter((finding) => finding.rule === "missing-dep").length,
100
- duplicateDeclarations: dependencyFindings.filter((finding) => finding.rule === "duplicate-dep").length,
101
- unusedRequiringReview: dependencyFindings.filter((finding) => finding.rule === "unused-dep" && finding.verification?.decision === "REVIEW_REQUIRED").length,
102
- missingWithSourceEvidence: dependencyFindings.filter((finding) => finding.rule === "missing-dep" && finding.verification?.indexedSourceImports?.status === "FOUND").length,
103
- packageScopes: packageScopes.length,
104
- reason: status === "NOT_CHECKED"
105
- ? "No dependency manifest was discovered, so manifest-to-import verification did not run and no dependency verdict was produced."
106
- : status === "COMPLETE"
107
- ? "Every discovered dependency ecosystem has complete supported manifest-to-import evidence for the indexed repository."
108
- : present.some((item) => item.status === "NOT_SUPPORTED")
109
- ? `Dependency evidence is PARTIAL: ${present.filter((item) => item.status === "NOT_SUPPORTED").map((item) => item.ecosystem).join(", ")} manifests were counted, but package-to-artifact verification is NOT_SUPPORTED.`
110
- : "Dependency checks ran at their documented evidence level, but at least one graph or ecosystem surface is partial; this is not a repository-wide clean bill.",
111
- },
112
- };
113
- }
@@ -1,78 +0,0 @@
1
- import {dirname, posix} from 'node:path'
2
- import {createRepoBoundary} from '../../repo-path.js'
3
- import {parseRequirementsNames, parsePyprojectDeps, parsePipfileDeps, pep503} from '../manifests.js'
4
- import {listRepoFiles, readRepoText} from './repo-files.js'
5
-
6
- const normalizeRoot = (root) => {
7
- const value = String(root || '').replace(/\\/g, '/').replace(/^\.\//, '').replace(/^\/+|\/+$/g, '')
8
- return value === '.' ? '' : value
9
- }
10
-
11
- // Python dependencies are owned by the nearest manifest root, including nested services.
12
- export function collectPyManifest(repoRoot) {
13
- const boundary = createRepoBoundary(repoRoot)
14
- const scopes = new Map()
15
- const scopeFor = (root) => {
16
- const normalized = normalizeRoot(root)
17
- if (!scopes.has(normalized)) scopes.set(normalized, {root: normalized, present: false, deps: [], manifests: []})
18
- return scopes.get(normalized)
19
- }
20
- const addManifest = (root, manifest, parsedDeps, present = true) => {
21
- if (!present) return
22
- const scope = scopeFor(root)
23
- scope.present = true
24
- scope.manifests.push(manifest)
25
- scope.deps.push(...parsedDeps.map((dep) => ({...dep, manifest})))
26
- }
27
- const files = listRepoFiles(repoRoot)
28
- const fileSet = new Set(files.map((file) => file.replace(/\\/g, '/')))
29
- const reasons = []
30
- for (const file of files.filter((name) => /(^|\/)requirements[\w.-]*\.(?:txt|in)$/i.test(name)
31
- || /(^|\/)requirements\/[^/]+\.(?:txt|in)$/i.test(name))) {
32
- const text = readRepoText(boundary, file)
33
- if (text == null) continue
34
- const parent = normalizeRoot(dirname(file))
35
- const root = /(^|\/)requirements$/i.test(parent) ? normalizeRoot(dirname(parent)) : parent
36
- const dev = /dev|test|lint|doc|ci/i.test(file.slice(file.lastIndexOf('/') + 1))
37
- addManifest(root, file, parseRequirementsNames(text).map((dep) => ({...dep, dev})))
38
- for (const match of text.matchAll(/^\s*(?:-r|--requirement|-c|--constraint)\s+(?:=\s*)?([^\s#]+)/gmi)) {
39
- const parentDir = normalizeRoot(dirname(file))
40
- const target = normalizeRoot(posix.normalize(`${parentDir ? `${parentDir}/` : ''}${match[1].replace(/\\/g, '/')}`))
41
- if (!target || target.startsWith('../') || !fileSet.has(target)) reasons.push(`${file}: referenced requirements file ${match[1]} was not discovered`)
42
- }
43
- }
44
- for (const file of files.filter((name) => /(^|\/)pyproject\.toml$/i.test(name))) {
45
- const text = readRepoText(boundary, file)
46
- const parsed = parsePyprojectDeps(text)
47
- const dependencyManifest = parsed.present || /^\s*\[(?:project|tool\.poetry)\]/m.test(text || '')
48
- addManifest(dirname(file), file, parsed.deps, dependencyManifest)
49
- if (/\bdynamic\s*=\s*\[[^\]]*["']dependencies["']/s.test(text || '')) reasons.push(`${file}: project dependencies are dynamic`)
50
- }
51
- for (const file of files.filter((name) => /(^|\/)Pipfile$/i.test(name))) {
52
- const text = readRepoText(boundary, file)
53
- const parsed = parsePipfileDeps(text)
54
- addManifest(dirname(file), file, parsed.deps, parsed.present || /^\s*\[(?:packages|dev-packages)\]/mi.test(text || ''))
55
- }
56
- const normalizedScopes = [...scopes.values()]
57
- .map((scope) => {
58
- const seen = new Set()
59
- return {
60
- ...scope,
61
- manifests: [...new Set(scope.manifests)].sort(),
62
- deps: scope.deps.filter((dep) => {
63
- const key = pep503(dep.name)
64
- if (!key || seen.has(key)) return false
65
- seen.add(key)
66
- return true
67
- }),
68
- }
69
- })
70
- .sort((left, right) => right.root.length - left.root.length || left.root.localeCompare(right.root))
71
- return {
72
- present: normalizedScopes.some((scope) => scope.present),
73
- deps: normalizedScopes.flatMap((scope) => scope.deps),
74
- scopes: normalizedScopes,
75
- completeness: reasons.length ? 'PARTIAL' : 'COMPLETE',
76
- reasons: [...new Set(reasons)].sort(),
77
- }
78
- }
@@ -1,50 +0,0 @@
1
- import {readFileSync, readdirSync} from 'node:fs'
2
- import {join} from 'node:path'
3
- import {runGit} from '../../git-exec.js'
4
- import {filterWeavatrixIgnored} from '../../path-ignore.js'
5
-
6
- export const readText = (path) => {
7
- try { return readFileSync(path, 'utf8') } catch { return null }
8
- }
9
-
10
- export const readJson = (path) => {
11
- try { return JSON.parse(readFileSync(path, 'utf8')) } catch { return null }
12
- }
13
-
14
- const readRepoFile = (boundary, relativePath, reader) => {
15
- const resolved = boundary.resolve(relativePath)
16
- return resolved.ok ? reader(resolved.path) : null
17
- }
18
-
19
- export const readRepoText = (boundary, relativePath) => readRepoFile(boundary, relativePath, readText)
20
-
21
- export const readRepoJson = (boundary, relativePath) => readRepoFile(boundary, relativePath, readJson)
22
-
23
- const SKIP_DIRS = new Set([
24
- '.git', '.hg', '.svn', 'node_modules', 'vendor', 'dist', 'build', 'coverage', '.next', 'out',
25
- 'release', 'weavatrix-graphs', '__pycache__', '.venv', 'venv', 'env', '.tox', 'site-packages',
26
- '.mypy_cache', '.pytest_cache',
27
- ])
28
-
29
- export function listRepoFiles(repoRoot) {
30
- try {
31
- const result = runGit(repoRoot, ['ls-files', '--cached', '--others', '--exclude-standard', '-z'], {timeout: 15_000, maxBuffer: 32 * 1024 * 1024})
32
- if (result.status === 0) {
33
- const files = String(result.stdout || '').split('\0').filter(Boolean).map((file) => file.replace(/\\/g, '/'))
34
- return filterWeavatrixIgnored(repoRoot, files)
35
- }
36
- } catch { /* non-Git repo or git unavailable: use the bounded walker below */ }
37
-
38
- const files = []
39
- const walk = (absolute, parts = []) => {
40
- let entries = []
41
- try { entries = readdirSync(absolute, {withFileTypes: true}) } catch { return }
42
- for (const entry of entries) {
43
- if (entry.isDirectory()) {
44
- if (!SKIP_DIRS.has(entry.name)) walk(join(absolute, entry.name), [...parts, entry.name])
45
- } else if (entry.isFile()) files.push([...parts, entry.name].join('/'))
46
- }
47
- }
48
- walk(repoRoot)
49
- return filterWeavatrixIgnored(repoRoot, files)
50
- }