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,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
- }