@mrclrchtr/supi-code-intelligence 6.1.0 → 6.3.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 (141) hide show
  1. package/README.md +3 -1
  2. package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  3. package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  4. package/node_modules/@mrclrchtr/supi-core/src/debug-identity.ts +11 -0
  5. package/node_modules/@mrclrchtr/supi-core/src/debug.ts +5 -0
  6. package/node_modules/@mrclrchtr/supi-lsp/README.md +23 -3
  7. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  8. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  9. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-identity.ts +11 -0
  10. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug.ts +5 -0
  11. package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/README.md +52 -0
  12. package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/index.js +785 -129
  13. package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/legacy.js +660 -98
  14. package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/package.json +10 -4
  15. package/node_modules/@mrclrchtr/supi-lsp/package.json +4 -5
  16. package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +16 -7
  17. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +1 -1
  18. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +0 -5
  19. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-publication.ts +6 -3
  20. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +2 -1
  21. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +5 -2
  22. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +2 -1
  23. package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +17 -5
  24. package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +40 -18
  25. package/node_modules/@mrclrchtr/supi-lsp/src/config/config.ts +164 -30
  26. package/node_modules/@mrclrchtr/supi-lsp/src/config/lsp-settings.ts +9 -87
  27. package/node_modules/@mrclrchtr/supi-lsp/src/config/server-config.ts +0 -1
  28. package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-scope.ts +4 -5
  29. package/node_modules/@mrclrchtr/supi-lsp/src/config/types.ts +0 -29
  30. package/node_modules/@mrclrchtr/supi-lsp/src/debug-telemetry.ts +7 -21
  31. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-severity.ts +6 -0
  32. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-summary.ts +11 -14
  33. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +0 -5
  34. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/stale-diagnostics.ts +0 -1
  35. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/workspace-sentinels.ts +29 -49
  36. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +1 -1
  37. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +4 -8
  38. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-helpers.ts +1 -9
  39. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-process-crash-report.ts +106 -0
  40. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +6 -3
  41. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +9 -1
  42. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +26 -41
  43. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +577 -152
  44. package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +4 -1
  45. package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-symbol-mapper.ts +59 -28
  46. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +27 -19
  47. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +54 -0
  48. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registration.ts +0 -17
  49. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +74 -19
  50. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +5 -2
  51. package/node_modules/@mrclrchtr/supi-lsp/src/session/scanner.ts +24 -21
  52. package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +29 -3
  53. package/node_modules/@mrclrchtr/supi-lsp/src/summary.ts +19 -40
  54. package/node_modules/@mrclrchtr/supi-lsp/src/utils.ts +13 -19
  55. package/node_modules/@mrclrchtr/supi-lsp/src/workspace-path-policy.ts +296 -0
  56. package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +6 -18
  57. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  58. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  59. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-identity.ts +11 -0
  60. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug.ts +5 -0
  61. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/README.md +29 -1
  62. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs +99 -19
  63. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs.map +4 -4
  64. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js +94 -18
  65. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js.map +4 -4
  66. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm +0 -0
  67. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm.map +14 -14
  68. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/package.json +13 -8
  69. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs +97 -19
  70. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs.map +4 -4
  71. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts +28 -8
  72. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts.map +1 -1
  73. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts +28 -8
  74. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts.map +1 -1
  75. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js +92 -18
  76. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js.map +4 -4
  77. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm +0 -0
  78. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm.map +17 -17
  79. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +7 -6
  80. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/kotlin/tree-sitter-kotlin.wasm +0 -0
  81. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/kotlin/tree-sitter-kotlin.wasm.json +2 -2
  82. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/sql/tree-sitter-sql.wasm +0 -0
  83. package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/sql/tree-sitter-sql.wasm.json +2 -2
  84. package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +1 -11
  85. package/node_modules/@mrclrchtr/supi-tree-sitter/src/coordinates.ts +19 -0
  86. package/node_modules/@mrclrchtr/supi-tree-sitter/src/language.ts +5 -23
  87. package/node_modules/@mrclrchtr/supi-tree-sitter/src/operation-support.ts +3 -21
  88. package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +5 -9
  89. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +10 -20
  90. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +7 -1
  91. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client.ts +9 -5
  92. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-protocol.ts +134 -9
  93. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-name.ts +96 -0
  94. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +11 -12
  95. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +39 -56
  96. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/exports.ts +9 -7
  97. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/js-binding-pattern.ts +26 -0
  98. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/node-at.ts +2 -21
  99. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline-html-sql.ts +144 -12
  100. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline.ts +50 -37
  101. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/scope.ts +138 -0
  102. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +0 -7
  103. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store.ts +1 -14
  104. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime.ts +0 -10
  105. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/service.ts +6 -8
  106. package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/worker-main.ts +34 -10
  107. package/package.json +5 -5
  108. package/src/analysis/capability/capability-warnings.ts +4 -22
  109. package/src/analysis/search/ast-scan-timing.ts +4 -2
  110. package/src/analysis/search/ast-scan.ts +1 -1
  111. package/src/api.ts +1 -0
  112. package/src/extension.ts +4 -2
  113. package/src/session/health-refresh.ts +26 -2
  114. package/src/session/health-types.ts +19 -0
  115. package/src/session/input/health-refactor.ts +16 -14
  116. package/src/session/refactor-types.ts +14 -1
  117. package/src/session/refactor-workflow.ts +21 -16
  118. package/src/substrate/lsp/lifecycle.ts +0 -3
  119. package/src/substrate/lsp/maintenance.ts +4 -5
  120. package/src/substrate/lsp/settings.ts +7 -9
  121. package/src/substrate/lsp/state.ts +0 -2
  122. package/src/substrate/workspace-provider-host.ts +2 -2
  123. package/src/tool/code_health/file-scope-markdown.ts +43 -0
  124. package/src/tool/code_health/markdown.ts +66 -66
  125. package/src/tool/code_health/refresh-outcome.ts +76 -0
  126. package/src/tool/code_health/refresh-status.ts +212 -23
  127. package/src/tool/code_health/result.ts +1 -0
  128. package/src/tool/code_health/tui.ts +18 -5
  129. package/src/tool/code_refactor_apply/guidance.ts +3 -2
  130. package/src/tool/code_refactor_plan/guidance.ts +1 -1
  131. package/src/tool/register.ts +5 -2
  132. package/src/tool/schemas.ts +21 -11
  133. package/node_modules/@mrclrchtr/supi-lsp/src/config/server-actions.ts +0 -59
  134. package/node_modules/@mrclrchtr/supi-lsp/src/pattern-matcher.ts +0 -24
  135. package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/generate-kotlin-wasm.mjs +0 -132
  136. package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/generate-sql-wasm.mjs +0 -158
  137. package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/vendor-wasm.mjs +0 -167
  138. package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +0 -42
  139. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-registration.ts +0 -37
  140. package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/service-registry.ts +0 -30
  141. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/structure.ts +0 -8
