@mrclrchtr/supi-code-intelligence 6.3.0 → 7.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 (136) hide show
  1. package/README.md +164 -82
  2. package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  3. package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +8 -1
  4. package/node_modules/@mrclrchtr/supi-core/README.md +8 -0
  5. package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  6. package/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +10 -3
  7. package/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
  8. package/node_modules/@mrclrchtr/supi-core/src/llm.ts +141 -16
  9. package/node_modules/@mrclrchtr/supi-lsp/README.md +35 -13
  10. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  11. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +8 -1
  12. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +8 -0
  13. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  14. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +10 -3
  15. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
  16. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/llm.ts +141 -16
  17. package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/index.js +3 -1
  18. package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/legacy.js +3 -1
  19. package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/package.json +1 -1
  20. package/node_modules/@mrclrchtr/supi-lsp/package.json +3 -3
  21. package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +16 -0
  22. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +43 -35
  23. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +83 -17
  24. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-collection.ts +108 -92
  25. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-evidence.ts +44 -82
  26. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-host.ts +3 -4
  27. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-publication.ts +9 -68
  28. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-pull.ts +45 -58
  29. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +230 -331
  30. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-request.ts +201 -1
  31. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +129 -70
  32. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-typescript.ts +395 -0
  33. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-waiters.ts +8 -12
  34. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +685 -183
  35. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-state.ts +2 -2
  36. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-sync.ts +60 -60
  37. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-request-enrollment.ts +75 -0
  38. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-semantic-input-barrier.ts +443 -0
  39. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-semantic-input-errors.ts +30 -0
  40. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-semantic-input-file.ts +15 -0
  41. package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +290 -37
  42. package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +72 -16
  43. package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +1 -0
  44. package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-scope.ts +30 -4
  45. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +1 -1
  46. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/workspace-sentinels.ts +4 -32
  47. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/workspace-sources.ts +108 -0
  48. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +10 -4
  49. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-process-crash-report.ts +50 -1
  50. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +11 -7
  51. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +770 -56
  52. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostic-surface.ts +3 -1
  53. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +37 -4
  54. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +48 -12
  55. package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +50 -4
  56. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  57. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +8 -1
  58. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +8 -0
  59. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  60. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +10 -3
  61. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
  62. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/llm.ts +141 -16
  63. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +3 -3
  64. package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +2 -0
  65. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callee-display-name.ts +165 -0
  66. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +67 -9
  67. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +2 -0
  68. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +19 -18
  69. package/node_modules/yaml/browser/dist/nodes/Alias.js +25 -23
  70. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +19 -18
  71. package/node_modules/yaml/dist/nodes/Alias.js +25 -23
  72. package/node_modules/yaml/package.json +1 -1
  73. package/package.json +5 -5
  74. package/src/analysis/health/diagnostics.ts +1 -2
  75. package/src/analysis/health/file-scope.ts +4 -1
  76. package/src/analysis/health/server-status.ts +1 -1
  77. package/src/analysis/relations/callees.ts +17 -8
  78. package/src/analysis/relations/implementations.ts +1 -2
  79. package/src/analysis/relations/references.ts +8 -4
  80. package/src/analysis/relations/types.ts +6 -30
  81. package/src/analysis/target/anchored.ts +9 -1
  82. package/src/analysis/target/symbol.ts +29 -11
  83. package/src/analysis/target/types.ts +14 -6
  84. package/src/api.ts +2 -0
  85. package/src/session/graph/collect.ts +18 -3
  86. package/src/session/health-refresh.ts +27 -11
  87. package/src/session/health-types.ts +21 -4
  88. package/src/session/health-workflow.ts +28 -22
  89. package/src/session/orientation-types.ts +5 -6
  90. package/src/session/orientation-workflow.ts +10 -2
  91. package/src/session/session.ts +12 -5
  92. package/src/session/target-workflow.ts +9 -6
  93. package/src/substrate/lsp/maintenance.ts +53 -47
  94. package/src/substrate/lsp/source-tracking.ts +252 -0
  95. package/src/tool/code_find/guidance.ts +3 -3
  96. package/src/tool/code_find/spec.ts +5 -4
  97. package/src/tool/code_find/tui.ts +7 -1
  98. package/src/tool/code_graph/details.ts +32 -0
  99. package/src/tool/code_graph/display.ts +54 -0
  100. package/src/tool/code_graph/format.ts +60 -0
  101. package/src/tool/code_graph/guidance.ts +2 -2
  102. package/src/tool/code_graph/markdown.ts +76 -198
  103. package/src/tool/code_graph/read-next.ts +65 -0
  104. package/src/tool/code_graph/result.ts +118 -83
  105. package/src/tool/code_graph/tui.ts +216 -54
  106. package/src/tool/code_health/guidance.ts +3 -5
  107. package/src/tool/code_health/markdown.ts +90 -57
  108. package/src/tool/code_health/refresh-outcome.ts +51 -0
  109. package/src/tool/code_health/refresh-status.ts +130 -43
  110. package/src/tool/code_health/scope.ts +78 -0
  111. package/src/tool/code_health/spec.ts +1 -1
  112. package/src/tool/code_health/tui.ts +29 -38
  113. package/src/tool/code_inspect/guidance.ts +5 -3
  114. package/src/tool/code_inspect/tui.ts +7 -1
  115. package/src/tool/code_orientation/guidance.ts +3 -4
  116. package/src/tool/code_orientation/result.ts +31 -8
  117. package/src/tool/code_orientation/tui.ts +26 -5
  118. package/src/tool/code_refactor_apply/guidance.ts +1 -1
  119. package/src/tool/code_refactor_apply/tui.ts +7 -3
  120. package/src/tool/code_refactor_plan/guidance.ts +3 -5
  121. package/src/tool/code_refactor_plan/tui.ts +7 -1
  122. package/src/tool/code_resolve/guidance.ts +3 -5
  123. package/src/tool/code_resolve/result.ts +13 -10
  124. package/src/tool/code_resolve/tui.ts +18 -1
  125. package/src/tool/guidance.ts +11 -9
  126. package/src/tool/infra/truncate.ts +39 -13
  127. package/src/tool/result/candidate-row.ts +27 -0
  128. package/src/tool/result/errors.ts +21 -6
  129. package/src/tool/result/types.ts +7 -3
  130. package/src/tool/schemas.ts +5 -0
  131. package/src/types/execution.ts +2 -0
  132. package/src/types/index.ts +2 -0
  133. package/src/ui/tui/candidate-legacy-body.ts +69 -0
  134. package/src/ui/tui/candidate-selection.ts +366 -0
  135. package/src/ui/tui/common.ts +26 -31
  136. package/src/ui/tui/execution-error.ts +92 -0
