@mrclrchtr/supi-code-intelligence 4.10.0 → 6.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 (269) hide show
  1. package/README.md +4 -3
  2. package/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  3. package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  4. package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  5. package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  6. package/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  7. package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  8. package/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  9. package/node_modules/@mrclrchtr/supi-core/package.json +2 -2
  10. package/node_modules/@mrclrchtr/supi-core/src/api.ts +1 -1
  11. package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  12. package/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  13. package/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -6
  14. package/node_modules/@mrclrchtr/supi-core/src/debug.ts +9 -0
  15. package/node_modules/@mrclrchtr/supi-core/src/index.ts +1 -1
  16. package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  17. package/node_modules/@mrclrchtr/supi-lsp/README.md +111 -5
  18. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  19. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  20. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  21. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  22. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  23. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  24. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  25. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +2 -2
  26. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/api.ts +1 -1
  27. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  28. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  29. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -6
  30. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug.ts +9 -0
  31. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +1 -1
  32. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  33. package/node_modules/@mrclrchtr/supi-lsp/package.json +7 -6
  34. package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +22 -1
  35. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +245 -0
  36. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +78 -0
  37. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-collection.ts +171 -0
  38. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-evidence.ts +413 -0
  39. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-host.ts +15 -0
  40. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-publication.ts +214 -0
  41. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-pull.ts +62 -0
  42. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +690 -0
  43. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-request.ts +9 -0
  44. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +97 -16
  45. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-waiters.ts +206 -0
  46. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +448 -298
  47. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-state.ts +70 -0
  48. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-sync.ts +231 -0
  49. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-file-state.ts +25 -0
  50. package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +529 -119
  51. package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +161 -33
  52. package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +12 -3
  53. package/node_modules/@mrclrchtr/supi-lsp/src/config/config.ts +5 -5
  54. package/node_modules/@mrclrchtr/supi-lsp/src/config/defaults.json +1 -1
  55. package/node_modules/@mrclrchtr/supi-lsp/src/config/server-config.ts +3 -0
  56. package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-extends.ts +68 -0
  57. package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-path.ts +8 -0
  58. package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-scope.ts +176 -24
  59. package/node_modules/@mrclrchtr/supi-lsp/src/debug-telemetry.ts +45 -0
  60. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +42 -0
  61. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/workspace-sentinels.ts +46 -10
  62. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +79 -9
  63. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +17 -7
  64. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +350 -26
  65. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +5 -2
  66. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +586 -96
  67. package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-refactor-provider.ts +130 -0
  68. package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +45 -329
  69. package/node_modules/@mrclrchtr/supi-lsp/src/provider/refactor-planning.ts +57 -120
  70. package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-edit-normalizer.ts +320 -0
  71. package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-symbol-mapper.ts +207 -0
  72. package/node_modules/@mrclrchtr/supi-lsp/src/session/readiness.ts +72 -2
  73. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +151 -26
  74. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostic-surface.ts +42 -0
  75. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +92 -0
  76. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +165 -118
  77. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +49 -0
  78. package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +102 -0
  79. package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +17 -7
  80. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  81. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  82. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  83. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  84. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  85. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  86. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  87. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +2 -2
  88. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/api.ts +1 -1
  89. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  90. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  91. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -6
  92. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug.ts +9 -0
  93. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +1 -1
  94. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  95. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/LICENSE +21 -0
  96. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/README.md +258 -0
  97. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/babel.cjs +257 -0
  98. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/jiti.cjs +1 -0
  99. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-cli.mjs +34 -0
  100. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-hooks.mjs +124 -0
  101. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-native.mjs +121 -0
  102. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.d.mts +1 -0
  103. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.mjs +4 -0
  104. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-static.mjs +23 -0
  105. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.cjs +30 -0
  106. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.cts +8 -0
  107. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.mts +8 -0
  108. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.mjs +29 -0
  109. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/types.d.ts +420 -0
  110. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/package.json +146 -0
  111. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +6 -3
  112. package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +0 -9
  113. package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +0 -8
  114. package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +16 -12
  115. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +65 -87
  116. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +47 -95
  117. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-timing.ts +147 -0
  118. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client-lifecycle.ts +39 -0
  119. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client.ts +561 -0
  120. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-message-size.ts +24 -0
  121. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-protocol.ts +452 -0
  122. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +4 -2
  123. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +12 -4
  124. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/exports.ts +4 -2
  125. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/imports.ts +4 -2
  126. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/node-at.ts +5 -3
  127. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +33 -12
  128. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/blocking-test-bootstrap.mjs +34 -0
  129. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/bootstrap.mjs +8 -0
  130. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store-helpers.ts +23 -0
  131. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store.ts +400 -0
  132. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/request-control.ts +48 -0
  133. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-parser-helpers.ts +24 -0
  134. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-query-helpers.ts +43 -0
  135. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime.ts +421 -0
  136. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/service.ts +116 -0
  137. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/worker-main.ts +201 -0
  138. package/package.json +5 -5
  139. package/src/analysis/health/diagnostics.ts +221 -77
  140. package/src/analysis/health/file-scope.ts +184 -0
  141. package/src/analysis/health/recovery.ts +14 -3
  142. package/src/analysis/provider.ts +58 -0
  143. package/src/analysis/readiness.ts +34 -9
  144. package/src/analysis/refactor/apply.ts +45 -1
  145. package/src/analysis/refactor/mutation-authority.ts +143 -0
  146. package/src/analysis/relations/callees.ts +9 -1
  147. package/src/analysis/relations/types.ts +5 -2
  148. package/src/analysis/search/ast-scan-timing.ts +9 -2
  149. package/src/analysis/search/ast-scan.ts +5 -2
  150. package/src/analysis/search/deadline.ts +2 -2
  151. package/src/analysis/search/pattern-analysis.ts +54 -33
  152. package/src/analysis/search/pattern.ts +18 -3
  153. package/src/analysis/target/anchored.ts +20 -11
  154. package/src/analysis/target/file.ts +18 -11
  155. package/src/analysis/target/identity.ts +19 -3
  156. package/src/analysis/target/symbol.ts +36 -15
  157. package/src/api.ts +4 -0
  158. package/src/config.ts +35 -1
  159. package/src/diagnostics/evidence.ts +51 -0
  160. package/src/extension.ts +57 -14
  161. package/src/overview/overview-data.ts +9 -2
  162. package/src/overview/overview.ts +49 -30
  163. package/src/overview/types.ts +2 -0
  164. package/src/session/capability-adapter.ts +12 -3
  165. package/src/session/find-types.ts +2 -2
  166. package/src/session/find-workflow.ts +20 -9
  167. package/src/session/graph/collect.ts +18 -2
  168. package/src/session/graph-workflow.ts +19 -12
  169. package/src/session/health-refresh.ts +175 -0
  170. package/src/session/health-types.ts +43 -15
  171. package/src/session/health-workflow.ts +69 -54
  172. package/src/session/input/workflows.ts +2 -2
  173. package/src/session/inspect/collect.ts +20 -3
  174. package/src/session/inspect-workflow.ts +12 -6
  175. package/src/session/orientation/collect.ts +12 -3
  176. package/src/session/orientation/context-facts.ts +3 -1
  177. package/src/session/orientation/context-sections.ts +20 -7
  178. package/src/session/orientation/gather.ts +17 -11
  179. package/src/session/orientation-types.ts +4 -1
  180. package/src/session/orientation-workflow.ts +23 -10
  181. package/src/session/refactor-plans.ts +2 -0
  182. package/src/session/refactor-workflow.ts +61 -15
  183. package/src/session/session.ts +29 -2
  184. package/src/session/target-workflow.ts +54 -23
  185. package/src/session/workflow-control.ts +7 -3
  186. package/src/substrate/lsp/lifecycle.ts +26 -46
  187. package/src/substrate/lsp/maintenance.ts +284 -28
  188. package/src/substrate/lsp/recovery.ts +11 -5
  189. package/src/substrate/lsp/state.ts +2 -2
  190. package/src/substrate/workspace-provider-host.ts +25 -3
  191. package/src/tool/{find → code_find}/execute.ts +2 -16
  192. package/src/tool/code_find/guidance.ts +8 -0
  193. package/src/tool/{find → code_find}/render.ts +21 -4
  194. package/src/tool/{result/find.ts → code_find/result.ts} +78 -9
  195. package/src/tool/code_find/spec.ts +37 -0
  196. package/src/tool/code_find/tui.ts +41 -0
  197. package/src/tool/code_graph/execute.ts +24 -0
  198. package/src/tool/code_graph/guidance.ts +6 -0
  199. package/src/tool/{graph → code_graph}/markdown.ts +1 -1
  200. package/src/tool/{result/graph.ts → code_graph/result.ts} +111 -3
  201. package/src/tool/code_graph/spec.ts +39 -0
  202. package/src/tool/code_graph/tui.ts +117 -0
  203. package/src/tool/{health → code_health}/execute.ts +2 -13
  204. package/src/tool/code_health/guidance.ts +8 -0
  205. package/src/tool/{health → code_health}/markdown.ts +119 -27
  206. package/src/tool/code_health/refresh-status.ts +105 -0
  207. package/src/tool/{result/health.ts → code_health/result.ts} +80 -3
  208. package/src/tool/code_health/spec.ts +41 -0
  209. package/src/tool/{health → code_health}/tui.ts +95 -98
  210. package/src/tool/{inspect → code_inspect}/execute.ts +2 -16
  211. package/src/tool/code_inspect/guidance.ts +6 -0
  212. package/src/tool/{inspect → code_inspect}/markdown.ts +1 -1
  213. package/src/tool/{result/inspect.ts → code_inspect/result.ts} +143 -2
  214. package/src/tool/code_inspect/spec.ts +25 -0
  215. package/src/tool/code_inspect/tui.ts +44 -0
  216. package/src/tool/code_orientation/execute.ts +25 -0
  217. package/src/tool/code_orientation/guidance.ts +9 -0
  218. package/src/tool/{orientation → code_orientation}/markdown.ts +1 -1
  219. package/src/tool/code_orientation/result.ts +248 -0
  220. package/src/tool/code_orientation/spec.ts +25 -0
  221. package/src/tool/{orientation → code_orientation}/tui.ts +51 -35
  222. package/src/tool/code_refactor_apply/execute.ts +17 -0
  223. package/src/tool/code_refactor_apply/guidance.ts +5 -0
  224. package/src/tool/{refactor-apply/execute.ts → code_refactor_apply/result.ts} +8 -11
  225. package/src/tool/code_refactor_apply/spec.ts +26 -0
  226. package/src/tool/code_refactor_apply/tui.ts +73 -0
  227. package/src/tool/code_refactor_plan/execute.ts +27 -0
  228. package/src/tool/code_refactor_plan/guidance.ts +8 -0
  229. package/src/tool/{refactor-plan/execute.ts → code_refactor_plan/result.ts} +13 -22
  230. package/src/tool/code_refactor_plan/spec.ts +25 -0
  231. package/src/tool/code_refactor_plan/tui.ts +54 -0
  232. package/src/tool/code_resolve/execute.ts +19 -0
  233. package/src/tool/code_resolve/guidance.ts +8 -0
  234. package/src/tool/{resolve → code_resolve}/markdown.ts +1 -1
  235. package/src/tool/{result/resolve.ts → code_resolve/result.ts} +79 -29
  236. package/src/tool/code_resolve/spec.ts +25 -0
  237. package/src/tool/code_resolve/tui.ts +60 -0
  238. package/src/tool/guidance.ts +71 -52
  239. package/src/tool/infra/truncate.ts +40 -0
  240. package/src/tool/infra/workflow-control.ts +8 -0
  241. package/src/tool/{refactor-plan/markdown.ts → refactor-markdown.ts} +4 -7
  242. package/src/tool/register.ts +105 -88
  243. package/src/tool/result/display.ts +107 -0
  244. package/src/tool/result/errors.ts +20 -17
  245. package/src/tool/result/refactor.ts +37 -8
  246. package/src/tool/result/types.ts +20 -0
  247. package/src/tool/schemas.ts +26 -157
  248. package/src/tool/specs.ts +40 -126
  249. package/src/types/execution.ts +18 -5
  250. package/src/types/index.ts +8 -1
  251. package/src/ui/status-command.ts +5 -3
  252. package/src/ui/status-overlay.ts +4 -0
  253. package/src/ui/tui/common.ts +108 -10
  254. package/src/ui/tui/display.ts +48 -0
  255. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime.ts +0 -351
  256. package/src/tool/find/tui.ts +0 -39
  257. package/src/tool/graph/execute.ts +0 -62
  258. package/src/tool/graph/tui.ts +0 -104
  259. package/src/tool/inspect/tui.ts +0 -36
  260. package/src/tool/orientation/execute.ts +0 -62
  261. package/src/tool/refactor-apply/tui.ts +0 -55
  262. package/src/tool/refactor-plan/tui.ts +0 -41
  263. package/src/tool/resolve/execute.ts +0 -36
  264. package/src/tool/resolve/tui.ts +0 -42
  265. package/src/tool/result/orientation.ts +0 -132
  266. /package/src/tool/{find → code_find}/ast-kinds.ts +0 -0
  267. /package/src/tool/{find → code_find}/markdown.ts +0 -0
  268. /package/src/tool/{find → code_find}/modes.ts +0 -0
  269. /package/src/tool/{health → code_health}/semantic-state.ts +0 -0
