weavatrix 0.3.13 → 1.0.0

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