microsoft / microsoft/vscode

Customizations: consolidate the two independent "disabled" stores

Open
#329,753 0 comments 0 reactions 2 assignees Claimed by @aeschli View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

### Problem

Whether a chat customization is "disabled" is tracked in **two independent, unsynchronised stores**:

| # | Store | Storage key | Scope / target | Serialization | Written by |
|---|---|---|---|---|---|
| 1 | `IPromptsService.get/setDisabledPromptFiles(type)` (`promptsServiceImpl.ts`) | `chat.disabledPromptFiles.` | `PROFILE` / `USER` | `uri.toJSON()` + `URI.revive()` | the **Disable/Enable** actions in `aiCustomizationManagement.contribution.ts` |
| 2 | `AgentCustomizationSyncProvider` (`ICustomizationSyncProvider`) | `customizationSync.disabled.` | `PROFILE` / `MACHINE` | `uri.toString()` | only `pluginListWidget.ts` (plugins) |

Nothing keeps them in agreement, and they differ in storage target (`USER` vs `MACHINE`, so one syncs across machines and the other does not) and in URI serialization.

Consumers pick one essentially at random:

- `enumerateLocalCustomizationsForHarness` read store 2 only.
- `PureItemProviderItemSource` read neither.
- `ItemProviderItemSource` reads store 1.
- The older sessions tree view (`aiCustomizationTreeViewViews.ts`) reads store 1.

This is the direct cause of #329751, where the Agents window wrote to store 1 and every relevant consumer read store 2. It produced a particularly confusing symptom: the older sessions tree view *did* reflect the disabled state, so the same skill appeared disabled in one surface and enabled in another, while the agent host kept receiving it either way.

### Why this is worth fixing structurally

The immediate fix for #329751 makes the agent-host wire consult *both* stores (`syncProvider.isDisabled(uri) || userDisabled.has(uri)`). That resolves the user-visible bug but entrenches the split: every future consumer now has to remember to OR the two together, and every future writer has to pick the right one. The bug is likely to recur in the next surface that ships.

### Suggested direction

Consolidate on a single source of truth for "is this customization disabled", most naturally on `IPromptsService`, with the sync provider's per-harness store either folded into it or kept strictly as a harness-scoped overlay with an explicit, documented precedence rule. Whichever way it goes, there should be exactly one function that answers the question, and the storage target and URI serialization should be consistent.

The two stores and the requirement to consult both are documented for now in `src/vs/sessions/AI_CUSTOMIZATIONS.md` under *Built-in Skills → Enabling and Disabling Built-in Skills*.

Found while investigating #329751.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.