@@ -56,8 +56,8 @@ export function hasCurrentDiagnosticEvidence(
56
56
  /**
57
57
  * Test whether cached diagnostics confirm the current document state.
58
58
  *
59
- * A current tentative push matches the document state but cannot support a
60
- * clean-result or cache-reuse claim until a republish confirms it (ADR 0021).
59
+ * A current push matches the document state but cannot support a clean-result
60
+ * or cache-reuse claim until request evidence replaces it.
61
61
  */
62
62
  export function hasConfirmedDiagnosticEvidence(
63
63
  document: OpenDocumentState | undefined,
@@ -1,5 +1,5 @@
1
1
  import { readFileSync } from "node:fs";
2
- import type { TextDocumentItem, VersionedTextDocumentIdentifier } from "../config/types.ts";
2
+ import type { VersionedTextDocumentIdentifier } from "../config/types.ts";
3
3
  import type { DiagnosticSynchronization } from "./client-diagnostic-evidence.ts";
4
4
  import type { DiagnosticWaitRegistry } from "./client-diagnostic-waiters.ts";
5
5
  import { fingerprintDocumentContent, type OpenDocumentState } from "./client-document-state.ts";
@@ -47,13 +47,20 @@ function contentChanges(
47
47
  return [{ text: content }];
48
48
  }
49
49
 
50
- /** Advance and publish one explicit document synchronization. */
51
- export function synchronizeDocument(options: SynchronizeDocumentOptions): void {
50
+ /** Retain one document synchronization while advancing its evidence revision. */
51
+ function retainDocumentSynchronization(
52
+ options: Pick<SynchronizeDocumentOptions, "uri" | "document" | "evidenceRevision" | "waiters">,
53
+ ): void {
52
54
  options.waiters.releaseFile(options.uri);
53
55
  options.waiters.cancelSettle();
56
+ options.document.evidenceRevision = options.evidenceRevision;
57
+ }
58
+
59
+ /** Advance and publish one explicit document synchronization. */
60
+ export function synchronizeDocument(options: SynchronizeDocumentOptions): void {
61
+ retainDocumentSynchronization(options);
54
62
  options.document.version = options.version;
55
63
  options.document.synchronizationId = options.synchronizationId;
56
- options.document.evidenceRevision = options.evidenceRevision;
57
64
  const changes = contentChanges(
58
65
  options.document.content,
59
66
  options.content,
@@ -83,44 +90,6 @@ export function clearTrackedDocumentState(
83
90
  waiters.cancelSettle();
84
91
  }
85
92
 
86
- /** Close and reopen one open document while preserving cache and version history. */
87
- export function reopenDocument(options: {
88
- uri: string;
89
- content: string;
90
- document: OpenDocumentState;
91
- languageId: string;
92
- nextVersion(): number;
93
- nextSynchronizationId(): number;
94
- evidenceRevision: number;
95
- waiters: DiagnosticWaitRegistry;
96
- sendNotification: NotificationSender;
97
- markUnversionedSyncMoment?(): void;
98
- }): void {
99
- // Mirror didClose release semantics: pending waiters for this URI observe
100
- // the protocol close, and the settle generation is cancelled so concurrent
101
- // settles re-arm against the reopened state.
102
- options.waiters.releaseFile(options.uri);
103
- options.waiters.cancelSettle();
104
- options.markUnversionedSyncMoment?.();
105
- options.sendNotification("textDocument/didClose", {
106
- textDocument: { uri: options.uri },
107
- });
108
- const version = options.nextVersion();
109
- options.document.version = version;
110
- options.document.synchronizationId = options.nextSynchronizationId();
111
- options.document.evidenceRevision = options.evidenceRevision;
112
- options.document.content = options.content;
113
- options.document.contentFingerprint = fingerprintDocumentContent(options.content);
114
- options.sendNotification("textDocument/didOpen", {
115
- textDocument: {
116
- uri: options.uri,
117
- languageId: options.languageId,
118
- version,
119
- text: options.content,
120
- } satisfies TextDocumentItem,
121
- });
122
- }
123
-
124
93
  /** Synchronize one open document, or open it when the route is not tracked yet. */
125
94
  export function synchronizeTrackedDocument(options: {
126
95
  uri: string;
@@ -161,6 +130,10 @@ interface ResynchronizeDocumentsOptions {
161
130
  nextVersion(uri: string): number;
162
131
  nextSynchronizationId(): number;
163
132
  evidenceRevision: number;
133
+ /** Invalidate route evidence before the first changed document is applied. */
134
+ noteInputContentChange(): number;
135
+ /** Record the verified disk content in the shared semantic barrier. */
136
+ observeDiskContent(uri: string, content: string): void;
164
137
  incrementalSync: boolean;
165
138
  sendNotification: NotificationSender;
166
139
  uriToFile(uri: string): string;
@@ -188,32 +161,49 @@ export interface ResynchronizeDocumentsResult {
188
161
  export function resynchronizeOpenDocuments(
189
162
  options: ResynchronizeDocumentsOptions,
190
163
  ): ResynchronizeDocumentsResult {
191
- const synchronizations: DiagnosticSynchronization[] = [];
164
+ const synchronizedUris = new Set<string>();
192
165
  const resynchronizedUris = new Set<string>();
193
166
  const removedFiles: string[] = [];
194
167
  const failedFiles: string[] = [];
168
+ let synchronizationRevision = options.evidenceRevision;
169
+ let inputChangeNoted = false;
195
170
  for (const [uri, document] of options.openDocuments) {
196
171
  const filePath = options.uriToFile(uri);
197
172
  try {
198
173
  options.markUnversionedSyncMoment(uri);
199
- synchronizeDocument({
200
- uri,
201
- content: options.preloadedContent?.get(uri) ?? readFileSync(filePath, "utf-8"),
202
- document,
203
- version: options.nextVersion(uri),
204
- synchronizationId: options.nextSynchronizationId(),
205
- evidenceRevision: options.evidenceRevision,
206
- incrementalSync: options.incrementalSync,
207
- waiters: options.waiters,
208
- sendNotification: options.sendNotification,
209
- });
174
+ const content = options.preloadedContent?.get(uri) ?? readFileSync(filePath, "utf-8");
175
+ const contentChanged = fingerprintDocumentContent(content) !== document.contentFingerprint;
176
+ if (contentChanged) {
177
+ if (!inputChangeNoted) {
178
+ synchronizationRevision = options.noteInputContentChange();
179
+ inputChangeNoted = true;
180
+ }
181
+ synchronizeDocument({
182
+ uri,
183
+ content,
184
+ document,
185
+ version: options.nextVersion(uri),
186
+ synchronizationId: options.nextSynchronizationId(),
187
+ evidenceRevision: synchronizationRevision,
188
+ incrementalSync: options.incrementalSync,
189
+ waiters: options.waiters,
190
+ sendNotification: options.sendNotification,
191
+ });
192
+ } else {
193
+ // A failed read can select an unchanged open document for recovery.
194
+ // Keep its protocol identity stable, but make the current evidence
195
+ // generation eligible for a fresh request or push observation.
196
+ retainDocumentSynchronization({
197
+ uri,
198
+ document,
199
+ evidenceRevision: synchronizationRevision,
200
+ waiters: options.waiters,
201
+ });
202
+ }
203
+ options.observeDiskContent(uri, content);
210
204
  options.clearFailedFile(uri);
211
- resynchronizedUris.add(uri);
212
- synchronizations.push({
213
- uri,
214
- synchronizationId: document.synchronizationId,
215
- evidenceRevision: document.evidenceRevision,
216
- });
205
+ synchronizedUris.add(uri);
206
+ if (contentChanged) resynchronizedUris.add(uri);
217
207
  } catch {
218
208
  if (getDiagnosticFileState(filePath) === "removed") {
219
209
  options.clearFile(uri);
@@ -227,5 +217,15 @@ export function resynchronizeOpenDocuments(
227
217
  // Keep the document open when a transient read fails.
228
218
  }
229
219
  }
220
+ const synchronizations: DiagnosticSynchronization[] = [];
221
+ for (const uri of synchronizedUris) {
222
+ const document = options.openDocuments.get(uri);
223
+ if (!document) continue;
224
+ synchronizations.push({
225
+ uri,
226
+ synchronizationId: document.synchronizationId,
227
+ evidenceRevision: document.evidenceRevision,
228
+ });
229
+ }
230
230
  return { synchronizations, resynchronizedUris, removedFiles, failedFiles };
231
231
  }
@@ -0,0 +1,75 @@
1
+ import {
2
+ isSemanticInputEnrollmentError,
3
+ type SemanticInputSynchronizationError,
4
+ } from "./client-semantic-input-errors.ts";
5
+
6
+ const MAX_REQUEST_ENROLLMENT_RETRIES = 1;
7
+
8
+ /** A request-level enrollment retry decision owned by one request attempt. */
9
+ export type RequestEnrollmentRetryDecision =
10
+ | { readonly kind: "retry" }
11
+ | { readonly kind: "stop"; readonly error: unknown };
12
+
13
+ /** Look up the current input change after a failed request revision. */
14
+ export type SemanticInputChangeLookup = (
15
+ revision: number,
16
+ ) => SemanticInputSynchronizationError | undefined;
17
+
18
+ /**
19
+ * Keep one semantic or diagnostic request's enrollment retry policy cohesive.
20
+ *
21
+ * Synchronization passes have their own rejoin budget. This guard only owns
22
+ * the request-level budget and the first failed revision used to classify
23
+ * later changes.
24
+ */
25
+ export class SemanticInputRequestRetryGuard {
26
+ #requestRetries = 0;
27
+ #firstFailedRevision: number | undefined;
28
+
29
+ constructor(private readonly currentChangeSince: SemanticInputChangeLookup) {}
30
+
31
+ /** Number of request-level retries permitted for this request so far. */
32
+ get retryCount(): number {
33
+ return this.#requestRetries;
34
+ }
35
+
36
+ /** Whether this request already used its one request-level retry. */
37
+ get hasRetried(): boolean {
38
+ return this.#requestRetries > 0;
39
+ }
40
+
41
+ /** Throw the current non-enrollment cause when it blocks a retry. */
42
+ assertCurrent(): void {
43
+ const blockingChange = this.#getBlockingChange();
44
+ if (blockingChange) throw blockingChange;
45
+ }
46
+
47
+ /** Classify one failed attempt and decide whether it may be retried. */
48
+ decide(error: unknown, inputRevision: number | undefined): RequestEnrollmentRetryDecision {
49
+ if (!isSemanticInputEnrollmentError(error)) {
50
+ return { kind: "stop", error };
51
+ }
52
+
53
+ if (this.#firstFailedRevision !== undefined) {
54
+ const blockingChange = this.#getBlockingChange();
55
+ if (blockingChange) return { kind: "stop", error: blockingChange };
56
+ }
57
+ if (inputRevision === undefined) return { kind: "stop", error };
58
+
59
+ this.#firstFailedRevision ??= inputRevision;
60
+ const blockingChange = this.#getBlockingChange();
61
+ if (blockingChange) return { kind: "stop", error: blockingChange };
62
+ if (this.#requestRetries >= MAX_REQUEST_ENROLLMENT_RETRIES) {
63
+ return { kind: "stop", error };
64
+ }
65
+
66
+ this.#requestRetries++;
67
+ return { kind: "retry" };
68
+ }
69
+
70
+ #getBlockingChange(): SemanticInputSynchronizationError | undefined {
71
+ if (this.#firstFailedRevision === undefined) return undefined;
72
+ const currentChange = this.currentChangeSince(this.#firstFailedRevision);
73
+ return currentChange?.changeKind === "enrollment" ? undefined : currentChange;
74
+ }
75
+ }