@mrclrchtr/supi-code-intelligence 4.9.0 → 5.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 (215) hide show
  1. package/README.md +2 -1
  2. package/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  3. package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  4. package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  5. package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  6. package/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  7. package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  8. package/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  9. package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  10. package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  11. package/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  12. package/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
  13. package/node_modules/@mrclrchtr/supi-core/src/debug-timing.ts +34 -21
  14. package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  15. package/node_modules/@mrclrchtr/supi-lsp/README.md +80 -5
  16. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  17. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  18. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  19. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  20. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  21. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  22. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  23. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  24. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  25. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  26. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
  27. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-timing.ts +34 -21
  28. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  29. package/node_modules/@mrclrchtr/supi-lsp/package.json +7 -6
  30. package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +10 -0
  31. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +206 -0
  32. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +78 -0
  33. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-collection.ts +114 -0
  34. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-evidence.ts +372 -0
  35. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-host.ts +14 -0
  36. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-pull.ts +62 -0
  37. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +491 -0
  38. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-request.ts +9 -0
  39. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +215 -0
  40. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-waiters.ts +206 -0
  41. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +370 -266
  42. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-state.ts +52 -0
  43. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-sync.ts +185 -0
  44. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-file-state.ts +25 -0
  45. package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +467 -115
  46. package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +238 -11
  47. package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +10 -1
  48. package/node_modules/@mrclrchtr/supi-lsp/src/config/defaults.json +1 -1
  49. package/node_modules/@mrclrchtr/supi-lsp/src/debug-telemetry.ts +45 -0
  50. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +38 -0
  51. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +79 -9
  52. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +13 -4
  53. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +300 -24
  54. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +5 -2
  55. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +464 -96
  56. package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-refactor-provider.ts +130 -0
  57. package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +45 -329
  58. package/node_modules/@mrclrchtr/supi-lsp/src/provider/refactor-planning.ts +57 -120
  59. package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-edit-normalizer.ts +320 -0
  60. package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-symbol-mapper.ts +207 -0
  61. package/node_modules/@mrclrchtr/supi-lsp/src/session/readiness.ts +72 -2
  62. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +151 -26
  63. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostic-surface.ts +40 -0
  64. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +50 -0
  65. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +136 -120
  66. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +49 -0
  67. package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +102 -0
  68. package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +26 -6
  69. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
  70. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  71. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
  72. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
  73. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
  74. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
  75. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +2 -0
  76. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  77. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
  78. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
  79. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
  80. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-timing.ts +34 -21
  81. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
  82. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/LICENSE +21 -0
  83. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/README.md +258 -0
  84. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/babel.cjs +257 -0
  85. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/jiti.cjs +1 -0
  86. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-cli.mjs +34 -0
  87. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-hooks.mjs +124 -0
  88. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-native.mjs +121 -0
  89. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.d.mts +1 -0
  90. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.mjs +4 -0
  91. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-static.mjs +23 -0
  92. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.cjs +30 -0
  93. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.cts +8 -0
  94. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.mts +8 -0
  95. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.mjs +29 -0
  96. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/types.d.ts +420 -0
  97. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/package.json +146 -0
  98. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm +0 -0
  99. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm.map +4 -4
  100. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/package.json +1 -1
  101. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm +0 -0
  102. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm.map +4 -4
  103. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +7 -3
  104. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/kotlin/tree-sitter-kotlin.wasm.json +1 -1
  105. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/sql/tree-sitter-sql.wasm.json +1 -1
  106. package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +0 -9
  107. package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +0 -8
  108. package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +16 -12
  109. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +65 -87
  110. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +47 -95
  111. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-timing.ts +147 -0
  112. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client-lifecycle.ts +39 -0
  113. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client.ts +561 -0
  114. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-message-size.ts +24 -0
  115. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-protocol.ts +452 -0
  116. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +4 -2
  117. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +12 -4
  118. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/exports.ts +4 -2
  119. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/imports.ts +4 -2
  120. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/node-at.ts +5 -3
  121. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +33 -12
  122. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/blocking-test-bootstrap.mjs +34 -0
  123. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/bootstrap.mjs +8 -0
  124. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store-helpers.ts +23 -0
  125. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store.ts +400 -0
  126. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/request-control.ts +48 -0
  127. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-parser-helpers.ts +24 -0
  128. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-query-helpers.ts +43 -0
  129. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime.ts +421 -0
  130. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/service.ts +116 -0
  131. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/worker-main.ts +201 -0
  132. package/package.json +5 -5
  133. package/src/analysis/health/diagnostics.ts +236 -24
  134. package/src/analysis/health/recovery.ts +6 -2
  135. package/src/analysis/provider.ts +58 -0
  136. package/src/analysis/readiness.ts +30 -9
  137. package/src/analysis/refactor/apply.ts +59 -20
  138. package/src/analysis/refactor/mutation-authority.ts +143 -0
  139. package/src/analysis/refactor/position.ts +47 -0
  140. package/src/analysis/refactor/safety.ts +18 -10
  141. package/src/analysis/relations/callees.ts +9 -1
  142. package/src/analysis/relations/types.ts +5 -2
  143. package/src/analysis/search/ast-scan-timing.ts +9 -4
  144. package/src/analysis/search/ast-scan.ts +1 -1
  145. package/src/analysis/search/deadline.ts +2 -2
  146. package/src/analysis/search/pattern-analysis.ts +46 -32
  147. package/src/analysis/search/pattern.ts +12 -2
  148. package/src/analysis/target/anchored.ts +20 -11
  149. package/src/analysis/target/file.ts +18 -11
  150. package/src/analysis/target/identity.ts +19 -3
  151. package/src/analysis/target/symbol.ts +36 -15
  152. package/src/api.ts +4 -0
  153. package/src/diagnostics/evidence.ts +51 -0
  154. package/src/session/capability-adapter.ts +12 -3
  155. package/src/session/find-workflow.ts +17 -7
  156. package/src/session/graph/collect.ts +18 -2
  157. package/src/session/graph-workflow.ts +19 -12
  158. package/src/session/health-refresh.ts +148 -0
  159. package/src/session/health-types.ts +37 -15
  160. package/src/session/health-workflow.ts +37 -39
  161. package/src/session/inspect/collect.ts +20 -3
  162. package/src/session/inspect-workflow.ts +10 -5
  163. package/src/session/orientation/collect.ts +10 -1
  164. package/src/session/orientation/context-facts.ts +3 -1
  165. package/src/session/orientation/context-sections.ts +20 -7
  166. package/src/session/orientation/gather.ts +17 -11
  167. package/src/session/orientation-types.ts +2 -1
  168. package/src/session/orientation-workflow.ts +15 -8
  169. package/src/session/refactor-plans.ts +2 -0
  170. package/src/session/refactor-workflow.ts +59 -14
  171. package/src/session/session.ts +4 -1
  172. package/src/session/target-workflow.ts +54 -23
  173. package/src/session/workflow-control.ts +7 -3
  174. package/src/substrate/lsp/lifecycle.ts +26 -46
  175. package/src/substrate/lsp/maintenance.ts +199 -25
  176. package/src/substrate/lsp/state.ts +2 -2
  177. package/src/substrate/workspace-provider-host.ts +25 -3
  178. package/src/tool/find/execute.ts +7 -1
  179. package/src/tool/find/render.ts +20 -3
  180. package/src/tool/find/tui.ts +23 -21
  181. package/src/tool/graph/execute.ts +23 -3
  182. package/src/tool/graph/tui.ts +59 -46
  183. package/src/tool/health/execute.ts +7 -2
  184. package/src/tool/health/markdown.ts +56 -14
  185. package/src/tool/health/refresh-status.ts +105 -0
  186. package/src/tool/health/tui.ts +95 -98
  187. package/src/tool/infra/workflow-control.ts +8 -0
  188. package/src/tool/inspect/execute.ts +7 -1
  189. package/src/tool/inspect/tui.ts +26 -18
  190. package/src/tool/orientation/execute.ts +21 -3
  191. package/src/tool/orientation/tui.ts +51 -35
  192. package/src/tool/refactor-apply/execute.ts +3 -0
  193. package/src/tool/refactor-apply/tui.ts +43 -25
  194. package/src/tool/refactor-plan/execute.ts +4 -0
  195. package/src/tool/refactor-plan/tui.ts +33 -20
  196. package/src/tool/register.ts +127 -22
  197. package/src/tool/resolve/execute.ts +18 -1
  198. package/src/tool/resolve/tui.ts +42 -24
  199. package/src/tool/result/display.ts +107 -0
  200. package/src/tool/result/errors.ts +20 -17
  201. package/src/tool/result/find.ts +52 -8
  202. package/src/tool/result/graph.ts +44 -1
  203. package/src/tool/result/health.ts +53 -1
  204. package/src/tool/result/inspect.ts +113 -1
  205. package/src/tool/result/orientation.ts +66 -14
  206. package/src/tool/result/refactor.ts +36 -4
  207. package/src/tool/result/resolve.ts +44 -7
  208. package/src/tool/result/types.ts +20 -0
  209. package/src/types/execution.ts +18 -5
  210. package/src/types/index.ts +8 -1
  211. package/src/ui/status-command.ts +5 -3
  212. package/src/ui/status-overlay.ts +4 -0
  213. package/src/ui/tui/common.ts +108 -10
  214. package/src/ui/tui/display.ts +48 -0
  215. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime.ts +0 -247
