LSP Integration
What LSP integration provides
LSP (Language Server Protocol) integration enriches the context available to the model with the same semantic code understanding an operator has in their IDE: type information, symbol definitions, cross-references, and live diagnostics. LSP-derived context is assembled passively and injected into the context window — the model does not directly invoke LSP queries (lsp_integration_spec.md §1).
Design principles
LSP integration follows six principles (lsp_integration_spec.md §3):
- LSP-001: Same context as the operator — the model should see what the operator sees
- LSP-002: Context enrichment is passive — the context assembler initiates queries, not the model
- LSP-003: LSP queries are governed reads — they traverse canonicalization and policy evaluation with a
readcapability class, but do not require operator approval under default policy - LSP-004: Diagnostics are validation evidence — new errors after code modification must be captured and recorded
- LSP-005: Capability degradation is not a failure — sessions continue without LSP context rather than halting
- LSP-006: No fabrication — errors or timeouts must not be substituted with inferred type information without explicit marking
LSP server lifecycle
Discovery
At session start, the control plane discovers applicable LSP servers in priority order (lsp_integration_spec.md §4.1):
- Explicit registration — operator-registered servers in Syndicate Code configuration
- Workspace configuration —
.syndicate/lsp.jsonor equivalent - Auto-detection — scan for well-known LSP server binaries matching workspace file types
Auto-detection must not start servers without operator awareness. In non-interactive mode, auto-detection is disabled; only explicitly registered servers may be used.
Auto-detection heuristics
| Language | Server Binary | File Extensions |
|---|---|---|
| Go | gopls | .go |
| TypeScript / JavaScript | typescript-language-server | .ts, .tsx, .js, .jsx |
| Rust | rust-analyzer | .rs |
| Python | pylsp or pyright | .py |
| C / C++ | clangd | .c, .cpp, .h, .hpp |
| Java | jdtls | .java |
| Ruby | ruby-lsp or solargraph | .rb |
| C# | omnisharp | .cs |
Registration
A registered LSP server must declare (lsp_integration_spec.md §4.3):
- language identifier (e.g.,
go,typescript,rust) - server binary path and launch arguments (process-based) or server endpoint (socket-based)
- declared workspace scope
- initialization options (passed to
initializerequest)
Startup
LSP server startup follows the standard LSP initialization handshake:
- Control plane spawns the server process
- Runtime sends
initializerequest with workspace root and client capabilities - Server responds with
InitializeResultdeclaring capabilities - Runtime sends
initializednotification - Control plane records declared capabilities
Startup failure must not halt the Syndicate Code session. The LSP server is marked unavailable; sessions proceed without LSP context for the affected language.
Shutdown
LSP servers shut down when the session ends, following the LSP shutdown + exit sequence.
Capabilities used
Context enrichment
These capabilities feed into context assembly before or during a turn:
| Capability | LSP Request | Purpose |
|---|---|---|
| Hover information | textDocument/hover | Type information, documentation, signatures |
| Go to definition | textDocument/definition | Resolve symbol definition for context |
| Type definition | textDocument/typeDefinition | Resolve underlying type of a symbol |
| Document symbols | textDocument/documentSymbol | Structural summary of a file |
| Workspace symbols | workspace/symbol | Cross-workspace symbol search |
| References | textDocument/references | Find all usages of a symbol |
| Signature help | textDocument/signatureHelp | Call signature at invocation points |
| Inlay hints | textDocument/inlayHint | Inferred type annotations and parameter labels |
Validation
These capabilities are used after code modifications:
| Capability | LSP Request | Purpose |
|---|---|---|
| Pull diagnostics | textDocument/diagnostic | Request current diagnostics for a modified file |
| Push diagnostics | textDocument/publishDiagnostics | Server-pushed diagnostics on file change |
| Workspace diagnostics | workspace/diagnostic | Diagnostics across the entire workspace |
Capabilities explicitly not used
textDocument/completion— the model generates completionstextDocument/formatting— Syndicate Code uses the configured formatter directlytextDocument/codeAction— code actions are model-drivenworkspace/executeCommand— would require full governed execution lifecycle treatment
Governed invocation path
LSP queries are classified as read capability class (lsp_integration_spec.md §6). They access in-memory semantic representations; they do not write to the filesystem, execute code, or make network calls.
Under default policy, read capability class operations within the active execution envelope do not require per-request operator approval. LSP queries are therefore pre-authorized within an active envelope by default.
Policy may override this for specific deployment modes, sensitive workspaces, or specific LSP capabilities.
Evidence requirements
Each LSP query batch must emit a lsp_query_batch evidence event recording:
- language server identity and version
- query types issued
- file or symbol targets
- whether the server responded, timed out, or returned an error
- response byte count
Context assembly integration
LSP-derived context is classified as (lsp_integration_spec.md §7):
- Source type:
lsp_semantic - Priority class:
supporting(below direct workspace file content, above heuristic summaries) - Purity: impure (requires a live LSP server; cannot be computed deterministically)
Context items from LSP
| Context Item | Derived From | Inclusion Policy |
|---|---|---|
| Type signatures | textDocument/hover, textDocument/typeDefinition | When the model's current operation involves a symbol whose type is not visible in the local excerpt |
| Definition excerpts | textDocument/definition | When the model references a symbol defined outside the current file |
| Structural summary | textDocument/documentSymbol | As a compact summary when the full file is not in context |
| Diagnostic state | textDocument/diagnostic | After any code modification |
| Inlay hints | textDocument/inlayHint | At the context assembler's discretion based on available budget |
Staleness handling
If a file has been modified since the query was issued, the LSP context for that file may be stale. The context assembler must:
- record file modification time at query time and injection time
- re-query if the file has changed between query and injection
- if re-query is not possible, mark the context item as potentially stale with the original query timestamp
Diagnostic validation after code modification
After any tool that modifies files, the context assembler must query LSP diagnostics for all modified files before closing the execution turn (lsp_integration_spec.md §8.1).
Diagnostic result classes
| Class | Meaning | Disposition |
|---|---|---|
clean | No new errors or warnings | Record in evidence; continue |
warnings_only | New warnings but no new errors | Record in evidence; surface to model; continue |
new_errors | New diagnostic errors introduced | Record in evidence; feed back to model for self-correction; emit diagnostic_regression event |
baseline_error | Errors present before modification; no change | Record in evidence; not attributed to modification |
lsp_unavailable | LSP server did not respond | Record absence in evidence; continue without diagnostic validation |
When new_errors are detected, diagnostics must be included in the model's next context window for self-correction. Default self-correction iterations: 2. After permitted iterations exhaust without resolution, the unresolved state is surfaced to the operator.
Failure handling
| ID | Condition | Result |
|---|---|---|
| LSP-FH-001 | Server startup failure | Mark unavailable; proceed without LSP context |
| LSP-FH-002 | Query timeout | Return empty result; consecutive timeouts trigger health evaluation |
| LSP-FH-003 | Server crash | Attempt restart once; if restart fails, mark unavailable for session |
| LSP-FH-004 | Unsupported capability | Skip silently; do not inject fabricated context |
| LSP-FH-005 | Stale context detected | Re-query if possible; mark as stale if not |
| LSP-FH-006 | Diagnostic query returns server error | Classify as lsp_unavailable; continue without blocking |
Required invariants
- INV-LSP-001 — No LSP context may be injected without a corresponding context record entry documenting source, query type, and timestamp
- INV-LSP-002 — No LSP capability may be invoked unless declared available in the server's
InitializeResult - INV-LSP-003 — No LSP query result may be substituted with inferred or cached data without explicit staleness marking
- INV-LSP-004 — No file-modifying LSP request may be issued; LSP integration is read-only
- INV-LSP-005 — LSP server unavailability must not halt execution; sessions proceed with degraded context
- INV-LSP-006 — Every code-modifying execution turn must attempt diagnostic validation before the turn is closed