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