docs/design/daemon-skill-toggle.md
Expose workspace Skill settings writes through daemon REST and the TypeScript SDK, including immediate refresh of active ACP sessions without making the runtime Skill catalog an ownership source.
POST /workspace/skills/:name/enablePOST /workspaces/:workspace/skills/:name/enable{ "enabled": boolean }DaemonClient.setWorkspaceSkillEnabled and WorkspaceDaemonClient.setWorkspaceSkillEnabledworkspace_skill_settings_toggleThe response contains the trimmed requested name, requested state, whether persistence changed, activation state, and session refresh counts. activation reflects child liveness and any required refresh independently from changed: applied means a child was live and any required refresh succeeded, deferred means no child was live at the liveness check or a changed request lost its child/session during the required refresh, and partial means at least one other required refresh failed after persistence committed. A no-op can therefore be applied or deferred while changed remains false.
The API changes workspace skills.disabled and skills.enabled by name without consulting the runtime Skill catalog. Enabling a default-disabled Skill writes an explicit opt-in; disabling it removes the opt-in and writes a hard workspace disable. Updating one target removes target duplicates and case variants without deleting orphan entries for unavailable Skills. A name may be disabled before installation, while hidden from user invocation, or while its Extension is inactive. Enabling removes an existing workspace disable or records an opt-in for an effective skills.defaultDisabled entry. An existing workspace skills.enabled declaration is preserved and normalized to the requested casing. With no existing workspace declaration and no effective skills.defaultDisabled entry, enable is a no-op (changed: false). A second identical request is also a no-op.
A hard skills.disabled entry inherited from a higher scope remains authoritative for effective availability, but does not prevent workspace scope from recording or removing its own declaration. Workspace declarations otherwise participate in the usual skills.disabled > skills.enabled > skills.defaultDisabled resolution and can override higher-scope skills.defaultDisabled or skills.enabled entries. The route retains request-shape, authentication, client identity, workspace trust, and runtime-generation gates; none of those require a Skill catalog lookup.
The workspace read-modify-write happens inside the daemon's per-workspace settings lock. A failed write stops before refresh and event publication.
disable-model-invocationskills.disabled is an operator hard denylist merged as a case-insensitive union across scopes. skills.defaultDisabled supplies overridable defaults and skills.enabled supplies explicit opt-ins, with disabled > enabled > defaultDisabled precedence. Effective disables remove matching skill slash commands and model-visible skill entries, and execution-time validation rejects the skill. The daemon endpoint writes the workspace members of disabled and enabled.
disable-model-invocation is SKILL.md metadata. It hides a skill from model invocation while preserving direct user invocation. The existing managed-skill ACP operation edits that metadata and is intentionally not reused by this API.
changed: false without cache invalidation, refresh, or event publication.qwen/control/workspace/skills/refresh.available_commands_update, and notifies SkillManager consumers.settings_changed event for each changed skill-settings key.An in-flight model request cannot be rewritten. Subsequent skill execution checks, command snapshots, and model contexts read the new state.
disabled > enabled > defaultDisabled precedence.userInvocable.settings_changed consumers observe each committed skills.disabled or skills.enabled value; there is no new event type.deferred; the next child loads the setting at startup.changed: false; no refresh or event occurs. activation still reflects whether a child was live, but no activation work is needed.partial.deferred; other refresh failures are reported as partial.