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,17 +0,0 @@
1
- // Read-only analysis primitives the weavatrix-refactor package composes into refactoring
2
- // plan producers. Everything exported here is PURE READ: graph identity helpers, cycle
3
- // detection, architecture verification, the bundled tree-sitter grammars, the read-only
4
- // TypeScript language-server client, and dead-code risk signals. None of it writes, applies,
5
- // or references applying a change — the core catalog and the release gate keep the core
6
- // provably free of any source-write or edit-plan path. The refactoring engines live in
7
- // weavatrix-refactor and import this surface.
8
-
9
- export {graphEndpointId, fileOfId} from './graph/node-id.js'
10
- export {Parser, Query, EXT_LANG, ensureParser} from './graph/internal-builder.langs.js'
11
- export {querySymbolPrecision} from './precision/symbol-query.js'
12
- export {createTypeScriptLspClient} from './precision/typescript-provider/client.js'
13
- export {verifyArchitecture} from './analysis/architecture/contract-verification.js'
14
- export {normalizeArchitectureContract} from './analysis/architecture-contract.js'
15
- export {buildFileImportGraph, findSccs} from './analysis/structure/dependency-graph.js'
16
- export {isFrameworkEntryFile} from './analysis/dead-check.js'
17
- export {hasDynamicCode, REFLECTION_CODE_RE} from './analysis/dead-code-review/policy.js'
package/src/bounds.js DELETED
@@ -1,4 +0,0 @@
1
- export function boundedInteger(value, fallback, minimum, maximum) {
2
- const number = Number(value);
3
- return Math.max(minimum, Math.min(maximum, Number.isFinite(number) ? Math.floor(number) : fallback));
4
- }
@@ -1,209 +0,0 @@
1
- // Graph build — weavatrix's own web-tree-sitter builder.
2
- // Emits <weavatrix-graphs/<repo>>/graph.json for the rest of the pipeline.
3
- //
4
- // The parse itself runs in a WORKER THREAD (build-worker.js): in-process it pinned Electron's main
5
- // event loop for the whole repo walk, and since Windows routes window input through the main process
6
- // the ENTIRE app froze on big repos. The worker writes graph.json itself and returns only counts +
7
- // summaries. If the worker can't even start (exotic packaging), we fall back to the in-process build
8
- // rather than lose the feature.
9
- import { existsSync, readFileSync, mkdirSync } from "node:fs";
10
- import { join, resolve } from "node:path";
11
- import { Worker } from "node:worker_threads";
12
- import { childProcessEnv } from "./child-env.js";
13
- import { graphHomeDir, graphOutDirForRepo, graphStorageKey, repoTopFolders, summarizeCommunities, summarizeHotspots, filterGraphForMode, filterGraphByScope } from "./graph/layout.js";
14
- import { registerRepository } from "./graph/repo-registry.js";
15
- import { refreshGraphIncrementally, snapshotRepository } from "./graph/incremental-refresh.js";
16
- import { atomicWriteFileSync, withFileLock } from "./graph/file-lock.js";
17
- import { graphSchemaIsCurrent, repositoryFreshnessProbe, stampRepositoryFreshness } from "./graph/freshness-probe.js";
18
- import { buildLspPrecisionOverlay, invalidatePrecisionOverlay, precisionSummary } from "./precision/lsp-overlay.js";
19
-
20
- // The worker path deadlocks web-tree-sitter's WASM in Electron's worker threads (fine in plain Node) — off
21
- // until that's Electron-safe. In-process + event-loop yielding keeps the window responsive without it.
22
- const USE_BUILD_WORKER = false;
23
-
24
- // Hard ceiling so a wedged parse (WASM stuck, pathological file, symlink loop) can NEVER leave the UI on
25
- // an eternal "BUILDING GRAPH…". On timeout we terminate the worker and reject as a REAL failure (no
26
- // workerStartFailed → we do NOT fall back to the in-process build, which would hang the same way and
27
- // freeze the whole app on the main thread). 4 min is generous for very large repos.
28
- const BUILD_WORKER_TIMEOUT_MS = 4 * 60 * 1000;
29
-
30
- export function defaultPrecisionMode(env = process.env) {
31
- return env?.WEAVATRIX_PRECISION === "off" ? "off" : "lsp";
32
- }
33
-
34
- // One-line human status for a precision summary (precisionSummary shape) — the graph_stats
35
- // composition, shared by the build log and open_repo so every surface reads the same fraction.
36
- export function precisionStatusLine(precision) {
37
- const p = precision || {};
38
- if (p.state === "NONE") return `Semantic precision: NONE — ${p.reason || "no eligible JavaScript/TypeScript semantic targets"}`;
39
- return `Semantic precision: ${p.state || "UNAVAILABLE"} — ${p.queried || 0}/${p.candidates || 0} bounded target(s) queried${p.truncated ? " (truncated)" : ""}; ${p.verifiedEdges || 0} EXACT_LSP edge(s)${p.state !== "COMPLETE" && p.reason ? `; ${p.reason}` : ""}`;
40
- }
41
-
42
- function buildGraphInWorker(payload) {
43
- return new Promise((resolve, reject) => {
44
- let worker;
45
- try {
46
- worker = new Worker(new URL("./graph/build-worker.js", import.meta.url), { workerData: payload, env: childProcessEnv() });
47
- } catch (e) {
48
- reject(Object.assign(e, { workerStartFailed: true }));
49
- return;
50
- }
51
- let settled = false;
52
- let timer = null;
53
- const done = (fn, v) => {
54
- if (settled) return;
55
- settled = true;
56
- if (timer) { clearTimeout(timer); timer = null; }
57
- fn(v);
58
- };
59
- timer = setTimeout(() => {
60
- try { worker.terminate(); } catch { /* already gone */ }
61
- done(reject, new Error(`graph build timed out after ${Math.round(BUILD_WORKER_TIMEOUT_MS / 1000)}s (the parser is wedged on this repo — try again, or report it)`));
62
- }, BUILD_WORKER_TIMEOUT_MS);
63
- worker.once("message", (msg) => {
64
- if (msg && msg.ok) done(resolve, msg);
65
- else done(reject, new Error((msg && msg.error) || "graph worker failed"));
66
- });
67
- worker.once("error", (e) => done(reject, Object.assign(e, { workerStartFailed: true })));
68
- worker.once("exit", (code) => { if (code !== 0) done(reject, Object.assign(new Error(`graph worker exited with code ${code}`), { workerStartFailed: true })); });
69
- });
70
- }
71
-
72
- async function buildAndWriteInProcess(repoPath, { mode, scope, precision, graphJson, central }) {
73
- const { buildInternalGraph } = await import("./graph/internal-builder.js");
74
- // Capture the cheap Git state on both sides of the authoritative build. Only an unchanged pair is
75
- // safe to persist: if the working tree moves while parsing, the next process must take the slow path.
76
- const probeBefore = scope ? null : repositoryFreshnessProbe(repoPath);
77
- let graph;
78
- let refresh = null;
79
- if (mode === "full" && !scope && existsSync(graphJson)) {
80
- try {
81
- const existing = JSON.parse(readFileSync(graphJson, "utf8"));
82
- if (existing.graphBuildMode === "full" && !existing.graphBuildScope && graphSchemaIsCurrent(existing)) {
83
- refresh = await refreshGraphIncrementally(repoPath, existing, { buildGraph: buildInternalGraph });
84
- graph = refresh.graph;
85
- }
86
- } catch { /* malformed/legacy graph: the safe path below is a full rebuild */ }
87
- }
88
- if (!graph && mode !== "full" && !scope && existsSync(graphJson)) {
89
- try {
90
- const existing = JSON.parse(readFileSync(graphJson, "utf8"));
91
- if (existing.graphBuildMode === mode && existing.graphRevision && graphSchemaIsCurrent(existing)) {
92
- const snapshot = snapshotRepository(repoPath);
93
- if (snapshot.revision === existing.graphRevision) {
94
- graph = existing;
95
- refresh = { kind: "none", changedFiles: [], reason: "content-unchanged", revision: snapshot.revision };
96
- }
97
- }
98
- } catch { /* malformed/legacy filtered graph: rebuild below */ }
99
- }
100
- if (!graph) {
101
- graph = await buildInternalGraph(repoPath);
102
- refresh = { kind: "full", changedFiles: [], reason: "full-build-requested", revision: graph.graphRevision };
103
- }
104
- // mode (no-tests/tests-only) + path-scope reuse the same pure filters graph-builder used.
105
- if (mode === "no-tests" || mode === "tests-only") graph = filterGraphForMode(graph, mode, { repoRoot: repoPath });
106
- if (scope) graph = filterGraphByScope(graph, scope);
107
- graph.graphBuildMode = mode;
108
- graph.graphBuildScope = scope || "";
109
- const requestedPrecision = precision === "off" ? "off" : "lsp";
110
- const precisionModeChanged = graph.graphPrecisionMode !== requestedPrecision;
111
- graph.graphPrecisionMode = requestedPrecision;
112
- const probeAfter = scope ? null : repositoryFreshnessProbe(repoPath);
113
- const stableProbe = probeBefore && probeAfter === probeBefore ? probeAfter : null;
114
- const freshnessMetadataChanged = stampRepositoryFreshness(graph, stableProbe, mode);
115
- // Auto-refresh runs before every graph/health call. A no-op must not serialize and rewrite a
116
- // multi-megabyte graph merely to answer that nothing changed (or manufacture a newer mtime).
117
- // A one-time metadata-only write is intentional for legacy graphs so the next MCP process can use
118
- // the persisted probe instead of repeating a full repository snapshot.
119
- if (refresh?.kind !== "none" || freshnessMetadataChanged || precisionModeChanged) {
120
- mkdirSync(central, { recursive: true });
121
- atomicWriteFileSync(graphJson, JSON.stringify(graph), "utf8");
122
- }
123
- mkdirSync(central, { recursive: true });
124
- let precisionOverlay = await buildLspPrecisionOverlay({
125
- repoRoot: repoPath,
126
- graph,
127
- graphPath: graphJson,
128
- mode: requestedPrecision,
129
- });
130
- if (requestedPrecision === "lsp") {
131
- try {
132
- // LSP deliberately runs after graph serialization and can outlive the initial snapshot. A
133
- // complete second content snapshot catches source/config add-delete races (including Git
134
- // assume-unchanged paths) that a status-only token cannot prove away.
135
- if (snapshotRepository(repoPath).revision !== graph.graphRevision) {
136
- precisionOverlay = invalidatePrecisionOverlay(graphJson, graph);
137
- }
138
- } catch {
139
- precisionOverlay = invalidatePrecisionOverlay(
140
- graphJson,
141
- graph,
142
- "repository freshness could not be verified after semantic precision",
143
- );
144
- }
145
- }
146
- return {
147
- nodes: graph.nodes.length,
148
- links: graph.links.length,
149
- communities: summarizeCommunities(graphJson),
150
- hotspots: summarizeHotspots(graphJson),
151
- refresh,
152
- precision: precisionSummary(precisionOverlay),
153
- };
154
- }
155
-
156
- export async function buildGraphForRepo(repoPath, {
157
- mode = "full",
158
- scope = "",
159
- precision = defaultPrecisionMode(),
160
- outDir,
161
- graphHome,
162
- } = {}) {
163
- if (!existsSync(repoPath)) return { ok: false, error: "Repo path not found", builder: "internal" };
164
- const registryHome = graphHome || graphHomeDir();
165
- const canonicalDir = graphHome ? join(registryHome, graphStorageKey(repoPath)) : graphOutDirForRepo(repoPath);
166
- const central = outDir || canonicalDir;
167
- const graphJson = join(central, "graph.json");
168
- try {
169
- // In-process is the ONLY path now. The worker (buildGraphInWorker) hung web-tree-sitter's WASM inside an
170
- // Electron worker thread → an eternal "BUILDING GRAPH…" for JS repos, even though the same code finishes
171
- // in ~3s on the main thread (and in a plain-Node worker). buildInternalGraph now YIELDS the event loop
172
- // between file chunks, so the main-thread parse no longer freezes the window — the reason the worker was
173
- // introduced. buildGraphInWorker/USE_BUILD_WORKER are kept for a future Electron-safe re-enable.
174
- const build = () => USE_BUILD_WORKER
175
- ? buildGraphInWorker({ repoPath, mode, scope, precision, graphJson, central }).catch((e) => {
176
- if (e && e.workerStartFailed) return buildAndWriteInProcess(repoPath, { mode, scope, precision, graphJson, central });
177
- throw e;
178
- })
179
- : buildAndWriteInProcess(repoPath, { mode, scope, precision, graphJson, central });
180
- // Canonical graphs are shared by all local MCP clients. Serialize the complete read/refresh/write
181
- // transaction so an older process cannot overwrite a newer incremental result.
182
- const canonical = !scope && resolve(central) === resolve(canonicalDir);
183
- const built = canonical
184
- ? await withFileLock(join(central, ".graph.lock"), build, { timeoutMs: 5 * 60_000, staleMs: 10 * 60_000 })
185
- : await build();
186
- // Scoped builds are disposable diagnostics under modules/<scope>; registering one would retarget
187
- // list_known_repos and cross-repo analysis away from the complete canonical graph.
188
- if (canonical) {
189
- registerRepository({ repoPath, graphDir: central, graphHome: registryHome });
190
- }
191
- return {
192
- ok: true,
193
- builder: "internal",
194
- mode,
195
- scope,
196
- topFolders: repoTopFolders(repoPath),
197
- report: "",
198
- graphFile: "", // no graph.html — weavatrix renders its own GUI board/relations views
199
- graphDir: central,
200
- communities: built.communities,
201
- hotspots: built.hotspots,
202
- refresh: built.refresh,
203
- precision: built.precision,
204
- log: `built-in builder: ${built.nodes} nodes, ${built.links} static links (${built.refresh?.kind || "full"}: ${built.refresh?.reason || "build"}); ${precisionStatusLine(built.precision)}`
205
- };
206
- } catch (error) {
207
- return { ok: false, error: `graph build failed: ${error.message}`, builder: "internal" };
208
- }
209
- }
package/src/child-env.js DELETED
@@ -1,7 +0,0 @@
1
- // Child processes and worker threads never need credentials owned by a composing connector.
2
- // Keep connector secrets in the parent MCP process and out of Git/LSP/test subprocesses.
3
- export function childProcessEnv(overrides = {}) {
4
- const env = { ...process.env, ...overrides };
5
- delete env.WEAVATRIX_SYNC_TOKEN;
6
- return env;
7
- }
package/src/config.js DELETED
@@ -1,5 +0,0 @@
1
- // weavatrix config (Node).
2
- import { fileURLToPath } from "node:url";
3
-
4
- const MAIN_DIR = fileURLToPath(new URL(".", import.meta.url));
5
- export const ROOT_DIR = MAIN_DIR; // fallback cwd for repo-list helpers when a call passes none
@@ -1,75 +0,0 @@
1
- import {readFileSync, statSync} from 'node:fs'
2
- import {createHash} from 'node:crypto'
3
- import {basename} from 'node:path'
4
- import {graphStaleness} from '../mcp/graph-context.mjs'
5
- import {createSyncPayload, createSyncPayloadV3, MAX_SYNC_BODY_BYTES} from '../mcp/sync-payload.mjs'
6
- import {createEvidenceSnapshot} from '../mcp/evidence-snapshot.mjs'
7
- import {graphHomeDir, graphOutDirForRepo} from '../graph/layout.js'
8
- import {registerRepository, repositoryRecord} from '../graph/repo-registry.js'
9
- import {writeCachedArchitectureContract} from '../analysis/architecture-contract.js'
10
- import {collectInstalled} from '../security/installed.js'
11
- import {toolResult} from '../mcp/tool-result.mjs'
12
- import {
13
- commitAdvisoryRefresh, createAdvisoryQueryPlan, DEFAULT_STORE, storeMeta,
14
- } from '../security/advisory-store.js'
15
-
16
- const MAX_GRAPH_FILE_BYTES = 64 * 1024 * 1024
17
-
18
- const repositoryLabel = (repoRoot) => {
19
- const safe = basename(String(repoRoot || '')).normalize('NFKC').replace(/[^a-z0-9._-]+/gi, '-').replace(/^-+|-+$/g, '')
20
- return (safe || 'repo').slice(0, 128)
21
- }
22
-
23
- const identityFor = (repoRoot) => repositoryRecord(repoRoot, graphHomeDir())
24
- || registerRepository({repoPath: repoRoot, graphDir: graphOutDirForRepo(repoRoot), graphHome: graphHomeDir()})
25
-
26
- // Produces the exact source-free wire material locally. It reads no credentials and performs no
27
- // network I/O; the caller owns destination policy, consent, authentication and transport.
28
- export async function createSourceFreeSyncMaterial(graph, {payloadVersion = 3} = {}, ctx = {}) {
29
- if (!graph) throw new Error('No graph loaded — build one first (open_repo / rebuild_graph).')
30
- if (!ctx.graphPath || !ctx.repoRoot) throw new Error('No active repository graph — open_repo first.')
31
- const size = statSync(ctx.graphPath).size
32
- if (size > MAX_GRAPH_FILE_BYTES) throw new Error(`graph.json exceeds the ${MAX_GRAPH_FILE_BYTES / 1024 / 1024} MB local safety limit`)
33
- const raw = JSON.parse(readFileSync(ctx.graphPath, 'utf8'))
34
- let payload
35
- if (Number(payloadVersion) === 2) {
36
- payload = createSyncPayload(raw)
37
- } else {
38
- if (graphStaleness(ctx).stale) throw new Error('Cannot produce synchronized evidence from a stale graph. Run rebuild_graph first.')
39
- payload = createSyncPayloadV3(raw, await createEvidenceSnapshot({repoRoot: ctx.repoRoot, graph: raw}))
40
- }
41
- const body = JSON.stringify(payload)
42
- const bodyBytes = Buffer.byteLength(body)
43
- if (bodyBytes > MAX_SYNC_BODY_BYTES) throw new Error(`source-free payload exceeds the ${MAX_SYNC_BODY_BYTES / 1024} KB safety limit`)
44
- const identity = identityFor(ctx.repoRoot)
45
- return Object.freeze({
46
- payload,
47
- body,
48
- bodyBytes,
49
- bodyHash: createHash('sha256').update(body).digest('hex'),
50
- repoName: repositoryLabel(ctx.repoRoot),
51
- repositoryId: identity.repositoryId,
52
- graphPath: ctx.graphPath,
53
- })
54
- }
55
-
56
- export function activeRepositoryIdentity(ctx = {}) {
57
- if (!ctx.repoRoot || !ctx.graphPath) throw new Error('No active repository graph — open_repo first.')
58
- const identity = identityFor(ctx.repoRoot)
59
- return Object.freeze({repositoryId: identity.repositoryId, repoName: repositoryLabel(ctx.repoRoot), graphPath: ctx.graphPath})
60
- }
61
-
62
- export const cacheArchitectureContract = (graphPath, contract) => writeCachedArchitectureContract(graphPath, contract)
63
-
64
- export function installedPackageCoordinates(repoRoot) {
65
- if (!repoRoot) throw new Error('No repository root is active.')
66
- return collectInstalled(repoRoot).installed
67
- }
68
-
69
- export const advisoryCacheMetadata = (storePath = DEFAULT_STORE) => ({
70
- path: storePath,
71
- ...storeMeta(storePath),
72
- })
73
-
74
- export {commitAdvisoryRefresh, createAdvisoryQueryPlan}
75
- export {toolResult}
package/src/git-exec.js DELETED
@@ -1,67 +0,0 @@
1
- // The single chokepoint for launching git. Every git subprocess in the package routes through here,
2
- // so there is one place that applies `-C <repoRoot>` containment, a credential-stripped child
3
- // environment, a hidden Windows window and a bounded timeout — instead of a dozen near-identical
4
- // spawnSync wrappers scattered across the analysis, graph and MCP layers.
5
- import { spawnSync, spawn } from "node:child_process";
6
- import { childProcessEnv } from "./child-env.js";
7
-
8
- // Synchronous git. Returns the raw spawnSync result ({status, stdout, stderr, error}) so callers keep
9
- // their existing status/stdout/error handling. encoding defaults to "utf8" (pass "buffer" for binary
10
- // stdout); maxBuffer and stdio are forwarded only when provided so Node's defaults are preserved.
11
- export function runGit(repoRoot, args, options = {}) {
12
- const spawnOptions = {
13
- encoding: options.encoding ?? "utf8",
14
- windowsHide: true,
15
- timeout: options.timeout ?? 8000,
16
- env: childProcessEnv(options.env),
17
- };
18
- if (options.maxBuffer != null) spawnOptions.maxBuffer = options.maxBuffer;
19
- if (options.stdio != null) spawnOptions.stdio = options.stdio;
20
- return spawnSync("git", ["-C", repoRoot, ...args], spawnOptions);
21
- }
22
-
23
- // Streaming git for the history collector: byte-bounded stdout, a hard timeout that SIGKILLs the child,
24
- // and a resolved {stdout, stderr, exitCode, truncated}. The caller owns cwd/env so reads can be scoped
25
- // to a specific worktree.
26
- export function boundedGitCommand(command, args, options) {
27
- return new Promise((resolve, reject) => {
28
- const child = spawn(command, args, {
29
- cwd: options.cwd, env: options.env, shell: false, windowsHide: true,
30
- stdio: ["ignore", "pipe", "pipe"],
31
- });
32
- const stdout = [], stderr = [];
33
- let stdoutBytes = 0, stderrBytes = 0, truncated = false, timedOut = false, settled = false;
34
- const finish = (callback) => {
35
- if (settled) return;
36
- settled = true;
37
- clearTimeout(timer);
38
- callback();
39
- };
40
- const stop = () => { try { child.kill("SIGKILL"); } catch { /* process already exited */ } };
41
- const timer = setTimeout(() => { timedOut = true; stop(); }, options.timeoutMs);
42
- child.stdout?.on("data", (chunk) => {
43
- if (truncated) return;
44
- const remaining = options.maxOutputBytes - stdoutBytes;
45
- if (remaining <= 0) { truncated = true; stop(); return; }
46
- const kept = chunk.length <= remaining ? chunk : chunk.subarray(0, remaining);
47
- stdout.push(kept); stdoutBytes += kept.length;
48
- if (kept.length !== chunk.length) { truncated = true; stop(); }
49
- });
50
- child.stderr?.on("data", (chunk) => {
51
- const remaining = 64 * 1024 - stderrBytes;
52
- if (remaining <= 0) return;
53
- const kept = chunk.length <= remaining ? chunk : chunk.subarray(0, remaining);
54
- stderr.push(kept); stderrBytes += kept.length;
55
- });
56
- child.on("error", (error) => finish(() => reject(error)));
57
- child.on("close", (exitCode) => finish(() => {
58
- if (timedOut) return reject(new Error("git history collection timed out"));
59
- resolve({
60
- stdout: Buffer.concat(stdout),
61
- stderr: Buffer.concat(stderr).toString("utf8"),
62
- exitCode: Number(exitCode ?? 1),
63
- truncated,
64
- });
65
- }));
66
- });
67
- }
@@ -1,49 +0,0 @@
1
- // build-worker.js — runs the web-tree-sitter graph build OFF Electron's main thread. In-process the
2
- // parse blocks the main event loop for the whole repo walk (big repos = many seconds), and on Windows
3
- // window input routing lives on the main process — so the ENTIRE app froze during "BUILDING THE
4
- // GRAPH…". The worker builds, filters, writes graph.json and computes the summaries; only the small
5
- // result object crosses back (never the graph itself — structured-cloning a huge graph would stall
6
- // the main thread again).
7
- import { parentPort, workerData } from "node:worker_threads";
8
- import { buildInternalGraph } from "./internal-builder.js";
9
- import { filterGraphForMode, filterGraphByScope, summarizeCommunities, summarizeHotspots } from "./layout.js";
10
- import { atomicWriteFileSync } from "./file-lock.js";
11
- import { snapshotRepository } from "./incremental-refresh.js";
12
- import { buildLspPrecisionOverlay, invalidatePrecisionOverlay, precisionSummary } from "../precision/lsp-overlay.js";
13
-
14
- (async () => {
15
- const { repoPath, mode, scope, precision, graphJson, central } = workerData || {};
16
- try {
17
- let graph = await buildInternalGraph(repoPath);
18
- if (mode === "no-tests" || mode === "tests-only") graph = filterGraphForMode(graph, mode, { repoRoot: repoPath });
19
- if (scope) graph = filterGraphByScope(graph, scope);
20
- graph.graphBuildMode = mode;
21
- graph.graphBuildScope = scope || "";
22
- graph.graphPrecisionMode = precision === "off" ? "off" : "lsp";
23
- atomicWriteFileSync(graphJson, JSON.stringify(graph), "utf8");
24
- let overlay = await buildLspPrecisionOverlay({repoRoot: repoPath, graph, graphPath: graphJson, mode: graph.graphPrecisionMode});
25
- if (graph.graphPrecisionMode === "lsp") {
26
- try {
27
- if (snapshotRepository(repoPath).revision !== graph.graphRevision) {
28
- overlay = invalidatePrecisionOverlay(graphJson, graph);
29
- }
30
- } catch {
31
- overlay = invalidatePrecisionOverlay(
32
- graphJson,
33
- graph,
34
- "repository freshness could not be verified after semantic precision",
35
- );
36
- }
37
- }
38
- parentPort.postMessage({
39
- ok: true,
40
- nodes: graph.nodes.length,
41
- links: graph.links.length,
42
- communities: summarizeCommunities(graphJson),
43
- hotspots: summarizeHotspots(graphJson),
44
- precision: precisionSummary(overlay),
45
- });
46
- } catch (e) {
47
- parentPort.postMessage({ ok: false, error: (e && e.message) || String(e) });
48
- }
49
- })();
@@ -1,112 +0,0 @@
1
- import {goTypeName} from './lang-go.js'
2
-
3
- const dirOf = (file) => file.includes('/') ? file.slice(0, file.lastIndexOf('/')) : ''
4
-
5
- export function createGoReceiverResolution({resolution, nodeById, importedLocals}) {
6
- const {dirSymbols, dirMethods, dirMethodsByName, dirTypes, resolveCall} = resolution
7
- const typeRef = (rawType, contextFile, fallbackDir = dirOf(contextFile)) => {
8
- const raw = String(rawType || '').trim()
9
- if (!raw) return null
10
- const dot = raw.indexOf('.')
11
- if (dot > 0) {
12
- const imported = importedLocals.get(contextFile)?.get(raw.slice(0, dot))
13
- return imported?.targetDir ? {dir: imported.targetDir, name: raw.slice(dot + 1)} : null
14
- }
15
- return {dir: fallbackDir, name: raw}
16
- }
17
- const fieldType = (receiver, fieldName) => {
18
- if (!receiver?.name || !fieldName) return null
19
- const typeId = dirTypes.get(receiver.dir)?.get(receiver.name)
20
- const typeNode = typeId && nodeById.get(typeId)
21
- const rawFieldType = typeNode?.field_types?.[fieldName]
22
- return rawFieldType ? typeRef(rawFieldType, typeNode.source_file, receiver.dir) : null
23
- }
24
- const exactMethod = (receiver, methodName) => {
25
- const candidates = receiver && dirMethods.get(receiver.dir)?.get(receiver.name)?.get(methodName)
26
- return candidates?.length === 1 ? candidates[0] : null
27
- }
28
- const uniqueMethod = (dir, methodName) => {
29
- const candidates = dirMethodsByName.get(dir)?.get(methodName) || []
30
- return candidates.length === 1 ? candidates[0] : null
31
- }
32
- const returnType = (targetId, callerFile) => {
33
- const target = targetId && nodeById.get(targetId)
34
- return target?.return_type
35
- ? typeRef(target.return_type, target.source_file || callerFile, dirOf(target.source_file || callerFile))
36
- : null
37
- }
38
- const fieldChildren = (node, name) => {
39
- const children = node?.childrenForFieldName?.(name)
40
- if (Array.isArray(children) && children.length) return children
41
- const child = node?.childForFieldName?.(name)
42
- return child ? [child] : []
43
- }
44
- const receiverBindings = (selector, file) => {
45
- const bindings = new Map()
46
- let scope = selector
47
- while (scope?.parent && !['function_declaration', 'method_declaration'].includes(scope.type)) scope = scope.parent
48
- if (!scope || !['function_declaration', 'method_declaration'].includes(scope.type)) return bindings
49
- const callRow = selector.startPosition.row
50
- const containsCall = (node) => node.startIndex <= selector.startIndex && node.endIndex >= selector.endIndex
51
- const expressionType = (node) => {
52
- if (!node) return null
53
- const declared = goTypeName(node)
54
- if (declared) return typeRef(declared, file)
55
- if (['parenthesized_expression', 'unary_expression'].includes(node.type)) {
56
- return expressionType(node.childForFieldName?.('operand') || node.namedChildren?.[0])
57
- }
58
- if (node.type === 'composite_literal') return typeRef(goTypeName(node.childForFieldName?.('type')), file)
59
- if (node.type === 'identifier') return bindings.get(node.text) || null
60
- if (node.type === 'selector_expression') return fieldType(expressionType(node.childForFieldName?.('operand')), node.childForFieldName?.('field')?.text)
61
- if (node.type !== 'call_expression') return null
62
- const fn = node.childForFieldName?.('function')
63
- if (fn?.type === 'identifier') {
64
- const returned = returnType(resolveCall(fn.text, file), file)
65
- if (returned) return returned
66
- if (dirTypes.get(dirOf(file))?.has(fn.text)) return typeRef(fn.text, file)
67
- if (/^New[A-Z_]/.test(fn.text)) return typeRef(fn.text.slice(3), file)
68
- }
69
- if (fn?.type === 'selector_expression') {
70
- const operand = fn.childForFieldName?.('operand'), member = fn.childForFieldName?.('field')?.text
71
- const imported = operand?.type === 'identifier' && importedLocals.get(file)?.get(operand.text)
72
- if (imported?.targetDir && member) {
73
- const returned = returnType(dirSymbols.get(imported.targetDir)?.get(member), file)
74
- if (returned) return returned
75
- if (/^New[A-Z_]/.test(member)) return {dir: imported.targetDir, name: member.slice(3)}
76
- }
77
- }
78
- return null
79
- }
80
- const bindTyped = (node) => {
81
- const reference = typeRef(goTypeName(node.childForFieldName?.('type')), file)
82
- const names = fieldChildren(node, 'name').filter((name) => ['identifier', 'field_identifier'].includes(name.type))
83
- if (reference) for (const name of names) bindings.set(name.text, reference)
84
- else if (node.type === 'var_spec') {
85
- const values = node.childForFieldName?.('value')?.namedChildren || []
86
- for (let index = 0; index < Math.min(names.length, values.length); index++) {
87
- const inferred = expressionType(values[index])
88
- if (inferred) bindings.set(names[index].text, inferred)
89
- }
90
- }
91
- }
92
- const bindAssignment = (node) => {
93
- const left = node.childForFieldName?.('left')?.namedChildren || []
94
- const right = node.childForFieldName?.('right')?.namedChildren || []
95
- for (let index = 0; index < Math.min(left.length, right.length); index++) {
96
- if (left[index].type !== 'identifier') continue
97
- const inferred = expressionType(right[index])
98
- if (inferred) bindings.set(left[index].text, inferred)
99
- }
100
- }
101
- const visit = (node) => {
102
- if (!node || node.startPosition.row > callRow) return
103
- if (node !== scope && ['function_declaration', 'method_declaration', 'func_literal'].includes(node.type) && !containsCall(node)) return
104
- if (['parameter_declaration', 'var_spec'].includes(node.type)) bindTyped(node)
105
- else if (['short_var_declaration', 'assignment_statement'].includes(node.type)) bindAssignment(node)
106
- for (const child of node.namedChildren || []) visit(child)
107
- }
108
- visit(scope)
109
- return bindings
110
- }
111
- return {dirOf, fieldType, exactMethod, uniqueMethod, receiverBindings}
112
- }
@@ -1,26 +0,0 @@
1
- // Resolve only the bounded local-file portion of URL-based dynamic imports.
2
- // Runtime substitutions remain uncertain; this candidate exists solely so a
3
- // statically named module is not mislabeled as an orphan.
4
- export function boundedUrlImportTarget(arg, {field, fileRel, resolveJsImport}) {
5
- if (!arg || arg.type !== "member_expression" || field(arg, "property")?.text !== "href") return null;
6
- const created = field(arg, "object");
7
- if (!created || created.type !== "new_expression" || field(created, "constructor")?.text !== "URL") return null;
8
- const urlArgs = field(created, "arguments")?.namedChildren || [];
9
- if (urlArgs.length !== 2 || urlArgs[1].text !== "import.meta.url") return null;
10
-
11
- const source = urlArgs[0];
12
- let rawSpec = "";
13
- if (source.type === "string") {
14
- rawSpec = source.text.replace(/^['"`]|['"`]$/g, "");
15
- } else if (source.type === "template_string") {
16
- const parts = source.namedChildren || [];
17
- if (parts.length !== 2 || parts[0].type !== "string_fragment" || parts[1].type !== "template_substitution") return null;
18
- rawSpec = parts[0].text;
19
- } else return null;
20
-
21
- if (!/^\.\.?\//.test(rawSpec)) return null;
22
- const staticPath = rawSpec.split(/[?#]/)[0];
23
- if (!/\.[cm]?[jt]sx?$/i.test(staticPath)) return null;
24
- const target = resolveJsImport(fileRel, staticPath);
25
- return target ? {rawSpec: staticPath, target} : null;
26
- }
@@ -1,48 +0,0 @@
1
- export const CALLABLE = /arrow_function|function|function_expression|generator_function/
2
-
3
- export const FUNCS = `
4
- (function_declaration name: (identifier) @fn)
5
- (generator_function_declaration name: (identifier) @fn)
6
- (class_declaration name: (_) @class)
7
- (method_definition name: (_) @method)`
8
-
9
- export const TOPVARS = `
10
- (program (lexical_declaration (variable_declarator) @decl))
11
- (program (variable_declaration (variable_declarator) @decl))
12
- (program (export_statement (lexical_declaration (variable_declarator) @decl)))
13
- (program (export_statement (variable_declaration (variable_declarator) @decl)))`
14
-
15
- export const TYPES = `
16
- (interface_declaration name: (_) @interface)
17
- (type_alias_declaration name: (_) @type)
18
- (enum_declaration name: (_) @enum)`
19
-
20
- export const REQUIRE = `(variable_declarator name: (_) @lhs value: (call_expression function: (identifier) @req arguments: (arguments (string (string_fragment) @src))))`
21
-
22
- export function parseExportSpecifiers(raw) {
23
- return String(raw || '').split(',').map((part) => {
24
- const text = part.trim()
25
- const typeOnly = /^type\s+/.test(text)
26
- const clean = text.replace(/^type\s+/, '').trim()
27
- const match = clean.match(/^([A-Za-z_$][\w$]*|default)(?:\s+as\s+([A-Za-z_$][\w$]*|default))?$/)
28
- return match ? {imported: match[1], exported: match[2] || match[1], typeOnly} : null
29
- }).filter(Boolean)
30
- }
31
-
32
- export function importTypeOnly(node) {
33
- if (/^\s*import\s+type\b/.test(node.text)) return true
34
- const clause = node.namedChildren.find((child) => child.type === 'import_clause')
35
- if (!clause) return false
36
- const parts = clause.namedChildren
37
- if (parts.some((child) => child.type === 'identifier' || child.type === 'namespace_import')) return false
38
- const named = parts.find((child) => child.type === 'named_imports')
39
- const specifiers = named?.namedChildren.filter((child) => child.type === 'import_specifier') || []
40
- return specifiers.length > 0 && specifiers.every((specifier) => /^\s*type\b/.test(specifier.text))
41
- }
42
-
43
- export function reexportTypeOnly(node) {
44
- if (/^\s*export\s+type\b/.test(node.text)) return true
45
- const clause = node.namedChildren.find((child) => child.type === 'export_clause')
46
- const specifiers = clause?.namedChildren.filter((child) => child.type === 'export_specifier') || []
47
- return specifiers.length > 0 && specifiers.every((specifier) => /^\s*type\b/.test(specifier.text))
48
- }