Files
cleveragents-core/features/lsp_functional_runtime.feature
hamza.khyari 4ff075e0da
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 18s
CI / quality (pull_request) Successful in 32s
CI / typecheck (pull_request) Successful in 56s
CI / security (pull_request) Successful in 57s
CI / lint (pull_request) Successful in 3m19s
CI / integration_tests (pull_request) Successful in 3m44s
CI / unit_tests (pull_request) Successful in 6m39s
CI / docker (pull_request) Successful in 1m9s
CI / e2e_tests (pull_request) Successful in 9m38s
CI / coverage (pull_request) Successful in 11m19s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Failing after 1h13m38s
feat(lsp): implement functional LSP runtime
Replace local-mode stubs with real LSP protocol support:

- StdioTransport: subprocess management with JSON-RPC framing
- LspClient: LSP protocol (initialize/shutdown/diagnostics/completions)
- LspLifecycleManager: reference-counted instances, health checks, crash restart
- LspRuntime: registry-based server lookup, auto-restart on crash
- LspToolAdapter: runtime-delegating handlers with local-mode fallback
- LanguageDiscovery: 4-layer detection (extension, shebang, UKO, project)
- activate_bindings/deactivate_bindings: actor compiler LSP binding wiring

Tests: 27 Behave scenarios, 6 Robot integration tests, 250 existing pass.

ISSUES CLOSED: #826
2026-03-24 13:01:12 +00:00

150 lines
6.7 KiB
Gherkin

Feature: Functional LSP Runtime
As an actor runtime
I need LSP servers to provide real code intelligence
So that actors can get diagnostics and completions
# StdioTransport
Scenario: StdioTransport rejects empty command
When I try to create a StdioTransport with empty command
Then a ValueError should be raised for transport
Scenario: StdioTransport reports not alive before start
Given I create a StdioTransport for "echo"
Then the transport should not be alive
Scenario: StdioTransport start and stop with echo
Given I create a StdioTransport for "cat"
When I start the transport
Then the transport should be alive
When I stop the transport
Then the transport should not be alive
# ── LspClient ─────────────────────────────────────────────────────
Scenario: LspClient starts not initialized
Given I create an LspClient with a mock transport
Then the client should not be initialized
Scenario: LspClient tracks request IDs
Given I create an LspClient with a mock transport
When I get two request IDs from the client
Then the IDs should be sequential
# ── LspLifecycleManager ──────────────────────────────────────────
Scenario: LspLifecycleManager starts empty
Given I create an LspLifecycleManager
Then the manager should have no running servers
Scenario: LspLifecycleManager stop unknown server raises error
Given I create an LspLifecycleManager
When I try to stop server "local/unknown" on the manager
Then an LspServerNotFoundError should be raised for lifecycle
Scenario: LspLifecycleManager health check returns false for unknown
Given I create an LspLifecycleManager
Then health check for "local/unknown" should return false
# ── LspRuntime with registry ─────────────────────────────────────
Scenario: LspRuntime start_server rejects empty name
Given I create a functional LspRuntime
When I try to start server with empty name and workspace "/tmp"
Then a ValueError should be raised for runtime
Scenario: LspRuntime start_server rejects empty workspace
Given I create a functional LspRuntime
When I try to start server "local/test" with empty workspace
Then a ValueError should be raised for runtime
Scenario: LspRuntime start_server raises for unregistered server
Given I create a functional LspRuntime
When I try to start unregistered server "local/missing"
Then an LspServerNotFoundError should be raised for runtime
Scenario: LspRuntime get_diagnostics rejects empty name
Given I create a functional LspRuntime
When I try to get diagnostics with empty name
Then a ValueError should be raised for runtime
Scenario: LspRuntime get_completions validates line >= 1
Given I create a functional LspRuntime
When I try to get completions with line 0
Then a ValueError should be raised for runtime
Scenario: LspRuntime get_completions validates column >= 1
Given I create a functional LspRuntime
When I try to get completions with column 0
Then a ValueError should be raised for runtime
# ── LanguageDiscovery ────────────────────────────────────────────
Scenario: LanguageDiscovery detects Python from extension
Given I create a LanguageDiscovery instance
Then language for "test.py" should be "python"
And language for "test.pyi" should be "python"
Scenario: LanguageDiscovery detects TypeScript from extension
Given I create a LanguageDiscovery instance
Then language for "app.ts" should be "typescript"
And language for "app.tsx" should be "typescriptreact"
Scenario: LanguageDiscovery detects Rust from extension
Given I create a LanguageDiscovery instance
Then language for "main.rs" should be "rust"
Scenario: LanguageDiscovery returns plaintext for unknown
Given I create a LanguageDiscovery instance
Then language for "data.xyz" should be "plaintext"
Scenario: LanguageDiscovery detects Dockerfile by name
Given I create a LanguageDiscovery instance
Then language for "Dockerfile" should be "dockerfile"
Scenario: LanguageDiscovery uses project language as fallback
Given I create a LanguageDiscovery with project language "go"
Then language for "unknown_file" should be "go"
Scenario: LanguageDiscovery cache invalidation works
Given I create a LanguageDiscovery instance
When I detect language for "test.py"
And I invalidate "test.py" from discovery cache
Then the cache should not contain "test.py"
Scenario: LanguageDiscovery detects shebang for Python script
Given I create a LanguageDiscovery instance
And I create a temp file with shebang "#!/usr/bin/env python3"
Then the temp file language should be "python"
Scenario: LanguageDiscovery detects shebang for bash script
Given I create a LanguageDiscovery instance
And I create a temp file with shebang "#!/bin/bash"
Then the temp file language should be "shellscript"
# ── LspToolAdapter with runtime ──────────────────────────────────
Scenario: LspToolAdapter generates runtime-backed handlers when runtime provided
Given I create an LspToolAdapter with a functional runtime
And I have an LSP server config with diagnostics capability
When I generate functional tool specs from the adapter
Then the tool specs should have runtime handlers
Scenario: LspToolAdapter generates local-mode handlers without runtime
Given I create an LspToolAdapter without runtime
And I have an LSP server config with diagnostics capability
When I generate functional tool specs from the adapter
Then the tool specs should have local-mode handlers
# ── Binding activation ───────────────────────────────────────────
Scenario: LspRuntime activate_bindings with no bindings returns empty
Given I create a functional LspRuntime
When I activate bindings with empty list
Then the activated servers list should be empty
Scenario: LspRuntime activate_bindings skips unregistered servers
Given I create a functional LspRuntime
When I activate bindings with unregistered server binding
Then the activated servers list should be empty