@@ -0,0 +1,201 @@
1
+ import type { MessagePort } from "node:worker_threads";
2
+ import { isCodeRequestDeadlineError } from "@mrclrchtr/supi-code-runtime/api";
3
+ import type { StructuralTimingEvent } from "../session/structural-timing.ts";
4
+ import { assertStructuralProtocolMessageSize } from "../session/structural-worker-message-size.ts";
5
+ import {
6
+ encodeStructuralResult,
7
+ type ParentToStructuralWorkerMessage,
8
+ STRUCTURAL_WORKER_PROTOCOL_VERSION,
9
+ type StructuralWorkerChunkAckMessage,
10
+ type StructuralWorkerRequestMessage,
11
+ validateStructuralWorkerRequest,
12
+ } from "../session/structural-worker-protocol.ts";
13
+ import type { TreeSitterResult } from "../types.ts";
14
+ import type { StructuralRequestControl } from "./request-control.ts";
15
+ import { TreeSitterRuntime } from "./runtime.ts";
16
+ import { StructuralWorkerService } from "./service.ts";
17
+
18
+ interface WorkerBootstrapData {
19
+ readonly cwd: string;
20
+ readonly generation: number;
21
+ }
22
+
23
+ interface ActiveWorkerRequest {
24
+ readonly message: StructuralWorkerRequestMessage;
25
+ readonly control: StructuralRequestControl;
26
+ readonly abortController: AbortController;
27
+ chunks: Uint8Array[];
28
+ nextSequence: number;
29
+ awaitingAck: boolean;
30
+ outcome: "completed" | "cancelled" | "timeout";
31
+ }
32
+
33
+ /** Start the package-private Structural Worker implementation. */
34
+ // biome-ignore lint/complexity/noExcessiveLinesPerFunction: one Worker loop owns active request and chunk acknowledgement state
35
+ export async function runStructuralWorker(
36
+ parentPort: MessagePort,
37
+ workerData: WorkerBootstrapData,
38
+ ): Promise<void> {
39
+ const runtime = new TreeSitterRuntime(workerData.cwd, (event) => forwardObservation(event));
40
+ const service = new StructuralWorkerService(runtime);
41
+ let active: ActiveWorkerRequest | null = null;
42
+
43
+ const post = (message: unknown) => {
44
+ assertStructuralProtocolMessageSize(message);
45
+ parentPort.postMessage(message);
46
+ };
47
+ const forwardObservation = (observation: StructuralTimingEvent) => {
48
+ if (!active) return;
49
+ post({
50
+ kind: "observation",
51
+ version: STRUCTURAL_WORKER_PROTOCOL_VERSION,
52
+ generation: workerData.generation,
53
+ requestId: active.message.requestId,
54
+ observation,
55
+ });
56
+ };
57
+
58
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: protocol dispatch keeps request, cancel, and acknowledgement validation together
59
+ parentPort.on("message", (message: ParentToStructuralWorkerMessage) => {
60
+ if (message.version !== STRUCTURAL_WORKER_PROTOCOL_VERSION) return;
61
+ if (message.generation !== workerData.generation) return;
62
+ if (message.kind === "cancel") {
63
+ if (active?.message.requestId === message.requestId) active.abortController.abort();
64
+ return;
65
+ }
66
+ if (message.kind === "chunk-ack") {
67
+ if (active?.message.requestId === message.requestId) sendNextChunk(message);
68
+ return;
69
+ }
70
+ if (message.kind !== "request" || active) return;
71
+ const validation = validateStructuralWorkerRequest(message);
72
+ if (validation.kind === "invalid") return;
73
+ void execute(validation.message);
74
+ });
75
+
76
+ try {
77
+ await runtime.ensureGrammarParser("javascript");
78
+ post({
79
+ kind: "ready",
80
+ version: STRUCTURAL_WORKER_PROTOCOL_VERSION,
81
+ generation: workerData.generation,
82
+ });
83
+ } catch (error) {
84
+ post({
85
+ kind: "startup-failure",
86
+ version: STRUCTURAL_WORKER_PROTOCOL_VERSION,
87
+ generation: workerData.generation,
88
+ message: error instanceof Error ? error.message : "Structural Worker startup failed",
89
+ });
90
+ runtime.dispose();
91
+ }
92
+
93
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one terminal boundary classifies every operation result and interruption
94
+ async function execute(message: StructuralWorkerRequestMessage): Promise<void> {
95
+ const abortController = new AbortController();
96
+ const cancellationFlag = new Int32Array(message.cancellationFlag);
97
+ const control: StructuralRequestControl = {
98
+ operationId: message.operationId,
99
+ signal: abortController.signal,
100
+ deadline: message.deadline,
101
+ cancellationFlag,
102
+ };
103
+ active = {
104
+ message,
105
+ control,
106
+ abortController,
107
+ chunks: [],
108
+ nextSequence: 0,
109
+ awaitingAck: false,
110
+ outcome: "completed",
111
+ };
112
+ let result: TreeSitterResult<unknown>;
113
+ try {
114
+ result = await service.execute(message.input, control);
115
+ } catch (error) {
116
+ const timedOut =
117
+ isCodeRequestDeadlineError(error) ||
118
+ (message.deadline !== undefined && Date.now() >= message.deadline);
119
+ const cancelled = abortController.signal.aborted || Atomics.load(cancellationFlag, 0) !== 0;
120
+ active.outcome = timedOut ? "timeout" : cancelled ? "cancelled" : "completed";
121
+ result = {
122
+ kind: "runtime-error",
123
+ message: timedOut
124
+ ? "Structural request deadline exceeded"
125
+ : cancelled
126
+ ? "Structural request cancelled"
127
+ : error instanceof Error
128
+ ? error.message
129
+ : "Structural Worker operation failed",
130
+ };
131
+ }
132
+ if (!active || active.message.requestId !== message.requestId) return;
133
+ try {
134
+ active.chunks = encodeStructuralResult(result);
135
+ } catch (error) {
136
+ active.chunks = encodeStructuralResult({
137
+ kind: "runtime-error",
138
+ message: error instanceof Error ? error.message : "Structural result encoding failed",
139
+ });
140
+ }
141
+ sendChunk();
142
+ }
143
+
144
+ function sendNextChunk(message: StructuralWorkerChunkAckMessage): void {
145
+ if (!active?.awaitingAck || message.sequence !== active.nextSequence - 1) return;
146
+ active.awaitingAck = false;
147
+ if (active.nextSequence >= active.chunks.length) {
148
+ postTerminal();
149
+ return;
150
+ }
151
+ sendChunk();
152
+ }
153
+
154
+ function sendChunk(): void {
155
+ if (!active || active.awaitingAck) return;
156
+ updateInterruptionOutcome(active);
157
+ const sequence = active.nextSequence;
158
+ const payload = active.chunks[sequence];
159
+ if (!payload) {
160
+ postTerminal();
161
+ return;
162
+ }
163
+ active.nextSequence += 1;
164
+ active.awaitingAck = true;
165
+ post({
166
+ kind: "chunk",
167
+ version: STRUCTURAL_WORKER_PROTOCOL_VERSION,
168
+ generation: workerData.generation,
169
+ requestId: active.message.requestId,
170
+ sequence,
171
+ final: active.nextSequence === active.chunks.length,
172
+ encodedBytes: payload.byteLength,
173
+ payload,
174
+ });
175
+ }
176
+
177
+ function postTerminal(): void {
178
+ if (!active) return;
179
+ updateInterruptionOutcome(active);
180
+ post({
181
+ kind: "terminal",
182
+ version: STRUCTURAL_WORKER_PROTOCOL_VERSION,
183
+ generation: workerData.generation,
184
+ requestId: active.message.requestId,
185
+ outcome: active.outcome,
186
+ });
187
+ active = null;
188
+ }
189
+
190
+ function updateInterruptionOutcome(request: ActiveWorkerRequest): void {
191
+ if (request.message.deadline !== undefined && Date.now() >= request.message.deadline) {
192
+ request.outcome = "timeout";
193
+ } else if (
194
+ request.abortController.signal.aborted ||
195
+ (request.control.cancellationFlag !== undefined &&
196
+ Atomics.load(request.control.cancellationFlag, 0) !== 0)
197
+ ) {
198
+ request.outcome = "cancelled";
199
+ }
200
+ }
201
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-code-intelligence",
3
- "version": "4.10.0",
3
+ "version": "6.0.0",
4
4
  "description": "LSP and AST navigation, search, diagnostics, and refactoring",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -35,10 +35,10 @@
35
35
  ],
