UAT: LspClient missing textDocument/didChange notification — file synchronization incomplete per spec #3530

Open
opened 2026-04-05 18:58:33 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: bugfix/lsp-did-change-notification
  • Commit Message: fix(lsp): add textDocument/didChange notification to LspClient
  • Milestone: (none — backlog)
  • Parent Epic: #824

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


Background and Context

Per docs/specification.md (LSP Integration section):

The LSP Runtime in the Infrastructure layer manages server lifecycle, workspace mapping, and file synchronization.

The LSP specification requires that as an actor reads and modifies files (via tools), the LSP Runtime sends textDocument/didOpen, textDocument/didChange, and textDocument/didClose notifications to keep the language server's view synchronized with the actor's mutations. All three notifications are required for correct file synchronization.

Current Behavior (Bug)

LspClient in src/cleveragents/lsp/client.py currently implements:

  • did_open() — sends textDocument/didOpen
  • did_close() — sends textDocument/didClose
  • did_change() — MISSING

There is no did_change() method or textDocument/didChange notification support anywhere in LspClient. When an actor modifies a file, the language server is never notified of the change, causing it to analyze stale file content.

Additionally, src/cleveragents/lsp/runtime.py contains no calls to did_change() in any runtime method.

Steps to Reproduce

  1. Start an LSP server for a Python file
  2. Open the file via did_open()
  3. Modify the file content on disk
  4. Call get_diagnostics() — observe that diagnostics reflect the old content, not the modified content

Expected Behavior

LspClient must implement did_change() to send textDocument/didChange notifications. LspRuntime must call did_change() whenever file content has been modified, so that the language server always analyzes current content.

Impact

When an actor modifies a file (e.g., via a write tool), the LSP server continues to analyze the original file content. Subsequent calls to get_diagnostics(), get_completions(), etc. return results based on pre-modification content, not current content. This makes LSP-assisted code editing unreliable.

Code Locations

  • src/cleveragents/lsp/client.py — Missing did_change() method
  • src/cleveragents/lsp/runtime.py — No calls to did_change() in any runtime method

Subtasks

  • Add did_change() method to LspClient that sends textDocument/didChange with the new content
  • Call did_change() in LspRuntime methods when file content has been modified
  • Add unit tests for did_change() in features/lsp_client_coverage.feature
  • Verify all nox stages pass

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • LspClient.did_change() is implemented and sends textDocument/didChange notifications correctly.
  • LspRuntime calls did_change() whenever file content changes, keeping the language server synchronized.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
  • All nox stages pass.
  • Coverage >= 97%.

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

## Metadata - **Branch**: `bugfix/lsp-did-change-notification` - **Commit Message**: `fix(lsp): add textDocument/didChange notification to LspClient` - **Milestone**: *(none — backlog)* - **Parent Epic**: #824 > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.6.0. It does not block milestone completion and has been > placed in the backlog for human review and future milestone assignment. --- ## Background and Context Per `docs/specification.md` (LSP Integration section): > The LSP Runtime in the Infrastructure layer manages server lifecycle, workspace mapping, and **file synchronization**. The LSP specification requires that as an actor reads and modifies files (via tools), the LSP Runtime sends `textDocument/didOpen`, **`textDocument/didChange`**, and `textDocument/didClose` notifications to keep the language server's view synchronized with the actor's mutations. All three notifications are required for correct file synchronization. ## Current Behavior (Bug) `LspClient` in `src/cleveragents/lsp/client.py` currently implements: - `did_open()` — sends `textDocument/didOpen` ✅ - `did_close()` — sends `textDocument/didClose` ✅ - **`did_change()` — MISSING** ❌ There is no `did_change()` method or `textDocument/didChange` notification support anywhere in `LspClient`. When an actor modifies a file, the language server is never notified of the change, causing it to analyze stale file content. Additionally, `src/cleveragents/lsp/runtime.py` contains no calls to `did_change()` in any runtime method. ### Steps to Reproduce 1. Start an LSP server for a Python file 2. Open the file via `did_open()` 3. Modify the file content on disk 4. Call `get_diagnostics()` — observe that diagnostics reflect the **old** content, not the modified content ## Expected Behavior `LspClient` must implement `did_change()` to send `textDocument/didChange` notifications. `LspRuntime` must call `did_change()` whenever file content has been modified, so that the language server always analyzes current content. ## Impact When an actor modifies a file (e.g., via a write tool), the LSP server continues to analyze the original file content. Subsequent calls to `get_diagnostics()`, `get_completions()`, etc. return results based on pre-modification content, not current content. This makes LSP-assisted code editing unreliable. ## Code Locations - `src/cleveragents/lsp/client.py` — Missing `did_change()` method - `src/cleveragents/lsp/runtime.py` — No calls to `did_change()` in any runtime method ## Subtasks - [ ] Add `did_change()` method to `LspClient` that sends `textDocument/didChange` with the new content - [ ] Call `did_change()` in `LspRuntime` methods when file content has been modified - [ ] Add unit tests for `did_change()` in `features/lsp_client_coverage.feature` - [ ] Verify all nox stages pass ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - `LspClient.did_change()` is implemented and sends `textDocument/didChange` notifications correctly. - `LspRuntime` calls `did_change()` whenever file content changes, keeping the language server synchronized. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. - All nox stages pass. - Coverage >= 97%. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: High — Without textDocument/didChange, the LSP server analyzes stale file content after any modification. This makes LSP-assisted code editing unreliable — diagnostics, completions, and hover information will be based on pre-modification content.
  • Milestone: v3.6.0 — LSP file synchronization is in scope for M7 (Epic #824).
  • Story Points: 3 — M — Requires adding a did_change() method to LspClient, wiring it into LspRuntime, and adding tests. Follows the existing did_open/did_close pattern.
  • MoSCoW: Must Have — File synchronization is a fundamental requirement for LSP correctness. Without didChange, the entire LSP integration produces incorrect results after any file modification. The spec explicitly requires all three notifications.
  • Parent Epic: #824 (LSP Functional Runtime)

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

Issue triaged by project owner: - **State**: Verified - **Priority**: High — Without `textDocument/didChange`, the LSP server analyzes stale file content after any modification. This makes LSP-assisted code editing unreliable — diagnostics, completions, and hover information will be based on pre-modification content. - **Milestone**: v3.6.0 — LSP file synchronization is in scope for M7 (Epic #824). - **Story Points**: 3 — M — Requires adding a `did_change()` method to LspClient, wiring it into LspRuntime, and adding tests. Follows the existing `did_open`/`did_close` pattern. - **MoSCoW**: Must Have — File synchronization is a fundamental requirement for LSP correctness. Without `didChange`, the entire LSP integration produces incorrect results after any file modification. The spec explicitly requires all three notifications. - **Parent Epic**: #824 (LSP Functional Runtime) --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
freemo added this to the v3.6.0 milestone 2026-04-05 19:37:46 +00:00
freemo removed this from the v3.6.0 milestone 2026-04-06 23:43:23 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

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