session: scoped customization enablement - #385
Draft
Connor Peet (connor4312) wants to merge 1 commit into
Draft
Conversation
Customizations gain an optional `enablement` array of explicit decisions, one
per scope that has one:
CustomizationEnablement =
| { kind: 'global'; enabled: boolean }
| { kind: 'workspace'; uri: URI; enabled: boolean }
| { kind: 'session'; enabled: boolean }
The array is a wire contract. Producers MUST publish entries sorted by
descending specificity (session, workspace, then global), and the agent host
emits at most one workspace entry, for the session's primary working directory.
Consumers MAY therefore treat `enablement[0]` as decisive, with
`enablement?.[0]?.enabled ?? true` as the effective value. An absent or empty
array means no explicit decision, so the customization is enabled by default.
Only the host publishes this; clients treat it as read-only provenance.
The field lives on the customization base rather than on MCP servers alone, so
it applies to every customization type.
`session/customizationToggled` carries `enablement` in place of `enabled` and
replaces the complete decision set, so a caller changing one scope must include
every decision it intends to preserve. An empty array clears all decisions and
restores the default.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Protocol side of the scoped customization enablement work in microsoft/vscode#329047. Draft until that PR settles, since the two need to agree.
What changed
Customizations gain an optional
enablementarray of explicit decisions, one entry per scope that has one:The array is a wire contract, not just a bag of data. Producers MUST publish entries sorted by descending specificity — session, workspace, then global — and the agent host emits at most one workspace entry, for the session's primary working directory. Consumers MAY therefore treat
enablement[0]as decisive, withenablement?.[0]?.enabled ?? trueas the effective value, and never have to implement precedence themselves. An absent or empty array means no explicit decision, so the customization is enabled by default.Only the host publishes this; clients treat it as read-only provenance.
The field lives on the customization base rather than on
McpServerCustomizationalone, so it applies to every customization type. The VS Code side already uses it for both MCP servers and plugins.session/customizationTogglednow carriesenablementin place ofenabled, and replaces the complete decision set. A caller changing one scope must include every decision it intends to preserve; an empty array clears all decisions and restores the default. Wholesale replacement avoids needing a separate "clear this scope" action and keeps the reducer total.Why not merge semantics
Merging would need a way to express "remove the workspace decision" distinctly from "no opinion about the workspace decision", which either means a nullable field or a second action. Replacement makes the client state the full intent it wants, which is also what the UI naturally has on hand.
Container cascade
Note for reviewers, since the guide currently says a child's
enabledis independent of its container: on the VS Code side a disabled container short-circuits its children, but that is applied at consumption, not by rewriting the child's publishedenabled. A child keeps its own decisions and its own resolved value, so re-enabling a container restores each child's prior state. This is what keeps theenablement[0]invariant true for the customization it appears on. I have deliberately not changed the guide wording here — if you would rather the spec state the cascade explicitly, say so and I will add it.Validation
npm run generateis reproducible: re-running it produces zero diff, so the generated Go/Kotlin/Rust/Swift sources and JSON schemas are genuinely generated rather than hand-edited.npm test— 389 passing, 0 failing, 100% reducer coverage.go test ./...andcargo test --workspacepass. Both consume the sharedtypes/test-cases/reducers/fixtures, so the new fixture exercises the TypeScript, Go, and Rust reducers alike.263-session-customizationtoggled-clears-enablementpins the subtle case: an empty array drops the field and restores the default.Not verified: Kotlin Gradle tests (no Java runtime available) and Swift tests (missing CoreSimulator). Swift sources compile. Those two clients' reducer ports would benefit from a reviewer running them.