feat(lsp): add missing LspCapability enum values #1063
No reviewers
Labels
No labels
auto/needs-reevaluation
controller-managed
auto/blocked-by-deps
auto/ci-timeout
auto/claimed-implementer
auto/claimed-merge
auto/claimed-reviewer
auto/driver-down
auto/invariant-violation
auto/last-attempt-tier-0
auto/last-attempt-tier-1
auto/last-attempt-tier-2
auto/last-attempt-tier-min
Automation Tracking
auto/needs-conflict-resolution
auto/needs-implementer
auto/postmortem
auto/ready-to-merge
auto/restart-throttled
auto/revert
auto/sentinel
auto/stale-inactivity
auto/unstable
Blocked
Bounty
$100
Bounty
$1000
Bounty
$10000
Bounty
$20
Bounty
$2000
Bounty
$250
Bounty
$50
Bounty
$500
Bounty
$5000
Bounty
$750
MoSCoW
Could have
MoSCoW
Must have
MoSCoW
Should have
Needs Feedback
Points
1
Points
13
Points
2
Points
21
Points
3
Points
34
Points
5
Points
55
Points
8
Points
88
Priority
Backlog
Priority
CI Blocker
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Signed-off: Owner
Signed-off: Scrum Master
Signed-off: Tech Lead
Spike
State
Completed
State
Duplicate
State
In Progress
State
In Review
State
Paused
State
Unverified
State
Verified
State
Wont Do
Type
Automation
Type
Bug
Type
Discussion
Type
Documentation
Type
Epic
Type
Feature
Type
Legendary
Type
Refactor
Type
Support
Type
Task
Type
Testing
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
cleveragents/cleveragents-core!1063
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/lsp-capability-enum"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds 5 missing LSP capabilities to the
LspCapabilityenum, aligning it with the spec's 11-capability set. Updates the tool adapter to generate tool specs and input schemas for all capabilities.Closes #834
Changes
Enum (
models.py)DIAGNOSTICSDIAGNOSTICSTYPE_INFOHOVER(renamed)SYMBOLSDOCUMENT_SYMBOLS(renamed)COMPLETIONSCOMPLETIONSREFERENCESREFERENCESRENAMERENAMECODE_ACTIONSCODE_ACTIONSFORMATFORMATDEFINITIONS(new)SIGNATURE_HELP(new)WORKSPACE_SYMBOLS(new)Tool Adapter (
tool_adapter.py)_CAPABILITY_TOOL_MAP: 11 entries with spec-aligned tool suffixes_input_schema_for(): 3 schema categories:queryfield)Server (
server.py)No changes needed —
_STUBBED_CAPABILITIESalready includes all 11 LSP provider keys.Tests
28 Behave scenarios covering: enum member count and values, tool map completeness, tool spec generation for each capability, input schema correctness, stubbed server capability keys.
Spec Reference
docs/specification.mdlines 20705-20717Planning review (Day 42):
bugbut the title and body describe a feature addition (feat(lsp): add missing LspCapability enum values). Should beType/Featureper CONTRIBUTING.md conventions.Otherwise looks good: milestone set (v3.6.0), closes #834, 2 reviewers assigned (freemo + brent.edwards).
PR Review: !1063 (Ticket #834)
Verdict: Request Changes
This PR makes solid progress aligning the
LspCapabilityenum with the spec's 11-capability table and adds well-structured BDD tests. However, the build is broken — renamingTYPE_INFO→HOVERandSYMBOLS→DOCUMENT_SYMBOLSwas not propagated to 3 other files that still reference the old string values, causing 13+ test scenario failures. In addition, there are spec compliance gaps (tool suffix mismatch, enum value mismatch), missing process artifacts (changelog, documentation), and a stale branch. These must be resolved before merge.Critical Issues
1. Broken test fixture
_VALID_YAMLuses removed enum valuetype_infofeatures/steps/lsp_cli_new_coverage_steps.py, line 41- type_infoas a capability. SinceTYPE_INFO = "type_info"was renamed toHOVER = "hover",LspCapability("type_info")now raisesValueError. This breaks 12 test scenarios infeatures/lsp_cli_new_coverage.feature. Confirmed by runningnox -s unit_tests.- type_info→- hoveron line 41.2. Broken test fixture
_VALID_YAML_2uses removed enum valuesymbolsfeatures/steps/lsp_cli_new_coverage_steps.py, line 54- symbolsas a capability. SinceSYMBOLS = "symbols"was renamed toDOCUMENT_SYMBOLS = "document_symbols", this also raisesValueError, compounding the failures from issue #1.- symbols→- document_symbolson line 54.3. Broken Behave scenario uses removed
type_infocapabilityfeatures/consolidated_misc.feature, line 1227And the LSP server config has capabilities "diagnostics,completions,type_info"passes"type_info"to a step that builds a map fromLspCapabilityvalues. Since"type_info"is no longer a valid value, this throwsKeyErrorat runtime. Confirmed failing innox -s unit_tests."diagnostics,completions,type_info"→"diagnostics,completions,hover".Major Issues
4. Tool suffix for
CODE_ACTIONSuses underscore instead of spec-required hyphensrc/cleveragents/lsp/tool_adapter.py, line 52lsp/code-actions(hyphen). The_CAPABILITY_TOOL_MAPentry uses"code_actions"(underscore), producing tool names likelocal/pyright/code_actionsinstead oflocal/pyright/code-actions. The PR modifies this map to align all 11 entries with the spec — leaving this one misaligned defeats the purpose."code_actions"→"code-actions"and update the Behave test example atfeatures/lsp_capability_enum.featureline 51 accordingly.5. Enum value
FORMAT = "format"does not match spec capability nameformattingsrc/cleveragents/lsp/models.py, line 36formatting, notformat. The PR renamesTYPE_INFO→HOVERandSYMBOLS→DOCUMENT_SYMBOLSto align with spec names, but does not apply the same treatment toFORMAT. This is inconsistent and technically violates acceptance criterion #1 ("enum includes all 11 spec-defined values").FORMATTING = "formatting"and update all references. The tool suffix should remain"format"per the spec's tool namelsp/format.6.
_input_schema_for()has an unguarded fallthrough for unknown capabilitiessrc/cleveragents/lsp/tool_adapter.py, lines 161–213file_only,position_based,query_based), the function silently returns{"type": "object", "properties": {}}with norequiredfield. No warning, no assertion, no logging. If someone adds a new enum member but forgets to add it to a tuple, the tool will be generated with an empty schema undetected.elseclause that raisesValueError(f"No schema defined for {capability}"), or add an exhaustive-check assertion.7.
RENAMEcapability schema missing requirednew_nameparametersrc/cleveragents/lsp/tool_adapter.py, lines 169–204RENAMEis categorized asposition_based, generating a schema with onlyfile_path,line,column. However, the LSPtextDocument/renamerequest requires anewNameparameter — you can't rename without knowing what to rename to. While pre-existing, this PR refactored the schema function and had the opportunity to fix it.RENAMEits own schema category that includesfile_path,line,column, andnew_name.8.
docs/reference/lsp.mdis stale and incorrectdocs/reference/lsp.md, lines 23–32 and 96–109TYPE_INFO,SYMBOLS). The YAML example still usestype_info. Acceptance criterion #4 requires "Documentation updated with full capability list." No documentation was updated.9. Missing CHANGELOG.md entry
CHANGELOG.md(not modified)## Unreleaseddescribing the addition of 5 new LSP capabilities.10. Branch is 43 commits behind master — stale artifacts and merge hazards
CHANGELOG.md,CONTRIBUTORS.mdorigin/master. The CHANGELOG on the branch is missing ~120 lines of entries from master.CONTRIBUTORS.mdhas a duplicate "Rui Hu" entry and is missing a contributor that exists on master. A merge would create destructive conflicts.Minor Issues
11. CLI docstring example uses removed
type_infovaluesrc/cleveragents/cli/commands/lsp.py, line 30capabilities: ["diagnostics", "completions", "type_info"]. Users copying this example will get a Pydantic validation error."type_info"→"hover".12. Schema tests only cover 1 member per category — inadequate categorization coverage
features/lsp_capability_enum.feature, lines 59–73diagnostics(file_only),hover(position_based), andworkspace_symbols(query_based) are tested. Ifformatordocument_symbolswere accidentally placed in the wrong category, no test would catch it.Scenario Outlinecovering at least 2–3 members per category.13. Tool name assertion uses fragile substring matching
features/steps/lsp_capability_enum_steps.py, lines 103–108any(suffix in n for n in names)means suffix"symbols"(fordocument_symbols) would also match"workspace-symbols". Could produce false positives.n.endswith(f"/{suffix}")for more precise matching.14. Weak assertion in
step_specs_not_empty_lsp_cap— only checks existencefeatures/steps/lsp_capability_enum_steps.py, lines 96–100len(specs) > 0. Never validates that generated specs have expected keys (name,input_schema). A malformed spec would pass.15. Stubbed capabilities test only checks 5 of 11 provider keys
features/lsp_capability_enum.feature, lines 77–83completionProvider) would go undetected.16. Category tuples in
_input_schema_for()are recreated on every callsrc/cleveragents/lsp/tool_adapter.py, lines 163–179_FILE_ONLY_CAPABILITIES,_POSITION_BASED_CAPABILITIES,_QUERY_BASED_CAPABILITIES).Nits
17. No negative/edge-case test scenarios
features/lsp_capability_enum.featureLspCapability("nonexistent")→ValueError, or empty capabilities list, orNoneconfig togenerate_tool_specs().18. JSON schemas lack
additionalProperties: falsesrc/cleveragents/lsp/tool_adapter.py, line 161"additionalProperties": Falseto the base dict.19. Feature file trailing whitespace alignment inconsistency
features/lsp_capability_enum.feature, line 29| workspace_symbols|is missing the trailing space before|that all other entries have.| workspace_symbols |.20. No
max_lengthconstraint onLspServerConfig.namesrc/cleveragents/lsp/models.py, lines 54–58namehasmin_length=1but no upper bound. An extremely long name would produce oversized tool names and bloat specs.max_length=256.Summary
The PR demonstrates good engineering: a clean commit message matching ticket metadata, well-structured BDD tests with proper naming, thorough tool adapter refactoring, and passing lint/typecheck/format gates. However, the enum rename migration was incomplete, leaving 3 files with stale references that break 13+ test scenarios (confirmed by
nox -s unit_tests). Beyond the broken build, there are spec alignment gaps (code_actionssuffix,formatvsformatting), missing process artifacts (changelog, documentation), and a stale branch. These issues require changes before this PR is mergeable.0c0b3df945626c2606a8Response to Review (hurui200320)
All 20 findings addressed. Rebased onto master, pushed
626c2606.Critical (1-3): Stale enum references — FIXED
lsp_cli_new_coverage_steps.py:41:type_info->hoverlsp_cli_new_coverage_steps.py:54:symbols->document_symbolsconsolidated_misc.feature:1231:type_info->hoverMajor (4-9):
code_actionsunderscorecode-actions(hyphen) in tool mapFORMATvs specformattingFORMATTING = "formatting". Tool suffix stays"format"per spec tool namelsp/format_input_schema_forelse: raise ValueError(...)defensive clausenew_namefile_path,line,column,new_namedocs/reference/lsp.mdstale## UnreleasedMajor 10: Branch stale — FIXED
Rebased onto current master. Clean rebase.
Minor (11-16):
type_infohovern.endswith(f"/{suffix}")step_spec_has_keysassertingnameandinput_schemakeys_FILE_ONLY_CAPABILITIES,_POSITION_BASED_CAPABILITIES,_RENAME_CAPABILITY,_QUERY_BASED_CAPABILITIESNits (17-20):
additionalProperties: falsemax_lengthonLspServerConfig.nameCurrent state: 37 scenarios, 135 steps, lint clean. All stale references fixed.
PR Review: !1063 (Ticket #834)
Verdict: Request Changes
This PR fixes most of the previously reported defects and aligns the enum/tool mapping with the spec’s 11-capability list.
However, there are still major gaps: one ticket acceptance criterion is not implemented, and there is a runtime correctness mismatch for
workspace_symbols.Critical Issues
None.
Major Issues
Ticket AC not fully implemented: capability negotiation in initialize request not updated
src/cleveragents/lsp/client.py229-243LspClient.initialize()still only advertises diagnostics/completion/synchronization/workspaceFolders; it does not advertise newly added capabilities like hover/definition/signature/document/workspace symbols.params["capabilities"]payload ininitialize()to include the required capabilities (or explicitly adjust ticket/spec expectations if intentionally deferred).workspace_symbolsschema/handler contract mismatch in runtime modesrc/cleveragents/lsp/tool_adapter.py124-127,303-310_input_schema_for(LspCapability.WORKSPACE_SYMBOLS)requires onlyquery, but_make_runtime_handler()unconditionally requiresfile_pathbefore capability dispatch. So schema-valid input can fail with{"error": "file_path is required"}.WORKSPACE_SYMBOLS, accept query-only input (or raise consistentLspNotAvailableErrorwithout demandingfile_path).Minor Issues
“All provider keys” test misses diagnostics provider
features/lsp_capability_enum.feature100-112diagnosticProvider, which exists in_STUBBED_CAPABILITIES.diagnosticProvider(and ideally assert exact expected key set/count).src/cleveragents/lsp/server.py:90.New step file introduces many
type: ignoresuppressions against CONTRIBUTING guidancefeatures/steps/lsp_capability_enum_steps.py20, 26, 36, 48, 56, 65, 67, ... , 161CONTRIBUTING.mddisallows suppression usage.CONTRIBUTING.md:546-548.Input hardening gap: unbounded LSP server name
src/cleveragents/lsp/models.py54-58LspServerConfig.namehasmin_lengthbut no upper bound. This value is embedded in generated tool names and logs, which can inflate payload/log size.max_length(e.g. 256).Nits
ValueErrorbranch in schema builder is not directly testedsrc/cleveragents/lsp/tool_adapter.py311-312Summary
workspace_symbolshandler input contract.626c2606a8656dc1aeddResponse to Review Round 2 (hurui200320)
All validated findings addressed. Rebased onto master, pushed
656dc1ae.Major
initialize()doesn't advertise new capabilitiesclient.py:229-257to advertise all 11 capabilities: hover (with contentFormat), definition, references, rename, codeAction (with codeActionKind), formatting, signatureHelp (with parameterInformation), documentSymbol (with hierarchical support), and workspace symbol.workspace_symbolshandler requiresfile_pathbut schema only requiresquery_make_runtime_handler()now checksworkspace_symbolsfirst and accepts query-only input without demandingfile_path.Minor
diagnosticProviderdiagnosticProviderin the feature file.type: ignoresuppressions in step fileLspServerConfig.namenomax_lengthNit
ValueErrorbranch untestedCurrent state: 38 scenarios, 138 steps, lint clean. Rebased onto master.
PR Review: !1063 (Ticket #834)
Verdict: Approve
This PR is in excellent shape after three review rounds. All prior critical and major bugs (broken tests, stale enum references, missing capability negotiation, workspace_symbols handler mismatch) have been correctly resolved. Spec compliance is strong — all 11 capabilities are present, tool suffixes match the spec, documentation and CHANGELOG are updated, and commit/branch conventions are correct. The code is functionally correct and complete.
The findings below are suggestions for improvement — none are blockers. Feel free to address them in this PR or defer to follow-up work.
Critical Issues
None.
Major Issues
None.
Minor Issues (Suggestions)
1. No test for
_make_runtime_handlerworkspace_symbols code pathsrc/cleveragents/lsp/tool_adapter.py, lines 124–133WORKSPACE_SYMBOLSbranch in_make_runtime_handlervalidatesqueryinstead offile_pathand short-circuits before the generic validation. This behavioral branch has no direct test coverage. The code is correct, but a regression would go undetected.WORKSPACE_SYMBOLSand verifies it accepts query-only input and rejects empty queries.2. No test for
client.pycapability negotiation changessrc/cleveragents/lsp/client.py, lines 235–268initialize()payload now advertises all 11 capabilities, but no test validates the payload contents. Since these are static hardcoded fields, regression risk is low, but coverage would be nice.3. Error handling inconsistency in
_make_runtime_handler: dict vs exceptionsrc/cleveragents/lsp/tool_adapter.py, lines 127–133 vs 136–137{"error": ...}dicts, while unimplemented capabilities raiseLspNotAvailableError. Callers must handle both. This is a pre-existing pattern that the newworkspace_symbolscode follows consistently.4.
_CAPABILITY_TOOL_MAP.get()fallback silently masks missing map entriessrc/cleveragents/lsp/tool_adapter.py, lines 202–205.get()with a fallback tuple provides a silent default for missing capabilities. Since_input_schema_for()would catch unknown capabilities withValueErroranyway, this is a safety-net gap rather than a bug._CAPABILITY_TOOL_MAP[capability]for clearer error messages.5. No
maxLengthconstraint onqueryandnew_nameschema fieldssrc/cleveragents/lsp/tool_adapter.py, lines 308–321workspace_symbolsqueryandrenamenew_namestring fields have no length bounds. Currently all handlers raiseLspNotAvailableError, so there's no runtime risk, but setting limits now establishes the correct API contract for when these are wired to real LSP servers."maxLength": 1000toqueryand"maxLength": 256tonew_name.6. Function-level imports in step definition file
features/steps/lsp_capability_enum_steps.py, lines 54 and 168_STUBBED_CAPABILITIESandStrEnumare imported inside function bodies. CONTRIBUTING.md requires top-of-file imports.7.
workspacecapability negotiation sends emptysymbolKindobjectsrc/cleveragents/lsp/client.py, line 268"symbol": {"symbolKind": {}}is technically correct per LSP spec (server falls back to defaults), but explicitly declaringvalueSetwould harden the contract.{"valueSet": list(range(1, 27))}.Nits
1. Markdown table misalignment in
docs/reference/lsp.mddocs/reference/lsp.md, line 35 —WORKSPACE_SYMBOLSrow missing trailing space before|.2. No assertion on
additionalProperties: falsein schema testsfeatures/lsp_capability_enum.feature— code adds"additionalProperties": Falseto every schema but no test validates it.3. Schema tests validate
requiredbut notpropertiescontentfeatures/steps/lsp_capability_enum_steps.py, lines 122–135 — steps only checkrequiredarray, never verify property definitions exist with correct types.4.
# type: ignore[arg-type]in negative testfeatures/steps/lsp_capability_enum_steps.py, line 175 — the 22[attr-defined]suppressions follow the systemic Behave pattern (770+ project-wide), but this single[arg-type]is unique. Considercast()or a documenting comment.Summary
The PR delivers on all ticket requirements: the
LspCapabilityenum has all 11 spec-defined values, the tool adapter generates specs for all capabilities with correct suffixes, capability negotiation is implemented, and documentation is updated. The code is clean, well-structured, and follows project conventions. All findings from two prior review rounds have been addressed.The remaining suggestions focus on test coverage for new behavioral code paths and minor hardening — all deferrable at the author's discretion.
656dc1aeddc30712da38New commits pushed, approval review dismissed automatically according to repository settings
c30712da386a8f724299