@@ -0,0 +1,207 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import type {
3
+ CodeLocation,
4
+ CodeSymbol,
5
+ DeclarationNesting,
6
+ DocumentCodeSymbol,
7
+ SourceRange,
8
+ } from "@mrclrchtr/supi-code-runtime/api";
9
+ import { uriToFile } from "@mrclrchtr/supi-core/path";
10
+ import type {
11
+ DocumentSymbol,
12
+ Hover,
13
+ Location,
14
+ LocationLink,
15
+ MarkupContent,
16
+ SymbolInformation,
17
+ } from "../config/types.ts";
18
+
19
+ /** Map one LSP location result to shared code locations. */
20
+ export function mapLocations(value: Location | Location[] | LocationLink[] | null): CodeLocation[] {
21
+ if (!value) return [];
22
+ const locations = Array.isArray(value) ? value : [value];
23
+ return locations.flatMap((item) => {
24
+ const location = toCodeLocation(item);
25
+ return location ? [location] : [];
26
+ });
27
+ }
28
+
29
+ function toCodeLocation(item: Location | LocationLink): CodeLocation | null {
30
+ const loc = item as Record<string, unknown>;
31
+ const uri = loc.uri ?? loc.targetUri;
32
+ if (typeof uri !== "string") return null;
33
+ const range = loc.targetSelectionRange ?? loc.targetRange ?? loc.range;
34
+ if (!range || typeof range !== "object") return null;
35
+ const r = range as { start: Record<string, unknown>; end: Record<string, unknown> };
36
+ if (!r.start || !r.end) return null;
37
+ return {
38
+ uri,
39
+ range: {
40
+ start: {
41
+ line: (r.start.line as number) ?? 0,
42
+ character: (r.start.character as number) ?? 0,
43
+ },
44
+ end: { line: (r.end.line as number) ?? 0, character: (r.end.character as number) ?? 0 },
45
+ },
46
+ };
47
+ }
48
+
49
+ const SYMBOL_KIND_NAMES: Record<number, string> = {
50
+ 1: "File",
51
+ 2: "Module",
52
+ 3: "Namespace",
53
+ 4: "Package",
54
+ 5: "Class",
55
+ 6: "Method",
56
+ 7: "Property",
57
+ 8: "Field",
58
+ 9: "Constructor",
59
+ 10: "Enum",
60
+ 11: "Interface",
61
+ 12: "Function",
62
+ 13: "Variable",
63
+ 14: "Constant",
64
+ 15: "String",
65
+ 16: "Number",
66
+ 17: "Boolean",
67
+ 18: "Array",
68
+ 19: "Object",
69
+ 20: "Key",
70
+ 21: "Null",
71
+ 22: "EnumMember",
72
+ 23: "Struct",
73
+ 24: "Event",
74
+ 25: "Operator",
75
+ 26: "TypeParameter",
76
+ };
77
+
78
+ function symbolKindName(kind: number): string {
79
+ return SYMBOL_KIND_NAMES[kind] ?? "Unknown";
80
+ }
81
+
82
+ /** Flatten provider symbols while preserving declaration and name anchors. */
83
+ export async function mapDocumentSymbols(
84
+ symbols: DocumentSymbol[] | SymbolInformation[],
85
+ filePath: string,
86
+ ): Promise<DocumentCodeSymbol[]> {
87
+ return flattenDocumentSymbols(symbols, filePath, null, {
88
+ sourceLines: await readSourceLines(filePath),
89
+ nesting: "top-level",
90
+ });
91
+ }
92
+
93
+ function flattenDocumentSymbols(
94
+ symbols: DocumentSymbol[] | SymbolInformation[],
95
+ filePath: string,
96
+ container: string | null,
97
+ context: { sourceLines: readonly string[] | null; nesting: DeclarationNesting },
98
+ ): DocumentCodeSymbol[] {
99
+ const result: DocumentCodeSymbol[] = [];
100
+ for (const sym of symbols) {
101
+ let information: SymbolInformation | null = null;
102
+ let document: DocumentSymbol | null = null;
103
+ if (isSymbolInformation(sym)) information = sym;
104
+ else document = sym;
105
+ const declStart = document?.range.start ?? information?.location.range.start;
106
+ if (!declStart) continue;
107
+ const nameStart = document
108
+ ? resolveDocumentSymbolNameStart(document, context.sourceLines)
109
+ : null;
110
+ const symbol: DocumentCodeSymbol = {
111
+ name: sym.name,
112
+ kind: symbolKindName(sym.kind),
113
+ file: filePath,
114
+ declarationAnchor: { line: declStart.line + 1, character: declStart.character + 1 },
115
+ container: information?.containerName ?? container,
116
+ nesting: information ? "unknown" : context.nesting,
117
+ };
118
+ if (nameStart) {
119
+ symbol.nameAnchor = { line: nameStart.line + 1, character: nameStart.character + 1 };
120
+ }
121
+ result.push(symbol);
122
+ if (document?.children?.length) {
123
+ result.push(
124
+ ...flattenDocumentSymbols(document.children, filePath, sym.name, {
125
+ sourceLines: context.sourceLines,
126
+ nesting: "nested",
127
+ }),
128
+ );
129
+ }
130
+ }
131
+ return result;
132
+ }
133
+
134
+ function isSymbolInformation(
135
+ symbol: DocumentSymbol | SymbolInformation,
136
+ ): symbol is SymbolInformation {
137
+ return "location" in symbol;
138
+ }
139
+
140
+ async function readSourceLines(filePath: string): Promise<readonly string[] | null> {
141
+ try {
142
+ return (await readFile(filePath, "utf-8")).split(/\r?\n/);
143
+ } catch {
144
+ return null;
145
+ }
146
+ }
147
+
148
+ function resolveDocumentSymbolNameStart(
149
+ symbol: DocumentSymbol,
150
+ sourceLines: readonly string[] | null,
151
+ ): { line: number; character: number } | null {
152
+ const selectionStart = symbol.selectionRange?.start;
153
+ if (!selectionStart) return null;
154
+ if (!sourceLines) return selectionStart;
155
+ const sourceLine = sourceLines[selectionStart.line];
156
+ if (sourceLine === undefined) return null;
157
+ if (
158
+ sourceLine.slice(selectionStart.character, selectionStart.character + symbol.name.length) ===
159
+ symbol.name
160
+ ) {
161
+ return selectionStart;
162
+ }
163
+ const rangeStart = symbol.range?.start;
164
+ const rangeEnd = symbol.range?.end;
165
+ const from = rangeStart?.line === selectionStart.line ? rangeStart.character : 0;
166
+ const until = rangeEnd?.line === selectionStart.line ? rangeEnd.character : sourceLine.length;
167
+ const character = sourceLine.indexOf(symbol.name, from);
168
+ if (character < 0 || character + symbol.name.length > until) return null;
169
+ return { line: selectionStart.line, character };
170
+ }
171
+
172
+ /** Map one workspace symbol to the shared representation. */
173
+ export function toCodeSymbol(sym: SymbolInformation): CodeSymbol {
174
+ const start = sym.location?.range?.start;
175
+ return {
176
+ name: sym.name,
177
+ kind: symbolKindName(sym.kind),
178
+ file: uriToFile(sym.location?.uri ?? ""),
179
+ declarationAnchor: {
180
+ line: start ? start.line + 1 : 0,
181
+ character: start ? start.character + 1 : 0,
182
+ },
183
+ container: sym.containerName ?? null,
184
+ };
185
+ }
186
+
187
+ /** Convert an LSP hover response to the shared representation. */
188
+ export function convertLspHover(hover: Hover): { contents: string; range?: SourceRange } {
189
+ const result: { contents: string; range?: SourceRange } = {
190
+ contents: extractHoverText(hover.contents),
191
+ };
192
+ if (hover.range) {
193
+ result.range = {
194
+ start: { line: hover.range.start.line, character: hover.range.start.character },
195
+ end: { line: hover.range.end.line, character: hover.range.end.character },
196
+ };
197
+ }
198
+ return result;
199
+ }
200
+
201
+ function extractHoverText(contents: Hover["contents"]): string {
202
+ if (typeof contents === "string") return contents;
203
+ if (Array.isArray(contents)) {
204
+ return contents.map((item) => (typeof item === "string" ? item : item.value)).join("\n");
205
+ }
206
+ return (contents as MarkupContent).value ?? "";
207
+ }
@@ -1,3 +1,10 @@
1
+ import {
2
+ type CodeRequestControl,
3
+ CodeRequestDeadlineError,
4
+ isCodeRequestInterruption,
5
+ throwIfCodeRequestInterrupted,
6
+ } from "@mrclrchtr/supi-code-runtime/api";
7
+
1
8
  const DEFAULT_SEMANTIC_READY_TIMEOUT_MS = 15_000;
