weavatrix 0.3.13 → 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 (303) 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 -65
  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.2.md +0 -15
  28. package/docs/releases/v0.3.3.md +0 -25
  29. package/docs/releases/v0.3.4.md +0 -40
  30. package/docs/releases/v0.3.5.md +0 -50
  31. package/docs/releases/v0.3.6.md +0 -44
  32. package/docs/releases/v0.3.7.md +0 -37
  33. package/docs/releases/v0.3.8.md +0 -21
  34. package/docs/releases/v0.3.9.md +0 -36
  35. package/scripts/run-agent-task-benchmark.mjs +0 -118
  36. package/src/analysis/allowed-test-runner.js +0 -70
  37. package/src/analysis/architecture/contract-graph.js +0 -119
  38. package/src/analysis/architecture/contract-schema.js +0 -110
  39. package/src/analysis/architecture/contract-storage.js +0 -35
  40. package/src/analysis/architecture/contract-verification.js +0 -168
  41. package/src/analysis/architecture-contract.js +0 -16
  42. package/src/analysis/audit-debt.js +0 -94
  43. package/src/analysis/audit-extensions.js +0 -60
  44. package/src/analysis/cargo-dependency-evidence.js +0 -108
  45. package/src/analysis/cargo-manifests.js +0 -81
  46. package/src/analysis/change-classification/diff-parser.js +0 -103
  47. package/src/analysis/change-classification/options.js +0 -40
  48. package/src/analysis/change-classification/symbol-classifier.js +0 -177
  49. package/src/analysis/change-classification.js +0 -188
  50. package/src/analysis/coverage-reports.js +0 -235
  51. package/src/analysis/cycle-route.js +0 -14
  52. package/src/analysis/data-flow-evidence.js +0 -114
  53. package/src/analysis/dead-check.js +0 -300
  54. package/src/analysis/dead-code-review/candidates.js +0 -194
  55. package/src/analysis/dead-code-review/policy.js +0 -23
  56. package/src/analysis/dead-code-review.js +0 -119
  57. package/src/analysis/dep-check-ecosystems.js +0 -205
  58. package/src/analysis/dep-check.js +0 -290
  59. package/src/analysis/dep-rules.js +0 -10
  60. package/src/analysis/dependency/conventions.js +0 -16
  61. package/src/analysis/dependency/scoped-dependencies.js +0 -51
  62. package/src/analysis/dependency/source-references.js +0 -21
  63. package/src/analysis/duplicate-groups.js +0 -104
  64. package/src/analysis/duplicates-worker.js +0 -11
  65. package/src/analysis/duplicates.compute.js +0 -269
  66. package/src/analysis/duplicates.js +0 -15
  67. package/src/analysis/duplicates.run.js +0 -52
  68. package/src/analysis/duplicates.tokenize.js +0 -199
  69. package/src/analysis/endpoints/common.js +0 -62
  70. package/src/analysis/endpoints/extract.js +0 -107
  71. package/src/analysis/endpoints/inventory.js +0 -84
  72. package/src/analysis/endpoints/mounts.js +0 -129
  73. package/src/analysis/endpoints-java.js +0 -260
  74. package/src/analysis/endpoints-rust.js +0 -124
  75. package/src/analysis/endpoints.js +0 -3
  76. package/src/analysis/findings.js +0 -70
  77. package/src/analysis/git-history/analytics.js +0 -177
  78. package/src/analysis/git-history/collector.js +0 -67
  79. package/src/analysis/git-history/options.js +0 -66
  80. package/src/analysis/git-history.js +0 -143
  81. package/src/analysis/git-ref-graph.js +0 -76
  82. package/src/analysis/go-dependency-evidence.js +0 -62
  83. package/src/analysis/graph-analysis.aggregate.js +0 -295
  84. package/src/analysis/graph-analysis.edges.js +0 -24
  85. package/src/analysis/graph-analysis.js +0 -7
  86. package/src/analysis/graph-analysis.refs.js +0 -154
  87. package/src/analysis/graph-analysis.summaries.js +0 -65
  88. package/src/analysis/health-capabilities.js +0 -83
  89. package/src/analysis/hot-path-review.js +0 -266
  90. package/src/analysis/http-contract-wrappers.js +0 -241
  91. package/src/analysis/http-contracts/analysis.js +0 -179
  92. package/src/analysis/http-contracts/client-call-detection.js +0 -82
  93. package/src/analysis/http-contracts/client-call-parser.js +0 -273
  94. package/src/analysis/http-contracts/graph-context.js +0 -143
  95. package/src/analysis/http-contracts/matching.js +0 -61
  96. package/src/analysis/http-contracts/shared.js +0 -85
  97. package/src/analysis/http-contracts.js +0 -6
  98. package/src/analysis/internal-audit/dependency-health.js +0 -113
  99. package/src/analysis/internal-audit/python-manifests.js +0 -78
  100. package/src/analysis/internal-audit/repo-files.js +0 -50
  101. package/src/analysis/internal-audit/supply-chain.js +0 -149
  102. package/src/analysis/internal-audit.collect.js +0 -213
  103. package/src/analysis/internal-audit.js +0 -9
  104. package/src/analysis/internal-audit.reach.js +0 -173
  105. package/src/analysis/internal-audit.run.js +0 -256
  106. package/src/analysis/java-source.js +0 -36
  107. package/src/analysis/jvm-artifact-index.js +0 -87
  108. package/src/analysis/jvm-dependency-evidence.js +0 -138
  109. package/src/analysis/jvm-manifests.js +0 -114
  110. package/src/analysis/manifests.js +0 -123
  111. package/src/analysis/package-reachability.js +0 -39
  112. package/src/analysis/source-complexity.ast.js +0 -97
  113. package/src/analysis/source-complexity.constants.js +0 -55
  114. package/src/analysis/source-complexity.js +0 -14
  115. package/src/analysis/source-complexity.report.js +0 -81
  116. package/src/analysis/source-complexity.walk.js +0 -228
  117. package/src/analysis/source-correctness/retry-patterns.js +0 -93
  118. package/src/analysis/source-correctness.js +0 -222
  119. package/src/analysis/static-test-reachability.js +0 -150
  120. package/src/analysis/structure/dependency-graph.js +0 -151
  121. package/src/analysis/structure/findings.js +0 -162
  122. package/src/analysis/task-retrieval.js +0 -107
  123. package/src/analysis/transport-contracts.js +0 -224
  124. package/src/analysis/transport-runtime-evidence.js +0 -155
  125. package/src/analysis-kit.mjs +0 -17
  126. package/src/bounds.js +0 -4
  127. package/src/build-graph.js +0 -209
  128. package/src/child-env.js +0 -7
  129. package/src/config.js +0 -5
  130. package/src/extension/local-services.mjs +0 -75
  131. package/src/git-exec.js +0 -67
  132. package/src/graph/build-worker.js +0 -49
  133. package/src/graph/builder/go-receiver-resolution.js +0 -112
  134. package/src/graph/builder/js/dynamic-import.js +0 -26
  135. package/src/graph/builder/js/queries.js +0 -48
  136. package/src/graph/builder/lang-csharp.js +0 -40
  137. package/src/graph/builder/lang-css.js +0 -29
  138. package/src/graph/builder/lang-go.js +0 -140
  139. package/src/graph/builder/lang-html.js +0 -29
  140. package/src/graph/builder/lang-java-calls.js +0 -142
  141. package/src/graph/builder/lang-java.js +0 -215
  142. package/src/graph/builder/lang-js.js +0 -291
  143. package/src/graph/builder/lang-python.js +0 -235
  144. package/src/graph/builder/lang-rust-calls.js +0 -63
  145. package/src/graph/builder/lang-rust.js +0 -299
  146. package/src/graph/builder/lang-solidity.js +0 -126
  147. package/src/graph/builder/lang-sql.js +0 -263
  148. package/src/graph/builder/pass2-resolution.js +0 -81
  149. package/src/graph/builder/spec-pkg.js +0 -87
  150. package/src/graph/community.js +0 -27
  151. package/src/graph/edge-provenance.js +0 -31
  152. package/src/graph/file-lock.js +0 -69
  153. package/src/graph/freshness-probe.js +0 -142
  154. package/src/graph/graph-filter.js +0 -63
  155. package/src/graph/incremental-refresh.js +0 -235
  156. package/src/graph/internal-builder.barrels.js +0 -235
  157. package/src/graph/internal-builder.build.js +0 -300
  158. package/src/graph/internal-builder.java.js +0 -33
  159. package/src/graph/internal-builder.js +0 -12
  160. package/src/graph/internal-builder.langs.js +0 -157
  161. package/src/graph/internal-builder.pass2.js +0 -163
  162. package/src/graph/internal-builder.resolvers.js +0 -286
  163. package/src/graph/layout.js +0 -51
  164. package/src/graph/node-id.js +0 -7
  165. package/src/graph/parser-artifact-boundary.js +0 -55
  166. package/src/graph/relations.js +0 -4
  167. package/src/graph/repo-registry.js +0 -124
  168. package/src/graph/resolvers/rust.js +0 -117
  169. package/src/infra/infra-items.js +0 -255
  170. package/src/infra/infra-registry.js +0 -184
  171. package/src/infra/infra.detect.js +0 -119
  172. package/src/infra/infra.js +0 -38
  173. package/src/infra/infra.match.js +0 -102
  174. package/src/infra/infra.scan.js +0 -93
  175. package/src/mcp/actions/graph-lifecycle.mjs +0 -148
  176. package/src/mcp/architecture-bootstrap.mjs +0 -168
  177. package/src/mcp/architecture-starter.mjs +0 -234
  178. package/src/mcp/catalog.mjs +0 -233
  179. package/src/mcp/company-contract-page.mjs +0 -142
  180. package/src/mcp/company-contract-reconcile.mjs +0 -87
  181. package/src/mcp/company-contract-verdict.mjs +0 -42
  182. package/src/mcp/evidence/bun-lock-graph.mjs +0 -209
  183. package/src/mcp/evidence/duplicate-member-order.mjs +0 -8
  184. package/src/mcp/evidence/package-graph-common.mjs +0 -115
  185. package/src/mcp/evidence/package-lock-graph.mjs +0 -92
  186. package/src/mcp/evidence-snapshot.architecture.mjs +0 -80
  187. package/src/mcp/evidence-snapshot.common.mjs +0 -158
  188. package/src/mcp/evidence-snapshot.duplicates.mjs +0 -213
  189. package/src/mcp/evidence-snapshot.health.mjs +0 -102
  190. package/src/mcp/evidence-snapshot.inventory.mjs +0 -148
  191. package/src/mcp/evidence-snapshot.mjs +0 -50
  192. package/src/mcp/evidence-snapshot.package-graph.mjs +0 -34
  193. package/src/mcp/evidence-snapshot.structure.mjs +0 -84
  194. package/src/mcp/extension-api.mjs +0 -77
  195. package/src/mcp/git-output.mjs +0 -7
  196. package/src/mcp/graph/context-core.mjs +0 -111
  197. package/src/mcp/graph/context-seeds.mjs +0 -207
  198. package/src/mcp/graph/context-state.mjs +0 -85
  199. package/src/mcp/graph/reverse-reach.mjs +0 -42
  200. package/src/mcp/graph/tools-core.mjs +0 -143
  201. package/src/mcp/graph/tools-query.mjs +0 -276
  202. package/src/mcp/graph-context.mjs +0 -5
  203. package/src/mcp/graph-diff.mjs +0 -218
  204. package/src/mcp/health/audit-format.mjs +0 -199
  205. package/src/mcp/health/audit.mjs +0 -174
  206. package/src/mcp/health/dead-code.mjs +0 -110
  207. package/src/mcp/health/duplicates.mjs +0 -85
  208. package/src/mcp/health/endpoints.mjs +0 -71
  209. package/src/mcp/health/structure.mjs +0 -219
  210. package/src/mcp/runtime-version.mjs +0 -31
  211. package/src/mcp/server/auto-refresh.mjs +0 -66
  212. package/src/mcp/server/runtime-config.mjs +0 -43
  213. package/src/mcp/server/shutdown.mjs +0 -40
  214. package/src/mcp/staleness-notice.mjs +0 -20
  215. package/src/mcp/sync/evidence-architecture.mjs +0 -54
  216. package/src/mcp/sync/evidence-common.mjs +0 -88
  217. package/src/mcp/sync/evidence-duplicates.mjs +0 -97
  218. package/src/mcp/sync/evidence-health.mjs +0 -56
  219. package/src/mcp/sync/evidence-packages.mjs +0 -95
  220. package/src/mcp/sync/payload-common.mjs +0 -97
  221. package/src/mcp/sync/payload-v2.mjs +0 -54
  222. package/src/mcp/sync/payload-v3.mjs +0 -79
  223. package/src/mcp/sync-evidence.mjs +0 -23
  224. package/src/mcp/sync-payload.mjs +0 -70
  225. package/src/mcp/tool-result.mjs +0 -54
  226. package/src/mcp/tools-actions.mjs +0 -11
  227. package/src/mcp/tools-architecture.mjs +0 -177
  228. package/src/mcp/tools-company.mjs +0 -251
  229. package/src/mcp/tools-context.mjs +0 -222
  230. package/src/mcp/tools-endpoints.mjs +0 -207
  231. package/src/mcp/tools-graph-hubs.mjs +0 -78
  232. package/src/mcp/tools-graph.mjs +0 -17
  233. package/src/mcp/tools-health.mjs +0 -24
  234. package/src/mcp/tools-history.mjs +0 -28
  235. package/src/mcp/tools-impact-change.mjs +0 -220
  236. package/src/mcp/tools-impact-precision.mjs +0 -89
  237. package/src/mcp/tools-impact.mjs +0 -169
  238. package/src/mcp/tools-source.mjs +0 -238
  239. package/src/mcp/tools-verified-change.mjs +0 -200
  240. package/src/mcp-rg.mjs +0 -50
  241. package/src/mcp-runtime.mjs +0 -2
  242. package/src/mcp-server.mjs +0 -298
  243. package/src/mcp-source-tools.mjs +0 -163
  244. package/src/path-classification.js +0 -220
  245. package/src/path-ignore.js +0 -69
  246. package/src/precision/lsp-client/constants.js +0 -12
  247. package/src/precision/lsp-client/environment.js +0 -20
  248. package/src/precision/lsp-client/errors.js +0 -15
  249. package/src/precision/lsp-client/lifecycle.js +0 -114
  250. package/src/precision/lsp-client/message-parser.js +0 -81
  251. package/src/precision/lsp-client/protocol.js +0 -212
  252. package/src/precision/lsp-client/registry.js +0 -59
  253. package/src/precision/lsp-client/repo-uri.js +0 -60
  254. package/src/precision/lsp-client/stdio-client.js +0 -140
  255. package/src/precision/lsp-client.js +0 -10
  256. package/src/precision/lsp-overlay/budget-policy.js +0 -78
  257. package/src/precision/lsp-overlay/build.js +0 -261
  258. package/src/precision/lsp-overlay/contract.js +0 -61
  259. package/src/precision/lsp-overlay/reference-results.js +0 -108
  260. package/src/precision/lsp-overlay/semantic-inputs.js +0 -62
  261. package/src/precision/lsp-overlay/source-session.js +0 -142
  262. package/src/precision/lsp-overlay/store.js +0 -150
  263. package/src/precision/lsp-overlay/target-index.js +0 -152
  264. package/src/precision/lsp-overlay/target-query.js +0 -55
  265. package/src/precision/lsp-overlay.js +0 -11
  266. package/src/precision/symbol-query.js +0 -224
  267. package/src/precision/typescript-lsp-provider.js +0 -12
  268. package/src/precision/typescript-provider/client.js +0 -89
  269. package/src/precision/typescript-provider/discovery.js +0 -124
  270. package/src/precision/typescript-provider/isolated-runtime.js +0 -39
  271. package/src/precision/typescript-provider/project-host.js +0 -254
  272. package/src/precision/typescript-provider/project-safety.js +0 -166
  273. package/src/precision/typescript-provider/reference-usage.js +0 -53
  274. package/src/process.js +0 -95
  275. package/src/repo-path.js +0 -53
  276. package/src/scan/discover.inventory.js +0 -78
  277. package/src/scan/discover.js +0 -5
  278. package/src/scan/discover.list.js +0 -79
  279. package/src/scan/discover.stack.js +0 -227
  280. package/src/scan/search.core.js +0 -24
  281. package/src/scan/search.git.js +0 -102
  282. package/src/scan/search.js +0 -9
  283. package/src/scan/search.node.js +0 -83
  284. package/src/scan/search.preview.js +0 -49
  285. package/src/scan/search.rg.js +0 -145
  286. package/src/security/advisory-store.js +0 -172
  287. package/src/security/installed-jvm-rust.js +0 -46
  288. package/src/security/installed.js +0 -280
  289. package/src/security/malware-file-heuristics.js +0 -121
  290. package/src/security/malware-heuristics.exclusions.js +0 -134
  291. package/src/security/malware-heuristics.js +0 -15
  292. package/src/security/malware-heuristics.roots.js +0 -145
  293. package/src/security/malware-heuristics.scan.js +0 -89
  294. package/src/security/malware-heuristics.sweep.js +0 -122
  295. package/src/security/malware-scoring.js +0 -105
  296. package/src/security/match.js +0 -85
  297. package/src/security/registry-sig.classify.js +0 -137
  298. package/src/security/registry-sig.js +0 -18
  299. package/src/security/registry-sig.rules.js +0 -192
  300. package/src/security/rust-advisory-report.js +0 -60
  301. package/src/security/typosquat.js +0 -81
  302. package/src/util.js +0 -40
  303. 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
- }