LSP Auditor
π README β @cheasee-pi/lsp-auditor on npm
Why. Runs real Language Server Protocol diagnostics on changed files before code review β catches errors, warnings, and hints the LLM might miss. Called automatically by the supervisor pipeline during the Audit stage.
How it works. Triggered manually via /lsp-auditor or automatically by supervisor (runPreAudit()). Uses git diff <defaultBranch> --name-only to find changed files. Groups by file extension (.ts β typescript-language-server, .py β pylsp, .rs β rust-analyzer, .go β gopls). Spawns LSP servers per group, opens files via didOpen, collects publishDiagnostics notifications. Filters by per-server severityThreshold (error/warning/info). Retries up to 3 times with session-stored retry counters. Trust-gated β untrusted projects skip LSP audit (returns { proceed: true } with warning, matching VS Code Restricted Mode precedent).
Location: .pi/extensions/lsp-auditor/
Details
Architecture
Multi-server LSP orchestrator with file discovery and retry logic:
βββ index.ts # Entry: command registration (/lsp-auditor), runPreAudit export
βββ run-pre-audit.ts # Orchestrator: discover files β group by server β audit each group
βββ lsp-client.ts # LSP client: spawn server, didOpen, collect publishDiagnostics
βββ server-mappings.ts # Extension β server mapping (.tsβtypescript-language-server, .pyβpylsp, etc.)
βββ file-discovery.ts # git diff file discovery + extension grouping
βββ formatting.ts # Diagnostic formatting, severity filtering, result merging
βββ settings.ts # Read .pi/settings.json for defaultBranch
βββ retry.ts # Retry logic: countRetryAttempts, shouldRetry, MAX_RETRIES=3
βββ output-adapter.ts # Mode-adaptive output formatting (TUI/RPC/JSON/print)
βββ types.ts # LspDiagnostic, ServerMapping, AuditResult interfaces
βββ test/ # Unit + integration tests
Execution Flow
flowchart TD
A[Trigger: /lsp-auditor or supervisor runPreAudit] --> B[file-discovery.ts: git diff defaultBranch]
B --> C[groupFilesByServer: extension β LSP server]
C --> D{For each server group}
D --> E[lsp-client.ts: spawn LSP server]
E --> F[didOpen each file]
F --> G[collect publishDiagnostics]
G --> H[Filter by severityThreshold]
H --> I[mergeResults across servers]
I --> J{retry.shouldRetry?}
J -- yes < 3 retries --> D
J -- no --> K[formatting.ts: format output]
K --> L[Return AuditResult: proceed / note]
Server Mappings
| Extension | LSP Server | Notes |
|---|---|---|
.ts |
typescript-language-server |
Full TS/TSX support |
.py |
pylsp |
Python LSP |
.rs |
rust-analyzer |
Rust LSP |
.go |
gopls |
Go LSP |
| (others) | β | Skipped with warning |
Key Design Decisions
- File discovery via
git diffβ Only checks modified files vs defaultBranch. Prevents checking entire codebase.git diff <defaultBranch> --name-only. - Per-server severity threshold β Each server mapping configures
severityThreshold(error/warning/info). Diagnostics below threshold are filtered out. - Retry with session-stored counters β Retries up to 3 times per server group. Counter stored in session scope.
shouldRetry()checks both attempt count and error type (transient vs permanent). - Trust gate β Untrusted projects skip LSP audit entirely (returns
{ proceed: true }with warning). Matches VS Code Restricted Mode precedent. - Mode-adaptive output β TUI: notification + clickable markdown. RPC/JSON: structured
{ proceed, note, diagnostics }. Print: plain text. - Passive by default β No lifecycle hooks. Activated by supervisorβs
runPreAudit()or manual/lsp-auditorcommand. All public API re-exported for supervisor imports. - Spawn + didOpen protocol β LSP servers are spawned on-demand, files opened via
didOpen, diagnostics collected frompublishDiagnosticsnotifications. No file watching needed.
Retry Logic
MAX_RETRIES = 3
function shouldRetry(attempts: number, error: Error): boolean {
if (attempts >= MAX_RETRIES) return false;
// Only retry on transient errors (connection refused, timeout, process crash)
// Not on permanent errors (invalid file, missing server binary)
return error.message.includes('ECONNREFUSED') ||
error.message.includes('ETIMEDOUT') ||
error.message.includes('process exited');
}
Testing
Tests cover:
- File discovery: git diff parsing, empty diffs, binary file exclusion
- Server mappings: extension matching, unknown extension fallback
- LSP client: spawn, didOpen, diagnostic collection, timeout handling
- Retry logic: attempt counting, transient vs permanent error classification
- Formatting: severity filtering, result merging, markdown generation
- Output adapter: all 4 modes (TUI, RPC, JSON, print)