2
9
 
3
10
  export type ReadinessValueResult<T> =
@@ -5,26 +12,88 @@ export type ReadinessValueResult<T> =
5
12
  | { kind: "timeout" }
6
13
  | { kind: "unavailable"; reason: string };
7
14
 
15
+ /**
16
+ * Race one promise against request-control interruption (abort or absolute
17
+ * deadline) and rethrow the interruption. The underlying promise keeps its
18
+ * own lifecycle; only the caller's wait stops promptly.
19
+ */
20
+ export async function raceRequestControl<T>(
21
+ promise: Promise<T>,
22
+ control?: CodeRequestControl,
23
+ ): Promise<T> {
24
+ if (!control) return promise;
25
+ // Preflight: an already-cancelled caller stops even when the awaited
26
+ // promise is already settled.
27
+ throwIfCodeRequestInterrupted(control);
28
+ const deadlineRemaining =
29
+ control.deadline === undefined ? undefined : control.deadline - Date.now();
30
+ let timer: ReturnType<typeof setTimeout> | undefined;
31
+ let abortHandler: (() => void) | undefined;
32
+ try {
33
+ return await Promise.race([
34
+ promise,
35
+ new Promise<never>((_resolve, reject) => {
36
+ if (deadlineRemaining !== undefined && deadlineRemaining <= 0) {
37
+ reject(new CodeRequestDeadlineError());
38
+ return;
39
+ }
40
+ if (deadlineRemaining !== undefined) {
41
+ timer = setTimeout(() => reject(new CodeRequestDeadlineError()), deadlineRemaining);
42
+ }
43
+ abortHandler = () => reject(control.signal?.reason ?? new Error("Request cancelled"));
44
+ if (control.signal?.aborted) abortHandler();
45
+ else control.signal?.addEventListener("abort", abortHandler, { once: true });
46
+ }),
47
+ ]);
48
+ } finally {
49
+ if (timer) clearTimeout(timer);
50
+ if (abortHandler) control.signal?.removeEventListener("abort", abortHandler);
51
+ }
52
+ }
53
+
8
54
  /** Await one readiness operation while preserving its concrete success value. */
