weavatrix 0.3.14 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (305) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +231 -199
  3. package/bin/native/darwin-arm64/weavatrix +0 -0
  4. package/bin/native/darwin-x64/weavatrix +0 -0
  5. package/bin/native/linux-arm64/weavatrix +0 -0
  6. package/bin/native/linux-x64/weavatrix +0 -0
  7. package/bin/native/win32-arm64/weavatrix.exe +0 -0
  8. package/bin/native/win32-x64/weavatrix.exe +0 -0
  9. package/bin/resolve-binary.mjs +73 -0
  10. package/bin/run-native.mjs +26 -0
  11. package/bin/weavatrix-mcp.mjs +7 -6
  12. package/bin/weavatrix.mjs +5 -0
  13. package/package.json +8 -66
  14. package/skill/SKILL.md +62 -374
  15. package/skill/agents/openai.yaml +4 -0
  16. package/skill/references/tool-routing.md +45 -0
  17. package/SECURITY.md +0 -101
  18. package/docs/adr/0001-v0.3-offline-online-split.md +0 -60
  19. package/docs/agent-task-benchmark.md +0 -58
  20. package/docs/releases/v0.2.19.md +0 -33
  21. package/docs/releases/v0.3.0.md +0 -43
  22. package/docs/releases/v0.3.1.md +0 -30
  23. package/docs/releases/v0.3.10.md +0 -76
  24. package/docs/releases/v0.3.11.md +0 -55
  25. package/docs/releases/v0.3.12.md +0 -44
  26. package/docs/releases/v0.3.13.md +0 -34
  27. package/docs/releases/v0.3.14.md +0 -37
  28. package/docs/releases/v0.3.2.md +0 -15
  29. package/docs/releases/v0.3.3.md +0 -25
  30. package/docs/releases/v0.3.4.md +0 -40
  31. package/docs/releases/v0.3.5.md +0 -50
  32. package/docs/releases/v0.3.6.md +0 -44
  33. package/docs/releases/v0.3.7.md +0 -37
  34. package/docs/releases/v0.3.8.md +0 -21
  35. package/docs/releases/v0.3.9.md +0 -36
  36. package/scripts/run-agent-task-benchmark.mjs +0 -118
  37. package/src/analysis/allowed-test-runner.js +0 -70
  38. package/src/analysis/architecture/contract-graph.js +0 -119
  39. package/src/analysis/architecture/contract-schema.js +0 -110
  40. package/src/analysis/architecture/contract-storage.js +0 -35
  41. package/src/analysis/architecture/contract-verification.js +0 -168
  42. package/src/analysis/architecture-contract.js +0 -16
  43. package/src/analysis/audit-debt.js +0 -94
  44. package/src/analysis/audit-extensions.js +0 -60
  45. package/src/analysis/cargo-dependency-evidence.js +0 -108
  46. package/src/analysis/cargo-manifests.js +0 -81
  47. package/src/analysis/change-classification/diff-parser.js +0 -103
  48. package/src/analysis/change-classification/options.js +0 -40
  49. package/src/analysis/change-classification/symbol-classifier.js +0 -177
  50. package/src/analysis/change-classification.js +0 -188
  51. package/src/analysis/coverage-reports-tarpaulin.js +0 -112
  52. package/src/analysis/coverage-reports.js +0 -246
  53. package/src/analysis/cycle-route.js +0 -14
  54. package/src/analysis/data-flow-evidence.js +0 -114
  55. package/src/analysis/dead-check.js +0 -300
  56. package/src/analysis/dead-code-review/candidates.js +0 -194
  57. package/src/analysis/dead-code-review/policy.js +0 -23
  58. package/src/analysis/dead-code-review.js +0 -119
  59. package/src/analysis/dep-check-ecosystems.js +0 -205
  60. package/src/analysis/dep-check.js +0 -290
  61. package/src/analysis/dep-rules.js +0 -10
  62. package/src/analysis/dependency/conventions.js +0 -16
  63. package/src/analysis/dependency/scoped-dependencies.js +0 -51
  64. package/src/analysis/dependency/source-references.js +0 -21
  65. package/src/analysis/duplicate-groups.js +0 -104
  66. package/src/analysis/duplicates-worker.js +0 -11
  67. package/src/analysis/duplicates.compute.js +0 -269
  68. package/src/analysis/duplicates.js +0 -15
  69. package/src/analysis/duplicates.run.js +0 -52
  70. package/src/analysis/duplicates.tokenize.js +0 -199
  71. package/src/analysis/endpoints/common.js +0 -79
  72. package/src/analysis/endpoints/extract.js +0 -120
  73. package/src/analysis/endpoints/inventory.js +0 -84
  74. package/src/analysis/endpoints/mounts.js +0 -129
  75. package/src/analysis/endpoints-java.js +0 -260
  76. package/src/analysis/endpoints-rust.js +0 -124
  77. package/src/analysis/endpoints.js +0 -3
  78. package/src/analysis/findings.js +0 -70
  79. package/src/analysis/git-history/analytics.js +0 -177
  80. package/src/analysis/git-history/collector.js +0 -67
  81. package/src/analysis/git-history/options.js +0 -66
  82. package/src/analysis/git-history.js +0 -143
  83. package/src/analysis/git-ref-graph.js +0 -76
  84. package/src/analysis/go-dependency-evidence.js +0 -62
  85. package/src/analysis/graph-analysis.aggregate.js +0 -296
  86. package/src/analysis/graph-analysis.edges.js +0 -24
  87. package/src/analysis/graph-analysis.js +0 -7
  88. package/src/analysis/graph-analysis.refs.js +0 -202
  89. package/src/analysis/graph-analysis.summaries.js +0 -65
  90. package/src/analysis/health-capabilities.js +0 -83
  91. package/src/analysis/hot-path-review.js +0 -266
  92. package/src/analysis/http-contract-wrappers.js +0 -241
  93. package/src/analysis/http-contracts/analysis.js +0 -179
  94. package/src/analysis/http-contracts/client-call-detection.js +0 -82
  95. package/src/analysis/http-contracts/client-call-parser.js +0 -273
  96. package/src/analysis/http-contracts/graph-context.js +0 -143
  97. package/src/analysis/http-contracts/matching.js +0 -61
  98. package/src/analysis/http-contracts/shared.js +0 -85
  99. package/src/analysis/http-contracts.js +0 -6
  100. package/src/analysis/internal-audit/dependency-health.js +0 -113
  101. package/src/analysis/internal-audit/python-manifests.js +0 -78
  102. package/src/analysis/internal-audit/repo-files.js +0 -50
  103. package/src/analysis/internal-audit/supply-chain.js +0 -149
  104. package/src/analysis/internal-audit.collect.js +0 -213
  105. package/src/analysis/internal-audit.js +0 -9
  106. package/src/analysis/internal-audit.reach.js +0 -201
  107. package/src/analysis/internal-audit.run.js +0 -256
  108. package/src/analysis/java-source.js +0 -36
  109. package/src/analysis/jvm-artifact-index.js +0 -87
  110. package/src/analysis/jvm-dependency-evidence.js +0 -138
  111. package/src/analysis/jvm-manifests.js +0 -114
  112. package/src/analysis/manifests.js +0 -123
  113. package/src/analysis/package-reachability.js +0 -39
  114. package/src/analysis/source-complexity.ast.js +0 -97
  115. package/src/analysis/source-complexity.constants.js +0 -55
  116. package/src/analysis/source-complexity.js +0 -14
  117. package/src/analysis/source-complexity.report.js +0 -81
  118. package/src/analysis/source-complexity.walk.js +0 -228
  119. package/src/analysis/source-correctness/retry-patterns.js +0 -93
  120. package/src/analysis/source-correctness.js +0 -222
  121. package/src/analysis/static-test-reachability.js +0 -150
  122. package/src/analysis/structure/dependency-graph.js +0 -151
  123. package/src/analysis/structure/findings.js +0 -162
  124. package/src/analysis/task-retrieval.js +0 -107
  125. package/src/analysis/transport-contracts.js +0 -224
  126. package/src/analysis/transport-runtime-evidence.js +0 -155
  127. package/src/analysis-kit.mjs +0 -17
  128. package/src/bounds.js +0 -4
  129. package/src/build-graph.js +0 -209
  130. package/src/child-env.js +0 -7
  131. package/src/config.js +0 -5
  132. package/src/extension/local-services.mjs +0 -75
  133. package/src/git-exec.js +0 -67
  134. package/src/graph/build-worker.js +0 -49
  135. package/src/graph/builder/go-receiver-resolution.js +0 -112
  136. package/src/graph/builder/js/dynamic-import.js +0 -26
  137. package/src/graph/builder/js/queries.js +0 -48
  138. package/src/graph/builder/lang-csharp.js +0 -40
  139. package/src/graph/builder/lang-css.js +0 -29
  140. package/src/graph/builder/lang-go.js +0 -140
  141. package/src/graph/builder/lang-html.js +0 -29
  142. package/src/graph/builder/lang-java-calls.js +0 -142
  143. package/src/graph/builder/lang-java.js +0 -215
  144. package/src/graph/builder/lang-js.js +0 -291
  145. package/src/graph/builder/lang-python.js +0 -235
  146. package/src/graph/builder/lang-rust-calls.js +0 -63
  147. package/src/graph/builder/lang-rust.js +0 -299
  148. package/src/graph/builder/lang-solidity.js +0 -126
  149. package/src/graph/builder/lang-sql.js +0 -263
  150. package/src/graph/builder/pass2-resolution.js +0 -81
  151. package/src/graph/builder/spec-pkg.js +0 -87
  152. package/src/graph/community.js +0 -27
  153. package/src/graph/edge-provenance.js +0 -31
  154. package/src/graph/file-lock.js +0 -69
  155. package/src/graph/freshness-probe.js +0 -142
  156. package/src/graph/graph-filter.js +0 -63
  157. package/src/graph/incremental-refresh.js +0 -235
  158. package/src/graph/internal-builder.barrels.js +0 -235
  159. package/src/graph/internal-builder.build.js +0 -300
  160. package/src/graph/internal-builder.java.js +0 -33
  161. package/src/graph/internal-builder.js +0 -12
  162. package/src/graph/internal-builder.langs.js +0 -157
  163. package/src/graph/internal-builder.pass2.js +0 -163
  164. package/src/graph/internal-builder.resolvers.js +0 -286
  165. package/src/graph/layout.js +0 -51
  166. package/src/graph/node-id.js +0 -7
  167. package/src/graph/parser-artifact-boundary.js +0 -55
  168. package/src/graph/relations.js +0 -4
  169. package/src/graph/repo-registry.js +0 -124
  170. package/src/graph/resolvers/rust.js +0 -117
  171. package/src/infra/infra-items.js +0 -255
  172. package/src/infra/infra-registry.js +0 -184
  173. package/src/infra/infra.detect.js +0 -119
  174. package/src/infra/infra.js +0 -38
  175. package/src/infra/infra.match.js +0 -102
  176. package/src/infra/infra.scan.js +0 -93
  177. package/src/mcp/actions/graph-lifecycle.mjs +0 -148
  178. package/src/mcp/architecture-bootstrap.mjs +0 -168
  179. package/src/mcp/architecture-starter.mjs +0 -234
  180. package/src/mcp/catalog.mjs +0 -233
  181. package/src/mcp/company-contract-page.mjs +0 -142
  182. package/src/mcp/company-contract-reconcile.mjs +0 -87
  183. package/src/mcp/company-contract-verdict.mjs +0 -42
  184. package/src/mcp/evidence/bun-lock-graph.mjs +0 -209
  185. package/src/mcp/evidence/duplicate-member-order.mjs +0 -8
  186. package/src/mcp/evidence/package-graph-common.mjs +0 -115
  187. package/src/mcp/evidence/package-lock-graph.mjs +0 -92
  188. package/src/mcp/evidence-snapshot.architecture.mjs +0 -80
  189. package/src/mcp/evidence-snapshot.common.mjs +0 -158
  190. package/src/mcp/evidence-snapshot.duplicates.mjs +0 -213
  191. package/src/mcp/evidence-snapshot.health.mjs +0 -102
  192. package/src/mcp/evidence-snapshot.inventory.mjs +0 -148
  193. package/src/mcp/evidence-snapshot.mjs +0 -50
  194. package/src/mcp/evidence-snapshot.package-graph.mjs +0 -34
  195. package/src/mcp/evidence-snapshot.structure.mjs +0 -84
  196. package/src/mcp/extension-api.mjs +0 -77
  197. package/src/mcp/git-output.mjs +0 -7
  198. package/src/mcp/graph/context-core.mjs +0 -111
  199. package/src/mcp/graph/context-seeds.mjs +0 -207
  200. package/src/mcp/graph/context-state.mjs +0 -85
  201. package/src/mcp/graph/reverse-reach.mjs +0 -42
  202. package/src/mcp/graph/tools-core.mjs +0 -143
  203. package/src/mcp/graph/tools-query.mjs +0 -276
  204. package/src/mcp/graph-context.mjs +0 -5
  205. package/src/mcp/graph-diff.mjs +0 -218
  206. package/src/mcp/health/audit-format.mjs +0 -199
  207. package/src/mcp/health/audit.mjs +0 -199
  208. package/src/mcp/health/dead-code.mjs +0 -110
  209. package/src/mcp/health/duplicates.mjs +0 -121
  210. package/src/mcp/health/endpoints.mjs +0 -71
  211. package/src/mcp/health/structure.mjs +0 -220
  212. package/src/mcp/runtime-version.mjs +0 -31
  213. package/src/mcp/server/auto-refresh.mjs +0 -66
  214. package/src/mcp/server/runtime-config.mjs +0 -43
  215. package/src/mcp/server/shutdown.mjs +0 -40
  216. package/src/mcp/staleness-notice.mjs +0 -20
  217. package/src/mcp/sync/evidence-architecture.mjs +0 -54
  218. package/src/mcp/sync/evidence-common.mjs +0 -88
  219. package/src/mcp/sync/evidence-duplicates.mjs +0 -97
  220. package/src/mcp/sync/evidence-health.mjs +0 -56
  221. package/src/mcp/sync/evidence-packages.mjs +0 -95
  222. package/src/mcp/sync/payload-common.mjs +0 -97
  223. package/src/mcp/sync/payload-v2.mjs +0 -54
  224. package/src/mcp/sync/payload-v3.mjs +0 -79
  225. package/src/mcp/sync-evidence.mjs +0 -23
  226. package/src/mcp/sync-payload.mjs +0 -70
  227. package/src/mcp/tool-result.mjs +0 -54
  228. package/src/mcp/tools-actions.mjs +0 -11
  229. package/src/mcp/tools-architecture.mjs +0 -177
  230. package/src/mcp/tools-company.mjs +0 -251
  231. package/src/mcp/tools-context.mjs +0 -222
  232. package/src/mcp/tools-endpoints.mjs +0 -207
  233. package/src/mcp/tools-graph-hubs.mjs +0 -78
  234. package/src/mcp/tools-graph.mjs +0 -17
  235. package/src/mcp/tools-health.mjs +0 -24
  236. package/src/mcp/tools-history.mjs +0 -28
  237. package/src/mcp/tools-impact-change.mjs +0 -220
  238. package/src/mcp/tools-impact-precision.mjs +0 -89
  239. package/src/mcp/tools-impact.mjs +0 -169
  240. package/src/mcp/tools-source.mjs +0 -238
  241. package/src/mcp/tools-verified-change.mjs +0 -200
  242. package/src/mcp-rg.mjs +0 -50
  243. package/src/mcp-runtime.mjs +0 -2
  244. package/src/mcp-server.mjs +0 -298
  245. package/src/mcp-source-tools.mjs +0 -163
  246. package/src/path-classification.js +0 -226
  247. package/src/path-ignore.js +0 -69
  248. package/src/precision/lsp-client/constants.js +0 -12
  249. package/src/precision/lsp-client/environment.js +0 -20
  250. package/src/precision/lsp-client/errors.js +0 -15
  251. package/src/precision/lsp-client/lifecycle.js +0 -114
  252. package/src/precision/lsp-client/message-parser.js +0 -81
  253. package/src/precision/lsp-client/protocol.js +0 -212
  254. package/src/precision/lsp-client/registry.js +0 -59
  255. package/src/precision/lsp-client/repo-uri.js +0 -60
  256. package/src/precision/lsp-client/stdio-client.js +0 -140
  257. package/src/precision/lsp-client.js +0 -10
  258. package/src/precision/lsp-overlay/budget-policy.js +0 -78
  259. package/src/precision/lsp-overlay/build.js +0 -261
  260. package/src/precision/lsp-overlay/contract.js +0 -61
  261. package/src/precision/lsp-overlay/reference-results.js +0 -108
  262. package/src/precision/lsp-overlay/semantic-inputs.js +0 -62
  263. package/src/precision/lsp-overlay/source-session.js +0 -142
  264. package/src/precision/lsp-overlay/store.js +0 -150
  265. package/src/precision/lsp-overlay/target-index.js +0 -152
  266. package/src/precision/lsp-overlay/target-query.js +0 -55
  267. package/src/precision/lsp-overlay.js +0 -11
  268. package/src/precision/symbol-query.js +0 -224
  269. package/src/precision/typescript-lsp-provider.js +0 -12
  270. package/src/precision/typescript-provider/client.js +0 -89
  271. package/src/precision/typescript-provider/discovery.js +0 -124
  272. package/src/precision/typescript-provider/isolated-runtime.js +0 -39
  273. package/src/precision/typescript-provider/project-host.js +0 -254
  274. package/src/precision/typescript-provider/project-safety.js +0 -166
  275. package/src/precision/typescript-provider/reference-usage.js +0 -53
  276. package/src/process.js +0 -95
  277. package/src/repo-path.js +0 -53
  278. package/src/scan/discover.inventory.js +0 -78
  279. package/src/scan/discover.js +0 -5
  280. package/src/scan/discover.list.js +0 -79
  281. package/src/scan/discover.stack.js +0 -227
  282. package/src/scan/search.core.js +0 -24
  283. package/src/scan/search.git.js +0 -102
  284. package/src/scan/search.js +0 -9
  285. package/src/scan/search.node.js +0 -83
  286. package/src/scan/search.preview.js +0 -49
  287. package/src/scan/search.rg.js +0 -145
  288. package/src/security/advisory-store.js +0 -172
  289. package/src/security/installed-jvm-rust.js +0 -46
  290. package/src/security/installed.js +0 -280
  291. package/src/security/malware-file-heuristics.js +0 -121
  292. package/src/security/malware-heuristics.exclusions.js +0 -134
  293. package/src/security/malware-heuristics.js +0 -15
  294. package/src/security/malware-heuristics.roots.js +0 -145
  295. package/src/security/malware-heuristics.scan.js +0 -89
  296. package/src/security/malware-heuristics.sweep.js +0 -122
  297. package/src/security/malware-scoring.js +0 -105
  298. package/src/security/match.js +0 -85
  299. package/src/security/registry-sig.classify.js +0 -137
  300. package/src/security/registry-sig.js +0 -18
  301. package/src/security/registry-sig.rules.js +0 -192
  302. package/src/security/rust-advisory-report.js +0 -60
  303. package/src/security/typosquat.js +0 -81
  304. package/src/util.js +0 -40
  305. package/src/version.js +0 -7
