@mrclrchtr/supi-code-intelligence 1.16.1 → 2.0.1

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 (344) hide show
  1. package/README.md +373 -63
  2. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +6 -1
  3. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
  4. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
  5. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
  6. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
  7. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
  8. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
  9. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
  10. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
  11. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
  12. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
  13. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
  14. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
  15. package/node_modules/@mrclrchtr/supi-code-runtime/package.json +3 -2
  16. package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +7 -0
  17. package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +56 -2
  18. package/node_modules/@mrclrchtr/supi-code-runtime/src/evidence-badge.ts +40 -0
  19. package/node_modules/@mrclrchtr/supi-code-runtime/src/index.ts +5 -0
  20. package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +76 -3
  21. package/node_modules/@mrclrchtr/supi-code-runtime/src/workspace/runtime.ts +37 -2
  22. package/node_modules/@mrclrchtr/supi-core/package.json +6 -1
  23. package/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
  24. package/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
  25. package/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
  26. package/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
  27. package/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
  28. package/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
  29. package/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
  30. package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
  31. package/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
  32. package/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
  33. package/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
  34. package/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
  35. package/node_modules/@mrclrchtr/supi-lsp/README.md +44 -56
  36. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +6 -1
  37. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
  38. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
  39. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
  40. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
  41. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
  42. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
  43. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
  44. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
  45. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
  46. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
  47. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
  48. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
  49. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +3 -2
  50. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +7 -0
  51. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +56 -2
  52. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/evidence-badge.ts +40 -0
  53. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/index.ts +5 -0
  54. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +76 -3
  55. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/workspace/runtime.ts +37 -2
  56. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +6 -1
  57. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
  58. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
  59. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
  60. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
  61. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
  62. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
  63. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
  64. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
  65. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
  66. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
  67. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
  68. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
  69. package/node_modules/@mrclrchtr/supi-lsp/package.json +4 -31
  70. package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +27 -0
  71. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-refresh.ts +5 -0
  72. package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +246 -1
  73. package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +4 -0
  74. package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +3 -0
  75. package/node_modules/@mrclrchtr/supi-lsp/src/config/config.ts +4 -2
  76. package/node_modules/@mrclrchtr/supi-lsp/src/config/lsp-settings.ts +102 -0
  77. package/node_modules/@mrclrchtr/supi-lsp/src/config/server-actions.ts +59 -0
  78. package/node_modules/@mrclrchtr/supi-lsp/src/config/server-config.ts +4 -0
  79. package/node_modules/@mrclrchtr/supi-lsp/src/index.ts +11 -0
  80. package/node_modules/@mrclrchtr/supi-lsp/src/manager/capability-index.ts +1 -1
  81. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +2 -1
  82. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +115 -26
  83. package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +177 -134
  84. package/node_modules/@mrclrchtr/supi-lsp/src/provider/refactor-planning.ts +214 -0
  85. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +320 -0
  86. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registration.ts +26 -5
  87. package/node_modules/@mrclrchtr/supi-lsp/src/session/service-registry.ts +81 -4
  88. package/node_modules/@mrclrchtr/supi-lsp/src/summary.ts +2 -0
  89. package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +18 -37
  90. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +6 -1
  91. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
  92. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
  93. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
  94. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
  95. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
  96. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
  97. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
  98. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
  99. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
  100. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
  101. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
  102. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
  103. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +3 -2
  104. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +7 -0
  105. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +56 -2
  106. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/evidence-badge.ts +40 -0
  107. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/index.ts +5 -0
  108. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +76 -3
  109. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/workspace/runtime.ts +37 -2
  110. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +6 -1
  111. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/abort-utils.ts +31 -0
  112. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/api.ts +8 -0
  113. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +10 -4
  114. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +1 -0
  115. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +1 -1
  116. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +6 -0
  117. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/model-selection.ts +134 -0
  118. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +9 -2
  119. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +109 -4
  120. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +5 -1
  121. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/spinner-frames.ts +11 -0
  122. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/status-spinner.ts +68 -0
  123. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/LICENSE +21 -0
  124. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/README.md +265 -0
  125. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs +4661 -0
  126. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs.map +7 -0
  127. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js +4605 -0
  128. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js.map +7 -0
  129. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm +0 -0
  130. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm.map +57 -0
  131. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/package.json +100 -0
  132. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs +4063 -0
  133. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs.map +7 -0
  134. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts +1025 -0
  135. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts.map +58 -0
  136. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts +1025 -0
  137. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts.map +58 -0
  138. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js +4007 -0
  139. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js.map +7 -0
  140. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm +0 -0
  141. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm.map +55 -0
  142. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +6 -12
  143. package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +29 -0
  144. package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +28 -0
  145. package/node_modules/@mrclrchtr/supi-tree-sitter/src/language.ts +5 -0
  146. package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +14 -2
  147. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +157 -0
  148. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +8 -1
  149. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +86 -0
  150. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +35 -16
  151. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/structure.ts +1 -0
  152. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +10 -0
  153. package/package.json +14 -9
  154. package/src/{model.ts → analysis/architecture/discovery.ts} +15 -72
  155. package/src/analysis/architecture/model.ts +76 -0
  156. package/src/analysis/brief/directory.ts +324 -0
  157. package/src/analysis/brief/enrich.ts +157 -0
  158. package/src/analysis/brief/file.ts +84 -0
  159. package/src/analysis/brief/inventory.ts +177 -0
  160. package/src/analysis/brief/main.ts +176 -0
  161. package/src/analysis/brief/models.ts +75 -0
  162. package/src/{brief.ts → analysis/brief/public-brief.ts} +21 -26
  163. package/src/analysis/brief/summarize.ts +208 -0
  164. package/src/analysis/brief/types.ts +27 -0
  165. package/src/{use-case/generate-brief.ts → analysis/brief/use-case.ts} +67 -144
  166. package/src/analysis/coverage/coverage-warnings.ts +224 -0
  167. package/src/analysis/evidence.ts +91 -0
  168. package/src/{semantic-action-helpers.ts → analysis/helpers.ts} +4 -4
  169. package/src/analysis/provider.ts +186 -0
  170. package/src/analysis/read-next.ts +126 -0
  171. package/src/analysis/readiness.ts +73 -0
  172. package/src/{refactor → analysis/refactor}/safety.ts +1 -1
  173. package/src/{use-case/support/semantic-references.ts → analysis/references/semantic-refs.ts} +58 -26
  174. package/src/analysis/search/pattern.ts +345 -0
  175. package/src/analysis/search/ripgrep.ts +473 -0
  176. package/src/{git-context.ts → analysis/signals/git.ts} +20 -7
  177. package/src/{prioritization-signals.ts → analysis/signals/project.ts} +33 -19
  178. package/src/analysis/target/anchored.ts +349 -0
  179. package/src/analysis/target/bridge.ts +152 -0
  180. package/src/analysis/target/file-resolution.ts +125 -0
  181. package/src/{targeting/resolve-file.ts → analysis/target/file.ts} +40 -20
  182. package/src/{planner → analysis/target}/planner.ts +30 -20
  183. package/src/{targeting → analysis/target}/query.ts +17 -3
  184. package/src/analysis/target/resolve-common.ts +115 -0
  185. package/src/analysis/target/service.ts +229 -0
  186. package/src/analysis/target/symbol.ts +196 -0
  187. package/src/{targeting → analysis/target}/types.ts +17 -1
  188. package/src/analysis/tests/likely-tests.ts +174 -0
  189. package/src/analysis/tests/test-discovery.ts +540 -0
  190. package/src/analysis/tests/vitest.ts +87 -0
  191. package/src/api.ts +34 -41
  192. package/src/app/app.ts +125 -0
  193. package/src/app/manager.ts +65 -0
  194. package/src/extension.ts +132 -1
  195. package/src/index.ts +1 -57
  196. package/src/session/refactor-plans.ts +82 -0
  197. package/src/session/session.ts +300 -0
  198. package/src/session/target-store.ts +293 -0
  199. package/src/substrate/lsp/diagnostic-injection.ts +218 -0
  200. package/src/substrate/lsp/lifecycle.ts +66 -0
  201. package/src/substrate/lsp/overrides.ts +132 -0
  202. package/src/substrate/lsp/recovery.ts +55 -0
  203. package/src/substrate/lsp/settings.ts +286 -0
  204. package/src/substrate/lsp/state.ts +46 -0
  205. package/src/substrate/lsp/utils.ts +17 -0
  206. package/src/substrate/tree-sitter/lifecycle.ts +52 -0
  207. package/src/tool/find/execute.ts +118 -0
  208. package/src/{presentation/markdown/pattern.ts → tool/find/markdown.ts} +102 -53
  209. package/src/{use-case/generate-pattern.ts → tool/find/orchestrate.ts} +67 -33
  210. package/src/tool/find/semantic-search.ts +114 -0
  211. package/src/tool/find/tui.ts +39 -0
  212. package/src/tool/graph/callees.ts +87 -0
  213. package/src/tool/graph/calls-md.ts +54 -0
  214. package/src/tool/graph/collect-relation.ts +371 -0
  215. package/src/tool/graph/execute.ts +95 -0
  216. package/src/tool/graph/implementations-md.ts +79 -0
  217. package/src/tool/graph/implementations.ts +76 -0
  218. package/src/tool/graph/markdown-base.ts +243 -0
  219. package/src/tool/graph/orchestrate.ts +285 -0
  220. package/src/tool/graph/references-md.ts +34 -0
  221. package/src/tool/graph/references.ts +81 -0
  222. package/src/tool/graph/tui.ts +120 -0
  223. package/src/tool/graph/types.ts +97 -0
  224. package/src/tool/guidance.ts +96 -49
  225. package/src/tool/health/execute.ts +76 -0
  226. package/src/tool/health/markdown.ts +280 -0
  227. package/src/tool/health/orchestrate.ts +159 -0
  228. package/src/tool/health/sections/diagnostics.ts +182 -0
  229. package/src/tool/health/sections/recovery.ts +89 -0
  230. package/src/tool/health/sections/signals.ts +89 -0
  231. package/src/tool/health/tui.ts +137 -0
  232. package/src/tool/impact/analysis.ts +247 -0
  233. package/src/tool/impact/change-set-impact.ts +151 -0
  234. package/src/tool/impact/execute.ts +98 -0
  235. package/src/tool/impact/file-level-impact.ts +81 -0
  236. package/src/tool/impact/markdown.ts +283 -0
  237. package/src/tool/impact/orchestrate.ts +97 -0
  238. package/src/tool/impact/result.ts +21 -0
  239. package/src/tool/impact/single-impact.ts +89 -0
  240. package/src/tool/impact/tui.ts +39 -0
  241. package/src/tool/impact/types.ts +34 -0
  242. package/src/tool/infra/cross-field.ts +335 -0
  243. package/src/tool/infra/error-results.ts +199 -0
  244. package/src/tool/infra/pipeline.ts +311 -0
  245. package/src/tool/infra/progress.ts +21 -0
  246. package/src/tool/infra/readiness-message.ts +5 -0
  247. package/src/tool/infra/truncate.ts +49 -0
  248. package/src/tool/inspect/execute.ts +76 -0
  249. package/src/tool/inspect/markdown.ts +169 -0
  250. package/src/tool/inspect/orchestrate.ts +156 -0
  251. package/src/tool/inspect/tui.ts +36 -0
  252. package/src/tool/orientation/deps.ts +63 -0
  253. package/src/tool/orientation/execute.ts +50 -0
  254. package/src/tool/orientation/markdown.ts +35 -0
  255. package/src/tool/orientation/mode.ts +88 -0
  256. package/src/tool/orientation/orchestrate.ts +478 -0
  257. package/src/tool/orientation/precise-target.ts +257 -0
  258. package/src/tool/orientation/tui.ts +131 -0
  259. package/src/{refactor/apply-workspace-edit.ts → tool/refactor-apply/apply.ts} +39 -16
  260. package/src/tool/refactor-apply/execute.ts +20 -0
  261. package/src/tool/refactor-apply/markdown.ts +118 -0
  262. package/src/tool/refactor-apply/orchestrate.ts +89 -0
  263. package/src/tool/refactor-apply/tui.ts +51 -0
  264. package/src/tool/refactor-plan/execute.ts +73 -0
  265. package/src/tool/refactor-plan/markdown.ts +118 -0
  266. package/src/tool/refactor-plan/orchestrate.ts +363 -0
  267. package/src/tool/refactor-plan/tui.ts +42 -0
  268. package/src/tool/register.ts +123 -0
  269. package/src/tool/resolve/execute.ts +82 -0
  270. package/src/tool/resolve/markdown.ts +150 -0
  271. package/src/tool/resolve/orchestrate.ts +134 -0
  272. package/src/tool/resolve/tui.ts +40 -0
  273. package/src/tool/schemas.ts +337 -0
  274. package/src/tool/specs.ts +257 -0
  275. package/src/types/details.ts +188 -0
  276. package/src/types/execution.ts +60 -0
  277. package/src/types/index.ts +28 -0
  278. package/src/{intent/types.ts → types/tool-names.ts} +15 -14
  279. package/src/ui/footer.ts +52 -0
  280. package/src/ui/markdown/brief.ts +218 -0
  281. package/src/ui/markdown/gather.ts +177 -0
  282. package/src/{use-case/build-overview.ts → ui/markdown/overview-data.ts} +2 -2
  283. package/src/{presentation → ui}/markdown/overview.ts +2 -2
  284. package/src/ui/markdown/types.ts +80 -0
  285. package/{node_modules/@mrclrchtr/supi-lsp/src/ui/renderer.ts → src/ui/message-renderer.ts} +11 -10
  286. package/src/ui/status-command.ts +260 -0
  287. package/src/ui/status-overlay.ts +500 -0
  288. package/src/ui/tui/common.ts +220 -0
  289. package/src/ui/tui/index.ts +37 -0
  290. package/node_modules/@mrclrchtr/supi-lsp/src/extension.ts +0 -1
  291. package/node_modules/@mrclrchtr/supi-lsp/src/format.ts +0 -373
  292. package/node_modules/@mrclrchtr/supi-lsp/src/handlers/diagnostic-injection.ts +0 -182
  293. package/node_modules/@mrclrchtr/supi-lsp/src/handlers/session-lifecycle.ts +0 -149
  294. package/node_modules/@mrclrchtr/supi-lsp/src/handlers/status-command.ts +0 -38
  295. package/node_modules/@mrclrchtr/supi-lsp/src/handlers/workspace-recovery.ts +0 -92
  296. package/node_modules/@mrclrchtr/supi-lsp/src/lsp.ts +0 -37
  297. package/node_modules/@mrclrchtr/supi-lsp/src/session/lsp-state.ts +0 -93
  298. package/node_modules/@mrclrchtr/supi-lsp/src/session/settings-registration.ts +0 -296
  299. package/node_modules/@mrclrchtr/supi-lsp/src/session/tree-persist.ts +0 -75
  300. package/node_modules/@mrclrchtr/supi-lsp/src/tool/guidance.ts +0 -69
  301. package/node_modules/@mrclrchtr/supi-lsp/src/tool/names.ts +0 -27
  302. package/node_modules/@mrclrchtr/supi-lsp/src/tool/overrides.ts +0 -204
  303. package/node_modules/@mrclrchtr/supi-lsp/src/tool/register-tools.ts +0 -69
  304. package/node_modules/@mrclrchtr/supi-lsp/src/tool/service-actions.ts +0 -399
  305. package/node_modules/@mrclrchtr/supi-lsp/src/tool/tool-specs.ts +0 -248
  306. package/node_modules/@mrclrchtr/supi-lsp/src/ui/ui.ts +0 -360
  307. package/node_modules/@mrclrchtr/supi-lsp/src/workspace-change.ts +0 -40
  308. package/node_modules/@mrclrchtr/supi-tree-sitter/src/extension.ts +0 -1
  309. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/formatting.ts +0 -104
  310. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/guidance.ts +0 -35
  311. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/handlers.ts +0 -196
  312. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/register-tools.ts +0 -107
  313. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/tool-specs.ts +0 -117
  314. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tree-sitter.ts +0 -47
  315. package/src/brief-focused.ts +0 -563
  316. package/src/code-intelligence.ts +0 -70
  317. package/src/pattern-structured.ts +0 -194
  318. package/src/presentation/markdown/affected.ts +0 -170
  319. package/src/presentation/markdown/brief.ts +0 -174
  320. package/src/presentation/markdown/map.ts +0 -54
  321. package/src/presentation/markdown/refactor.ts +0 -27
  322. package/src/presentation/markdown/relations.ts +0 -121
  323. package/src/resolve-target.ts +0 -130
  324. package/src/search-helpers.ts +0 -303
  325. package/src/substrates/types.ts +0 -30
  326. package/src/target-resolution.ts +0 -122
  327. package/src/targeting/resolve-anchored.ts +0 -80
  328. package/src/targeting/resolve-symbol.ts +0 -110
  329. package/src/tool/execute-affected.ts +0 -71
  330. package/src/tool/execute-brief.ts +0 -59
  331. package/src/tool/execute-map.ts +0 -35
  332. package/src/tool/execute-pattern.ts +0 -29
  333. package/src/tool/execute-refactor.ts +0 -101
  334. package/src/tool/execute-relations.ts +0 -79
  335. package/src/tool/register-tools.ts +0 -32
  336. package/src/tool/tool-specs.ts +0 -190
  337. package/src/tool/validation.ts +0 -43
  338. package/src/types.ts +0 -169
  339. package/src/use-case/generate-affected.ts +0 -297
  340. package/src/use-case/generate-map.ts +0 -176
  341. package/src/use-case/generate-relations.ts +0 -438
  342. package/src/use-case/types.ts +0 -43
  343. package/src/workspace/request-context.ts +0 -139
  344. /package/src/{query-params.ts → tool/params.ts} +0 -0
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Markdown renderer for code_health results.
3
+ *
4
+ * Renders structured health data from the code_health executor into
5
+ * readable markdown sections keyed by requested `include` values.
6
+ */
7
+
8
+ import type { CoverageWarningReport } from "../../analysis/coverage/coverage-warnings.ts";
9
+ import type { GitContext } from "../../analysis/signals/git.ts";
10
+ import { formatGitContext } from "../../analysis/signals/git.ts";
11
+
12
+ export type HealthSection = "diagnostics" | "servers" | "dirty" | "coverage" | "unused";
13
+
14
+ export interface HealthServerInfo {
15
+ name: string;
16
+ root: string;
17
+ fileTypes: string[];
18
+ status: string;
19
+ }
20
+
21
+ export interface HealthDiagnosticEntry {
22
+ file: string;
23
+ errors: number;
24
+ warnings: number;
25
+ }
26
+
27
+ export interface HealthCoverageEntry {
28
+ file: string;
29
+ pct: number;
30
+ }
31
+
32
+ export interface HealthCoverageData {
33
+ available: boolean;
34
+ entries: HealthCoverageEntry[];
35
+ }
36
+
37
+ export interface HealthUnusedExportEntry {
38
+ file: string;
39
+ name: string;
40
+ }
41
+
42
+ export interface HealthUnusedData {
43
+ available: boolean;
44
+ files: string[];
45
+ exports: HealthUnusedExportEntry[];
46
+ }
47
+
48
+ /** A suggested code action at a specific diagnostic location. */
49
+ export interface CodeActionSuggestion {
50
+ file: string;
51
+ line: number;
52
+ title: string;
53
+ kind?: string;
54
+ }
55
+
56
+ export interface HealthData {
57
+ includedSections: HealthSection[];
58
+ lspAvailable: boolean;
59
+ lspStatus: string;
60
+ recovered: boolean;
61
+ /** Structural (tree-sitter) substrate readiness. Undefined when not evaluated. */
62
+ structuralStatus?: string;
63
+ diagnostics: HealthDiagnosticEntry[];
64
+ servers: HealthServerInfo[];
65
+ gitContext: GitContext | null;
66
+ scopeFilter: string | null;
67
+ level: "summary" | "detailed";
68
+ /** Code action suggestions collected from LSP (only populated in detailed mode). */
69
+ codeActions: CodeActionSuggestion[] | null;
70
+ coverage: HealthCoverageData | null;
71
+ unused: HealthUnusedData | null;
72
+ /** Coverage warnings for degraded semantic/structural substrate. Undefined when fully healthy. */
73
+ degradedCoverage?: CoverageWarningReport;
74
+ /** Seconds since diagnostics were last refreshed, or undefined if never refreshed. */
75
+ diagnosticAgeSeconds?: number;
76
+ }
77
+
78
+ export function renderHealthResult(data: HealthData, cwd: string): string {
79
+ const lines: string[] = ["## Code Health", ""];
80
+
81
+ renderStatusLine(lines, data);
82
+ renderStalenessBanner(lines, data);
83
+
84
+ if (data.includedSections.includes("diagnostics")) {
85
+ renderDiagnosticsSection(lines, data, cwd);
86
+ }
87
+ if (data.includedSections.includes("coverage")) {
88
+ renderCoverageSection(lines, data, cwd);
89
+ }
90
+ if (data.includedSections.includes("unused")) {
91
+ renderUnusedSection(lines, data, cwd);
92
+ }
93
+ renderDegradedCoverageSection(lines, data);
94
+ if (data.includedSections.includes("servers")) {
95
+ renderServersSection(lines, data);
96
+ }
97
+ if (data.includedSections.includes("dirty")) {
98
+ renderDirtySection(lines, data);
99
+ }
100
+
101
+ return lines.join("\n");
102
+ }
103
+
104
+ function renderStalenessBanner(lines: string[], data: HealthData): void {
105
+ if (data.diagnosticAgeSeconds == null) {
106
+ lines.push("⚠ Diagnostics have not been refreshed this session. Use `refresh: true` to check.");
107
+ lines.push("");
108
+ return;
109
+ }
110
+ if (data.diagnosticAgeSeconds < 60) return;
111
+ const age =
112
+ data.diagnosticAgeSeconds < 120
113
+ ? `${Math.round(data.diagnosticAgeSeconds)}s ago`
114
+ : `${Math.round(data.diagnosticAgeSeconds / 60)}m ago`;
115
+ lines.push(`⚠ Diagnostics are ${age}. Use \`refresh: true\` to re-check.`);
116
+ lines.push("");
117
+ }
118
+
119
+ function renderDegradedCoverageSection(lines: string[], data: HealthData): void {
120
+ if (!data.degradedCoverage?.hasWarnings) return;
121
+
122
+ lines.push("### Degraded Coverage");
123
+ lines.push("");
124
+
125
+ for (const warning of data.degradedCoverage.warnings) {
126
+ const lang = warning.language ? `[${warning.language}] ` : "";
127
+ lines.push(`- ⚠ ${lang}${warning.message}`);
128
+ if (warning.detail) {
129
+ lines.push(` — ${warning.detail}`);
130
+ }
131
+ }
132
+ lines.push("");
133
+ }
134
+
135
+ function renderStatusLine(lines: string[], data: HealthData): void {
136
+ lines.push(`**LSP**: ${data.lspStatus}`);
137
+ if (data.structuralStatus) {
138
+ lines.push(`**Structural**: ${data.structuralStatus}`);
139
+ }
140
+ if (data.recovered) {
141
+ lines.push("**Recovery**: diagnostics refreshed");
142
+ }
143
+ lines.push("");
144
+ }
145
+
146
+ function renderDiagnosticsSection(lines: string[], data: HealthData, cwd: string): void {
147
+ lines.push("### Diagnostics");
148
+ lines.push("");
149
+
150
+ if (data.diagnostics.length === 0) {
151
+ lines.push("No diagnostics found.");
152
+ } else if (data.level === "summary") {
153
+ renderDiagnosticSummary(lines, data);
154
+ } else {
155
+ renderDiagnosticDetails(lines, data, cwd);
156
+ }
157
+
158
+ renderCodeActionsSection(lines, data, cwd);
159
+ lines.push("");
160
+ }
161
+
162
+ function renderDiagnosticSummary(lines: string[], data: HealthData): void {
163
+ const totalErrors = data.diagnostics.reduce((sum, d) => sum + d.errors, 0);
164
+ const totalWarnings = data.diagnostics.reduce((sum, d) => sum + d.warnings, 0);
165
+ const fileCount = data.diagnostics.length;
166
+ const s = (n: number) => (n !== 1 ? "s" : "");
167
+ lines.push(
168
+ `${fileCount} file${s(fileCount)} with issues: ${totalErrors} error${s(totalErrors)}, ${totalWarnings} warning${s(totalWarnings)}`,
169
+ );
170
+ }
171
+
172
+ function renderDiagnosticDetails(lines: string[], data: HealthData, cwd: string): void {
173
+ for (const entry of data.diagnostics) {
174
+ const relPath = makeRelative(cwd, entry.file);
175
+ const s = (n: number) => (n !== 1 ? "s" : "");
176
+ lines.push(
177
+ `- \`${relPath}\` — ${entry.errors} error${s(entry.errors)}, ${entry.warnings} warning${s(entry.warnings)}`,
178
+ );
179
+ }
180
+ }
181
+
182
+ function renderCodeActionsSection(lines: string[], data: HealthData, cwd: string): void {
183
+ if (!data.codeActions || data.codeActions.length === 0) return;
184
+
185
+ if (data.level === "summary") {
186
+ const count = data.codeActions.length;
187
+ lines.push(
188
+ `_${count} suggested fix${count !== 1 ? "es" : ""} available. Use \`level: "detailed"\` to see them._`,
189
+ );
190
+ return;
191
+ }
192
+
193
+ lines.push("");
194
+ lines.push("### Code Actions");
195
+ lines.push("");
196
+ lines.push("Available fixes (suggestions only — not applied):");
197
+ lines.push("");
198
+ for (const action of data.codeActions) {
199
+ const relPath = makeRelative(cwd, action.file);
200
+ const kindLabel = action.kind ? ` (${action.kind})` : "";
201
+ lines.push(`- \`${relPath}:${action.line}\` — "${action.title}"${kindLabel}`);
202
+ }
203
+ }
204
+
205
+ function renderCoverageSection(lines: string[], data: HealthData, cwd: string): void {
206
+ lines.push("### Coverage");
207
+ lines.push("");
208
+
209
+ if (!data.coverage?.available) {
210
+ lines.push("No coverage report found.");
211
+ lines.push("");
212
+ return;
213
+ }
214
+
215
+ if (data.coverage.entries.length === 0) {
216
+ lines.push("No low-coverage files found.");
217
+ lines.push("");
218
+ return;
219
+ }
220
+
221
+ for (const entry of data.coverage.entries) {
222
+ lines.push(`- \`${makeRelative(cwd, entry.file)}\` — ${entry.pct.toFixed(0)}%`);
223
+ }
224
+ lines.push("");
225
+ }
226
+
227
+ function renderUnusedSection(lines: string[], data: HealthData, cwd: string): void {
228
+ lines.push("### Unused");
229
+ lines.push("");
230
+
231
+ if (!data.unused?.available) {
232
+ lines.push("No unused report found.");
233
+ lines.push("");
234
+ return;
235
+ }
236
+
237
+ if (data.unused.files.length === 0 && data.unused.exports.length === 0) {
238
+ lines.push("No unused files or exports reported.");
239
+ lines.push("");
240
+ return;
241
+ }
242
+
243
+ for (const file of data.unused.files) {
244
+ lines.push(`- Unused file: \`${makeRelative(cwd, file)}\``);
245
+ }
246
+ for (const entry of data.unused.exports) {
247
+ lines.push(`- Unused export: \`${entry.name}\` in \`${makeRelative(cwd, entry.file)}\``);
248
+ }
249
+ lines.push("");
250
+ }
251
+
252
+ function renderServersSection(lines: string[], data: HealthData): void {
253
+ lines.push("### Servers");
254
+ lines.push("");
255
+
256
+ if (data.servers.length === 0) {
257
+ lines.push("No servers found.");
258
+ lines.push("");
259
+ return;
260
+ }
261
+
262
+ for (const server of data.servers) {
263
+ const statusIcon = server.status === "running" ? "✓" : "✗";
264
+ const types = server.fileTypes.join(", ");
265
+ lines.push(`- ${statusIcon} **${server.name}** (${types}) — ${server.status}`);
266
+ }
267
+ lines.push("");
268
+ }
269
+
270
+ function renderDirtySection(lines: string[], data: HealthData): void {
271
+ if (!data.gitContext) return;
272
+ lines.push(formatGitContext(data.gitContext));
273
+ }
274
+
275
+ function makeRelative(cwd: string, file: string): string {
276
+ if (file.startsWith(cwd)) {
277
+ return file.slice(cwd.length + 1);
278
+ }
279
+ return file;
280
+ }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Health orchestration use-case — gathers workspace health data and
3
+ * returns a rendered CodeIntelResult with structured details.
4
+ *
5
+ * Thin dispatcher: collects all requested sections, assembles the
6
+ * HealthData object, and delegates rendering to the markdown module.
7
+ * Section-specific collection lives in ./sections/.
8
+ */
9
+
10
+ import type { AgentToolUpdateCallback } from "@earendil-works/pi-coding-agent";
11
+ import type { CapabilityState } from "@mrclrchtr/supi-code-runtime/api";
12
+ import type { SessionLspServiceState } from "@mrclrchtr/supi-lsp/api";
13
+ import {
14
+ evaluateCoverageWarnings,
15
+ gatherCoverageEvalInput,
16
+ } from "../../analysis/coverage/coverage-warnings.ts";
17
+ import { loadPrioritizationSignals } from "../../analysis/signals/project.ts";
18
+ import type { CodeIntelResult, HealthDetails } from "../../types/index.ts";
19
+ import type { HealthData, HealthSection } from "./markdown.ts";
20
+ import { renderHealthResult } from "./markdown.ts";
21
+ import { collectCodeActions, collectDiagnostics } from "./sections/diagnostics.ts";
22
+ import {
23
+ buildHealthEvidenceLists,
24
+ describeStructuralState,
25
+ maybeRecover,
26
+ } from "./sections/recovery.ts";
27
+ import {
28
+ collectCoverageSection,
29
+ collectGitContext,
30
+ collectServers,
31
+ collectUnusedSection,
32
+ needsPrioritizationSignals,
33
+ } from "./sections/signals.ts";
34
+
35
+ export interface HealthInput {
36
+ scope?: string;
37
+ refresh?: boolean;
38
+ include?: string[];
39
+ level?: "summary" | "detailed";
40
+ coveragePath?: string;
41
+ unusedPath?: string;
42
+ }
43
+
44
+ export interface HealthDeps {
45
+ cwd: string;
46
+ lspState: SessionLspServiceState;
47
+ providerAvailable: boolean;
48
+ semanticStateKind: "pending" | "ready" | "inactive" | "disabled" | "unavailable";
49
+ structuralState: CapabilityState;
50
+ lspController: import("@mrclrchtr/supi-lsp/api").LspRuntimeController | null;
51
+ onUpdate?: AgentToolUpdateCallback;
52
+ scopeFilter: string | null;
53
+ lastRefresh: number | undefined;
54
+ }
55
+
56
+ const DEFAULT_INCLUDE: HealthSection[] = ["diagnostics", "servers"];
57
+
58
+ /** Last diagnostic refresh time by workspace path (for staleness banner). */
59
+ const lastRefreshByWorkspace = new Map<string, number>();
60
+
61
+ /** Track a diagnostic refresh for the given workspace. */
62
+ export function trackHealthRefresh(cwd: string): void {
63
+ lastRefreshByWorkspace.set(cwd, Date.now());
64
+ }
65
+
66
+ /** Get the last refresh time for a workspace. */
67
+ export function getLastHealthRefresh(cwd: string): number | undefined {
68
+ return lastRefreshByWorkspace.get(cwd);
69
+ }
70
+
71
+ /**
72
+ * Execute the health gathering use-case.
73
+ */
74
+ export async function executeHealth(
75
+ input: HealthInput,
76
+ deps: HealthDeps,
77
+ ): Promise<CodeIntelResult> {
78
+ const cwd = deps.cwd;
79
+ const included = (
80
+ input.include && input.include.length > 0 ? input.include : DEFAULT_INCLUDE
81
+ ) as HealthSection[];
82
+ const level = input.level ?? "summary";
83
+
84
+ const service = deps.lspState.kind === "ready" ? deps.lspState.service : null;
85
+
86
+ const { recovered, lspStatus } = await maybeRecover({
87
+ service,
88
+ refresh: input.refresh,
89
+ lspState: deps.lspState,
90
+ semanticStateKind: deps.semanticStateKind,
91
+ onUpdate: deps.onUpdate,
92
+ });
93
+ const structuralStatus = describeStructuralState(deps.structuralState);
94
+
95
+ const diagnostics = await collectDiagnostics(service, included, deps.scopeFilter, cwd);
96
+ const servers = collectServers(service, included);
97
+ const gitContext = collectGitContext(included, cwd);
98
+ const prioritizationSignals = needsPrioritizationSignals(included)
99
+ ? loadPrioritizationSignals(cwd, deps.lspState, {
100
+ coveragePath: input.coveragePath,
101
+ unusedPath: input.unusedPath,
102
+ })
103
+ : null;
104
+ const coverage = included.includes("coverage")
105
+ ? collectCoverageSection(prioritizationSignals, cwd, deps.scopeFilter, input.coveragePath)
106
+ : null;
107
+ const unused = included.includes("unused")
108
+ ? collectUnusedSection(prioritizationSignals, cwd, deps.scopeFilter, input.unusedPath)
109
+ : null;
110
+
111
+ const codeActions =
112
+ level === "detailed" && included.includes("diagnostics")
113
+ ? await collectCodeActions(service, deps.scopeFilter, cwd)
114
+ : null;
115
+
116
+ const degradedCoverage = evaluateCoverageWarnings(
117
+ gatherCoverageEvalInput(cwd, deps.lspController),
118
+ );
119
+
120
+ const diagnosticAgeSeconds =
121
+ deps.lastRefresh != null ? Math.round((Date.now() - deps.lastRefresh) / 1000) : undefined;
122
+
123
+ const data: HealthData = {
124
+ includedSections: included,
125
+ lspAvailable: service !== null,
126
+ lspStatus,
127
+ recovered,
128
+ structuralStatus,
129
+ diagnostics,
130
+ servers,
131
+ gitContext,
132
+ scopeFilter: input.scope ? deps.scopeFilter : null,
133
+ level,
134
+ codeActions,
135
+ coverage,
136
+ unused,
137
+ degradedCoverage: degradedCoverage.hasWarnings ? degradedCoverage : undefined,
138
+ diagnosticAgeSeconds,
139
+ };
140
+
141
+ const evidenceLists = buildHealthEvidenceLists(gitContext);
142
+ const content = renderHealthResult(data, cwd);
143
+
144
+ return {
145
+ content,
146
+ details: {
147
+ type: "health",
148
+ data: {
149
+ lspAvailable: data.lspAvailable,
150
+ lspStatus: data.lspStatus,
151
+ recovered: data.recovered,
152
+ structuralStatus: data.structuralStatus,
153
+ diagnosticFileCount: data.diagnostics.length,
154
+ serverCount: data.servers.length,
155
+ evidenceLists,
156
+ } satisfies HealthDetails,
157
+ },
158
+ };
159
+ }
@@ -0,0 +1,182 @@
1
+ // Diagnostics collection and code-action gathering for code_health.
2
+ // Extracted from orchestrate.ts.
3
+
4
+ import { existsSync, statSync } from "node:fs";
5
+ import { resolve } from "node:path";
6
+ import { isWithinOrEqual } from "@mrclrchtr/supi-core/api";
7
+ import type { SessionLspService } from "@mrclrchtr/supi-lsp/api";
8
+ import type { CodeActionSuggestion, HealthData } from "../markdown.ts";
9
+
10
+ // ── Diagnostics ───────────────────────────────────────────────────────
11
+
12
+ export function isScopedFile(scopeFilter: string | null): scopeFilter is string {
13
+ return scopeFilter !== null && existsSync(scopeFilter) && !isDirectory(scopeFilter);
14
+ }
15
+
16
+ export async function collectDiagnostics(
17
+ service: SessionLspService | null,
18
+ included: string[],
19
+ scopeFilter: string | null,
20
+ cwd: string,
21
+ ): Promise<HealthData["diagnostics"]> {
22
+ if (!included.includes("diagnostics") || !service) return [];
23
+
24
+ if (isScopedFile(scopeFilter)) {
25
+ return collectScopedFileDiagnostics(service, scopeFilter);
26
+ }
27
+
28
+ return collectWorkspaceDiagnostics(service, scopeFilter, cwd);
29
+ }
30
+
31
+ async function collectScopedFileDiagnostics(
32
+ service: SessionLspService,
33
+ scopeFilter: string,
34
+ ): Promise<HealthData["diagnostics"]> {
35
+ const diags = await service.fileDiagnostics(scopeFilter, 4);
36
+ if (!diags || diags.length === 0) {
37
+ return [];
38
+ }
39
+
40
+ const errors = diags.filter((d) => (d.severity ?? 1) === 1).length;
41
+ const warnings = diags.filter((d) => (d.severity ?? 1) === 2).length;
42
+ if (!hasIssueCounts(errors, warnings)) {
43
+ return [];
44
+ }
45
+
46
+ return [{ file: scopeFilter, errors, warnings }];
47
+ }
48
+
49
+ function collectWorkspaceDiagnostics(
50
+ service: SessionLspService,
51
+ scopeFilter: string | null,
52
+ cwd: string,
53
+ ): HealthData["diagnostics"] {
54
+ const summary = service.getWorkspaceDiagnosticSummary();
55
+ const result: HealthData["diagnostics"] = [];
56
+
57
+ for (const entry of summary) {
58
+ const filePath = resolve(cwd, entry.file);
59
+ if (scopeFilter && !isWithinOrEqual(scopeFilter, filePath)) continue;
60
+ if (!hasIssueCounts(entry.errors, entry.warnings)) continue;
61
+ result.push({ file: filePath, errors: entry.errors, warnings: entry.warnings });
62
+ }
63
+
64
+ return result;
65
+ }
66
+
67
+ function hasIssueCounts(errors: number, warnings: number): boolean {
68
+ return errors > 0 || warnings > 0;
69
+ }
70
+
71
+ // ── Code actions ──────────────────────────────────────────────────────
72
+
73
+ /** Max files to query for code actions in detailed health mode. */
74
+ const MAX_CODE_ACTION_FILES = 5;
75
+ /** Max total code action suggestions to return. */
76
+ const MAX_CODE_ACTION_SUGGESTIONS = 10;
77
+
78
+ export async function collectCodeActions(
79
+ service: SessionLspService | null,
80
+ scopeFilter: string | null,
81
+ cwd: string,
82
+ ): Promise<CodeActionSuggestion[]> {
83
+ if (!service) return [];
84
+
85
+ try {
86
+ const outstanding = service.getOutstandingDiagnostics(1);
87
+ const suggestions = await collectFromOutstanding(service, outstanding, scopeFilter, cwd);
88
+ return suggestions.slice(0, MAX_CODE_ACTION_SUGGESTIONS);
89
+ } catch {
90
+ return [];
91
+ }
92
+ }
93
+
94
+ async function collectFromOutstanding(
95
+ service: SessionLspService,
96
+ outstanding: ReturnType<SessionLspService["getOutstandingDiagnostics"]>,
97
+ scopeFilter: string | null,
98
+ cwd: string,
99
+ ): Promise<CodeActionSuggestion[]> {
100
+ const suggestions: CodeActionSuggestion[] = [];
101
+ let filesQueried = 0;
102
+
103
+ for (const entry of outstanding) {
104
+ if (suggestions.length >= MAX_CODE_ACTION_SUGGESTIONS) break;
105
+ if (filesQueried >= MAX_CODE_ACTION_FILES) break;
106
+ if (scopeFilter && !isWithinScope(scopeFilter, entry.file, cwd)) continue;
107
+
108
+ const newSuggestions = await collectFileCodeActions(service, entry);
109
+ if (newSuggestions.length === 0) continue;
110
+
111
+ filesQueried++;
112
+ mergeSuggestions(suggestions, newSuggestions);
113
+ }
114
+
115
+ return suggestions;
116
+ }
117
+
118
+ function mergeSuggestions(
119
+ existing: CodeActionSuggestion[],
120
+ incoming: CodeActionSuggestion[],
121
+ ): void {
122
+ const seen = new Set(existing.map((s) => `${s.file}:${s.title}`));
123
+ for (const s of incoming) {
124
+ const key = `${s.file}:${s.title}`;
125
+ if (!seen.has(key)) {
126
+ seen.add(key);
127
+ existing.push(s);
128
+ }
129
+ }
130
+ }
131
+
132
+ async function collectFileCodeActions(
133
+ service: SessionLspService,
134
+ entry: {
135
+ file: string;
136
+ diagnostics: Array<{
137
+ severity?: number;
138
+ range: {
139
+ start: { line: number; character: number };
140
+ end: { line: number; character: number };
141
+ };
142
+ }>;
143
+ },
144
+ ): Promise<CodeActionSuggestion[]> {
145
+ const errorDiag = entry.diagnostics.find((d) => (d.severity ?? 1) <= 1);
146
+ if (!errorDiag) return [];
147
+
148
+ try {
149
+ const actions = await service.codeActions(entry.file, {
150
+ line: errorDiag.range.start.line,
151
+ character: errorDiag.range.start.character,
152
+ });
153
+ if (!actions || actions.length === 0) return [];
154
+
155
+ const result: CodeActionSuggestion[] = [];
156
+ for (const a of actions) {
157
+ if (!a.title) continue;
158
+ result.push({
159
+ file: entry.file,
160
+ line: errorDiag.range.start.line + 1,
161
+ title: a.title,
162
+ kind: a.kind ?? undefined,
163
+ });
164
+ }
165
+ return result;
166
+ } catch {
167
+ return [];
168
+ }
169
+ }
170
+
171
+ function isWithinScope(scopeFilter: string, file: string, cwd: string): boolean {
172
+ const absPath = resolve(cwd, file);
173
+ return isWithinOrEqual(scopeFilter, absPath);
174
+ }
175
+
176
+ export function isDirectory(filePath: string): boolean {
177
+ try {
178
+ return statSync(filePath).isDirectory();
179
+ } catch {
180
+ return false;
181
+ }
182
+ }
@@ -0,0 +1,89 @@
1
+ // Recovery, state description, and evidence helpers for code_health.
2
+ // Extracted from orchestrate.ts.
3
+
4
+ import type { AgentToolUpdateCallback } from "@earendil-works/pi-coding-agent";
5
+ import type { CapabilityState } from "@mrclrchtr/supi-code-runtime/api";
6
+ import type { SessionLspService, SessionLspServiceState } from "@mrclrchtr/supi-lsp/api";
7
+ import { createEvidenceList, type EvidenceListMetadata } from "../../../analysis/evidence.ts";
8
+ import type { GitContext } from "../../../analysis/signals/git.ts";
9
+ import { emitToolProgress } from "../../infra/progress.ts";
10
+
11
+ // ── Recovery ──────────────────────────────────────────────────────────
12
+
13
+ interface RecoverOptions {
14
+ service: SessionLspService | null;
15
+ refresh: boolean | undefined;
16
+ lspState: SessionLspServiceState;
17
+ semanticStateKind?: "pending" | "ready" | "inactive" | "disabled" | "unavailable";
18
+ onUpdate?: AgentToolUpdateCallback;
19
+ }
20
+
21
+ export async function maybeRecover(
22
+ opts: RecoverOptions,
23
+ ): Promise<{ recovered: boolean; lspStatus: string }> {
24
+ const { service, refresh, lspState, semanticStateKind, onUpdate } = opts;
25
+ let recovered = false;
26
+ let lspStatus = semanticStateKind === "pending" ? "warming…" : describeLspState(lspState);
27
+
28
+ if (refresh && service) {
29
+ emitToolProgress(onUpdate, "code_health: refreshing diagnostics (may restart LSP)...");
30
+ try {
31
+ await service.recoverDiagnostics({ restartIfStillStale: true });
32
+ recovered = true;
33
+ lspStatus = "ready (recovered)";
34
+ } catch {
35
+ // Recovery failed but we continue
36
+ }
37
+ }
38
+
39
+ return { recovered, lspStatus };
40
+ }
41
+
42
+ // ── Evidence lists ────────────────────────────────────────────────────
43
+
44
+ export function buildHealthEvidenceLists(gitContext: GitContext | null): EvidenceListMetadata[] {
45
+ if (!gitContext) return [];
46
+ return [
47
+ createEvidenceList({
48
+ key: "health.dirtyFiles",
49
+ items: gitContext.dirtyFiles,
50
+ maxResults: 5,
51
+ }).metadata,
52
+ ];
53
+ }
54
+
55
+ // ── State description helpers ─────────────────────────────────────────
56
+
57
+ export function describeLspState(state: SessionLspServiceState): string {
58
+ switch (state.kind) {
59
+ case "ready":
60
+ return "ready";
61
+ case "pending":
62
+ return "starting…";
63
+ case "inactive":
64
+ return "inactive on current session branch";
65
+ case "disabled":
66
+ return "disabled by configuration";
67
+ case "unavailable":
68
+ return `unavailable — ${state.reason}`;
69
+ default:
70
+ return "unknown state";
71
+ }
72
+ }
73
+
74
+ export function describeStructuralState(state: CapabilityState): string {
75
+ switch (state.kind) {
76
+ case "ready":
77
+ return "ready";
78
+ case "pending":
79
+ return "starting…";
80
+ case "inactive":
81
+ return "inactive";
82
+ case "disabled":
83
+ return "disabled by configuration";
84
+ case "unavailable":
85
+ return `unavailable — ${state.reason}`;
86
+ default:
87
+ return "unknown state";
88
+ }
89
+ }