Context
Embedded-editor hosts now push PWEE-style buffers to the server addressed as the real generated MEMBER module (the MEMBER-header technique from ClarionLive/ClarionAssistant#56 / PR #74, same approach as ClarionMonacoEditor). That gives the server full PROGRAM scope inside embed buffers — completion, hover, definition, implementation, and signature help all resolve correctly, because those features only read.
Code actions / refactors write, and there the illusion breaks: the server believes the whole buffer is a normal editable file, but in an embeditor buffer only the embed slots are user-owned — everything else is template-generated, read-only in the editor, and regenerated from the .app at will.
The failure modes (why clients can't fully fix this alone)
Using Introduce EQUATE (#281) as the example:
- In-buffer, out-of-slot inserts: "declare in procedure local data" picks a textual insertion point in the data section — in an embed buffer that's a generated read-only line, even when a data embed slot sits a few lines away. The client can only block the edit (action appears to do nothing) or heuristically remap it after the fact.
- Cross-file edits into generated files: "Global (in App.clw)" writes to the generated PROGRAM file — the edit succeeds, compiles, and is silently wiped by the next generate. The durable home for that change is the .app, which is outside the LSP's world.
Clients can filter WorkspaceEdits against their known editable ranges (that's the planned v1 on the ClarionAssistant side), but filtering after computation means the server wastes work proposing actions that get hidden, and the useful variants (e.g. "declare in the data embed slot") never get offered because the server doesn't know slots exist.
Proposal
An opt-in notification, mirroring the shape of clarion/updatePaths:
Semantics:
- Absence of the notification (or an empty send with
ranges: null) = whole document editable — VS Code and every existing client are completely unaffected; this only activates for hosts that send it.
- Ranges describe the CURRENT buffer version; hosts re-send after edits move slots (they already track live ranges for their own read-only enforcement). Cleared on didClose.
- When present, providers that produce edits consult it:
- Code actions: only offer actions whose edits fall inside editable ranges — or better, prefer editable insertion targets when choosing where a declaration goes (e.g. Introduce EQUATE's scope quick-pick could offer "the data embed" because an editable range exists inside the data section).
- Rename: skip/flag edits landing in read-only regions of this document (cross-file rename is a separate question — those files may be generated too, but the host can filter file-level).
- Read-only features (completion/hover/nav/signature help/diagnostics) ignore it entirely.
Why server-side beats client-side filtering
- The server picks insertion points — only it can pick a different, legal one. Client filtering can only veto.
- Every embedded host (ClarionAssistant CA Embeditor, ClarionMonacoEditor, anything future) gets correct behavior from one implementation instead of N re-implemented filters.
- Actions that can't be satisfied inside editable ranges simply don't appear — no "I clicked and nothing happened".
Non-goals
- No change to VS Code behavior (never sends the notification).
- Not trying to model .app-level targets ("declare in global data" belonging in the app tree rather than generated source) — hosts that know about the .app can layer that on top; this proposal just stops the server from proposing edits into regions the user cannot own.
Discussion that led here: ClarionLive/ClarionAssistant PRs #74/#75/#78 (embed scope + signature help + go-to-implementation) — read-side features are now fully lit in embeds; this is the missing piece for the write-side (Ctrl+. code actions).
🤖 Generated with Claude Code
Context
Embedded-editor hosts now push PWEE-style buffers to the server addressed as the real generated MEMBER module (the MEMBER-header technique from ClarionLive/ClarionAssistant#56 / PR #74, same approach as ClarionMonacoEditor). That gives the server full PROGRAM scope inside embed buffers — completion, hover, definition, implementation, and signature help all resolve correctly, because those features only read.
Code actions / refactors write, and there the illusion breaks: the server believes the whole buffer is a normal editable file, but in an embeditor buffer only the embed slots are user-owned — everything else is template-generated, read-only in the editor, and regenerated from the .app at will.
The failure modes (why clients can't fully fix this alone)
Using Introduce EQUATE (#281) as the example:
Clients can filter WorkspaceEdits against their known editable ranges (that's the planned v1 on the ClarionAssistant side), but filtering after computation means the server wastes work proposing actions that get hidden, and the useful variants (e.g. "declare in the data embed slot") never get offered because the server doesn't know slots exist.
Proposal
An opt-in notification, mirroring the shape of
clarion/updatePaths:Semantics:
ranges: null) = whole document editable — VS Code and every existing client are completely unaffected; this only activates for hosts that send it.Why server-side beats client-side filtering
Non-goals
Discussion that led here: ClarionLive/ClarionAssistant PRs #74/#75/#78 (embed scope + signature help + go-to-implementation) — read-side features are now fully lit in embeds; this is the missing piece for the write-side (Ctrl+. code actions).
🤖 Generated with Claude Code