9
55
  export async function raceReadinessValue<T>(
10
56
  readiness: Promise<T>,
11
57
  timeoutMs: number | undefined,
58
+ control?: CodeRequestControl,
12
59
  ): Promise<ReadinessValueResult<T>> {
60
+ // Preflight: an already-cancelled caller stops even when the readiness
61
+ // promise is already settled.
62
+ throwIfCodeRequestInterrupted(control);
13
63
  const effectiveTimeoutMs = timeoutMs ?? DEFAULT_SEMANTIC_READY_TIMEOUT_MS;
64
+ const deadlineRemaining =
65
+ control?.deadline === undefined ? undefined : control.deadline - Date.now();
66
+ const bindMs =
67
+ deadlineRemaining === undefined
68
+ ? effectiveTimeoutMs
69
+ : Math.min(effectiveTimeoutMs, deadlineRemaining);
14
70
  let timer: ReturnType<typeof setTimeout> | null = null;
71
+ let abortHandler: (() => void) | undefined;
15
72
 
16
73
  try {
17
74
  const value = await Promise.race([
18
75
  readiness,
19
76
  new Promise<never>((_resolve, reject) => {
20
77
  timer = setTimeout(
21
- () => reject(new Error("semantic-readiness-timeout")),
22
- effectiveTimeoutMs,
78
+ () =>
79
+ reject(
80
+ deadlineRemaining !== undefined && deadlineRemaining < effectiveTimeoutMs
81
+ ? new CodeRequestDeadlineError()
82
+ : new Error("semantic-readiness-timeout"),
83
+ ),
84
+ Math.max(0, bindMs),
23
85
  );
24
86
  }),
87
+ new Promise<never>((_resolve, reject) => {
88
+ abortHandler = () =>
89
+ reject(control?.signal?.reason ?? new Error("Readiness wait cancelled"));
90
+ if (control?.signal?.aborted) abortHandler();
91
+ else control?.signal?.addEventListener("abort", abortHandler, { once: true });
92
+ }),
25
93
  ]);
26
94
  return { kind: "resolved", value };
27
95
  } catch (error) {
96
+ if (isCodeRequestInterruption(error, control)) throw error;
28
97
  if (error instanceof Error && error.message === "semantic-readiness-timeout") {
29
98
  return { kind: "timeout" };
30
99
  }
@@ -34,5 +103,6 @@ export async function raceReadinessValue<T>(
34
103
  };
35
104
  } finally {
36
105
  if (timer) clearTimeout(timer);
106
+ if (abortHandler) control?.signal?.removeEventListener("abort", abortHandler);
37
107
  }
38
108
  }
