summaryrefslogtreecommitdiffhomepage
path: root/PLAN-per-edit-diagnostics.md
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-24 16:48:46 +0900
committerAdam Malczewski <[email protected]>2026-06-24 16:48:46 +0900
commit8f6114be790016bd954fcfccbe80a88bd0cb758e (patch)
tree6be223628e35ce83759314f6fcce2161daa370ba /PLAN-per-edit-diagnostics.md
parent4935c268dd53592ec264c1b3eaa9805b3e069df5 (diff)
downloaddispatch-8f6114be790016bd954fcfccbe80a88bd0cb758e.tar.gz
dispatch-8f6114be790016bd954fcfccbe80a88bd0cb758e.zip
feat(lsp+tool-edit-file): multi-server diagnostics + per-edit auto-append
LSP extension: - Multi-server aggregation: query ALL connected servers matching the file's extension (not just the first), merge diagnostics tagged by source - Incremental sync: capture each server's textDocumentSync.change during initialize; compute prefix/suffix diff ranges for change:2 servers; full content for change:1 (generic, works for any LSP) - New diff.ts: pure computeChangeRange + offsetToPosition (O(n), tested) - Buffer sync: change(filePath, newText) sends didChange with post-edit in-memory content; openWithText for first open; tracks open doc text - languageId mapping: extended with .rb/.rbs/.c/.cpp/etc. (was 'unknown') - waitForDiagnostics: accepts text override + timeoutMs; returns { formatted, slow, timedOut }; polls for publishDiagnostics push - DiagnosticsStore: hasReceivedPush/clearReceived tracking; formatFiltered with minSeverity (1=Error, 2=Warning) for edit_file integration - LspService.getDiagnostics: service method for cross-extension use tool-edit-file: - After successful edit, calls LSP getDiagnostics with post-edit buffer - Only appends diagnostics with severity ≤ 2 (errors+warnings, no noise) - Appends slow warning (>10s): 'LSP is taking unusually long...' - 60s timeout; graceful degradation when no LSP available - Optional dep on @dispatch/lsp (getService pattern, not manifest depOn) 1468 vitest pass (was 1453, +15 new diff tests).
Diffstat (limited to 'PLAN-per-edit-diagnostics.md')
-rw-r--r--PLAN-per-edit-diagnostics.md44
1 files changed, 44 insertions, 0 deletions
diff --git a/PLAN-per-edit-diagnostics.md b/PLAN-per-edit-diagnostics.md
new file mode 100644
index 0000000..20671c2
--- /dev/null
+++ b/PLAN-per-edit-diagnostics.md
@@ -0,0 +1,44 @@
+# Plan — Live Per-Edit Diagnostics (General LSP)
+
+> **Status:** APPROVED — implementing.
+
+## Decisions (confirmed with user)
+
+1. **Multi-server aggregation** — query ALL connected servers matching the file's extension, merge diagnostics tagged by source.
+2. **Incremental sync** — capture each server's `textDocumentSync.change` during `initialize`; compute prefix/suffix diff ranges for `change: 2`; full content for `change: 1`. Generic, works for ALL LSPs.
+3. **`languageId` mapping** — extend the existing `language.ts` with `.rb`/`.rbs`, `.c`/`.cpp`, etc.
+4. **Auto-append to `edit_file`** — after a successful edit, run diagnostics on the post-edit buffer. Only append diagnostics if there are errors/warnings (severity ≤ 2). Don't append on clean edits (no noise).
+5. **60s timeout** — if diagnostics take >10s, prepend a warning: "LSP is taking unusually long. If this happens more than once, raise it to the user." Always append this if slow, regardless of whether there are errors.
+6. **General** — not Steep-specific. Works for any LSP server.
+
+## Implementation waves
+
+### Wave 1: `packages/lsp/` (single unit)
+
+| File | Change |
+|---|---|
+| `src/diff.ts` (NEW) | Pure diff: `computeChangeRange(oldText, newText)` + `offsetToPosition(text, offset)` |
+| `src/language.ts` | Add `.rb`/`.rbs` → `"ruby"`, `.c`/`.h` → `"c"`, `.cpp`/`.cc`/`.hpp` → `"cpp"` |
+| `src/diagnostics.ts` | Add `hasReceivedPush(uri)` tracking, `clearReceived(uri)`, `formatFiltered(uri, minSeverity?)` |
+| `src/client.ts` | Capture `textDocumentSync.change` from init; track open doc text; add `change(filePath, newText)` with incremental/full sync; fix `languageId` in `open()`; extend `waitForDiagnostics(filePath, opts?)` to accept `text` + `timeoutMs` + return `{ formatted, slow, timedOut }` |
+| `src/tool.ts` | `diagnostics` op: query ALL matching connected servers (not just first); merge tagged by source |
+| `src/types.ts` | Add `getDiagnostics(opts)` to `LspService` + `DiagnosticsResult` type |
+| `src/extension.ts` | Implement `getDiagnostics` (calls manager → all matching clients → merge) |
+| `src/diff.test.ts` (NEW) | Unit tests for diff functions |
+| `src/tool.test.ts` | Multi-server aggregation test |
+| `src/client.test.ts` | `change()`, `languageId`, `waitForDiagnostics` with text tests |
+
+### Wave 2: `packages/tool-edit-file/` (cross-extension)
+
+| File | Change |
+|---|---|
+| `src/extension.ts` | Import `lspServiceHandle` from `@dispatch/lsp`; `host.getService()` in activate; pass to tool |
+| `src/edit-file.ts` | After successful edit: call `getDiagnostics({ filePath, text: newContent, cwd, minSeverity: 2, timeoutMs: 60_000 })`; append if errors; append slow warning if >10s |
+| `package.json` | Add `@dispatch/lsp` dep |
+| `tsconfig.json` | Add `@dispatch/lsp` reference |
+
+### Wave 3: Build wiring (orchestrator)
+
+- Root `tsconfig.json`: add `@dispatch/tool-edit-file` → `@dispatch/lsp` ref if needed
+- `bun install` to link
+- Verify: typecheck + test + biome