@mrclrchtr/supi-code-intelligence 1.16.1 → 2.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 (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,257 @@
1
+ /**
2
+ * Precise-target resolution and execution for code_orientation.
3
+ *
4
+ * Handles targetId expansion, coordinate-based symbol resolution, and
5
+ * running the use-case layer for a resolved symbol target. Shared by
6
+ * the main code_orientation executor.
7
+ */
8
+
9
+ import { relative } from "node:path";
10
+ import { executeResolveService } from "../../analysis/target/service.ts";
11
+ import type { TargetStoreEntry } from "../../session/target-store.ts";
12
+ import type { CodeIntelResult, CodeIntelToolExecCtx, ContextDetails } from "../../types/index.ts";
13
+ import { orientationCoordinateRules } from "../infra/cross-field.ts";
14
+ import { unavailableContextDetails } from "../infra/error-results.ts";
15
+ import { prepareOrientationDeps } from "./deps.ts";
16
+ import type { CodeOrientationToolParams } from "./execute.ts";
17
+ import { executeOrientation } from "./orchestrate.ts";
18
+
19
+ /**
20
+ * A resolved precise target: the store entry (with handles) plus
21
+ * contextual notes (e.g. "targetId took precedence over focus").
22
+ */
23
+ export interface PreciseTarget {
24
+ entry: TargetStoreEntry;
25
+ notes: string[];
26
+ }
27
+
28
+ /**
29
+ * Outcome of precise-target resolution in code_orientation.
30
+ *
31
+ * {@link resolvePreciseTarget} returns this discriminated union instead
32
+ * of {@link CodeIntelResult} | null so callers can't silently fall through
33
+ * on a bug that produces null unintentionally.
34
+ */
35
+ export type PreciseTargetOutcome =
36
+ | { kind: "resolved"; result: CodeIntelResult }
37
+ | { kind: "fallthrough" };
38
+
39
+ /**
40
+ * Resolve a precise target ({@link CodeOrientationToolParams.targetId}
41
+ * wins over focus/coordinates), then run symbol-centered orientation
42
+ * sections. Falls through to orientation-mode when both targetId
43
+ * expansion and coordinate resolution produce no target.
44
+ */
45
+ export async function resolvePreciseTarget(
46
+ params: CodeOrientationToolParams,
47
+ ctx: CodeIntelToolExecCtx,
48
+ hasCoords: boolean,
49
+ ): Promise<PreciseTargetOutcome> {
50
+ if (params.targetId !== undefined && params.targetId !== null) {
51
+ const targetIdOutcome = await resolveTargetIdTarget(params, ctx, hasCoords);
52
+ if (targetIdOutcome.kind === "resolved") return targetIdOutcome;
53
+ }
54
+
55
+ if (hasCoords) {
56
+ const coordOutcome = await resolveCoordinateTarget(params, ctx);
57
+ if (coordOutcome.kind === "resolved") return coordOutcome;
58
+ }
59
+
60
+ return { kind: "fallthrough" };
61
+ }
62
+
63
+ /** Resolve a targetId-supplied precise target, or fallthrough. */
64
+ async function resolveTargetIdTarget(
65
+ params: CodeOrientationToolParams,
66
+ ctx: CodeIntelToolExecCtx,
67
+ hasCoords: boolean,
68
+ ): Promise<PreciseTargetOutcome> {
69
+ const expansion = ctx.session.expandTargetId(params);
70
+ if (expansion.kind === "error") {
71
+ return wrapOutcome({
72
+ content: expansion.message,
73
+ details: unavailableContextDetails([
74
+ "Verify the `targetId` is valid and from this session",
75
+ "Re-resolve with `code_resolve` to get a fresh targetId",
76
+ ]),
77
+ });
78
+ }
79
+ if (expansion.kind !== "ok") return { kind: "fallthrough" };
80
+
81
+ const notes: string[] = [];
82
+ if (params.focus || hasCoords) {
83
+ notes.push(
84
+ "_Note: `targetId` takes precedence over the supplied focus/coordinates; focus and coordinates were ignored._",
85
+ );
86
+ }
87
+
88
+ return wrapOutcome(
89
+ await runWithOrientationTarget(params, ctx, { entry: expansion.entry, notes }),
90
+ );
91
+ }
92
+
93
+ /** Resolve a focus+coordinate-supplied precise target, or fallthrough. */
94
+ async function resolveCoordinateTarget(
95
+ params: CodeOrientationToolParams,
96
+ ctx: CodeIntelToolExecCtx,
97
+ ): Promise<PreciseTargetOutcome> {
98
+ const coordError = validateCoordinateParams(params, ctx.cwd);
99
+ if (coordError) {
100
+ return wrapOutcome({
101
+ content: coordError,
102
+ details: unavailableContextDetails([
103
+ "Provide `focus`, `line`, and `character` together for symbol orientation",
104
+ ]),
105
+ });
106
+ }
107
+
108
+ const resolveResult = await executeResolveService(
109
+ { file: params.focus, line: params.line, character: params.character },
110
+ ctx.session,
111
+ );
112
+
113
+ if (resolveResult.kind === "error") {
114
+ return wrapOutcome({
115
+ content: resolveResult.message,
116
+ details: unavailableContextDetails([
117
+ "Use `code_inspect` for point-level facts at this coordinate",
118
+ "Or pass the identifier coordinate of a declaration",
119
+ ]),
120
+ });
121
+ }
122
+ if (resolveResult.kind === "disambiguation") {
123
+ return wrapOutcome(disambiguationResult(resolveResult));
124
+ }
125
+
126
+ const entry = resolveResult.targets[0];
127
+ if (!entry) {
128
+ return wrapOutcome({
129
+ content: "**Error:** Coordinate resolution returned no target.",
130
+ details: unavailableContextDetails(["Use `code_inspect` for point-level facts"]),
131
+ });
132
+ }
133
+
134
+ return wrapOutcome(await runWithOrientationTarget(params, ctx, { entry, notes: [] }));
135
+ }
136
+
137
+ /** Wrap a CodeIntelResult into a resolved PreciseTargetOutcome. */
138
+ function wrapOutcome(result: CodeIntelResult): PreciseTargetOutcome {
139
+ return { kind: "resolved", result };
140
+ }
141
+ async function runWithOrientationTarget(
142
+ params: CodeOrientationToolParams,
143
+ ctx: CodeIntelToolExecCtx,
144
+ precise: PreciseTarget,
145
+ ): Promise<CodeIntelResult> {
146
+ const entry = precise.entry;
147
+ params.file = entry.file;
148
+ params.line = entry.displayLine;
149
+ params.character = entry.displayCharacter;
150
+ params.targetName = entry.name;
151
+ params.targetKind = entry.kind;
152
+ params.targetAnchorKind = entry.anchorKind;
153
+
154
+ const deps = await prepareOrientationDeps(params, ctx);
155
+ if ("content" in deps) return deps;
156
+
157
+ const result = await executeOrientation(
158
+ {
159
+ target: buildOrientationTarget(params),
160
+ maxResults: params.maxResults ?? 10,
161
+ showGitContext: false,
162
+ },
163
+ { ...deps, cwd: ctx.cwd },
164
+ );
165
+
166
+ const content = prependNotes(result.content, precise.notes, entry, ctx.cwd);
167
+ const details: ContextDetails = { ...result.details, target: entry };
168
+ return { content, details: { type: "context", data: details } };
169
+ }
170
+
171
+ // ── Helpers ───────────────────────────────────────────────────────────
172
+
173
+ /**
174
+ * Cross-field rule for code_orientation coordinate mode.
175
+ *
176
+ * TypeBox already enforces line/character types and min >= 1.
177
+ * This covers only pairing, existence, and directory checks.
178
+ */
179
+ const validateCoordinateParams = orientationCoordinateRules<CodeOrientationToolParams>();
180
+
181
+ function buildOrientationTarget(params: CodeOrientationToolParams) {
182
+ if (!params.file || params.line == null || params.character == null) return null;
183
+ return {
184
+ file: params.file,
185
+ line: params.line,
186
+ character: params.character,
187
+ name: params.targetName ?? null,
188
+ kind: params.targetKind ?? null,
189
+ anchorKind: params.targetAnchorKind ?? "name",
190
+ };
191
+ }
192
+
193
+ /** Prepend notes + a resolved-target summary to rendered orientation content. */
194
+ function prependNotes(
195
+ content: string,
196
+ notes: string[],
197
+ entry: TargetStoreEntry,
198
+ cwd: string,
199
+ ): string {
200
+ const head: string[] = [];
201
+ if (notes.length > 0) {
202
+ head.push(notes.join("\n\n"));
203
+ head.push("");
204
+ }
205
+ const namePart = entry.name ? ` **${entry.name}**` : "";
206
+ const relFile = relative(cwd, entry.file) || entry.file;
207
+ head.push(
208
+ `Resolved target${namePart}: \`${relFile}\`:${entry.displayLine}:${entry.displayCharacter} — Target ID: \`${entry.targetId}\``,
209
+ );
210
+ head.push("");
211
+ return `${head.join("\n")}${content}`;
212
+ }
213
+
214
+ // ── Disambiguation ────────────────────────────────────────────────────
215
+
216
+ /** Build the ambiguous-coordinate result: candidate targetIds, no sections. */
217
+ function disambiguationResult(
218
+ result: Extract<Awaited<ReturnType<typeof executeResolveService>>, { kind: "disambiguation" }>,
219
+ ): CodeIntelResult {
220
+ const lines: string[] = ["# Multiple matches found", ""];
221
+ lines.push(
222
+ "Coordinate resolution was ambiguous. Use `focus` + `line` + `character` for one of the candidates (pass the identifier coordinate):",
223
+ );
224
+ lines.push("");
225
+ for (const c of result.candidates) {
226
+ const kind = c.kind ? ` (\`${c.kind}\`)` : "";
227
+ const container = c.container ? ` in \`${c.container}\`` : "";
228
+ lines.push(
229
+ `${c.rank}. **${c.name}**${kind}${container} — \`${c.file}\`:${c.line}:${c.character}`,
230
+ );
231
+ lines.push(` Target ID: \`${c.targetId}\``);
232
+ }
233
+
234
+ const details: ContextDetails = {
235
+ confidence: "semantic",
236
+ task: null,
237
+ focusTarget: null,
238
+ requestedSections: [],
239
+ renderedSections: [],
240
+ omittedCount: 0,
241
+ candidates: result.candidates.map((c) => ({
242
+ targetId: c.targetId,
243
+ name: c.name,
244
+ kind: c.kind,
245
+ container: c.container,
246
+ file: c.file,
247
+ line: c.line,
248
+ character: c.character,
249
+ rank: c.rank,
250
+ })),
251
+ nextQueries: [
252
+ "Use `focus` + `line` + `character` for one of the candidates above (pass the identifier coordinate)",
253
+ ],
254
+ };
255
+
256
+ return { content: lines.join("\n"), details: { type: "context", data: details } };
257
+ }
@@ -0,0 +1,131 @@
1
+ import { getMarkdownTheme, type Theme } from "@earendil-works/pi-coding-agent";
2
+ import { Container, Markdown, Spacer, Text } from "@earendil-works/pi-tui";
3
+ import { formatEvidenceBadge } from "@mrclrchtr/supi-code-runtime/api";
4
+ import { type ResultOptios, renderPartial, type ToolResult } from "../../ui/tui/common.ts";
5
+ import type { CodeOrientationToolParams } from "./execute.ts";
6
+
7
+ /** ── renderCall ────────────────────────────────────────────────── */
8
+
9
+ export function renderOrientationCall(args: unknown, theme: Theme, _context: unknown): Text {
10
+ const params = (args ?? {}) as CodeOrientationToolParams;
11
+
12
+ let content = theme.fg("toolTitle", "code_orientation");
13
+
14
+ if (params.targetId) {
15
+ content += ` ${theme.fg("accent", "target")}`;
16
+ } else if (params.focus) {
17
+ const focus = params.focus.split("/").pop() ?? params.focus;
18
+ content += ` ${theme.fg("accent", focus)}`;
19
+ if (params.line) content += theme.fg("warning", `:${params.line}`);
20
+ } else {
21
+ content += ` ${theme.fg("muted", "project")}`;
22
+ }
23
+
24
+ return new Text(content, 0, 0);
25
+ }
26
+
27
+ /** ── renderResult ──────────────────────────────────────────────── */
28
+
29
+ export function renderOrientationResult(
30
+ result: ToolResult,
31
+ options: ResultOptios,
32
+ theme: Theme,
33
+ _context: unknown,
34
+ ): Container | Text {
35
+ if (options.isPartial) {
36
+ return renderPartial("Orienting…", theme);
37
+ }
38
+
39
+ const container = new Container();
40
+ const data =
41
+ result.details?.type === "context" ? (result.details.data as Record<string, unknown>) : null;
42
+ const markdownText = result.content.find((c) => c.type === "text")?.text ?? "";
43
+
44
+ if (result.isError) {
45
+ container.addChild(new Text(theme.fg("error", "code_orientation failed"), 0, 0));
46
+ return container;
47
+ }
48
+
49
+ if (!options.expanded) {
50
+ container.addChild(buildCompactSummary(data, theme));
51
+ return container;
52
+ }
53
+
54
+ container.addChild(buildHeader(data, theme));
55
+
56
+ const target = data?.target as Record<string, unknown> | undefined;
57
+ if (target) {
58
+ container.addChild(new Spacer(1));
59
+ container.addChild(
60
+ new Text(
61
+ theme.fg(
62
+ "muted",
63
+ `${String(target.name ?? "symbol")} — ${String(target.file ?? "")}:${String(target.displayLine ?? "")}`,
64
+ ),
65
+ 0,
66
+ 0,
67
+ ),
68
+ );
69
+ }
70
+
71
+ const sections = (data?.renderedSections as string[] | undefined) ?? [];
72
+ if (sections.length > 0) {
73
+ container.addChild(new Spacer(1));
74
+ container.addChild(new Text(theme.fg("dim", `Sections: ${sections.join(", ")}`), 0, 0));
75
+ }
76
+
77
+ if (data?.omittedCount) {
78
+ const badge = formatEvidenceBadge({
79
+ shownCount: sections.length,
80
+ totalCount: sections.length + Number(data.omittedCount),
81
+ omittedCount: Number(data.omittedCount),
82
+ partialReason: null,
83
+ label: "sections",
84
+ });
85
+ container.addChild(new Text(theme.fg("dim", badge), 0, 0));
86
+ }
87
+
88
+ if (markdownText) {
89
+ container.addChild(new Spacer(1));
90
+ container.addChild(new Text(theme.fg("dim", "▸ raw markdown"), 0, 0));
91
+ container.addChild(new Markdown(markdownText, 0, 0, getMarkdownTheme()));
92
+ }
93
+
94
+ return container;
95
+ }
96
+
97
+ /** ── Helpers ───────────────────────────────────────────────────── */
98
+
99
+ function buildCompactSummary(data: Record<string, unknown> | null, theme: Theme): Text {
100
+ if (!data) return new Text(theme.fg("dim", "No orientation"), 0, 0);
101
+
102
+ const sections = (data?.renderedSections as string[] | undefined) ?? [];
103
+ const confidence = (data.confidence as string) ?? "";
104
+ const dot = theme.fg("dim", "·");
105
+ const segments: string[] = [
106
+ `${theme.fg("dim", "sections")} ${theme.fg("success", theme.bold(`${sections.length}`))}`,
107
+ ];
108
+
109
+ if (confidence) {
110
+ segments.push(`${theme.fg("dim", "confidence")} ${theme.fg("muted", confidence)}`);
111
+ }
112
+
113
+ const target = data.target as Record<string, unknown> | undefined;
114
+ if (target?.name) segments.push(theme.fg("muted", String(target.name)));
115
+
116
+ return new Text(segments.join(` ${dot} `), 0, 0);
117
+ }
118
+
119
+ function buildHeader(data: Record<string, unknown> | null, theme: Theme): Text {
120
+ if (!data) return new Text("", 0, 0);
121
+
122
+ const sections = (data?.renderedSections as string[] | undefined) ?? [];
123
+ const confidence = (data.confidence as string) ?? "";
124
+ const dot = theme.fg("dim", "·");
125
+ const parts = [
126
+ `${theme.fg("dim", "sections")} ${theme.fg("accent", theme.bold(`${sections.length}`))}`,
127
+ ];
128
+ if (confidence) parts.push(`${theme.fg("dim", "confidence")} ${theme.fg("muted", confidence)}`);
129
+
130
+ return new Text(parts.join(` ${dot} `), 0, 0);
131
+ }
@@ -12,8 +12,9 @@
12
12
  */
13
13
 
14
14
  import { readFileSync, writeFileSync } from "node:fs";
15
+ import { withFileMutationQueue } from "@earendil-works/pi-coding-agent";
15
16
  import type { FileEdit, WorkspaceEdit } from "@mrclrchtr/supi-code-runtime/api";
16
- import { validateEditAgainstFiles } from "./safety.ts";
17
+ import { validateEditAgainstFiles } from "../../analysis/refactor/safety.ts";
17
18
 
18
19
  export type ApplyResult =
19
20
  | { kind: "applied"; filesChanged: number; totalEdits: number }
@@ -25,23 +26,45 @@ export type ApplyResult =
25
26
  * Precomputes every file's new content in memory first, then commits
26
27
  * all writes. If a commit fails after some files were already written,
27
28
  * the function rolls those files back to their original contents.
29
+ *
30
+ * The whole precompute-then-commit (including range/safety re-checks) runs
31
+ * inside pi's per-file mutation queue, acquired for every involved file in
32
+ * sorted path order before reading. This serializes against sibling
33
+ * `edit`/`write` tools on the same file and prevents lock-ordering deadlock
34
+ * across concurrent applies, while preserving all-or-nothing across files
35
+ * (ADR 0006).
28
36
  */
29
- export function applyWorkspaceEdit(edit: WorkspaceEdit): ApplyResult {
30
- const validation = validateEditAgainstFiles(edit);
31
- if (!validation.safe) {
32
- return { kind: "error", reason: validation.reason };
33
- }
34
-
37
+ export async function applyWorkspaceEdit(edit: WorkspaceEdit): Promise<ApplyResult> {
35
38
  const grouped = groupEditsByFile(edit.edits);
36
- const originalContents = readOriginalContents(grouped);
37
- if (originalContents.kind === "error") return originalContents;
38
-
39
- const transformedContents = buildTransformedContents(grouped, originalContents.contents);
40
- return commitTransformedContents(
41
- transformedContents,
42
- originalContents.contents,
43
- edit.edits.length,
44
- );
39
+ const files = [...grouped.keys()].sort();
40
+ return withAllMutationQueues(files, async () => {
41
+ const validation = validateEditAgainstFiles(edit);
42
+ if (!validation.safe) {
43
+ return { kind: "error", reason: validation.reason };
44
+ }
45
+
46
+ const originalContents = readOriginalContents(grouped);
47
+ if (originalContents.kind === "error") return originalContents;
48
+
49
+ const transformedContents = buildTransformedContents(grouped, originalContents.contents);
50
+ return commitTransformedContents(
51
+ transformedContents,
52
+ originalContents.contents,
53
+ edit.edits.length,
54
+ );
55
+ });
56
+ }
57
+
58
+ /**
59
+ * Acquire pi's per-file mutation queue for every involved file in sorted path
60
+ * order before running `fn`, holding all locks for the duration. Sorted order
61
+ * prevents lock-ordering deadlock across concurrent applies; per-file queues
62
+ * serialize against sibling `edit`/`write` tools on the same file (ADR 0006).
63
+ */
64
+ async function withAllMutationQueues<T>(files: string[], fn: () => Promise<T>): Promise<T> {
65
+ if (files.length === 0) return fn();
66
+ const [head, ...rest] = files;
67
+ return withFileMutationQueue(head, () => withAllMutationQueues(rest, fn));
45
68
  }
46
69
 
47
70
  function groupEditsByFile(edits: FileEdit[]): Map<string, FileEdit[]> {
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Tool executor for the stored-plan application path.
3
+ *
4
+ * Thin executor: delegates to the refactor apply use-case for plan lookup,
5
+ * freshness checking, safety validation, and workspace edit application.
6
+ */
7
+
8
+ import type { CodeIntelResult, CodeIntelToolExecCtx } from "../../types/index.ts";
9
+ import { executeRefactorApply } from "./orchestrate.ts";
10
+
11
+ export interface CodeRefactorApplyToolParams {
12
+ planId: string;
13
+ }
14
+
15
+ export async function executeRefactorApplyTool(
16
+ params: CodeRefactorApplyToolParams,
17
+ _ctx: CodeIntelToolExecCtx,
18
+ ): Promise<CodeIntelResult> {
19
+ return executeRefactorApply({ planId: params.planId }, { session: _ctx.session });
20
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Markdown renderer for refactor results.
3
+ */
4
+
5
+ import { createEvidenceList, renderEvidenceListDisclosure } from "../../analysis/evidence.ts";
6
+ import { toDisplayPath } from "../../analysis/search/ripgrep.ts";
7
+ import type { RefactorPlan } from "../../session/refactor-plans.ts";
8
+ import type { ApplyResult } from "./apply.ts";
9
+
10
+ export interface RefactorRenderInput {
11
+ result: ApplyResult;
12
+ operation: string;
13
+ targetDescription: string;
14
+ }
15
+
16
+ /**
17
+ * Render a refactor result as human-readable markdown.
18
+ */
19
+ export function renderRefactorResult(input: RefactorRenderInput): string {
20
+ const { result, operation, targetDescription } = input;
21
+
22
+ if (result.kind === "error") {
23
+ return `**Refactor failed:** ${result.reason}`;
24
+ }
25
+
26
+ return [
27
+ `**Refactor applied:** ${operation} on ${targetDescription}`,
28
+ `- Files changed: ${result.filesChanged}`,
29
+ `- Total edits: ${result.totalEdits}`,
30
+ ].join("\n");
31
+ }
32
+
33
+ /**
34
+ * Render a refactor plan preview.
35
+ */
36
+ export function renderRefactorPlanResult(plan: RefactorPlan, cwd: string): string {
37
+ const lines: string[] = [];
38
+ const changedFiles = collectChangedFiles(plan);
39
+ const fileCount = changedFiles.length;
40
+
41
+ lines.push(`# Refactor Plan: ${plan.operation}`);
42
+ lines.push("");
43
+ lines.push(`**Plan ID:** \`${plan.id}\``);
44
+ lines.push(`**Operation:** \`${plan.operation}\``);
45
+ lines.push(
46
+ `**Target:** \`${toDisplayPath(cwd, plan.targetFile)}\`:${plan.targetLine}:${plan.targetCharacter}`,
47
+ );
48
+ if (plan.newName) {
49
+ lines.push(`**New name:** \`${plan.newName}\``);
50
+ }
51
+ if (plan.destination) {
52
+ lines.push(`**Destination:** \`${plan.destination}\``);
53
+ }
54
+ lines.push(`**Files to change:** ${fileCount} file${fileCount !== 1 ? "s" : ""}`);
55
+ lines.push(`**Total edits:** ${plan.edits.edits.length}`);
56
+ lines.push("");
57
+
58
+ lines.push("## Files");
59
+ for (const [file, count] of changedFiles) {
60
+ lines.push(`- \`${toDisplayPath(cwd, file)}\` — ${count} edit${count !== 1 ? "s" : ""}`);
61
+ }
62
+ lines.push("");
63
+ lines.push("## Preview");
64
+ lines.push("");
65
+ const editEvidence = createEvidenceList({
66
+ key: "refactor.edits",
67
+ items: plan.edits.edits,
68
+ maxResults: 5,
69
+ });
70
+ for (const edit of editEvidence.items) {
71
+ const range = edit.range;
72
+ lines.push(
73
+ `- \`${toDisplayPath(cwd, edit.file)}\` L${range.start.line + 1}:${range.start.character} → L${range.end.line + 1}:${range.end.character}`,
74
+ );
75
+ lines.push(" ```");
76
+ lines.push(` ${edit.newText.slice(0, 80).split("\n").join("\n ")}`);
77
+ lines.push(" ```");
78
+ }
79
+ const disclosure = renderEvidenceListDisclosure(editEvidence);
80
+ if (disclosure) {
81
+ lines.push(disclosure);
82
+ }
83
+ lines.push("");
84
+ lines.push("**This is a preview. No files were changed.**");
85
+ lines.push(`Use code_refactor_apply with planId: "${plan.id}" to apply this refactor.`);
86
+ return lines.join("\n");
87
+ }
88
+
89
+ /**
90
+ * Render a refactor apply result.
91
+ */
92
+ export function renderRefactorApplyResult(applyResult: ApplyResult, plan: RefactorPlan): string {
93
+ if (applyResult.kind === "error") {
94
+ return `**Refactor apply failed:** ${applyResult.reason}`;
95
+ }
96
+ const lines = [
97
+ `**Refactor applied successfully.** Plan: \`${plan.id}\``,
98
+ `- Operation: \`${plan.operation}\``,
99
+ `- Files changed: ${applyResult.filesChanged}`,
100
+ `- Total edits: ${applyResult.totalEdits}`,
101
+ ];
102
+ if (plan.newName) {
103
+ lines.push(`- New name: \`${plan.newName}\``);
104
+ }
105
+ if (plan.destination) {
106
+ lines.push(`- Destination: \`${plan.destination}\``);
107
+ }
108
+ lines.push("", "Verify the changes before continuing with other work.");
109
+ return lines.join("\n");
110
+ }
111
+
112
+ function collectChangedFiles(plan: RefactorPlan): Array<[file: string, count: number]> {
113
+ const counts = new Map<string, number>();
114
+ for (const edit of plan.edits.edits) {
115
+ counts.set(edit.file, (counts.get(edit.file) ?? 0) + 1);
116
+ }
117
+ return [...counts.entries()];
118
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Refactor apply orchestration use-case.
3
+ *
4
+ * Handles plan lookup, freshness checking, safety re-validation, and
5
+ * workspace edit application for a previously stored refactor plan.
6
+ * Returns a rendered CodeIntelResult.
7
+ *
8
+ * Extracted from execute-refactor-apply.ts as part of the thin-executor
9
+ * normalization.
10
+ */
11
+
12
+ import { validateEdit } from "../../analysis/refactor/safety.ts";
13
+ import { isPlanFresh } from "../../session/refactor-plans.ts";
14
+ import type { WorkspaceCodeIntelligenceSession } from "../../session/session.ts";
15
+ import type { CodeIntelResult } from "../../types/index.ts";
16
+ import { unavailableSearchDetails } from "../infra/error-results.ts";
17
+ import { renderRefactorApplyResult } from "../refactor-plan/markdown.ts";
18
+ import { applyWorkspaceEdit } from "./apply.ts";
19
+
20
+ export interface RefactorApplyInput {
21
+ planId: string;
22
+ }
23
+
24
+ export interface RefactorApplyDeps {
25
+ session: WorkspaceCodeIntelligenceSession;
26
+ }
27
+
28
+ /**
29
+ * Execute the refactor apply use-case.
30
+ *
31
+ * Validates plan existence, freshness, and safety, then applies the
32
+ * workspace edit. Removes the plan from the session store on success.
33
+ */
34
+ export async function executeRefactorApply(
35
+ input: RefactorApplyInput,
36
+ deps: RefactorApplyDeps,
37
+ ): Promise<CodeIntelResult> {
38
+ if (!input.planId) {
39
+ return {
40
+ content: "**Error:** `planId` is required.",
41
+ details: unavailableSearchDetails(null, ["Provide a valid `planId` from code_refactor_plan"]),
42
+ };
43
+ }
44
+
45
+ const plan = deps.session.getPlan(input.planId);
46
+ if (!plan) {
47
+ return {
48
+ content: `**Error:** Plan "${input.planId}" not found. The plan may have expired or was generated in a different session. Use code_refactor_plan to generate a new plan.`,
49
+ details: unavailableSearchDetails(null, ["Run code_refactor_plan to generate a new plan"]),
50
+ };
51
+ }
52
+
53
+ const freshness = isPlanFresh(plan);
54
+ if (!freshness.fresh) {
55
+ return {
56
+ content: `**Stale plan:** ${freshness.reason}`,
57
+ details: unavailableSearchDetails(null, ["Regenerate the plan with code_refactor_plan"]),
58
+ };
59
+ }
60
+
61
+ const validation = validateEdit(plan.edits);
62
+ if (!validation.safe) {
63
+ return {
64
+ content: `**Safety check failed:** ${validation.reason}. Regenerate the plan with code_refactor_plan.`,
65
+ details: unavailableSearchDetails(null, ["Regenerate the plan with code_refactor_plan"]),
66
+ };
67
+ }
68
+
69
+ const applyResult = await applyWorkspaceEdit(plan.edits);
70
+ if (applyResult.kind === "applied") {
71
+ deps.session.removePlan(plan.id);
72
+ }
73
+
74
+ const content = renderRefactorApplyResult(applyResult, plan);
75
+
76
+ return {
77
+ content,
78
+ details: {
79
+ type: "search" as const,
80
+ data: {
81
+ confidence: "semantic" as const,
82
+ scope: null,
83
+ candidateCount: applyResult.kind === "applied" ? applyResult.totalEdits : 0,
84
+ omittedCount: 0,
85
+ nextQueries: ["`code_health` to check for new issues after the refactor"],
86
+ },
87
+ },
88
+ };
89
+ }