@@ -7,13 +7,16 @@
7
7
  //
8
8
  // It does NOT import pi event types or ExtensionAPI.
9
9
 
10
+ // biome-ignore lint/style/noExcessiveLinesPerFile: session lifecycle, capability projection, and telemetry stay in one controller.
10
11
  import type { WorkspaceRuntime } from "@mrclrchtr/supi-code-runtime/api";
12
+ import { recordDebugEvent } from "@mrclrchtr/supi-core/debug";
11
13
  import { loadConfig } from "../config/config.ts";
12
14
  import { type LspSettings, loadLspSettings } from "../config/lsp-settings.ts";
13
15
  import { clearTsconfigCache } from "../config/tsconfig-scope.ts";
14
16
  import type { DetectedProjectServer, LspConfig, ProjectServerInfo } from "../config/types.ts";
17
+ import { truncateIdentity } from "../debug-telemetry.ts";
15
18
  import { scanWorkspaceSentinels } from "../diagnostics/workspace-sentinels.ts";
16
- import { LspManager } from "../manager/manager.ts";
19
+ import { LspManager, type ManagerLifecycleTransition } from "../manager/manager.ts";
17
20
  import {
18
21
  markLspCapabilitiesReady,
19
22
  registerPendingLspCapabilities,
@@ -25,6 +28,7 @@ import {
25
28
  setWorkspaceLspRuntimeState,
26
29
  type WorkspaceLspRuntime,
27
30
  } from "./runtime-registry.ts";
31
+ import { recordLspRuntimeTransition } from "./runtime-transition-debug.ts";
28
32
  import { scanMissingServers, scanProjectCapabilities, startDetectedServers } from "./scanner.ts";
29
33
 
30
34
  // ── Types ─────────────────────────────────────────────────────────────
@@ -72,6 +76,28 @@ export type LspStartResult =
72
76
  | { kind: "disabled"; message: string }
73
77
  | { kind: "unavailable"; reason: string };
74
78
 
79
+ /** Cause of one observable LSP runtime lifecycle transition. */
80
+ export type LspRuntimeTransitionKind =
81
+ | "startup"
82
+ | "readiness"
83
+ | "crash"
84
+ | "recovery"
85
+ | "shutdown"
86
+ | "tracked-files";
87
+
88
+ /** Immutable aggregate state published when the LSP runtime changes. */
89
+ export interface LspRuntimeTransition {
90
+ /** Monotonic transition generation for this controller instance. */
91
+ readonly generation: number;
92
+ readonly kind: LspRuntimeTransitionKind;
93
+ /** True only when at least one concrete client is active and ready. */
94
+ readonly semanticReady: boolean;
95
+ readonly projectServers: readonly ProjectServerInfo[];
96
+ }
97
+
98
+ /** Listener for aggregate LSP runtime transitions. */
99
+ export type LspRuntimeTransitionListener = (transition: LspRuntimeTransition) => void;
100
+
75
101
  function supersededStartResult(): LspStartResult {
76
102
  return { kind: "unavailable", reason: "LSP startup was superseded by a newer lifecycle event." };
77
103
  }
@@ -99,7 +125,13 @@ export class LspRuntimeController {
99
125
  readonly #cwd: string;
100
126
  #state: LspControllerState;
101
127
  #capabilityRuntime: WorkspaceRuntime | null;
102
- /** Monotonic ownership token for starts, shutdowns, and async warm-up. */
128
+ #activeManager: LspManager | null = null;
129
+ #latestManagerTransition: ManagerLifecycleTransition | null = null;
130
+ #projectedSemanticReady: boolean | null = null;
131
+ #lifecycleGeneration = 0;
132
+ #latestLifecycleTransition: LspRuntimeTransition | null = null;
133
+ readonly #lifecycleListeners = new Set<LspRuntimeTransitionListener>();
134
+ /** Monotonic ownership token for starts, shutdowns, and manager callbacks. */
103
135
  #readinessGeneration = 0;
104
136
 
105
137
  constructor(cwd: string, runtime?: WorkspaceRuntime) {
@@ -151,6 +183,22 @@ export class LspRuntimeController {
151
183
  this.#capabilityRuntime = runtime;
152
184
  }
153
185
 
186
+ /**
187
+ * Subscribe to aggregate runtime transitions.
188
+ *
189
+ * A late subscriber immediately receives the latest transition. The returned
190
+ * function is idempotent and stops all later notifications for this listener.
191
+ */
192
+ subscribeLifecycle(listener: LspRuntimeTransitionListener): () => void {
193
+ this.#lifecycleListeners.add(listener);
194
+ if (this.#latestLifecycleTransition) {
195
+ this.notifyLifecycleListener(listener, this.#latestLifecycleTransition);
196
+ }
197
+ return () => {
198
+ this.#lifecycleListeners.delete(listener);
199
+ };
200
+ }
201
+
154
202
  /**
155
203
  * Start the LSP session for this controller's cwd.
156
204
  *
@@ -191,8 +239,11 @@ export class LspRuntimeController {
191
239
  */
192
240
  private async cleanupExistingSession(): Promise<void> {
193
241
  if (this.#state.kind !== "ready") return;
242
+ this.#activeManager = null;
243
+ this.#latestManagerTransition = null;
194
244
  await this.#state.runtimeOwner.shutdown();
195
245
  if (this.#capabilityRuntime) unregisterLspCapabilities(this.#capabilityRuntime, this.#cwd);
246
+ this.#projectedSemanticReady = null;
196
247
  clearWorkspaceLspRuntime(this.#cwd);
197
248
  }
198
249
 
@@ -200,7 +251,10 @@ export class LspRuntimeController {
200
251
  private setDisabled(generation: number): LspStartResult {
201
252
  if (generation !== this.#readinessGeneration) return supersededStartResult();
202
253
  const message = "All language servers are disabled by configuration.";
254
+ this.#activeManager = null;
255
+ this.#latestManagerTransition = null;
203
256
  if (this.#capabilityRuntime) unregisterLspCapabilities(this.#capabilityRuntime, this.#cwd);
257
+ this.#projectedSemanticReady = null;
204
258
  this.#state = { kind: "disabled", message };
205
259
  setWorkspaceLspRuntimeState(this.#cwd, { kind: "disabled" });
206
260
  return { kind: "disabled", message };
@@ -210,6 +264,10 @@ export class LspRuntimeController {
210
264
  private setUnavailable(error: unknown, generation: number): LspStartResult {
211
265
  if (generation !== this.#readinessGeneration) return supersededStartResult();
212
266
  const reason = error instanceof Error ? error.message : String(error);
267
+ this.#activeManager = null;
268
+ this.#latestManagerTransition = null;
269
+ if (this.#capabilityRuntime) unregisterLspCapabilities(this.#capabilityRuntime, this.#cwd);
270
+ this.#projectedSemanticReady = null;
213
271
  this.#state = { kind: "unavailable", reason };
214
272
  setWorkspaceLspRuntimeState(this.#cwd, { kind: "unavailable", reason });
215
273
  return { kind: "unavailable", reason };
@@ -229,7 +287,13 @@ export class LspRuntimeController {
229
287
  if (Object.keys(config.servers).length === 0) return this.setDisabled(generation);
230
288
  this.#state = { kind: "pending" };
231
289
 
232
- const manager = new LspManager(config, this.#cwd);
290
+ let manager: LspManager;
291
+ manager = new LspManager(config, this.#cwd, (transition) => {
292
+ this.handleManagerLifecycle(manager, generation, transition);
293
+ });
294
+ this.#activeManager = manager;
295
+ this.#latestManagerTransition = null;
296
+ this.publishLifecycle("startup", false, []);
233
297
  manager.setExcludePatterns(settings.exclude);
234
298
  setWorkspaceLspRuntimeState(this.#cwd, { kind: "pending" });
235
299
 
@@ -237,6 +301,7 @@ export class LspRuntimeController {
237
301
  manager.registerDetectedServers(detectedServers);
238
302
  await startDetectedServers(manager, detectedServers);
239
303
  if (generation !== this.#readinessGeneration) {
304
+ if (this.#activeManager === manager) this.#activeManager = null;
240
305
  await manager.shutdownAll();
241
306
  return supersededStartResult();
242
307
  }
@@ -249,9 +314,17 @@ export class LspRuntimeController {
249
314
 
250
315
  if (this.#capabilityRuntime) {
251
316
  registerPendingLspCapabilities(this.#capabilityRuntime, this.#cwd, workspaceRuntime);
317
+ this.#projectedSemanticReady = false;
252
318
  }
253
319
 
254
- const projectServers = workspaceRuntime.getProjectServers();
320
+ const latestManagerTransition = this
321
+ .#latestManagerTransition as ManagerLifecycleTransition | null;
322
+ const projectServers = [
323
+ ...(latestManagerTransition?.projectServers ?? workspaceRuntime.getProjectServers()),
324
+ ];
325
+ const semanticReady =
326
+ latestManagerTransition?.semanticReady ??
327
+ projectServers.some((server) => server.status === "running" && server.ready);
255
328
 
256
329
  this.#state = {
257
330
  kind: "ready",
@@ -262,40 +335,88 @@ export class LspRuntimeController {
262
335
  settings,
263
336
  };
264
337
 
265
- void this.promoteSemanticReadiness(workspaceRuntime, generation);
338
+ this.projectSemanticReadiness(workspaceRuntime, semanticReady);
266
339
 
267
340
  return { kind: "ready", runtime: workspaceRuntime };
268
341
  }
269
342
 
270
- private async promoteSemanticReadiness(
271
- workspaceRuntime: WorkspaceLspRuntime,
343
+ private handleManagerLifecycle(
344
+ manager: LspManager,
272
345
  readinessGeneration: number,
273
- ): Promise<void> {
274
- try {
275
- const readiness = await workspaceRuntime.waitUntilReadyForWorkspace();
276
- if (readiness.kind !== "ready") return;
277
- } catch {
346
+ transition: ManagerLifecycleTransition,
347
+ ): void {
348
+ if (readinessGeneration !== this.#readinessGeneration) return;
349
+ if (this.#activeManager !== manager) return;
350
+ this.#latestManagerTransition = transition;
351
+ if (this.#state.kind === "ready") {
352
+ this.#state.projectServers = [...transition.projectServers];
353
+ this.projectSemanticReadiness(this.#state.workspaceRuntime, transition.semanticReady);
354
+ }
355
+ this.publishLifecycle(transition.kind, transition.semanticReady, transition.projectServers);
356
+ }
357
+
358
+ private projectSemanticReadiness(
359
+ workspaceRuntime: WorkspaceLspRuntime,
360
+ semanticReady: boolean,
361
+ ): void {
362
+ if (!this.#capabilityRuntime) return;
363
+ if (semanticReady) {
364
+ if (this.#projectedSemanticReady === true) return;
365
+ markLspCapabilitiesReady(this.#capabilityRuntime, this.#cwd);
366
+ this.#projectedSemanticReady = true;
367
+ this.recordCapabilityTransition(true);
278
368
  return;
279
369
  }
370
+ if (this.#projectedSemanticReady === false) return;
371
+ registerPendingLspCapabilities(this.#capabilityRuntime, this.#cwd, workspaceRuntime);
372
+ this.#projectedSemanticReady = false;
373
+ this.recordCapabilityTransition(false);
374
+ }
280
375
 
281
- if (!this.isCurrentRuntime(workspaceRuntime, readinessGeneration)) return;
282
- if (this.#state.kind !== "ready") return;
376
+ /** Record one semantic capability ready↔pending transition for telemetry. */
377
+ private recordCapabilityTransition(ready: boolean): void {
378
+ recordDebugEvent({
379
+ source: "lsp",
380
+ level: "debug",
381
+ category: "capability.transition",
382
+ message: `LSP capability transition: ${ready ? "ready" : "pending"}`,
383
+ cwd: truncateIdentity(this.#cwd),
384
+ data: { ready },
385
+ });
386
+ }
283
387
 
284
- this.#state.projectServers = workspaceRuntime.getProjectServers();
285
- if (this.#capabilityRuntime) {
286
- markLspCapabilitiesReady(this.#capabilityRuntime, this.#cwd);
388
+ private publishLifecycle(
389
+ kind: LspRuntimeTransitionKind,
390
+ semanticReady: boolean,
391
+ projectServers: readonly ProjectServerInfo[],
392
+ ): void {
393
+ const transition: LspRuntimeTransition = {
394
+ generation: ++this.#lifecycleGeneration,
395
+ kind,
396
+ semanticReady,
397
+ projectServers: projectServers.map((server) => ({
398
+ ...server,
399
+ fileTypes: [...server.fileTypes],
400
+ supportedActions: [...server.supportedActions],
401
+ openFiles: [...server.openFiles],
402
+ })),
403
+ };
404
+ recordLspRuntimeTransition(this.#cwd, transition);
405
+ this.#latestLifecycleTransition = transition;
406
+ for (const listener of this.#lifecycleListeners) {
407
+ this.notifyLifecycleListener(listener, transition);
287
408
  }
288
409
  }
289
410
 
290
- private isCurrentRuntime(
291
- workspaceRuntime: WorkspaceLspRuntime,
292
- readinessGeneration: number,
293
- ): boolean {
294
- return (
295
- readinessGeneration === this.#readinessGeneration &&
296
- this.#state.kind === "ready" &&
297
- this.#state.workspaceRuntime === workspaceRuntime
298
- );
411
+ private notifyLifecycleListener(
412
+ listener: LspRuntimeTransitionListener,
413
+ transition: LspRuntimeTransition,
414
+ ): void {
415
+ try {
416
+ listener(transition);
417
+ } catch {
418
+ // Lifecycle observers must not alter runtime behavior.
419
+ }
299
420
  }
300
421
 
301
422
  /**
@@ -307,10 +428,13 @@ export class LspRuntimeController {
307
428
  async shutdown(): Promise<void> {
308
429
  this.#readinessGeneration++;
309
430
  clearTsconfigCache();
431
+ this.#activeManager = null;
432
+ this.#latestManagerTransition = null;
310
433
 
311
434
  if (this.#capabilityRuntime) {
312
435
  unregisterLspCapabilities(this.#capabilityRuntime, this.#cwd);
313
436
  }
437
+ this.#projectedSemanticReady = null;
314
438
 
315
439
  if (this.#cwd) {
316
440
  clearWorkspaceLspRuntime(this.#cwd);
@@ -321,6 +445,7 @@ export class LspRuntimeController {
321
445
  }
322
446
 
323
447
  this.#state = { kind: "initial" };
448
+ this.publishLifecycle("shutdown", false, []);
324
449
  }
325
450
 
326
451
  /** Get the missing servers warning (servers whose binary is not on PATH). */
@@ -0,0 +1,40 @@
1
+ import type { CodeQueryResult, CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
2
+ import type { Diagnostic } from "../config/types.ts";
3
+ import type {
4
+ DiagnosticEvidenceSummary,
5
+ OutstandingDiagnosticSummaryEntry,
6
+ RecoverDiagnosticsResult,
7
+ WorkspaceDiagnosticSnapshot,
8
+ WorkspaceDiagnosticSummaryEntry,
9
+ } from "./runtime-diagnostics.ts";
10
+
11
+ /** Diagnostic and recovery operations owned by a workspace LSP runtime. */
12
+ export interface WorkspaceLspDiagnosticSurface {
13
+ fileDiagnostics(
14
+ filePath: string,
15
+ maxSeverity?: number,
16
+ control?: CodeRequestControl,
17
+ ): Promise<CodeQueryResult<Diagnostic[]>>;
18
+ /** Re-synchronize tracked documents and return exact five-state evidence coverage. */
19
+ refreshOpenDiagnostics(
20
+ options?: { maxWaitMs?: number; quietMs?: number },
21
+ control?: CodeRequestControl,
22
+ ): Promise<DiagnosticEvidenceSummary>;
23
+ /** Return tracked-file counts with aggregate cache freshness and evidence coverage. */
24
+ getWorkspaceDiagnosticSummary(): WorkspaceDiagnosticSnapshot<WorkspaceDiagnosticSummaryEntry>;
25
+ /** Return tracked-file messages with aggregate cache freshness and evidence coverage. */
26
+ getOutstandingDiagnostics(
27
+ maxSeverity?: number,
28
+ ): WorkspaceDiagnosticSnapshot<{ file: string; diagnostics: Diagnostic[] }>;
29
+ /** Return tracked-file severity counts with aggregate cache freshness and evidence coverage. */
30
+ getOutstandingDiagnosticSummary(
31
+ maxSeverity?: number,
32
+ ): WorkspaceDiagnosticSnapshot<OutstandingDiagnosticSummaryEntry>;
33
+ /** Run best-effort recovery and retain final diagnostic evidence, including failures. */
34
+ recoverDiagnostics(options?: {
35
+ restartIfStillStale?: boolean;
36
+ maxWaitMs?: number;
37
+ quietMs?: number;
38
+ control?: CodeRequestControl;
39
+ }): Promise<RecoverDiagnosticsResult>;
40
+ }