36
36
  "dependencies": {
37
37
  "yaml": "^2.9.0",
38
- "@mrclrchtr/supi-code-runtime": "4.10.0",
39
- "@mrclrchtr/supi-tree-sitter": "4.10.0",
40
- "@mrclrchtr/supi-lsp": "4.10.0",
41
- "@mrclrchtr/supi-core": "4.10.0"
38
+ "@mrclrchtr/supi-code-runtime": "6.0.0",
39
+ "@mrclrchtr/supi-lsp": "6.0.0",
40
+ "@mrclrchtr/supi-tree-sitter": "6.0.0",
41
+ "@mrclrchtr/supi-core": "6.0.0"
42
42
  },
43
43
  "bundledDependencies": [
44
44
  "@mrclrchtr/supi-code-runtime",
@@ -2,16 +2,29 @@
2
2
  // Extracted from orchestrate.ts.
3
3
 
4
4
  import { existsSync, statSync } from "node:fs";
5
- import { resolve } from "node:path";
5
+ import { relative, resolve } from "node:path";
6
+ import type { CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
6
7
  import { isWithinOrEqual } from "@mrclrchtr/supi-core/api";
7
- import type { Diagnostic, WorkspaceLspRuntime } from "@mrclrchtr/supi-lsp/api";
8
+ import type {
9
+ DiagnosticEvidenceDocument,
10
+ DiagnosticEvidenceSummary,
11
+ WorkspaceDiagnosticReport,
12
+ WorkspaceLspRuntime,
13
+ } from "@mrclrchtr/supi-lsp/api";
14
+ import { mergeDiagnosticEvidence } from "../../diagnostics/evidence.ts";
8
15
  import type {
9
16
  HealthDiagnosticEntry,
10
- HealthDiagnosticMessage,
11
17
  HealthDiagnosticObservation,
12
18
  HealthDiagnosticScope,
13
19
  HealthSection,
14
20
  } from "../../session/health-types.ts";
21
+ import {
22
+ collectScopedFileDiagnostics,
23
+ fileScopeStatus,
24
+ toFileDiagnosticEntries,
25
+ unavailableDiagnostics,
26
+ unavailableFileEvidence,
27
+ } from "./file-scope.ts";
15
28
 
16
29
  // ── Diagnostics ───────────────────────────────────────────────────────
17
30
 
@@ -28,95 +41,119 @@ export function diagnosticScope(scopeFilter: string | null): HealthDiagnosticSco
28
41
 
29
42
  interface CollectDiagnosticsOptions {
30
43
  readonly service: WorkspaceLspRuntime | null;
44
+ /** Runtime used for evidence snapshots when semantic operations are unavailable. */
45
+ readonly evidenceService?: WorkspaceLspRuntime | null;
31
46
  readonly included: readonly HealthSection[];
32
47
  readonly scope: HealthDiagnosticScope;
33
48
  readonly cwd: string;
34
49
  readonly unavailableReason: string;
35
50
  /** Collect individual messages per file (detailed level). */
36
51
  readonly detailed?: boolean;
52
+ readonly requestControl?: CodeRequestControl;
53
+ /** Evidence from an explicit workspace refresh, when one ran. */
54
+ readonly refreshEvidence?: DiagnosticEvidenceSummary;
55
+ /** Coherent final report from an explicit workspace refresh, when one ran. */
56
+ readonly refreshReport?: WorkspaceDiagnosticReport;
37
57
  }
38
58
 
39
59
  /** Collect diagnostics without widening the requested evidence scope. */
40
60
  export async function collectDiagnostics(
41
61
  options: CollectDiagnosticsOptions,
42
62
  ): Promise<HealthDiagnosticObservation> {
43
- const { service, included, scope, cwd, unavailableReason, detailed } = options;
63
+ const { service, included, scope, cwd, unavailableReason, detailed, requestControl } = options;
44
64
  if (!included.includes("diagnostics")) return { kind: "not-requested", entries: [] };
45
- if (!service) return unavailableDiagnostics(scope, unavailableReason);
65
+ if (!service) {
66
+ return unavailableDiagnostics(
67
+ scope,
68
+ unavailableReason,
69
+ unavailableScopeEvidence({
70
+ scope,
71
+ refreshEvidence: options.refreshEvidence,
72
+ refreshReport: options.refreshReport,
73
+ evidenceService: options.evidenceService,
74
+ cwd,
75
+ }),
76
+ scope.kind === "file" ? fileScopeStatus(scope.path, cwd) : undefined,
77
+ );
78
+ }
46
79
 
47
80
  return scope.kind === "file"
48
- ? collectScopedFileDiagnostics(service, scope, detailed)
49
- : collectTrackedFileDiagnostics(service, scope, cwd, detailed);
81
+ ? collectScopedFileDiagnostics({ service, scope, cwd, detailed, requestControl })
82
+ : collectTrackedFileDiagnostics({
83
+ service,
84
+ scope,
85
+ cwd,
86
+ detailed,
87
+ refreshEvidence: options.refreshEvidence,
88
+ refreshReport: options.refreshReport,
89
+ });
50
90
  }
51
91
 
52
- async function collectScopedFileDiagnostics(
53
- service: WorkspaceLspRuntime,
54
- scope: Extract<HealthDiagnosticScope, { kind: "file" }>,
55
- detailed?: boolean,
56
- ): Promise<HealthDiagnosticObservation> {
57
- try {
58
- const result = await service.fileDiagnostics(scope.path, 4);
59
- if (result.kind === "unavailable") return unavailableDiagnostics(scope, result.reason);
60
-
61
- const entries = toFileDiagnosticEntries(scope.path, result.data, detailed);
62
- return result.kind === "partial"
63
- ? { kind: "partial", scope, entries, reason: result.reason }
64
- : { kind: "completed", scope, entries };
65
- } catch (error) {
66
- return unavailableDiagnostics(scope, errorMessage(error, "File diagnostic request failed."));
67
- }
92
+ interface TrackedFileDiagnosticOptions {
93
+ readonly service: WorkspaceLspRuntime;
94
+ readonly scope: Extract<HealthDiagnosticScope, { kind: "tracked-files" }>;
95
+ readonly cwd: string;
96
+ readonly detailed?: boolean;
97
+ readonly refreshEvidence?: DiagnosticEvidenceSummary;
98
+ readonly refreshReport?: WorkspaceDiagnosticReport;
68
99
  }
69
100
 
70
101
  function collectTrackedFileDiagnostics(
71
- service: WorkspaceLspRuntime,
72
- scope: Extract<HealthDiagnosticScope, { kind: "tracked-files" }>,
73
- cwd: string,
74
- detailed?: boolean,
102
+ options: TrackedFileDiagnosticOptions,
75
103
  ): HealthDiagnosticObservation {
104
+ const { service, scope, cwd, detailed, refreshEvidence, refreshReport } = options;
76
105
  try {
77
- const entries = detailed
78
- ? collectWorkspaceDiagnosticsDetailed(service, scope.filter, cwd)
79
- : collectWorkspaceDiagnostics(service, scope.filter, cwd);
80
- return { kind: "completed", scope, entries };
106
+ const snapshot = detailed
107
+ ? collectWorkspaceDiagnosticsDetailed(service, scope.filter, cwd, refreshReport)
108
+ : collectWorkspaceDiagnostics(service, scope.filter, cwd, refreshReport);
109
+ const sourceEvidence = refreshReport
110
+ ? snapshot.evidence
111
+ : mergeEvidence(refreshEvidence, snapshot.evidence, cwd);
112
+ const scopedEvidence = selectTrackedFileEvidence(sourceEvidence, scope.filter, cwd);
113
+ const evidence = ensureEvidenceCoversEntries(scopedEvidence, snapshot.entries, cwd);
114
+ return evidenceIsComplete(evidence, snapshot.entries.length > 0, snapshot.current)
115
+ ? { kind: "completed", scope, entries: snapshot.entries, evidence }
116
+ : {
117
+ kind: "partial",
118
+ scope,
119
+ entries: snapshot.entries,
120
+ evidence,
121
+ reason: diagnosticEvidenceReason(evidence),
122
+ };
81
123
  } catch (error) {
124
+ const evidenceSource = options.refreshReport?.summary.evidence ?? options.refreshEvidence;
125
+ const evidence = evidenceSource
126
+ ? selectTrackedFileEvidence(evidenceSource, scope.filter, cwd)
127
+ : emptyEvidence();
82
128
  return unavailableDiagnostics(
83
129
  scope,
84
130
  errorMessage(error, "Tracked-file diagnostic snapshot is unavailable."),
131
+ evidence,
85
132
  );
86
133
  }
87
134
  }
88
135
 
89
- function toFileDiagnosticEntries(
90
- file: string,
91
- diagnostics: ReadonlyArray<Pick<Diagnostic, "severity" | "message" | "source" | "range">>,
92
- detailed?: boolean,
93
- ): HealthDiagnosticEntry[] {
94
- const errors = diagnostics.filter((diagnostic) => (diagnostic.severity ?? 1) === 1).length;
95
- const warnings = diagnostics.filter((diagnostic) => (diagnostic.severity ?? 1) === 2).length;
96
- if (!hasIssueCounts(errors, warnings)) return [];
97
- const entry: HealthDiagnosticEntry = { file, errors, warnings };
98
- if (detailed) {
99
- return [{ ...entry, messages: extractMessages(diagnostics) }];
100
- }
101
- return [entry];
102
- }
103
-
104
136
  function collectWorkspaceDiagnostics(
105
137
  service: WorkspaceLspRuntime,
106
138
  scopeFilter: string | null,
107
139
  cwd: string,
108
- ): HealthDiagnosticEntry[] {
109
- const summary = service.getWorkspaceDiagnosticSummary();
140
+ report?: WorkspaceDiagnosticReport,
141
+ ): {
142
+ entries: HealthDiagnosticEntry[];
143
+ current: boolean;
144
+ evidence: DiagnosticEvidenceSummary;
145
+ } {
146
+ const summary = report?.summary ?? service.getWorkspaceDiagnosticSummary();
110
147
  const result: HealthDiagnosticEntry[] = [];
111
148
 
112
- for (const entry of summary) {
149
+ for (const entry of summary.entries) {
113
150
  const filePath = resolve(cwd, entry.file);
114
151
  if (scopeFilter && !isWithinOrEqual(scopeFilter, filePath)) continue;
115
152
  if (!hasIssueCounts(entry.errors, entry.warnings)) continue;
116
153
  result.push({ file: filePath, errors: entry.errors, warnings: entry.warnings });
117
154
  }
118
155
 
119
- return result;
156
+ return { entries: result, current: summary.current, evidence: summary.evidence };
120
157
  }
121
158
 
122
159
  /** Detailed workspace path: full diagnostics with messages, capped per file. */
@@ -124,46 +161,64 @@ function collectWorkspaceDiagnosticsDetailed(
124
161
  service: WorkspaceLspRuntime,
125
162
  scopeFilter: string | null,
126
163
  cwd: string,
127
- ): HealthDiagnosticEntry[] {
128
- const outstanding = service.getOutstandingDiagnostics(2);
164
+ report?: WorkspaceDiagnosticReport,
165
+ ): {
166
+ entries: HealthDiagnosticEntry[];
167
+ current: boolean;
168
+ evidence: DiagnosticEvidenceSummary;
169
+ } {
170
+ const outstanding = report?.outstanding ?? service.getOutstandingDiagnostics(2);
129
171
  const result: HealthDiagnosticEntry[] = [];
130
172
 
131
- for (const { file, diagnostics } of outstanding) {
173
+ for (const { file, diagnostics } of outstanding.entries) {
132
174
  const filePath = resolve(cwd, file);
133
175
  if (scopeFilter && !isWithinOrEqual(scopeFilter, filePath)) continue;
134
176
  const entries = toFileDiagnosticEntries(filePath, diagnostics, true);
135
177
  result.push(...entries);
136
178
  }
137
179
 
138
- return result;
180
+ return { entries: result, current: outstanding.current, evidence: outstanding.evidence };
139
181
  }
140
182
 
141
- // ── Message extraction ────────────────────────────────────────────────
142
-
143
- const MAX_MESSAGES_PER_FILE = 3;
144
-
145
- function extractMessages(
146
- diagnostics: ReadonlyArray<Pick<Diagnostic, "severity" | "message" | "source" | "range">>,
147
- ): HealthDiagnosticMessage[] {
148
- const errorsAndWarnings = diagnostics
149
- .filter((d) => (d.severity ?? 1) <= 2)
150
- .sort(
151
- (a, b) => (a.severity ?? 1) - (b.severity ?? 1) || a.range.start.line - b.range.start.line,
152
- );
183
+ interface UnavailableScopeEvidenceOptions {
184
+ readonly scope: HealthDiagnosticScope;
185
+ readonly refreshEvidence?: DiagnosticEvidenceSummary;
186
+ readonly refreshReport?: WorkspaceDiagnosticReport;
187
+ readonly evidenceService?: WorkspaceLspRuntime | null;
188
+ readonly cwd: string;
189
+ }
153
190
 
154
- return errorsAndWarnings.slice(0, MAX_MESSAGES_PER_FILE).map((d) => ({
155
- line: d.range.start.line + 1,
156
- severity: (d.severity ?? 1) === 1 ? ("error" as const) : ("warning" as const),
157
- message: typeof d.message === "string" ? d.message : d.message.value,
158
- ...(d.source ? { source: d.source } : {}),
159
- }));
191
+ function unavailableScopeEvidence(
192
+ options: UnavailableScopeEvidenceOptions,
193
+ ): DiagnosticEvidenceSummary {
194
+ const { scope, refreshEvidence, refreshReport, evidenceService, cwd } = options;
195
+ const runtimeEvidence = refreshReport?.summary.evidence ?? readRuntimeEvidence(evidenceService);
196
+ const knownEvidence = refreshReport
197
+ ? runtimeEvidence
198
+ : refreshEvidence
199
+ ? mergeDiagnosticEvidence(refreshEvidence, runtimeEvidence, cwd, "conservative")
200
+ : runtimeEvidence;
201
+ if (knownEvidence.requested === 0 && knownEvidence.documents.length === 0) {
202
+ return scope.kind === "file" ? unavailableFileEvidence(scope.path) : emptyEvidence();
203
+ }
204
+ const scoped = selectTrackedFileEvidence(
205
+ knownEvidence,
206
+ scope.kind === "file" ? scope.path : scope.filter,
207
+ cwd,
208
+ );
209
+ if (scoped.requested > 0) return scoped;
210
+ return scope.kind === "file" ? unavailableFileEvidence(scope.path) : scoped;
160
211
  }
161
212
 
162
- function unavailableDiagnostics(
163
- scope: HealthDiagnosticScope,
164
- reason: string,
165
- ): HealthDiagnosticObservation {
166
- return { kind: "unavailable", scope, entries: [], reason };
213
+ function readRuntimeEvidence(
214
+ service: WorkspaceLspRuntime | null | undefined,
215
+ ): DiagnosticEvidenceSummary {
216
+ if (!service) return emptyEvidence();
217
+ try {
218
+ return service.getWorkspaceDiagnosticSummary().evidence;
219
+ } catch {
220
+ return emptyEvidence();
221
+ }
167
222
  }
168
223
 
169
224
  function errorMessage(error: unknown, fallback: string): string {
@@ -174,6 +229,95 @@ function hasIssueCounts(errors: number, warnings: number): boolean {
174
229
  return errors > 0 || warnings > 0;
175
230
  }
176
231
 
232
+ function emptyEvidence(): DiagnosticEvidenceSummary {
233
+ return {
234
+ requested: 0,
235
+ confirmed: 0,
236
+ unconfirmed: 0,
237
+ failed: 0,
238
+ removed: 0,
239
+ documents: [],
240
+ };
241
+ }
242
+
243
+ function mergeEvidence(
244
+ refreshEvidence: DiagnosticEvidenceSummary | undefined,
245
+ snapshotEvidence: DiagnosticEvidenceSummary,
246
+ cwd: string,
247
+ ): DiagnosticEvidenceSummary {
248
+ return refreshEvidence
249
+ ? mergeDiagnosticEvidence(refreshEvidence, snapshotEvidence, cwd, "conservative")
250
+ : snapshotEvidence;
251
+ }
252
+
253
+ function selectTrackedFileEvidence(
254
+ evidence: DiagnosticEvidenceSummary,
255
+ scopeFilter: string | null,
256
+ cwd: string,
257
+ ): DiagnosticEvidenceSummary {
258
+ if (evidence.documents.length === 0) return evidence;
259
+
260
+ const documents = evidence.documents.filter((document) => {
261
+ if (scopeFilter === null) return true;
262
+ return isWithinOrEqual(scopeFilter, resolve(cwd, document.file));
263
+ });
264
+ return summarizeEvidence(documents);
265
+ }
266
+
267
+ function ensureEvidenceCoversEntries(
268
+ evidence: DiagnosticEvidenceSummary,
269
+ entries: readonly HealthDiagnosticEntry[],
270
+ cwd: string,
271
+ ): DiagnosticEvidenceSummary {
272
+ if (entries.length === 0) return evidence;
273
+ const documents = [...evidence.documents];
274
+ const knownFiles = new Set(documents.map((document) => resolve(cwd, document.file)));
275
+ for (const entry of entries) {
276
+ const file = resolve(cwd, entry.file);
277
+ if (knownFiles.has(file)) continue;
278
+ knownFiles.add(file);
279
+ documents.push({ file: relative(cwd, file), status: "unconfirmed" });
280
+ }
281
+ return summarizeEvidence(documents);
282
+ }
283
+
284
+ function summarizeEvidence(
285
+ documents: readonly DiagnosticEvidenceDocument[],
286
+ ): DiagnosticEvidenceSummary {
287
+ const counts = {
288
+ requested: documents.length,
289
+ confirmed: 0,
290
+ unconfirmed: 0,
291
+ failed: 0,
292
+ removed: 0,
293
+ };
294
+ for (const document of documents) counts[document.status]++;
295
+ return { ...counts, documents: [...documents] };
296
+ }
297
+
298
+ function evidenceIsComplete(
299
+ evidence: DiagnosticEvidenceSummary,
300
+ hasDiagnosticEntries: boolean,
301
+ snapshotCurrent: boolean,
302
+ ): boolean {
303
+ if (!snapshotCurrent && evidence.requested === 0) return false;
304
+ if (evidence.requested === 0) return !hasDiagnosticEntries;
305
+ return (
306
+ evidence.confirmed + evidence.removed === evidence.requested &&
307
+ evidence.unconfirmed === 0 &&
308
+ evidence.failed === 0
309
+ );
310
+ }
311
+
312
+ function diagnosticEvidenceReason(evidence: DiagnosticEvidenceSummary): string {
313
+ let reason = `Diagnostic evidence is partial: ${evidence.requested} requested, ${evidence.confirmed} confirmed, ${evidence.unconfirmed} unconfirmed, ${evidence.failed} failed, ${evidence.removed} removed.`;
314
+ if (evidence.unconfirmed > 0) {
315
+ reason +=
316
+ " Unconfirmed documents await a later diagnostic republish before their evidence can be confirmed (ADR 0021).";
317
+ }
318
+ return reason;
319
+ }
320
+
177
321
  export function isDirectory(filePath: string): boolean {
178
322
  try {
179
323
  return statSync(filePath).isDirectory();