@@ -1,261 +0,0 @@
1
- import {createTypeScriptLspClient} from '../typescript-lsp-provider.js'
2
- import {precisionPrewarmBudget} from './budget-policy.js'
3
- import {baseOverlay} from './contract.js'
4
- import {precisionOverlayMatches} from './contract.js'
5
- import {collectReferenceResults} from './reference-results.js'
6
- import {
7
- PrecisionBudgetError,
8
- PrecisionLimitError,
9
- PrecisionStaleGraphError,
10
- PrecisionStaleSemanticInputsError,
11
- graphJavaScriptUniverse,
12
- precisionSemanticInputs,
13
- publicSemanticSafetyReason,
14
- } from './semantic-inputs.js'
15
- import {
16
- awaitWithBudget,
17
- ensureBudget,
18
- initializeSourceSession,
19
- remaining,
20
- } from './source-session.js'
21
- import {readPrecisionOverlay, writePrecisionOverlay} from './store.js'
22
- import {eligibleTargets, symbolIndex} from './target-index.js'
23
- import {queryPrecisionTarget} from './target-query.js'
24
-
25
- function persist(session, overlay) {
26
- return session.graphPath ? writePrecisionOverlay(session.graphPath, overlay) : overlay
27
- }
28
-
29
- function coverage(session, verifiedEdges = session.links.length) {
30
- return {
31
- candidates: session.eligible.total,
32
- selected: session.targets.length,
33
- queried: session.queried,
34
- references: session.references,
35
- unclassifiedReferences: session.unclassifiedReferences,
36
- verifiedEdges,
37
- truncated: session.truncated,
38
- }
39
- }
40
-
41
- function completedOverlay(session) {
42
- // Coherence guard: COMPLETE must mean every selected target was actually probed.
43
- const underQueried = session.queried < session.targets.length
44
- const state = session.errors || session.truncated || session.unclassifiedReferences || underQueried
45
- ? 'PARTIAL' : 'COMPLETE'
46
- return baseOverlay(session.graph, state, {
47
- request: session.request,
48
- engines: [{
49
- provider: session.client.provider || 'typescript-language-server',
50
- version: session.client.version || null,
51
- typescriptVersion: session.client.typescriptVersion || null,
52
- typescriptSource: session.client.typescriptSource || null,
53
- language: 'typescript/javascript',
54
- capability: 'textDocument/references',
55
- status: state,
56
- configuredPluginsSuppressed: session.semanticInputs.pluginsSuppressed || 0,
57
- repoLocalPluginLoads: false,
58
- }],
59
- semanticInputFingerprint: session.semanticInputs.fingerprint,
60
- pluginPolicy: {
61
- configuredPluginsSuppressed: session.semanticInputs.pluginsSuppressed || 0,
62
- repoLocalPluginLoads: false,
63
- },
64
- coverage: coverage(session),
65
- links: session.links,
66
- referenceEvidence: session.referenceEvidence,
67
- ...(session.collectLocations ? {locations: session.exactLocations} : {}),
68
- noReferenceSymbols: session.noReferenceSymbols,
69
- ...(session.errors ? {reason: `${session.errors} semantic request(s) failed or were refused`}
70
- : session.truncated ? {reason: 'semantic precision stopped at a configured safety limit'}
71
- : session.unclassifiedReferences
72
- ? {reason: 'some exact references could not be classified as runtime or type-only'}
73
- : underQueried
74
- ? {reason: 'semantic precision stopped before probing every selected target'} : {}),
75
- })
76
- }
77
-
78
- function failedOverlay(session, error) {
79
- const stale = error instanceof PrecisionStaleGraphError
80
- const semanticInputsChanged = error instanceof PrecisionStaleSemanticInputsError
81
- const deadlineReached = error instanceof PrecisionBudgetError || remaining(session) <= 0
82
- const state = stale || semanticInputsChanged || deadlineReached ? 'PARTIAL' : 'UNAVAILABLE'
83
- return baseOverlay(session.graph, state, {
84
- request: session.request,
85
- reason: stale
86
- ? 'repository content no longer matched the graph snapshot'
87
- : semanticInputsChanged ? 'TypeScript project inputs changed while semantic precision was running'
88
- : deadlineReached ? 'semantic precision stopped at its global deadline'
89
- : error?.name === 'LspTimeoutError' ? 'bundled TypeScript language server timed out'
90
- : 'bundled TypeScript language server was unavailable',
91
- engines: [{
92
- provider: 'typescript-language-server',
93
- version: null,
94
- language: 'typescript/javascript',
95
- capability: 'textDocument/references',
96
- status: state,
97
- }],
98
- coverage: {
99
- candidates: session.eligible.total,
100
- selected: session.targets.length,
101
- queried: stale || semanticInputsChanged ? 0 : session.queried,
102
- references: stale || semanticInputsChanged ? 0 : session.references,
103
- unclassifiedReferences: stale || semanticInputsChanged ? 0 : session.unclassifiedReferences,
104
- verifiedEdges: 0,
105
- truncated: session.truncated || stale || semanticInputsChanged || deadlineReached,
106
- },
107
- links: [],
108
- noReferenceSymbols: [],
109
- })
110
- }
111
-
112
- function createSession(options) {
113
- const budget = precisionPrewarmBudget(options)
114
- return {
115
- ...options,
116
- expandedPrewarm: budget.expanded,
117
- fullPrewarm: budget.full,
118
- boundedMax: budget.maxSymbols,
119
- boundedReferences: budget.maxReferences,
120
- boundedLinks: budget.maxLinks,
121
- maxOpenDocuments: budget.maxOpenDocuments,
122
- maxOpenBytes: budget.maxOpenBytes,
123
- maxClassificationDocuments: budget.maxClassificationDocuments,
124
- maxClassificationBytes: budget.maxClassificationBytes,
125
- deadline: Date.now() + budget.timeoutMs,
126
- request: {
127
- maxSymbols: budget.maxSymbols,
128
- maxReferences: budget.maxReferences,
129
- maxLinks: budget.maxLinks,
130
- },
131
- links: [],
132
- seen: new Set(),
133
- evidenceSeen: new Set(),
134
- queried: 0,
135
- references: 0,
136
- unclassifiedReferences: 0,
137
- errors: 0,
138
- truncated: false,
139
- noReferenceSymbols: [],
140
- referenceEvidence: [],
141
- exactLocations: [],
142
- collectLocations: Array.isArray(options.targetIds) && options.targetIds.length > 0,
143
- stop: false,
144
- }
145
- }
146
-
147
- export async function buildLspPrecisionOverlay({
148
- repoRoot,
149
- graph,
150
- graphPath,
151
- mode = 'lsp',
152
- maxSymbols,
153
- maxReferences,
154
- maxLinks,
155
- timeoutMs,
156
- prewarmMode,
157
- targetIds,
158
- clientFactory,
159
- } = {}) {
160
- if (!graph || !repoRoot) throw new Error('precision overlay requires repoRoot and graph')
161
- const session = createSession({
162
- repoRoot, graph, graphPath, mode, maxSymbols, maxReferences, maxLinks,
163
- timeoutMs, prewarmMode, targetIds, clientFactory,
164
- })
165
- if (mode === 'off') {
166
- return persist(session, baseOverlay(graph, 'OFF', {
167
- request: session.request,
168
- reason: 'precision disabled by request',
169
- }))
170
- }
171
- session.universe = graphJavaScriptUniverse(graph)
172
- if (!session.universe.files.length) {
173
- return persist(session, baseOverlay(graph, 'UNAVAILABLE', {
174
- request: session.request,
175
- reason: 'semantic precision currently supports JavaScript and TypeScript repositories',
176
- }))
177
- }
178
- session.semanticInputs = precisionSemanticInputs(repoRoot, graph, {deadline: session.deadline})
179
- if (!session.semanticInputs.safe) {
180
- return persist(session, baseOverlay(graph, 'UNAVAILABLE', {
181
- request: session.request,
182
- reason: publicSemanticSafetyReason(session.semanticInputs.reason),
183
- engines: [{
184
- provider: 'typescript-language-server', version: null,
185
- language: 'typescript/javascript', capability: 'textDocument/references',
186
- status: 'UNAVAILABLE',
187
- }],
188
- }))
189
- }
190
- if (graphPath) {
191
- const cached = readPrecisionOverlay(graphPath, graph)
192
- // NONE (no eligible targets) is as stable as COMPLETE for an unchanged fingerprint.
193
- if ((cached?.state === 'COMPLETE' || cached?.state === 'NONE')
194
- && precisionOverlayMatches(cached, graph, {request: session.request})
195
- && cached.semanticInputFingerprint === session.semanticInputs.fingerprint) return cached
196
- }
197
- session.eligible = eligibleTargets(graph, session.boundedMax, targetIds)
198
- session.targets = session.eligible.targets
199
- if (!session.targets.length) {
200
- return persist(session, baseOverlay(graph, 'NONE', {
201
- request: session.request,
202
- semanticInputFingerprint: session.semanticInputs.fingerprint,
203
- pluginPolicy: {
204
- configuredPluginsSuppressed: session.semanticInputs.pluginsSuppressed || 0,
205
- repoLocalPluginLoads: false,
206
- },
207
- reason: 'no eligible JavaScript/TypeScript semantic targets',
208
- }))
209
- }
210
- session.truncated = session.eligible.total > session.boundedMax
211
- session.index = symbolIndex(graph)
212
- session.nodesById = new Map((graph.nodes || []).map((node) => [String(node.id), node]))
213
- initializeSourceSession(session)
214
- try {
215
- const makeClient = clientFactory || createTypeScriptLspClient
216
- session.client = await awaitWithBudget(
217
- session,
218
- () => makeClient({repoRoot, timeoutMs: Math.max(100, remaining(session))}),
219
- )
220
- for (const target of session.targets) {
221
- let locations
222
- try {
223
- locations = await queryPrecisionTarget(session, target)
224
- } catch (error) {
225
- if (error instanceof PrecisionStaleGraphError) throw error
226
- if (error instanceof PrecisionBudgetError || error instanceof PrecisionLimitError
227
- || remaining(session) <= 0) {
228
- session.truncated = true
229
- session.stop = true
230
- break
231
- }
232
- session.errors++
233
- continue
234
- }
235
- collectReferenceResults(session, target, locations)
236
- if (remaining(session) <= 0) {
237
- session.truncated = true
238
- session.stop = true
239
- }
240
- if (session.stop) break
241
- }
242
- ensureBudget(session)
243
- const semanticInputsAfter = precisionSemanticInputs(repoRoot, graph, {deadline: session.deadline})
244
- ensureBudget(session)
245
- if (!semanticInputsAfter.safe
246
- || semanticInputsAfter.fingerprint !== session.semanticInputs.fingerprint) {
247
- throw new PrecisionStaleSemanticInputsError()
248
- }
249
- return persist(session, completedOverlay(session))
250
- } catch (error) {
251
- return persist(session, failedOverlay(session, error))
252
- } finally {
253
- if (session.client) {
254
- const closeBudget = Math.min(2_000, Math.max(0, remaining(session)))
255
- if (closeBudget > 0 && session.client.close) {
256
- try { await awaitWithBudget(session, () => session.client.close(closeBudget)) }
257
- catch { session.client.kill?.() }
258
- } else session.client.kill?.()
259
- }
260
- }
261
- }
@@ -1,61 +0,0 @@
1
- import {typeScriptLspContract} from '../typescript-lsp-provider.js'
2
-
3
- export const PRECISION_OVERLAY_V = 5
4
- export const PRECISION_FILE = 'precision.json'
5
- export const JS_TS_FILE = /\.(?:[cm]?[jt]sx?)$/i
6
- export const endpoint = (value) => String(value && typeof value === 'object' ? value.id : value)
7
- export const norm = (value) => String(value || '').replace(/\\/g, '/').replace(/^\.\//, '')
8
- export const graphMode = (graph) => ['full', 'no-tests', 'tests-only'].includes(graph?.graphBuildMode)
9
- ? graph.graphBuildMode : 'full'
10
- export const graphScope = (graph) => String(graph?.graphBuildScope || '')
11
- export const precisionMode = (graph) => graph?.graphPrecisionMode === 'off' ? 'off' : 'lsp'
12
- export const providerContractFor = (graph) => precisionMode(graph) === 'off' ? 'off' : typeScriptLspContract()
13
- export const graphContractFor = (graph) => ({
14
- extractorSchemaV: Number(graph?.extractorSchemaV) || 0,
15
- ...(graph?.repositoryFreshnessBuilderVersion != null
16
- ? {repositoryFreshnessBuilderVersion: String(graph.repositoryFreshnessBuilderVersion)} : {}),
17
- ...(graph?.graphBuilderVersion != null ? {graphBuilderVersion: String(graph.graphBuilderVersion)} : {}),
18
- ...(graph?.internalBuilderVersion != null ? {internalBuilderVersion: String(graph.internalBuilderVersion)} : {}),
19
- })
20
-
21
- function sameRequest(actual, expected) {
22
- if (!expected) return true
23
- return Number(actual?.maxSymbols) === Number(expected.maxSymbols)
24
- && Number(actual?.maxReferences) === Number(expected.maxReferences)
25
- && Number(actual?.maxLinks) === Number(expected.maxLinks)
26
- }
27
-
28
- export function precisionOverlayMatches(overlay, graph, {request} = {}) {
29
- const actualContract = overlay?.graphContract
30
- return Number(overlay?.precisionOverlayV) === PRECISION_OVERLAY_V
31
- && String(overlay?.baseGraphRevision || '') === String(graph?.graphRevision || '')
32
- && String(overlay?.graphBuildMode || 'full') === graphMode(graph)
33
- && String(overlay?.graphBuildScope || '') === graphScope(graph)
34
- && String(overlay?.precisionMode || '') === precisionMode(graph)
35
- && String(overlay?.providerContract || '') === providerContractFor(graph)
36
- && actualContract != null && typeof actualContract === 'object'
37
- && JSON.stringify(actualContract) === JSON.stringify(graphContractFor(graph))
38
- && sameRequest(overlay?.request, request)
39
- }
40
-
41
- export function baseOverlay(graph, state, extra = {}) {
42
- return {
43
- precisionOverlayV: PRECISION_OVERLAY_V,
44
- baseGraphRevision: String(graph.graphRevision || ''),
45
- graphBuildMode: graphMode(graph),
46
- graphBuildScope: graphScope(graph),
47
- precisionMode: precisionMode(graph),
48
- providerContract: providerContractFor(graph),
49
- graphContract: graphContractFor(graph),
50
- state,
51
- engines: [],
52
- coverage: {
53
- candidates: 0, selected: 0, queried: 0, references: 0,
54
- unclassifiedReferences: 0, verifiedEdges: 0, truncated: false,
55
- },
56
- links: [],
57
- referenceEvidence: [],
58
- noReferenceSymbols: [],
59
- ...extra,
60
- }
61
- }
@@ -1,108 +0,0 @@
1
- import {classifyTypeScriptReferenceUsage} from '../typescript-lsp-provider.js'
2
- import {endpoint, norm} from './contract.js'
3
- import {locationStart, repoFileFromLocation, sourceAt} from './target-index.js'
4
- import {remaining, sourceForClassification} from './source-session.js'
5
-
6
- function moduleDependencyAt(session, source, file, targetFile, exactLine) {
7
- if (source !== file || !targetFile) return null
8
- return (session.graph.links || []).find((link) => endpoint(link.source) === file
9
- && endpoint(link.target) === targetFile
10
- && ['imports', 're_exports'].includes(String(link.relation || ''))
11
- && Number.isInteger(link.line) && link.line === exactLine)
12
- }
13
-
14
- function addUnknownEvidence(session, source, targetId, line, character) {
15
- const key = `${source}\0${targetId}\0${line}\0${character}`
16
- if (session.evidenceSeen.has(key)) return true
17
- if (session.referenceEvidence.length >= session.boundedLinks) {
18
- session.truncated = true
19
- session.stop = true
20
- return false
21
- }
22
- session.evidenceSeen.add(key)
23
- session.unclassifiedReferences++
24
- session.referenceEvidence.push({
25
- source,
26
- target: targetId,
27
- line,
28
- character,
29
- classification: 'unknown',
30
- provider: 'typescript-language-server',
31
- })
32
- return true
33
- }
34
-
35
- function addExactLink(session, targetId, source, location, line, character, usage, moduleDependency) {
36
- const relation = 'references'
37
- const key = `${source}\0${relation}\0${targetId}\0${line}\0${character}`
38
- if (session.seen.has(key)) return true
39
- if (session.links.length >= session.boundedLinks) {
40
- session.truncated = true
41
- session.stop = true
42
- return false
43
- }
44
- session.seen.add(key)
45
- session.links.push({
46
- source,
47
- target: targetId,
48
- relation,
49
- line,
50
- character,
51
- ...(Number.isInteger(location?.range?.end?.line) ? {endLine: location.range.end.line + 1} : {}),
52
- ...(Number.isInteger(location?.range?.end?.character) ? {endCharacter: location.range.end.character} : {}),
53
- provenance: 'EXACT_LSP',
54
- provider: 'typescript-language-server',
55
- ...(usage === 'type' || moduleDependency?.typeOnly === true ? {typeOnly: true} : {}),
56
- ...(usage === 'compile' || moduleDependency?.compileOnly === true ? {compileOnly: true} : {}),
57
- })
58
- return true
59
- }
60
-
61
- export function collectReferenceResults(session, target, locations) {
62
- for (const location of locations) {
63
- if (remaining(session) <= 0 || session.references >= session.boundedReferences) {
64
- session.truncated = true
65
- session.stop = true
66
- break
67
- }
68
- session.references++
69
- const file = repoFileFromLocation(session.repoRoot, location)
70
- const start = locationStart(location)
71
- if (!file || !start || !Number.isInteger(start.line) || !Number.isInteger(start.character)) continue
72
- const source = sourceAt(session.index, file, start)
73
- const targetId = String(target.id)
74
- const exactLine = start.line + 1
75
- const character = start.character
76
- const targetFile = norm(target.source_file)
77
- const moduleDependency = moduleDependencyAt(
78
- session, source, file, targetFile, exactLine,
79
- )
80
- const sourceText = sourceForClassification(session, file)
81
- let usage = sourceText == null
82
- ? 'unknown'
83
- : classifyTypeScriptReferenceUsage(file, sourceText, start)
84
- if (usage === 'unknown' && moduleDependency?.typeOnly === true) usage = 'type'
85
- if (usage === 'unknown' && moduleDependency?.compileOnly === true) usage = 'compile'
86
- if (session.collectLocations) session.exactLocations.push({
87
- file,
88
- source: source || file,
89
- target: targetId,
90
- line: exactLine,
91
- character,
92
- ...(Number.isInteger(location?.range?.end?.line) ? {endLine: location.range.end.line + 1} : {}),
93
- ...(Number.isInteger(location?.range?.end?.character) ? {endCharacter: location.range.end.character} : {}),
94
- classification: usage,
95
- })
96
- if (!source || source === targetId) {
97
- if (usage === 'unknown') session.unclassifiedReferences++
98
- continue
99
- }
100
- if (usage === 'unknown') {
101
- if (!addUnknownEvidence(session, source, targetId, exactLine, character)) break
102
- continue
103
- }
104
- if (!addExactLink(
105
- session, targetId, source, location, exactLine, character, usage, moduleDependency,
106
- )) break
107
- }
108
- }
@@ -1,62 +0,0 @@
1
- import {typeScriptProjectSafety} from '../typescript-lsp-provider.js'
2
- import {JS_TS_FILE, graphMode, graphScope, norm} from './contract.js'
3
-
4
- export class PrecisionBudgetError extends Error {
5
- constructor(message = 'semantic precision deadline reached') {
6
- super(message)
7
- this.name = 'PrecisionBudgetError'
8
- }
9
- }
10
-
11
- export class PrecisionLimitError extends Error {
12
- constructor(message) { super(message); this.name = 'PrecisionLimitError' }
13
- }
14
-
15
- export class PrecisionStaleGraphError extends Error {
16
- constructor() {
17
- super('repository content did not match the graph snapshot')
18
- this.name = 'PrecisionStaleGraphError'
19
- }
20
- }
21
-
22
- export class PrecisionStaleSemanticInputsError extends Error {
23
- constructor() {
24
- super('TypeScript project inputs changed while semantic precision was running')
25
- this.name = 'PrecisionStaleSemanticInputsError'
26
- }
27
- }
28
-
29
- export function graphJavaScriptUniverse(graph) {
30
- const files = [...new Set((graph.nodes || []).filter((node) => {
31
- const id = String(node?.id || '')
32
- const file = norm(node?.source_file || id)
33
- return id === file && JS_TS_FILE.test(file)
34
- }).map((node) => norm(node.source_file || node.id)))].sort()
35
- const hashed = Object.keys(graph.fileHashes || {}).map(norm).filter((file) => JS_TS_FILE.test(file)).sort()
36
- const fileSet = new Set(files)
37
- const complete = graphMode(graph) === 'full' && !graphScope(graph)
38
- && files.length === hashed.length && hashed.every((file) => fileSet.has(file))
39
- return {files, complete}
40
- }
41
-
42
- export function precisionSemanticInputs(repoRoot, graph, options = {}) {
43
- const universe = graphJavaScriptUniverse(graph)
44
- if (!universe.files.length) {
45
- return {safe: false, reason: 'NO_JAVASCRIPT_TYPESCRIPT_INPUTS', fingerprint: null, universe}
46
- }
47
- return {...typeScriptProjectSafety(repoRoot, universe.files, options), universe}
48
- }
49
-
50
- export function precisionSemanticInputsMatch(overlay, repoRoot, graph) {
51
- const current = precisionSemanticInputs(repoRoot, graph)
52
- return current.safe === true
53
- && typeof current.fingerprint === 'string'
54
- && current.fingerprint.length > 0
55
- && String(overlay?.semanticInputFingerprint || '') === current.fingerprint
56
- }
57
-
58
- export function publicSemanticSafetyReason(reason) {
59
- return reason === 'CONFIGURED_TSSERVER_PLUGINS'
60
- ? 'configured TypeScript language-service plugins are not allowed'
61
- : 'TypeScript project configuration could not be verified safely'
62
- }
@@ -1,142 +0,0 @@
1
- import {createHash} from 'node:crypto'
2
- import {readFileSync, statSync} from 'node:fs'
3
- import {createRepoBoundary} from '../../repo-path.js'
4
- import {norm} from './contract.js'
5
- import {
6
- PrecisionBudgetError,
7
- PrecisionLimitError,
8
- PrecisionStaleGraphError,
9
- } from './semantic-inputs.js'
10
-
11
- export function initializeSourceSession(session) {
12
- session.boundary = createRepoBoundary(session.repoRoot)
13
- session.opened = new Set()
14
- session.openedTexts = new Map()
15
- session.classificationTexts = new Map()
16
- session.classificationBytes = 0
17
- session.openedBytes = 0
18
- session.fullUniverseOpened = false
19
- }
20
-
21
- export const remaining = (session) => session.deadline - Date.now()
22
-
23
- export function ensureBudget(session) {
24
- if (remaining(session) <= 0) throw new PrecisionBudgetError()
25
- }
26
-
27
- export function awaitWithBudget(session, operation) {
28
- ensureBudget(session)
29
- const wait = remaining(session)
30
- return new Promise((resolvePromise, rejectPromise) => {
31
- const timer = setTimeout(() => rejectPromise(new PrecisionBudgetError()), wait)
32
- Promise.resolve().then(operation).then(
33
- (value) => { clearTimeout(timer); resolvePromise(value) },
34
- (error) => { clearTimeout(timer); rejectPromise(error) },
35
- )
36
- })
37
- }
38
-
39
- function verifiedSource(session, relPath, maxBytes = 4 * 1024 * 1024) {
40
- const file = norm(relPath)
41
- const expectedHash = session.graph.fileHashes?.[file]
42
- if (!file || !/^[a-f0-9]{64}$/i.test(String(expectedHash || ''))) {
43
- throw new PrecisionStaleGraphError()
44
- }
45
- const resolvedFile = session.boundary.resolve(file)
46
- if (!resolvedFile.ok) throw new PrecisionStaleGraphError()
47
- let size
48
- try { size = statSync(resolvedFile.path).size }
49
- catch { throw new PrecisionStaleGraphError() }
50
- if (size > maxBytes) throw new PrecisionLimitError('precision source-read budget reached')
51
- let body
52
- try { body = readFileSync(resolvedFile.path) }
53
- catch { throw new PrecisionStaleGraphError() }
54
- if (body.byteLength > maxBytes) throw new PrecisionLimitError('precision source-read budget reached')
55
- if (createHash('sha256').update(body).digest('hex') !== expectedHash) {
56
- throw new PrecisionStaleGraphError()
57
- }
58
- return {file, body, bytes: body.byteLength, text: body.toString('utf8')}
59
- }
60
-
61
- export async function ensureOpen(session, relPath) {
62
- const file = norm(relPath)
63
- if (!file || session.opened.has(file)) return
64
- ensureBudget(session)
65
- const maxDocuments = Number(session.maxOpenDocuments) || 96
66
- const maxOpenBytes = Number(session.maxOpenBytes) || 32 * 1024 * 1024
67
- if (session.opened.size >= maxDocuments) {
68
- throw new PrecisionLimitError('precision open-document limit reached')
69
- }
70
- const maxBytes = Math.min(4 * 1024 * 1024, maxOpenBytes - session.openedBytes)
71
- const {bytes, text} = verifiedSource(session, file, maxBytes)
72
- if (bytes > 4 * 1024 * 1024) throw new PrecisionLimitError('precision document exceeds 4 MiB limit')
73
- if (session.openedBytes + bytes > maxOpenBytes) {
74
- throw new PrecisionLimitError('precision source-transfer budget reached')
75
- }
76
- await awaitWithBudget(session, () => session.client.openDocument(file, text))
77
- session.opened.add(file)
78
- session.openedTexts.set(file, text)
79
- session.openedBytes += bytes
80
- }
81
-
82
- export function sourceForClassification(session, relPath) {
83
- const file = norm(relPath)
84
- if (session.openedTexts.has(file)) return session.openedTexts.get(file)
85
- if (session.classificationTexts.has(file)) return session.classificationTexts.get(file)
86
- const maxDocuments = Number(session.maxClassificationDocuments) || 96
87
- const maxClassificationBytes = Number(session.maxClassificationBytes) || 32 * 1024 * 1024
88
- if (session.classificationTexts.size >= maxDocuments) return null
89
- let source
90
- try {
91
- source = verifiedSource(
92
- session,
93
- file,
94
- Math.min(4 * 1024 * 1024, maxClassificationBytes - session.classificationBytes),
95
- )
96
- } catch (error) {
97
- if (error instanceof PrecisionLimitError) return null
98
- throw error
99
- }
100
- session.classificationTexts.set(file, source.text)
101
- session.classificationBytes += source.bytes
102
- return source.text
103
- }
104
-
105
- export async function ensureFullUniverse(session) {
106
- if (session.fullUniverseOpened) return true
107
- if (!session.universe.complete) return false
108
- const additional = session.universe.files.filter((file) => !session.opened.has(file))
109
- const maxDocuments = Number(session.maxOpenDocuments) || 96
110
- const maxOpenBytes = Number(session.maxOpenBytes) || 32 * 1024 * 1024
111
- if (session.opened.size + additional.length > maxDocuments) {
112
- session.truncated = true
113
- return false
114
- }
115
- let projectedBytes = session.openedBytes
116
- for (const file of additional) {
117
- ensureBudget(session)
118
- if (!/^[a-f0-9]{64}$/i.test(String(session.graph.fileHashes?.[file] || ''))) {
119
- throw new PrecisionStaleGraphError()
120
- }
121
- const resolvedFile = session.boundary.resolve(file)
122
- if (!resolvedFile.ok) throw new PrecisionStaleGraphError()
123
- let bytes
124
- try { bytes = statSync(resolvedFile.path).size }
125
- catch { throw new PrecisionStaleGraphError() }
126
- if (bytes > 4 * 1024 * 1024 || projectedBytes + bytes > maxOpenBytes) {
127
- session.truncated = true
128
- return false
129
- }
130
- projectedBytes += bytes
131
- }
132
- for (const file of additional) await ensureOpen(session, file)
133
- session.fullUniverseOpened = session.universe.files.every((file) => session.opened.has(file))
134
- return session.fullUniverseOpened
135
- }
136
-
137
- export function requestReferences(session, relPath, position) {
138
- return awaitWithBudget(
139
- session,
140
- () => session.client.references(relPath, position, false, Math.max(1, remaining(session))),
141
- )
142
- }