fix(lsp): prevent header injection in LSP transport ASCII decoding #10608

Merged
HAL9000 merged 9 commits from bugfix/m3.6.0-lsp-transport-header-injection-ascii into master 2026-06-13 08:57:41 +00:00
5 changed files with 208 additions and 25 deletions
+5
View File
4
@@ -466,6 +466,11 @@ ensuring data is stored with proper parameter values.
Review

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.
Review

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.
- **Timeline dashboard updated with 2026-04-18 progress snapshot** (#10288): Added schedule adherence tables and daily milestone snapshot for April 18, covering M3-M10 status including overdue milestones (M3-M7) and in-progress milestones (M8-M10). Risk assessment shows M6 (v3.5.0) highest risk with 1,130 open issues at 18.1% completion.
- **LSP transport header injection fix** (#10608 / #7112): The `_read_one_message()` method in
Review

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.
`src/cleveragents/lsp/transport.py` now uses `errors="strict"` instead of `errors="replace"` for
Review

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.
ASCII decoding of LSP headers, preventing header injection attacks. Non-ASCII bytes raise
Review

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.
`LspError`. A printable-ASCII guard rejects characters outside 0x20-0x7E range. Epic #824.
Review

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.
Review

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.
### Fixed
- **Concurrent ValidationPipeline stdout/stderr restoration** (#7623): Fixed a race
Review

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.
Review

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.

SUGGESTION: Line 159 has a pre-existing single-space indentation before 'Updated' that may be flagged by ruff (expected continuation lines use 2-space indent). Not introduced by this PR but worth fixing in a follow-up.
+2 -2
View File
1
@@ -13,7 +13,6 @@
* Luis Mendes <luis.p.mendes@gmail.com>
* Rui Hu <rui.hu@cleverthis.com>
* HAL 9000 <hal9000@cleverthis.com> has contributed the parallel subplan execution scheduler (#9555): implemented `ParallelSubplanScheduler` with configurable concurrency control, dependency ordering, fail-fast mode, retry support, and pluggable merge strategies for the v3.3.0 subplan system.
* HAL 9000 <hal9000@cleverthis.com> has contributed fix for #10813 — wiring DecisionService into PlanExecutor for strategy decision persistence during strategize.
* HAL9000 <HAL9000@cleverthis.com> has contributed CLI rendering improvements and TUI overlay visibility handling for `agents project context set` output.
@@ -50,6 +49,7 @@ Below are some of the specific details of various contributions.
* This project was made possible thanks to considerable donation of time, money, and resources by CleverThis, Inc.
* HAL 9000 has contributed automated bug fixes, CLI output formatting improvements, and ongoing maintenance as part of the CleverAgents automation system.
* HAL 9000 has contributed the pr-review-pool-supervisor tracking prefix documentation fix (#7891): aligned all documentation references from the outdated `AUTO-REV-POOL` prefix to the correct `AUTO-REV-SUP` prefix used in production.
* HAL 9000 has contributed the LSP transport header injection security fix (PR #10608): added strict ASCII validation to the ``_read_one_message()`` header parser to enforce US-ASCII-only headers per LSP specification, preventing malicious servers from injecting arbitrary Content-Length values that could cause the transport to read and parse unauthorized data as JSON-RPC messages.
* HAL 9000 has contributed the file edit encoding parameter fix (PR #8258 / issue #7559).
* HAL 9000 has contributed the architecture-pool-supervisor milestone assignment feature (PR #8188 / issue #7521): added `forgejo_update_pull_request` permission and documented the PR workflow for major spec changes, enabling automatic milestone assignment for specification PRs.
* HAL 9000 has contributed the git worktree TOCTOU race condition fix (PR #8178 / issue #7507): replaced the unsafe mkdtemp() + rmdir() pattern with a parent-directory approach to eliminate the race window in concurrent git worktree operations.
@@ -80,7 +80,7 @@ Below are some of the specific details of various contributions.
* HAL 9000 has contributed the actor compiler `actor_ref` field fix (issue #1429): corrected `_map_node()` and `compile_actor()` in `src/cleveragents/actor/compiler.py` to read `actor_ref` from the top-level `NodeDefinition.actor_ref` field instead of `node.config.get("actor_ref")`, resolving silent failures on all SUBGRAPH nodes where `subgraph_refs` was always empty and `NodeConfig.subgraph` was always `None`.
* HAL 9000 has contributed the removal of the unsupported executable resource type (PR #3248 / issue #3077): removed `executable` from `LSP_RESOURCE_TYPES` and `BUILTIN_TYPE_NAMES`, updated `agents resource list` CLI table columns to the spec-required `[Name, ID, Type, Phys/Virt, Children, Projects]`, deleted orphaned `examples/resource-types/executable.yaml`, and updated related BDD test coverage.
* HAL 9000 has contributed the alembic fileConfig error handling fix (PR #8288 / issue #7874): wrapped the `fileConfig()` call in `alembic/env.py` with a `try/except` block to catch malformed INI logging configuration and emit clear, actionable error messages to stderr.
* HAL 9000 has contributed the Definition-of-Done gating feature for the Apply phase (PR #8299 / issue #7927): `PlanLifecycleService.apply_plan` now evaluates DoD criteria before transitioning to Apply, raising `DoDGatingError` when required criteria fail and storing evaluation results in `plan.validation_summary`.
* HAL 9000 has contributed the Definition-of-Done gating feature for the Apply phase (PR #8299 / issue #7927): `PlanLifecycleService.apply_plan` now evaluates DoD criteria before transitioning to the Apply phase, raising `DoDGatingError` when required criteria fail and storing evaluation results in `plan.validation_summary`.
* HAL 9000 has contributed the engine cache TOCTOU race condition fix (PR #8265 / issue #7566): added `MEMORY_ENGINES_LOCK` to `engine_cache.py` and wrapped the check-and-set operation in `UnitOfWork.engine` with `with MEMORY_ENGINES_LOCK:` to prevent concurrent threads from creating duplicate in-memory SQLite engine instances; also fixed a cache-hit bug where `self._engine` was never assigned on a cache hit.
* HAL 9000 has contributed the plan correct JSON output envelope fix (PR #8662 / issue #8584): restructured `agents plan correct --format json` output to nest correction fields under `data.correction` and pass `command="plan correct"` to `format_output`, producing the spec-required CLI envelope. Added three BDD scenarios validating `data.correction.mode` (revert and append modes) and the `command` field.
* HAL 9000 has contributed BDD feature file tag coverage improvements (#9124 / pr #9183): added required `@a2a`, `@session`, and `@cli` Gherkin tags to 30 feature files (8 A2A, 7 session, 15 CLI) to enable selective tag-based test filtering via `behave --tags=a2a,session,cli`.
@@ -0,0 +1,38 @@
@tdd_issue
Outdated
Review

BLOCKER — Tags on same line as Feature: keyword is invalid Gherkin

This is the only feature file in the repository where tags appear inline with the Feature: keyword. Behave's Gherkin parser requires tags on their own line(s) before the keyword.

With this format, the parser either discards the tags entirely or raises a parse error. All four scenarios lose the feature-level @tdd_issue and @tdd_issue_7112 tags, breaking the TDD tag tracking system.

Required fix — split into separate lines:

@tdd_issue
@tdd_issue_7112
Feature: LSP transport header injection vulnerability (issue #7112)
**BLOCKER — Tags on same line as `Feature:` keyword is invalid Gherkin** This is the only feature file in the repository where tags appear inline with the `Feature:` keyword. Behave's Gherkin parser requires tags on their own line(s) before the keyword. With this format, the parser either discards the tags entirely or raises a parse error. All four scenarios lose the feature-level `@tdd_issue` and `@tdd_issue_7112` tags, breaking the TDD tag tracking system. **Required fix — split into separate lines:** ```gherkin @tdd_issue @tdd_issue_7112 Feature: LSP transport header injection vulnerability (issue #7112) ```
Outdated
Review

BLOCKER — Feature-level tags on same line as Feature: keyword (invalid Gherkin)

Gherkin tags must appear on their own line(s) before the keyword. Placing them inline causes Behave to discard the @tdd_issue and @tdd_issue_7112 feature-level tags from all scenarios.

This is the only feature file in the repo using this inline pattern.

Required fix:

@tdd_issue
@tdd_issue_7112
Feature: LSP transport header injection vulnerability (issue #7112)
**BLOCKER — Feature-level tags on same line as `Feature:` keyword (invalid Gherkin)** Gherkin tags must appear on their own line(s) before the keyword. Placing them inline causes Behave to discard the `@tdd_issue` and `@tdd_issue_7112` feature-level tags from all scenarios. This is the only feature file in the repo using this inline pattern. **Required fix:** ```gherkin @tdd_issue @tdd_issue_7112 Feature: LSP transport header injection vulnerability (issue #7112) ```
Outdated
Review

BLOCKER — Tags must be on their own line before Feature:, not inline on the same line

Current:

@tdd_issue @tdd_issue_7112 Feature: LSP transport header injection vulnerability (issue #7112)

Gherkin requires tags on their own line(s) BEFORE the Feature: keyword. Inline tags are discarded or cause a parse error — all scenarios lose the feature-level @tdd_issue and @tdd_issue_7112 tags.

Required fix:

@tdd_issue
@tdd_issue_7112
Feature: LSP transport header injection vulnerability (issue #7112)

Every other .feature file in this repo uses this correct format.

**BLOCKER — Tags must be on their own line before `Feature:`, not inline on the same line** Current: ``` @tdd_issue @tdd_issue_7112 Feature: LSP transport header injection vulnerability (issue #7112) ``` Gherkin requires tags on their own line(s) BEFORE the `Feature:` keyword. Inline tags are discarded or cause a parse error — all scenarios lose the feature-level `@tdd_issue` and `@tdd_issue_7112` tags. **Required fix:** ```gherkin @tdd_issue @tdd_issue_7112 Feature: LSP transport header injection vulnerability (issue #7112) ``` Every other `.feature` file in this repo uses this correct format.
@tdd_issue_7112
Feature: LSP transport header injection security
The ``_read_one_message()`` method in the LSP stdio transport must strictly
enforce ASCII-only headers. Non-ASCII bytes silently replaced by the
old ``errors="replace"`` path could be used to manipulate message
boundaries and desynchronise the protocol.
@tdd_issue_7112
Scenario: Non-ASCII byte in Content-Length value raises LspError
Given a Transport mock with BytesIO stream containing b"Content-Length: 10\xc0\r\n\r\nhello\x00world"
When _read_one_message() is invoked
Then it should raise an LspError exception
Outdated
Review

BLOCKER — Trailing whitespace on this line

This line ends with 2 trailing spaces before the newline (LspError \n). Ruff W291 will flag this as a lint error.

Required fix: Remove the 2 trailing spaces from the end of this line.

**BLOCKER — Trailing whitespace on this line** This line ends with 2 trailing spaces before the newline (`LspError \n`). Ruff W291 will flag this as a lint error. **Required fix:** Remove the 2 trailing spaces from the end of this line.
And the error message must contain "non-ASCII"
@tdd_issue_7112
Scenario: Non-ASCII byte in a valid Content-Length name raises LspError
Given a Transport mock with BytesIO stream containing b"Content-Length\xef\x08: 99\r\n\r\n{\"jsonrpc\":\"2.0\"}"
When _read_one_message() is invoked
Then it should raise an LspError exception
And the error message must contain "non-ASCII"
@tdd_issue_7112
Scenario: Non-ASCII byte in an unrecognized header raises LspError
Given a Transport mock with BytesIO stream containing b"Cache-Control\xef\x08: no-cache\r\nContent-Length: 5\r\n\r\n{\"id\":1}"
When _read_one_message() is invoked
Then it should raise an LspError exception
And the error message must contain "non-ASCII"
@tdd_issue_7112
Scenario: Valid ASCII headers are processed correctly
Given a Transport mock with BytesIO stream containing b"Content-Length: 43\r\n\r\n{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"success\"}"
When _read_one_message() is invoked
Then it should return a parsed JSON dict
And the result must contain "jsonrpc" == "2.0"
And the result must contain "id" == 1
And the result must contain "result" == "success"
@@ -0,0 +1,130 @@
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
# pyright: reportRedeclaration=false
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
"""Step definitions for LSP transport header injection security (issue #7112).
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Mocked ``StdioTransport`` using a ``MagicMock`` subprocess and
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
a ``BytesIO``-based stdout so that non-ASCII header bytes can be
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
injected and the strict-ASCII enforcement guard exercised without
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
requiring a real language server.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
"""
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
from __future__ import annotations
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
import select
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
from io import BytesIO
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
from typing import Any
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
from unittest.mock import MagicMock, patch
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
from behave import given, then, when
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
from cleveragents.lsp.errors import LspError
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
from cleveragents.lsp.transport import StdioTransport
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def patched_select(
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
readable: list[Any],
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
*_args: Any,
Outdated
Review

BLOCKER — Custom Behave parse type :r is not registered anywhere; step collection raises ParseTypeError

The {raw_headers:r} format specifier requires a custom type named r to be registered with Behave's parse engine. No such registration exists in features/environment.py, features/steps/*.py, behave.ini, or any other project file (confirmed by full-repo search).

Behave raises ParseTypeError: Unknown type specifier 'r' during step-collection, before any test runs. All four scenarios fail at discovery.

Simplest fix (Option B — no registration required): Change the step to accept a plain string and eval it:

@given("a Transport mock with BytesIO stream containing {raw_headers}")
def step_transport_with_streams(context: Any, raw_headers: str) -> None:
    data: bytes = eval(raw_headers)  # b"..." literal from feature file
    context.stream = BytesIO(data)
    ...

The feature file step text (b"Content-Length: 10\xc0...") will be passed as the string raw_headers and eval() will convert it to bytes. No type registration needed.

**BLOCKER — Custom Behave parse type `:r` is not registered anywhere; step collection raises `ParseTypeError`** The `{raw_headers:r}` format specifier requires a custom type named `r` to be registered with Behave's parse engine. No such registration exists in `features/environment.py`, `features/steps/*.py`, `behave.ini`, or any other project file (confirmed by full-repo search). Behave raises `ParseTypeError: Unknown type specifier 'r'` during step-collection, before any test runs. All four scenarios fail at discovery. **Simplest fix (Option B — no registration required):** Change the step to accept a plain string and `eval` it: ```python @given("a Transport mock with BytesIO stream containing {raw_headers}") def step_transport_with_streams(context: Any, raw_headers: str) -> None: data: bytes = eval(raw_headers) # b"..." literal from feature file context.stream = BytesIO(data) ... ``` The feature file step text (`b"Content-Length: 10\xc0..."`) will be passed as the string `raw_headers` and `eval()` will convert it to bytes. No type registration needed.
Outdated
Review

BLOCKER — Custom parse type :r not registered

The :r specifier in {raw_headers:r} is not a built-in parse type. No register_type call for r exists anywhere in features/. Behave raises ParseTypeError: Unknown type specifier 'r' at step-collection time before any scenario can run — all four scenarios fail at discovery.

Simplest fix — remove :r and use plain string + eval:

@given("a Transport mock with BytesIO stream containing {raw_headers}")
def step_transport_with_streams(context: Any, raw_headers: str) -> None:
    data: bytes = eval(raw_headers)  # safe in test-only context
    context.stream = BytesIO(data)
    ...

This is consistent with test patterns used elsewhere in this codebase and requires no type registration.

**BLOCKER — Custom parse type `:r` not registered** The `:r` specifier in `{raw_headers:r}` is not a built-in `parse` type. No `register_type` call for `r` exists anywhere in `features/`. Behave raises `ParseTypeError: Unknown type specifier 'r'` at step-collection time before any scenario can run — all four scenarios fail at discovery. **Simplest fix — remove `:r` and use plain string + eval:** ```python @given("a Transport mock with BytesIO stream containing {raw_headers}") def step_transport_with_streams(context: Any, raw_headers: str) -> None: data: bytes = eval(raw_headers) # safe in test-only context context.stream = BytesIO(data) ... ``` This is consistent with test patterns used elsewhere in this codebase and requires no type registration.
Outdated
Review

BLOCKER — Custom parse type :r is not registered; step discovery fails for all scenarios

{raw_headers:r} uses a custom Behave/parse type specifier :r that is not a built-in parse type and is not registered anywhere in features/. Behave raises ParseTypeError: Unknown type specifier 'r' during step-collection — all four scenarios fail before running.

Recommended fix (Option B — simpler): Drop :r and use eval() inside the step:

@given("a Transport mock with BytesIO stream containing {raw_headers}")
def step_transport_with_streams(context: Any, raw_headers: str) -> None:
    data: bytes = eval(raw_headers)   # raw_headers is e.g. b"Content-Length: 10\\xc0..."
    context.stream = BytesIO(data)
    ...

Alternative (Option A): Register a bytes-literal parse type in features/environment.py using parse.with_pattern + register_type.

**BLOCKER — Custom parse type `:r` is not registered; step discovery fails for all scenarios** `{raw_headers:r}` uses a custom Behave/parse type specifier `:r` that is not a built-in `parse` type and is not registered anywhere in `features/`. Behave raises `ParseTypeError: Unknown type specifier 'r'` during step-collection — all four scenarios fail before running. **Recommended fix (Option B — simpler):** Drop `:r` and use `eval()` inside the step: ```python @given("a Transport mock with BytesIO stream containing {raw_headers}") def step_transport_with_streams(context: Any, raw_headers: str) -> None: data: bytes = eval(raw_headers) # raw_headers is e.g. b"Content-Length: 10\\xc0..." context.stream = BytesIO(data) ... ``` **Alternative (Option A):** Register a bytes-literal parse type in `features/environment.py` using `parse.with_pattern` + `register_type`.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
**_kwargs: Any,
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
) -> tuple[list[Any], list[Any], list[Any]]:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
"""Patch ``select.select`` to return a ready file descriptor immediately.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Returns a proper 3-tuple matching the ``select.select()`` API contract:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
``([readable[0]], [], [])`` rather than just ``[readable[0]]`` which
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
would cause ``ValueError`` during tuple unpacking in ``_read_one_message()``.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
"""
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
if readable:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
return ([readable[0]], [], [])
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
return ([], [], [])
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
# ── Given steps ──────────────────────────────────────────────────────────
Outdated
Review

BLOCKERcontext.mock_process.stdout is set to a BytesIO object, but _read_one_message() calls select.select([stdout], [], [], timeout) which requires a real Unix file descriptor. BytesIO has no fileno() and raises io.UnsupportedOperation: fileno when passed to select.select(). This exception is NOT caught by except LspError as e:, so it propagates unhandled, failing the scenario before the ASCII decode logic is ever exercised.

Fix by patching select.select in the transport module so it returns the mock stdout immediately:

from unittest.mock import patch

with patch("cleveragents.lsp.transport.select") as mock_select:
    mock_select.select.return_value = ([context.mock_process.stdout], [], [])
    try:
        context.transport.read_message(timeout=1.0)
    except LspError as e:
        context.exception = e

The same fix must be applied to all three @when step definitions that use BytesIO as the stdout mock (lines 39, 53, 67, and the valid-message step at line ~80). This is the root cause of the CI / unit_tests failure.

**BLOCKER** — `context.mock_process.stdout` is set to a `BytesIO` object, but `_read_one_message()` calls `select.select([stdout], [], [], timeout)` which requires a real Unix file descriptor. `BytesIO` has no `fileno()` and raises `io.UnsupportedOperation: fileno` when passed to `select.select()`. This exception is NOT caught by `except LspError as e:`, so it propagates unhandled, failing the scenario before the ASCII decode logic is ever exercised. Fix by patching `select.select` in the transport module so it returns the mock stdout immediately: ```python from unittest.mock import patch with patch("cleveragents.lsp.transport.select") as mock_select: mock_select.select.return_value = ([context.mock_process.stdout], [], []) try: context.transport.read_message(timeout=1.0) except LspError as e: context.exception = e ``` The same fix must be applied to all three `@when` step definitions that use `BytesIO` as the stdout mock (lines 39, 53, 67, and the valid-message step at line ~80). This is the root cause of the `CI / unit_tests` failure.
Outdated
Review

BLOCKER — This and the other three @when step implementations still use BytesIO as stdout without patching select.select. _read_one_message() calls select.select([stdout], [], [], timeout) (transport.py line 244). BytesIO has no file descriptor: BytesIO.fileno() raises io.UnsupportedOperation: fileno BEFORE the ASCII decode logic runs. This exception is not LspError, so the except LspError handler does not catch it — Behave sees an ERROR, not a PASS. This is the root cause of CI / unit_tests FAILING.

Required fix — wrap the read_message() call with a select patch in all four @when steps:

from unittest.mock import patch

with patch("cleveragents.lsp.transport.select") as mock_select:
    mock_select.select.return_value = ([context.mock_process.stdout], [], [])
    try:
        context.transport.read_message(timeout=1.0)
    except LspError as e:
        context.exception = e

Apply this pattern to all four @when step functions.

**BLOCKER** — This and the other three `@when` step implementations still use `BytesIO` as stdout without patching `select.select`. `_read_one_message()` calls `select.select([stdout], [], [], timeout)` (transport.py line 244). `BytesIO` has no file descriptor: `BytesIO.fileno()` raises `io.UnsupportedOperation: fileno` BEFORE the ASCII decode logic runs. This exception is not `LspError`, so the `except LspError` handler does not catch it — Behave sees an ERROR, not a PASS. This is the root cause of `CI / unit_tests` FAILING. **Required fix** — wrap the `read_message()` call with a `select` patch in all four `@when` steps: ```python from unittest.mock import patch with patch("cleveragents.lsp.transport.select") as mock_select: mock_select.select.return_value = ([context.mock_process.stdout], [], []) try: context.transport.read_message(timeout=1.0) except LspError as e: context.exception = e ``` Apply this pattern to all four `@when` step functions.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
@given("a Transport mock with BytesIO stream containing {raw_headers}")
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def step_transport_with_streams(context: Any, raw_headers: str) -> None:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
"""Set up a transport whose subprocess.stdout is a BytesIO initialised
Outdated
Review

BLOCKER — Incorrect mock: BytesIO is incompatible with select.select()

StdioTransport._read_one_message() calls select.select([stdout], [], [], timeout) (transport.py line 244). select.select() requires a real OS-level file descriptor — BytesIO has no fileno() and raises UnsupportedOperation: fileno immediately.

This means the test never reaches the line.decode("ascii", errors="strict") call and the UnsupportedOperation exception propagates out of the try: … except LspError: block uncaught, causing the Behave step to fail with an unexpected exception.

The same problem affects all four @when step functions.

Required fix: Patch select.select to simulate readiness before calling read_message(). For example:

from unittest.mock import patch

with patch("cleveragents.lsp.transport.select") as mock_sel:
    mock_sel.select.return_value = ([context.mock_process.stdout], [], [])
    try:
        context.transport.read_message(timeout=1.0)
    except LspError as e:
        context.exception = e

Apply this pattern to every @when step that calls context.transport.read_message().


Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker

**BLOCKER — Incorrect mock: `BytesIO` is incompatible with `select.select()`** `StdioTransport._read_one_message()` calls `select.select([stdout], [], [], timeout)` (transport.py line 244). `select.select()` requires a real OS-level file descriptor — `BytesIO` has no `fileno()` and raises `UnsupportedOperation: fileno` immediately. This means the test never reaches the `line.decode("ascii", errors="strict")` call and the `UnsupportedOperation` exception propagates out of the `try: … except LspError:` block uncaught, causing the Behave step to fail with an unexpected exception. The same problem affects all four `@when` step functions. **Required fix:** Patch `select.select` to simulate readiness before calling `read_message()`. For example: ```python from unittest.mock import patch with patch("cleveragents.lsp.transport.select") as mock_sel: mock_sel.select.return_value = ([context.mock_process.stdout], [], []) try: context.transport.read_message(timeout=1.0) except LspError as e: context.exception = e ``` Apply this pattern to every `@when` step that calls `context.transport.read_message()`. --- Automated by CleverAgents Bot Supervisor: PR Review | Agent: pr-review-worker
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
with the specified raw header+body bytes."""
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
data: bytes = eval(raw_headers)
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
transport = object.__new__(StdioTransport) # Bypass __init__ validation
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
transport._process = MagicMock()
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
transport._process.poll.return_value = None # Pretend process is alive
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
context.stream = BytesIO(data)
Outdated
Review

BLOCKER — Trailing whitespace (ruff W291) — root cause of CI / lint failure

This line contains 4 trailing spaces on an otherwise blank line. Ruff W291 flags trailing whitespace on non-empty lines.

Required fix: Delete the 4 trailing spaces so this is a completely empty line (just a newline character).

This is the only whitespace violation in the new files and is the root cause of the 1m5s lint CI failure.

**BLOCKER — Trailing whitespace (ruff `W291`) — root cause of `CI / lint` failure** This line contains 4 trailing spaces on an otherwise blank line. Ruff `W291` flags trailing whitespace on non-empty lines. **Required fix:** Delete the 4 trailing spaces so this is a completely empty line (just a newline character). This is the only whitespace violation in the new files and is the root cause of the 1m5s lint CI failure.
Outdated
Review

BLOCKER P0 — Trailing whitespace causes CI / lint failure

Line 50 contains 4 trailing spaces ( \n instead of \n). With select = ["E", "F", "W", "B", "UP", "I", "SIM", "RUF"] in pyproject.toml, ruff rule W291 (trailing whitespace on non-empty line) or W293 (whitespace before blank line) fires here.

Fix: delete the 4 spaces on this line so it is a plain empty line (\n).


Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker

**BLOCKER P0 — Trailing whitespace causes `CI / lint` failure** Line 50 contains 4 trailing spaces (` \n` instead of `\n`). With `select = ["E", "F", "W", "B", "UP", "I", "SIM", "RUF"]` in `pyproject.toml`, ruff rule `W291` (trailing whitespace on non-empty line) or `W293` (whitespace before blank line) fires here. Fix: delete the 4 spaces on this line so it is a plain empty line (`\n`). --- Automated by CleverAgents Bot Supervisor: PR Review | Agent: pr-review-worker
Outdated
Review

BLOCKER — Trailing whitespace (W291)

This line contains 4 trailing spaces: \n (spaces before the newline). Ruff reports this as W291 trailing whitespace. This is the root cause of CI / lint failing.

Required fix: Delete the 4 trailing spaces so the line is completely empty (\n only).

**BLOCKER — Trailing whitespace (W291)** This line contains 4 trailing spaces: ` \n` (spaces before the newline). Ruff reports this as `W291 trailing whitespace`. This is the root cause of `CI / lint` failing. **Required fix:** Delete the 4 trailing spaces so the line is completely empty (`\n` only).
Outdated
Review

BLOCKER — Trailing whitespace on this blank line (4 spaces)

This line contains 4 trailing spaces, causing ruff W291 (trailing whitespace). This is a contributing cause of CI / lint FAILING.

Required fix: Delete all trailing spaces — this line should be completely empty.

**BLOCKER — Trailing whitespace on this blank line (4 spaces)** This line contains 4 trailing spaces, causing `ruff W291` (trailing whitespace). This is a contributing cause of `CI / lint` FAILING. **Required fix:** Delete all trailing spaces — this line should be completely empty.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
transport._process.stdout = context.stream
Outdated
Review

BLOCKER — _patched_select returns 1-element list instead of 3-tuple; causes ValueError: not enough values to unpack in every test

transport.py line 236 unpacks the result of select.select as a 3-tuple:

ready, _, _ = select.select([stdout], [], [], timeout)

The real select.select always returns (rlist, wlist, xlist). Your patch returns:

return [readable[0]]  # only 1 element

Unpacking [stdout_obj] into ready, _, _ raises ValueError: not enough values to unpack (expected 3, got 1). This exception propagates to except Exception as exc in the step, so context.raised_error is a ValueError, not an LspError. The assertion isinstance(context.raised_error, (LspError, UnicodeDecodeError)) then fails.

Required fix:

def _patched_select(readable, *_args, **_kwargs):
    if readable:
        return ([readable[0]], [], [])  # correct 3-tuple
    return ([], [], [])                 # timeout

This also applies to the second select.select call inside _read_one_message (used for the body read after headers are parsed).

**BLOCKER — `_patched_select` returns 1-element list instead of 3-tuple; causes `ValueError: not enough values to unpack` in every test** `transport.py` line 236 unpacks the result of `select.select` as a 3-tuple: ```python ready, _, _ = select.select([stdout], [], [], timeout) ``` The real `select.select` always returns `(rlist, wlist, xlist)`. Your patch returns: ```python return [readable[0]] # only 1 element ``` Unpacking `[stdout_obj]` into `ready, _, _` raises `ValueError: not enough values to unpack (expected 3, got 1)`. This exception propagates to `except Exception as exc` in the step, so `context.raised_error` is a `ValueError`, not an `LspError`. The assertion `isinstance(context.raised_error, (LspError, UnicodeDecodeError))` then fails. **Required fix:** ```python def _patched_select(readable, *_args, **_kwargs): if readable: return ([readable[0]], [], []) # correct 3-tuple return ([], [], []) # timeout ``` This also applies to the second `select.select` call inside `_read_one_message` (used for the body read after headers are parsed).
Outdated
Review

BLOCKER — _patched_select returns wrong type

This function returns a 1-element list [readable[0]] but transport.py unpacks the return as a 3-tuple:

ready, _, _ = select.select([stdout], [], [], timeout)

This raises ValueError: not enough values to unpack (expected 3, got 1) immediately, before any LspError assertion is reached. The bare except Exception block catches it and stores it as context.raised_error, causing the assertion isinstance(..., LspError) to fail.

Required fix:

def _patched_select(readable, *_args: Any, **_kwargs: Any) -> tuple[list[Any], list[Any], list[Any]]:
    if readable:
        return ([readable[0]], [], [])  # Correct 3-tuple matching select.select() contract
    return ([], [], [])                 # Timeout path

Note: select.select is called twice in _read_one_message — once per header line in the while loop, and once for the body read. Both calls unpack a 3-tuple and both will hit this error.

**BLOCKER — `_patched_select` returns wrong type** This function returns a 1-element list `[readable[0]]` but `transport.py` unpacks the return as a 3-tuple: ```python ready, _, _ = select.select([stdout], [], [], timeout) ``` This raises `ValueError: not enough values to unpack (expected 3, got 1)` immediately, before any `LspError` assertion is reached. The bare `except Exception` block catches it and stores it as `context.raised_error`, causing the assertion `isinstance(..., LspError)` to fail. **Required fix:** ```python def _patched_select(readable, *_args: Any, **_kwargs: Any) -> tuple[list[Any], list[Any], list[Any]]: if readable: return ([readable[0]], [], []) # Correct 3-tuple matching select.select() contract return ([], [], []) # Timeout path ``` Note: `select.select` is called twice in `_read_one_message` — once per header line in the while loop, and once for the body read. Both calls unpack a 3-tuple and both will hit this error.
Outdated
Review

BLOCKER — _patched_select returns 1-element list instead of required 3-tuple

_read_one_message() unpacks select.select() as ready, _, _ = select.select(...) — a 3-tuple. This function returns [readable[0]] (1-element list) or [], causing ValueError: not enough values to unpack (expected 3, got 1) on every call. The ValueError is caught by bare except Exception, stored as context.raised_error, and the isinstance(context.raised_error, (LspError, UnicodeDecodeError)) assertion fails for all scenarios.

Required fix:

def _patched_select(
    readable: list[Any],
    *_args: Any,
    **_kwargs: Any,
) -> tuple[list[Any], list[Any], list[Any]]:
    if readable:
        return ([readable[0]], [], [])   # Correct 3-tuple matching select.select contract
    return ([], [], [])                  # Timeout path

Note: _read_one_message calls select.select TWICE (header loop + body read) — both need correct 3-tuple.

**BLOCKER — `_patched_select` returns 1-element list instead of required 3-tuple** `_read_one_message()` unpacks `select.select()` as `ready, _, _ = select.select(...)` — a 3-tuple. This function returns `[readable[0]]` (1-element list) or `[]`, causing `ValueError: not enough values to unpack (expected 3, got 1)` on every call. The ValueError is caught by bare `except Exception`, stored as `context.raised_error`, and the `isinstance(context.raised_error, (LspError, UnicodeDecodeError))` assertion fails for all scenarios. **Required fix:** ```python def _patched_select( readable: list[Any], *_args: Any, **_kwargs: Any, ) -> tuple[list[Any], list[Any], list[Any]]: if readable: return ([readable[0]], [], []) # Correct 3-tuple matching select.select contract return ([], [], []) # Timeout path ``` Note: `_read_one_message` calls `select.select` TWICE (header loop + body read) — both need correct 3-tuple.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
context.transport = transport
Outdated
Review

BLOCKER P0 — _patched_select returns wrong shape; causes ValueError: not enough values to unpack

transport.py unpacks the return value of select.select() as a 3-tuple:

ready, _, _ = select.select([stdout], [], [], timeout)

But _patched_select currently returns a 1-item list [readable[0]]. Python will raise ValueError: not enough values to unpack (expected 3, got 1) before the ASCII-decode code is reached.

This exception IS caught by except Exception as exc further down, but isinstance(ValueError(), (LspError, UnicodeDecodeError)) is False, so the @then "it should raise an LspError exception" step FAILS. This is the root cause of CI / unit_tests FAILING.

Required fix:

def _patched_select(readable, *_args, **_kwargs):
    if readable:
        return ([readable[0]], [], [])  # 3-tuple: (ready_read, ready_write, exceptional)
    return ([], [], [])

Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker

**BLOCKER P0 — `_patched_select` returns wrong shape; causes `ValueError: not enough values to unpack`** `transport.py` unpacks the return value of `select.select()` as a 3-tuple: ```python ready, _, _ = select.select([stdout], [], [], timeout) ``` But `_patched_select` currently returns a 1-item list `[readable[0]]`. Python will raise `ValueError: not enough values to unpack (expected 3, got 1)` before the ASCII-decode code is reached. This exception IS caught by `except Exception as exc` further down, but `isinstance(ValueError(), (LspError, UnicodeDecodeError))` is `False`, so the `@then "it should raise an LspError exception"` step FAILS. This is the root cause of `CI / unit_tests` FAILING. **Required fix:** ```python def _patched_select(readable, *_args, **_kwargs): if readable: return ([readable[0]], [], []) # 3-tuple: (ready_read, ready_write, exceptional) return ([], [], []) ``` --- Automated by CleverAgents Bot Supervisor: PR Review | Agent: pr-review-worker
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
context.mock_process = transport._process
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
# ── When steps ───────────────────────────────────────────────────────────
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
@when("_read_one_message() is invoked")
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def step_invoke_read_message(context: Any) -> None:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
"""Call ``_read_one_message`` on the mocked transport.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Because :meth:`select.select` does not work natively on ``BytesIO``, we
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
patch it so that a ready file descriptor is returned immediately,
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
unblocking ``stdout.readline()`` and driving the header-reading loop with
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

Suggestion: Consider narrowing the bare except Exception (line 65) to catch only the specific exceptions you want to capture. While this is test-only code and catching all exceptions here is acceptable for comprehensive coverage, narrowing to except (LspError, UnicodeDecodeError) would make the captured error scope more explicit and document which exception types are considered valid outcomes.

Suggestion: Consider narrowing the bare `except Exception` (line 65) to catch only the specific exceptions you want to capture. While this is test-only code and catching all exceptions here is acceptable for comprehensive coverage, narrowing to `except (LspError, UnicodeDecodeError)` would make the captured error scope more explicit and document which exception types are considered valid outcomes.
the data already sitting in the ``BytesIO`` buffer.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
"""
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
with patch.object(select, "select", side_effect=patched_select):
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
context.raised_error = None
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
try:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
context.read_result = context.transport._read_one_message(timeout=1.0)
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
except Exception as exc:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
context.raised_error = exc
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
# ── Then steps ───────────────────────────────────────────────────────────
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
@then("it should raise an LspError exception")
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def step_raises_lsp_error(context: Any) -> None:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert context.raised_error is not None, "Expected an error to be raised"
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert isinstance(context.raised_error, (LspError, UnicodeDecodeError)), (
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
f"Expected LspError or UnicodeDecodeError, got {type(context.raised_error).__name__}"
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
)
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
@then("it should return a parsed JSON dict")
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def step_returns_parsed_json_dict(context: Any) -> None:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert context.raised_error is None
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert isinstance(context.read_result, dict), (
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
f"Expected parsed dict, got {type(context.read_result).__name__}"
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
)
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
@then('the error message must contain "non-ASCII"')
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def step_error_contains_non_ascii(context: Any) -> None:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert context.raised_error is not None
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
error_text = str(context.raised_error).lower()
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert "non-ascii" in error_text or "unicode" in error_text
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
@then('the result must contain "jsonrpc" == "2.0"')
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def step_result_has_jsonrpc(context: Any) -> None:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert isinstance(context.read_result, dict), "Result should be a dict"
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert context.read_result.get("jsonrpc") == "2.0"
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
@then('the result must contain "id" == 1')
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def step_result_has_id(context: Any) -> None:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert isinstance(context.read_result, dict), "Result should be a dict"
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert context.read_result.get("id") == 1
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
@then('the result must contain "result" == "success"')
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def step_result_has_result(context: Any) -> None:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert isinstance(context.read_result, dict), "Result should be a dict"
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert context.read_result.get("result") == "success"
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
@then('the result must contain "Content-Length"')
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def step_result_has_content_length(context: Any) -> None:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert isinstance(context.read_result, dict), "Result should be a dict"
Outdated
Review

BLOCKER — Single-quoted string argument fails ruff format --check

hasattr(context, 'read_result') uses a single-quoted string. The project’s pyproject.toml configures quote-style = "double" for ruff format. The CI lint job runs nox -s format -- --check after nox -s lint — this line fails the format check.

Required fix: Change to hasattr(context, "read_result") (double quotes). The same fix applies to line 124 in step_check_message_json_parsing.


Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker

**BLOCKER — Single-quoted string argument fails `ruff format --check`** `hasattr(context, 'read_result')` uses a single-quoted string. The project’s `pyproject.toml` configures `quote-style = "double"` for `ruff format`. The CI `lint` job runs `nox -s format -- --check` after `nox -s lint` — this line fails the format check. **Required fix:** Change to `hasattr(context, "read_result")` (double quotes). The same fix applies to line 124 in `step_check_message_json_parsing`. --- Automated by CleverAgents Bot Supervisor: PR Review | Agent: pr-review-worker
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
cl = context.read_result.get("Content-Length")
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert cl is None or isinstance(cl, int)
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
@then("the transport should still be alive")
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
def step_transport_alive(context: Any) -> None:
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
assert context.mock_process.poll.return_value is None
Review

SUGGESTION: The @then("the result must contain \"Content-Length\"") step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.

SUGGESTION: The `@then("the result must contain \"Content-Length\"")` step tests for content-length key presence but is not covered by any scenario in the feature file. Consider removing this dead step or adding a scenario that exercises it.
+33 -23
View File
3
@@ -27,6 +27,8 @@ from typing import Any
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
import structlog
from cleveragents.lsp.errors import LspError
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
logger = structlog.get_logger(__name__)
# Maximum time (seconds) to wait for a graceful process termination
@@ -123,36 +125,15 @@ class StdioTransport:
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
cwd=self._cwd,
)
except FileNotFoundError as exc:
self._process = None
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
from cleveragents.lsp.errors import LspError
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
raise LspError(
f"LSP server command not found: {self._command}",
details={"command": self._command, "args": self._args},
) from exc
except OSError as exc:
# Popen may have partially started the subprocess before
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
# raising (e.g. execve failure post-fork on some platforms).
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
# Ensure cleanup so the process does not leak into the caller's
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
# address space.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
if self._process is not None:
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
self.stop()
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
self._process = None
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
from cleveragents.lsp.errors import LspError
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
raise LspError(
f"Failed to start LSP server: {exc}",
details={"command": self._command, "error": str(exc)},
) from exc
except Exception:
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
# Catch-all for any other low-level OSError / resource-error
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
# variants that might leave a zombie process behind.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
if self._process is not None:
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
self.stop()
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
self._process = None
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
raise
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
# All post-Popen initialization logic must be placed within the
# guarded block below to prevent orphaned subprocesses if init
@@ -275,7 +256,23 @@ class StdioTransport:
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
return self._read_one_message(effective_timeout)
def _read_one_message(self, timeout: float) -> dict[str, Any] | None:
"""Parse a single ``Content-Length`` framed JSON-RPC message."""
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
"""Parse a single ``Content-Length``-framed JSON-RPC message.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Header lines are decoded with ``errors="strict"``; any non-ASCII byte
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
raises :class:`~cleveragents.lsp.errors.LspError`. An additional
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
printable-ASCII guard rejects decoded headers containing characters
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
outside the codepoint range 0x20 (space) to 0x7E (tilde).
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Returns
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
-------
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
dict[str, Any] | None
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Parsed JSON body, or ``None`` on EOF / timeout.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Raises
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
------
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
LspError
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
If a header contains non-ASCII bytes or non-printable characters.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
"""
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
assert self._process is not None
assert self._process.stdout is not None
@@ -290,7 +287,20 @@ class StdioTransport:
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
line = stdout.readline()
if not line:
return None # EOF — server exited
decoded = line.decode("ascii", errors="replace").strip()
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
try:
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
decoded = line.decode("ascii", errors="strict").strip()
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
except UnicodeDecodeError as exc:
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
raise LspError(
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
f"LSP header contains non-ASCII bytes: {exc}",
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
details={"raw_header": repr(line)},
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
) from exc
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
# Printable-ASCII guard: reject control characters
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
# outside the range 0x20 (space) through 0x7E (tilde).
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
if not all(0x20 <= ord(c) <= 0x7E for c in decoded):
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
raise LspError(
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
f"LSP header contains non-printable ASCII characters: {decoded!r}",
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
details={"raw_header": repr(line)},
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
)
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
if not decoded:
break # Empty line = end of headers
if decoded.lower().startswith("content-length:"):
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.
Review

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates all(0x20 <= ord(c) <= 0x7E for c in decoded) which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.

SUGGESTION: Consider edge case for very long header lines. The printable-ASCII guard iterates `all(0x20 <= ord(c) <= 0x7E for c in decoded)` which is O(n) — fine for reasonable inputs but worth noting that extremely long headers could impact performance marginally.