UAT: LspLifecycleManager ignores TCP transport configuration — always uses StdioTransport #3401

Open
opened 2026-04-05 16:28:09 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: fix/lsp-lifecycle-tcp-transport
  • Commit Message: fix(lsp): honor transport field in LspLifecycleManager — support TCP transport
  • Milestone: none (backlog)
  • Parent Epic: #824

Backlog note: This issue was discovered during autonomous operation
on milestone v3.6.0. It does not block milestone completion and has been
placed in the backlog for human review and future milestone assignment.

Bug Description

LspLifecycleManager.start_server() and restart_server() always create a StdioTransport regardless of the transport field in LspServerConfig. When a server is configured with transport: tcp, the lifecycle manager silently ignores this and uses stdio instead.

Expected Behavior (from spec)

Per docs/specification.md line 20584:

transport | string | No | Communication transport: stdio (default) or tcp.

The LspTransport enum in src/cleveragents/lsp/models.py defines both STDIO and TCP values. When config.transport == LspTransport.TCP, the lifecycle manager should use a TCP transport (connecting to the server's configured port) instead of spawning a subprocess.

Actual Behavior

In src/cleveragents/lsp/lifecycle.py, both start_server() (line 102) and restart_server() (line 266) unconditionally create StdioTransport:

transport = StdioTransport(
    command=config.command,
    args=config.args,
    env=config.env,
    cwd=workspace_path,
)

The config.transport field is never checked. A server registered with transport: tcp will be started as a subprocess via stdio, which is incorrect behavior.

Code Location

  • File: src/cleveragents/lsp/lifecycle.py
    • Lines 102–108: start_server() — unconditional StdioTransport creation
    • Lines 266–272: restart_server() — unconditional StdioTransport creation
  • File: src/cleveragents/lsp/models.py
    • Lines 40–41: LspTransport.TCP = "tcp" defined but never used

Steps to Reproduce

from cleveragents.lsp.models import LspServerConfig, LspTransport
from cleveragents.lsp.lifecycle import LspLifecycleManager

config = LspServerConfig(
    name="local/clangd-tcp",
    command="clangd",
    languages=["c", "cpp"],
    transport=LspTransport.TCP,
    # port would need to be added to config
)
# The lifecycle manager will try to spawn clangd as a subprocess
# instead of connecting to it via TCP

Impact

  • LSP servers that only support TCP transport (e.g., remote language servers, servers already running as daemons) cannot be used
  • The transport configuration field in LspServerConfig is effectively dead code
  • The LspTransport.TCP enum value is unreachable

Subtasks

  • Implement TcpTransport class in src/cleveragents/lsp/transport.py (or a new file)
  • Update LspLifecycleManager.start_server() to select transport based on config.transport
  • Update LspLifecycleManager.restart_server() similarly
  • Add port field to LspServerConfig (required when transport=tcp)
  • Add unit tests for TCP transport path
  • Update features/lsp_lifecycle_coverage.feature to cover TCP transport

Definition of Done

  • LspLifecycleManager uses TcpTransport when config.transport == LspTransport.TCP
  • LspLifecycleManager uses StdioTransport when config.transport == LspTransport.STDIO
  • All unit tests pass
  • All nox stages pass
  • Coverage >= 97%

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/lsp-lifecycle-tcp-transport` - **Commit Message**: `fix(lsp): honor transport field in LspLifecycleManager — support TCP transport` - **Milestone**: none (backlog) - **Parent Epic**: #824 > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.6.0. It does not block milestone completion and has been > placed in the backlog for human review and future milestone assignment. ## Bug Description `LspLifecycleManager.start_server()` and `restart_server()` always create a `StdioTransport` regardless of the `transport` field in `LspServerConfig`. When a server is configured with `transport: tcp`, the lifecycle manager silently ignores this and uses stdio instead. ## Expected Behavior (from spec) Per `docs/specification.md` line 20584: > `transport` | string | No | Communication transport: `stdio` (default) or `tcp`. The `LspTransport` enum in `src/cleveragents/lsp/models.py` defines both `STDIO` and `TCP` values. When `config.transport == LspTransport.TCP`, the lifecycle manager should use a TCP transport (connecting to the server's configured port) instead of spawning a subprocess. ## Actual Behavior In `src/cleveragents/lsp/lifecycle.py`, both `start_server()` (line 102) and `restart_server()` (line 266) unconditionally create `StdioTransport`: ```python transport = StdioTransport( command=config.command, args=config.args, env=config.env, cwd=workspace_path, ) ``` The `config.transport` field is never checked. A server registered with `transport: tcp` will be started as a subprocess via stdio, which is incorrect behavior. ## Code Location - File: `src/cleveragents/lsp/lifecycle.py` - Lines 102–108: `start_server()` — unconditional `StdioTransport` creation - Lines 266–272: `restart_server()` — unconditional `StdioTransport` creation - File: `src/cleveragents/lsp/models.py` - Lines 40–41: `LspTransport.TCP = "tcp"` defined but never used ## Steps to Reproduce ```python from cleveragents.lsp.models import LspServerConfig, LspTransport from cleveragents.lsp.lifecycle import LspLifecycleManager config = LspServerConfig( name="local/clangd-tcp", command="clangd", languages=["c", "cpp"], transport=LspTransport.TCP, # port would need to be added to config ) # The lifecycle manager will try to spawn clangd as a subprocess # instead of connecting to it via TCP ``` ## Impact - LSP servers that only support TCP transport (e.g., remote language servers, servers already running as daemons) cannot be used - The `transport` configuration field in `LspServerConfig` is effectively dead code - The `LspTransport.TCP` enum value is unreachable ## Subtasks - [ ] Implement `TcpTransport` class in `src/cleveragents/lsp/transport.py` (or a new file) - [ ] Update `LspLifecycleManager.start_server()` to select transport based on `config.transport` - [ ] Update `LspLifecycleManager.restart_server()` similarly - [ ] Add `port` field to `LspServerConfig` (required when `transport=tcp`) - [ ] Add unit tests for TCP transport path - [ ] Update `features/lsp_lifecycle_coverage.feature` to cover TCP transport ## Definition of Done - [ ] `LspLifecycleManager` uses `TcpTransport` when `config.transport == LspTransport.TCP` - [ ] `LspLifecycleManager` uses `StdioTransport` when `config.transport == LspTransport.STDIO` - [ ] All unit tests pass - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Backlog (unchanged)
  • Story Points: 3 — M — Implement TCP transport support in LspLifecycleManager.
  • MoSCoW: Could Have — TCP transport is an alternative to stdio. Not blocking core LSP functionality.

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: Backlog (unchanged) - **Story Points**: 3 — M — Implement TCP transport support in LspLifecycleManager. - **MoSCoW**: Could Have — TCP transport is an alternative to stdio. Not blocking core LSP functionality. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
#824 Epic: LSP Functional Runtime
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#3401
No description provided.