@@ -2,11 +2,19 @@ import {
2
2
  type CodeRequestControl,
3
3
  isCodeRequestInterruption,
4
4
  } from "@mrclrchtr/supi-code-runtime/api";
5
- import type { WorkspaceDiagnosticReport, WorkspaceLspRuntime } from "@mrclrchtr/supi-lsp/api";
5
+ import {
6
+ emptyProcessCrashRecoveryReport,
7
+ type WorkspaceDiagnosticReport,
8
+ type WorkspaceLspRuntime,
9
+ } from "@mrclrchtr/supi-lsp/api";
6
10
  import { recoverDiagnosticRuntime } from "../analysis/health/recovery.ts";
7
11
  import { mergeDiagnosticEvidence } from "../diagnostics/evidence.ts";
8
12
  import { refreshFileLspMaintenance, refreshLspMaintenance } from "../substrate/lsp/maintenance.ts";
9
- import type { HealthDiagnosticScope, HealthRefreshAttempt } from "./health-types.ts";
13
+ import type {
14
+ HealthDiagnosticScope,
15
+ HealthFileReadiness,
16
+ HealthRefreshAttempt,
17
+ } from "./health-types.ts";
10
18
 
11
19
  interface HealthRefreshAttemptOptions {
12
20
  readonly runtime: WorkspaceLspRuntime;
@@ -51,6 +59,8 @@ async function collectFileRefreshAttempt(
51
59
  undefined,
52
60
  options.control,
53
61
  );
62
+ const fileReadiness: HealthFileReadiness =
63
+ readiness.kind === "ready" ? "ready" : readiness.kind === "timeout" ? "pending" : "unavailable";
54
64
  return {
55
65
  attempt: {
56
66
  kind: "completed",
@@ -59,7 +69,9 @@ async function collectFileRefreshAttempt(
59
69
  requestedDiagnosticScope: scope,
60
70
  operationScope: "file-runtime",
61
71
  attemptedActiveClients: readiness.kind === "ready" ? 1 : 0,
72
+ fileReadiness,
62
73
  restartedClients: 0,
74
+ processCrashRecovery: readiness.processCrashRecovery ?? emptyProcessCrashRecoveryReport(),
63
75
  staleAssessment: {
64
76
  scope: "file",
65
77
  suspected: null,
@@ -95,6 +107,7 @@ async function collectWorkspaceRefreshAttempt(
95
107
  requestedDiagnosticScope: options.diagnosticsScope,
96
108
  operationScope: "workspace-runtime",
97
109
  diagnosticEvidence: maintenance.diagnosticEvidence,
110
+ processCrashRecovery: emptyProcessCrashRecoveryReport(),
98
111
  reason: maintenance.failureReason,
99
112
  },
100
113
  };
@@ -126,7 +139,16 @@ async function collectWorkspaceRefreshAttempt(
126
139
  elapsedMs: Date.now() - options.attemptedAt,
127
140
  requestedDiagnosticScope: options.diagnosticsScope,
128
141
  operationScope: "workspace-runtime",
142
+ attemptedActiveClients: recovery.attemptedClients,
143
+ restartedClients: recovery.restartedClients,
144
+ staleAssessment: {
145
+ scope: "workspace",
146
+ suspected: recovery.staleAssessment.suspected,
147
+ matchedFileCount: recovery.staleAssessment.matchedFiles.length,
148
+ warning: recovery.staleAssessment.warning,
149
+ },
129
150
  diagnosticEvidence,
151
+ processCrashRecovery: recovery.processCrashRecovery,
130
152
  reason: recovery.refreshFailureReason,
131
153
  },
132
154
  diagnosticReport: recovery.diagnosticReport,
@@ -141,6 +163,7 @@ async function collectWorkspaceRefreshAttempt(
141
163
  operationScope: "workspace-runtime",
142
164
  attemptedActiveClients: recovery.attemptedClients,
143
165
  restartedClients: recovery.restartedClients,
166
+ processCrashRecovery: recovery.processCrashRecovery,
144
167
  diagnosticEvidence,
145
168
  staleAssessment: {
146
169
  scope: "workspace",
@@ -163,6 +186,7 @@ async function collectWorkspaceRefreshAttempt(
163
186
  requestedDiagnosticScope: options.diagnosticsScope,
164
187
  operationScope: "workspace-runtime",
165
188
  diagnosticEvidence: maintenance.diagnosticEvidence,
189
+ processCrashRecovery: emptyProcessCrashRecoveryReport(),
166
190
  reason: errorMessage(error),
167
191
  },
168
192
  };
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  DiagnosticEvidenceSummary,
3
3
  FileScopeDecision,
4
+ ProcessCrashRecoveryReport,
4
5
  ProjectServerInfo,
5
6
  ProjectServerStatusReason,
6
7
  } from "@mrclrchtr/supi-lsp/api";
@@ -93,6 +94,9 @@ export interface HealthStaleAssessment {
93
94
 
94
95
  export type HealthRefreshOperationScope = "file-runtime" | "workspace-runtime";
95
96
 
97
+ /** Readiness result for a file-scoped maintenance attempt. */
98
+ export type HealthFileReadiness = "ready" | "pending" | "unavailable";
99
+
96
100
  /** Shared facts for one completed refresh or file-maintenance attempt. */
97
101
  interface CompletedHealthRefreshAttempt {
98
102
  readonly kind: "completed";
@@ -103,7 +107,12 @@ interface CompletedHealthRefreshAttempt {
103
107
  readonly requestedDiagnosticScope: HealthDiagnosticScope;
104
108
  /** Active clients targeted by the best-effort operation; this is not a confirmed-success count. */
105
109
  readonly attemptedActiveClients: number;
110
+ /** File readiness after the bounded wait, when this is file-scoped. */
111
+ readonly fileReadiness?: HealthFileReadiness;
112
+ /** Clients restarted by stale-diagnostic recovery. */
106
113
  readonly restartedClients: number;
114
+ /** Separate outcome for process-crash route recovery. */
115
+ readonly processCrashRecovery: ProcessCrashRecoveryReport;
107
116
  readonly staleAssessment: HealthStaleAssessment;
108
117
  }
109
118
 
@@ -125,8 +134,18 @@ export type HealthRefreshAttempt =
125
134
  readonly elapsedMs: number;
126
135
  readonly requestedDiagnosticScope: HealthDiagnosticScope;
127
136
  readonly operationScope: HealthRefreshOperationScope;
137
+ /** Active clients targeted before the operation failed, when available. */
138
+ readonly attemptedActiveClients?: number;
139
+ /** Clients restarted by stale-diagnostic recovery, when available. */
140
+ readonly restartedClients?: number;
141
+ /** Stale-diagnostic assessment, when the recovery pass returned one. */
142
+ readonly staleAssessment?: HealthStaleAssessment;
128
143
  /** Evidence collected before the operation failed, when available. */
129
144
  readonly diagnosticEvidence?: DiagnosticEvidenceSummary;
145
+ /** Process-crash outcome, when the recovery pass returned one. */
146
+ readonly processCrashRecovery?: ProcessCrashRecoveryReport;
147
+ /** File readiness outcome, when a file-scoped attempt failed. */
148
+ readonly fileReadiness?: HealthFileReadiness;
130
149
  readonly reason: string;
131
150
  };
132
151
 
@@ -1,11 +1,12 @@
1
1
  /** Runtime parsers for health and refactor session workflows. */
2
2
 
3
3
  import type { HealthSection, HealthWorkflowInput } from "../health-types.ts";
4
- import type {
5
- PublicSourceRange,
6
- RefactorApplyWorkflowInput,
7
- RefactorOperationInput,
8
- RefactorPlanWorkflowInput,
4
+ import {
5
+ PUBLIC_REFACTOR_OPERATION_NAMES,
6
+ type PublicSourceRange,
7
+ type RefactorApplyWorkflowInput,
8
+ type RefactorOperationInput,
9
+ type RefactorPlanWorkflowInput,
9
10
  } from "../refactor-types.ts";
10
11
  import type { RefactorTargetInput } from "../target-input.ts";
11
12
  import {
@@ -94,22 +95,23 @@ export function parseRefactorPlanWorkflowInput(
94
95
  function parseRefactorOperation(value: unknown): InputValidation<RefactorOperationInput> {
95
96
  const record = requireRecord(value, "operation");
96
97
  if (record.kind === "invalid-input") return record;
97
- const keysError = requireOnlyKeys(
98
- record.value,
99
- ["rename_symbol", "extract_function", "extract_variable"],
100
- "operation",
101
- );
98
+ const keysError = requireOnlyKeys(record.value, PUBLIC_REFACTOR_OPERATION_NAMES, "operation");
102
99
  if (keysError) return invalid(keysError);
103
- const selected = (["rename_symbol", "extract_function", "extract_variable"] as const).filter(
104
- (key) => record.value[key] !== undefined,
105
- );
100
+ const selected = PUBLIC_REFACTOR_OPERATION_NAMES.filter((key) => record.value[key] !== undefined);
106
101
  if (selected.length !== 1) return invalid("Select exactly one refactor operation.");
107
102
 
108
103
  const name = selected[0];
109
104
  const payload = requireRecord(record.value[name], `operation.${name}`);
110
105
  if (payload.kind === "invalid-input") return payload;
111
106
  if (name === "rename_symbol") return parseRenameOperation(payload.value);
112
- return parseExtractOperation(name, payload.value);
107
+ if (name === "extract_function" || name === "extract_variable") {
108
+ return parseExtractOperation(name, payload.value);
109
+ }
110
+ const payloadError = requireOnlyKeys(payload.value, [], `operation.${name}`);
111
+ if (payloadError) return invalid(payloadError);
112
+ return name === "update_imports"
113
+ ? valid({ update_imports: {} })
114
+ : valid({ delete_dead_code: {} });
113
115
  }
114
116
 
115
117
  function parseRenameOperation(
@@ -3,6 +3,17 @@ import type { ApplyResult } from "../analysis/refactor/apply.ts";
3
3
  import type { RefactorPlan } from "./refactor-plans.ts";
4
4
  import type { RefactorTargetInput, SourcePointInput } from "./target-input.ts";
5
5
 
6
+ /** Public refactor operations exposed by code_refactor_plan. */
7
+ export const PUBLIC_REFACTOR_OPERATION_NAMES = [
8
+ "rename_symbol",
9
+ "extract_function",
10
+ "extract_variable",
11
+ "update_imports",
12
+ "delete_dead_code",
13
+ ] as const;
14
+
15
+ export type PublicRefactorOperationName = (typeof PUBLIC_REFACTOR_OPERATION_NAMES)[number];
16
+
6
17
  export interface PublicSourceRange {
7
18
  readonly start: Omit<SourcePointInput, "file">;
8
19
  readonly end: Omit<SourcePointInput, "file">;
@@ -21,7 +32,9 @@ export type RefactorOperationInput =
21
32
  readonly newName: string;
22
33
  readonly range: PublicSourceRange;
23
34
  };
24
- };
35
+ }
36
+ | { readonly update_imports: Record<string, never> }
37
+ | { readonly delete_dead_code: Record<string, never> };
25
38
 
26
39
  export interface RefactorPlanWorkflowInput {
27
40
  readonly target: RefactorTargetInput;
@@ -26,13 +26,14 @@ import {
26
26
  isPlanFresh,
27
27
  type RefactorPlan,
28
28
  } from "./refactor-plans.ts";
29
- import type {
30
- PublicSourceRange,
31
- RefactorApplyWorkflowInput,
32
- RefactorApplyWorkflowOutcome,
33
- RefactorOperationInput,
34
- RefactorPlanWorkflowInput,
35
- RefactorPlanWorkflowOutcome,
29
+ import {
30
+ PUBLIC_REFACTOR_OPERATION_NAMES,
31
+ type PublicSourceRange,
32
+ type RefactorApplyWorkflowInput,
33
+ type RefactorApplyWorkflowOutcome,
34
+ type RefactorOperationInput,
35
+ type RefactorPlanWorkflowInput,
36
+ type RefactorPlanWorkflowOutcome,
36
37
  } from "./refactor-types.ts";
37
38
  import { resolveTargetWorkflow, type TargetWorkflowDeps } from "./target-workflow.ts";
38
39
  import { reportProgress, throwIfAborted, type WorkflowControl } from "./workflow-control.ts";
@@ -208,13 +209,11 @@ function parseOperation(input: RefactorOperationInput):
208
209
  | {
209
210
  kind: "ok";
210
211
  operation: RefactorOperation;
211
- newName: string;
212
+ newName?: string;
212
213
  range?: PublicSourceRange;
213
214
  }
214
215
  | { kind: "invalid-input"; message: string } {
215
- const keys = ["rename_symbol", "extract_function", "extract_variable"].filter(
216
- (key) => key in input,
217
- );
216
+ const keys = PUBLIC_REFACTOR_OPERATION_NAMES.filter((key) => key in input);
218
217
  if (keys.length !== 1) {
219
218
  return { kind: "invalid-input", message: "Select exactly one refactor operation." };
220
219
  }
@@ -233,11 +232,17 @@ function parseOperation(input: RefactorOperationInput):
233
232
  range: input.extract_function.range,
234
233
  };
235
234
  }
235
+ if ("extract_variable" in input) {
236
+ return {
237
+ kind: "ok",
238
+ operation: "extract_variable",
239
+ newName: input.extract_variable.newName,
240
+ range: input.extract_variable.range,
241
+ };
242
+ }
236
243
  return {
237
244
  kind: "ok",
238
- operation: "extract_variable",
239
- newName: input.extract_variable.newName,
240
- range: input.extract_variable.range,
245
+ operation: "update_imports" in input ? "update_imports" : "delete_dead_code",
241
246
  };
242
247
  }
243
248
 
@@ -265,13 +270,13 @@ async function planWithProvider(
265
270
  file: string;
266
271
  position: { line: number; character: number };
267
272
  range?: SourceRange;
268
- newName: string;
273
+ newName?: string;
269
274
  },
270
275
  control?: WorkflowControl,
271
276
  ): Promise<RefactorResult> {
272
277
  if (!provider) return { kind: "unavailable", reason: "No semantic provider is active." };
273
278
  if (provider.refactor) return provider.refactor(request, control);
274
- if (request.operation === "rename_symbol" && provider.rename) {
279
+ if (request.operation === "rename_symbol" && request.newName !== undefined && provider.rename) {
275
280
  return provider.rename(request.file, request.position, request.newName, control);
276
281
  }
277
282
  return {
@@ -45,7 +45,6 @@ export function registerLspSessionLifecycle(
45
45
  await state.providerLease?.release();
46
46
  state.providerLease = null;
47
47
  state.controller = null;
48
- state.lspActive = false;
49
48
  state.sentinelSnapshot = new Map();
50
49
 
51
50
  const lease = await acquireWorkspaceProviderHost(ctx.cwd, {
@@ -53,7 +52,6 @@ export function registerLspSessionLifecycle(
53
52
  });
54
53
  state.providerLease = lease;
55
54
  state.controller = lease.lspController;
56
- state.lspActive = lease.lspController?.kind === "ready";
57
55
  state.sentinelSnapshot = lease.sentinelSnapshot;
58
56
  await onStarted?.(ctx);
59
57
  startLifecycleSubscription();
@@ -64,7 +62,6 @@ export function registerLspSessionLifecycle(
64
62
  await state.providerLease?.release();
65
63
  state.providerLease = null;
66
64
  state.controller = null;
67
- state.lspActive = false;
68
65
  state.sentinelSnapshot = new Map();
69
66
  dispatchStateChange();
70
67
  });
@@ -24,7 +24,6 @@ import {
24
24
  isLikelyStaleDiagnostic,
25
25
  isProjectConfigFileName,
26
26
  raceRequestControl,
27
- syncWorkspaceSentinelSnapshot,
28
27
  type WorkspaceLspRuntime,
29
28
  } from "@mrclrchtr/supi-lsp/api";
30
29
  import { mergeDiagnosticEvidence } from "../../diagnostics/evidence.ts";
@@ -56,7 +55,7 @@ export async function refreshLspMaintenance(
56
55
  sentinelSnapshot: Map<string, number>,
57
56
  options: LspMaintenanceOptions = {},
58
57
  ): Promise<WorkspaceLspMaintenanceResult> {
59
- const { snapshot } = await synchronizeSentinels(runtime, cwd, sentinelSnapshot, options);
58
+ const { snapshot } = await synchronizeSentinels(runtime, sentinelSnapshot, options);
60
59
  let diagnosticEvidence = emptyEvidence();
61
60
  let failureReason: string | undefined;
62
61
 
@@ -115,7 +114,7 @@ export async function refreshFileLspMaintenance(options: {
115
114
  const { runtime, cwd, sentinelSnapshot, filePath, control } = options;
116
115
  // A cancelled caller stops before any maintenance work starts.
117
116
  throwIfCodeRequestInterrupted(control);
118
- const { snapshot } = await synchronizeSentinels(runtime, cwd, sentinelSnapshot);
117
+ const { snapshot } = await synchronizeSentinels(runtime, sentinelSnapshot);
119
118
  const target = nodePath.resolve(filePath);
120
119
  const stale = confirmedOutstandingDiagnostics(runtime, cwd).some(
121
120
  (entry) =>
@@ -149,12 +148,11 @@ export async function refreshFileLspMaintenance(options: {
149
148
  */
150
149
  async function synchronizeSentinels(
151
150
  runtime: WorkspaceLspRuntime,
152
- cwd: string,
153
151
  sentinelSnapshot: Map<string, number>,
154
152
  options: LspMaintenanceOptions = {},
155
153
  ) {
156
154
  const primed = sentinelSnapshot.size > 0;
157
- const state = syncWorkspaceSentinelSnapshot(cwd, sentinelSnapshot, {
155
+ const state = runtime.syncWorkspaceSentinelSnapshot(sentinelSnapshot, {
158
156
  includeSourceFiles: true,
159
157
  });
160
158
 
@@ -193,6 +191,7 @@ async function trackCreatedSourceFiles(
193
191
  if (change.type !== FileChangeType.Created) continue;
194
192
  const filePath = uriToFile(change.uri);
195
193
  if (scope && !isWithinOrEqual(scope, filePath)) continue;
194
+ if (!runtime.isSupportedSourceFile(filePath)) continue;
196
195
  // Best-effort: a file no client can serve stays untracked and is
197
196
  // simply absent from evidence until a later explicit request.
198
197
  await runtime.trackFile(filePath);
@@ -1,8 +1,7 @@
1
1
  // LSP settings registration for the code-intelligence umbrella extension.
2
2
  //
3
- // Always-on LSP policy: the global `lsp.enabled` and `lsp.active` keys
4
- // are deprecated and ignored. Per-language disable via
5
- // `lsp.servers.<language>.enabled: false` is the only supported opt-out.
3
+ // Per-language disable via `lsp.servers.<language>.enabled: false` is the
4
+ // supported opt-out.
6
5
  //
7
6
  // Registered fields:
8
7
  // - exclude: stringList
@@ -21,11 +20,9 @@ import {
21
20
  } from "@mrclrchtr/supi-core/settings";
22
21
  import { type LspSettings, loadConfig } from "@mrclrchtr/supi-lsp/api";
23
22
 
24
- const LSP_DEFAULTS: LspSettings = {
25
- enabled: true,
26
- active: [],
27
- exclude: [],
28
- };
23
+ const LSP_DEFAULTS = {
24
+ exclude: [] as string[],
25
+ } satisfies LspSettings;
29
26
 
30
27
  /** Discover configured servers from the defaults + effective LSP config. */
31
28
  function getConfiguredServers(cwd: string): string[] {
@@ -153,7 +150,8 @@ export function registerLspSettings(pi: ExtensionAPI): void {
153
150
  kind: "stringList" as const,
154
151
  key: "exclude",
155
152
  label: "Exclude Patterns",
156
- description: "Gitignore patterns to suppress LSP diagnostics (comma-separated)",
153
+ description:
154
+ "Comma-separated gitignore patterns for automatic LSP workspace work. Exact file requests stay available.",
157
155
  },
158
156
  {
159
157
  kind: "custom" as const,
@@ -22,7 +22,6 @@ export interface LspAdapterState {
22
22
  controller: LspRuntimeController | null;
23
23
  providerLease: WorkspaceProviderHostLease | null;
24
24
  inspector: LspInspectorState;
25
- lspActive: boolean;
26
25
  /** Snapshot of workspace sentinel files (package.json, tsconfig, lockfiles) for change detection. */
27
26
  sentinelSnapshot: Map<string, number>;
28
27
  /** Fired for runtime lifecycle changes that require a footer render. */
@@ -34,7 +33,6 @@ export function createLspAdapterState(): LspAdapterState {
34
33
  controller: null,
35
34
  providerLease: null,
36
35
  inspector: { handle: null, close: null },
37
- lspActive: false,
38
36
  sentinelSnapshot: new Map(),
39
37
  stateChanges: new EventTarget(),
40
38
  };
@@ -1,7 +1,7 @@
1
1
  import { realpathSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
3
  import { getDefaultWorkspaceRuntime } from "@mrclrchtr/supi-code-runtime/api";
4
- import { LspRuntimeController, scanWorkspaceSentinels } from "@mrclrchtr/supi-lsp/api";
4
+ import { LspRuntimeController } from "@mrclrchtr/supi-lsp/api";
5
5
  import { TreeSitterRuntimeController } from "@mrclrchtr/supi-tree-sitter/api";
6
6
 
7
7
  const HOSTS = Symbol.for("supi-code-intelligence/workspace-provider-hosts");
@@ -77,7 +77,7 @@ class WorkspaceProviderHost {
77
77
  lspController: projectTrusted ? this.#lsp : null,
78
78
  sentinelSnapshot:
79
79
  projectTrusted && this.#lsp?.kind === "ready"
80
- ? scanWorkspaceSentinels(this.cwd)
80
+ ? (this.#lsp.workspaceRuntime?.scanWorkspaceSentinels() ?? new Map())
81
81
  : new Map(),
82
82
  release: async () => {
83
83
  if (released) return;
@@ -0,0 +1,43 @@
1
+ import type { HealthDiagnosticObservation } from "../../session/health-types.ts";
2
+
3
+ /** Render the tsconfig coverage result for a single-file health request. */
4
+ export function renderFileScopeStatus(
5
+ lines: string[],
6
+ observation: Extract<
7
+ HealthDiagnosticObservation,
8
+ { kind: "completed" | "partial" | "unavailable" }
9
+ >,
10
+ cwd: string,
11
+ ): void {
12
+ if (observation.scope.kind !== "file" || !observation.scopeStatus) return;
13
+
14
+ const decision = observation.scopeStatus;
15
+ switch (decision.status) {
16
+ case "included":
17
+ lines.push(
18
+ `**Tsconfig**: covered by ${formatConfigPath(decision.configPath, cwd)} — part of workspace diagnostics.`,
19
+ );
20
+ return;
21
+ case "excluded":
22
+ lines.push(
23
+ `**Tsconfig**: NOT covered by ${formatConfigPath(decision.configPath, cwd)} — not part of workspace diagnostics.`,
24
+ );
25
+ return;
26
+ case "no-config":
27
+ lines.push("**Tsconfig**: no tsconfig.json or jsconfig.json found — nothing filtered.");
28
+ return;
29
+ case "out-of-tree":
30
+ lines.push("**Tsconfig**: outside the project root — not part of workspace diagnostics.");
31
+ }
32
+ }
33
+
34
+ /** Format a config path relative to the current workspace. */
35
+ function formatConfigPath(configPath: string | null, cwd: string): string {
36
+ if (!configPath) return "no config";
37
+ return `\`${makeRelative(cwd, configPath)}\``;
38
+ }
39
+
40
+ /** Format a workspace path without exposing an absolute root. */
41
+ export function makeRelative(cwd: string, file: string): string {
42
+ return file.startsWith(cwd) ? file.slice(cwd.length + 1) : file;
43
+ }