Skip to content
Closed
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
f931162
feat(serve): scope extensions to workspace runtimes
Sep 5, 2026
f65c0e8
test(serve): cover extension runtime capabilities
Sep 5, 2026
9493fa6
Merge remote-tracking branch 'origin/main' into codex/daemon-workspac…
Sep 5, 2026
fbec518
fix(serve): address round-1 review findings on Extension runtime read…
qwen-code-ci-bot Sep 6, 2026
e77c512
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
wenshao Sep 6, 2026
d431d17
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 6, 2026
e9c084c
test(cli): wait out the serve bootstrap window in the capabilities en…
qwen-code-dev-bot Sep 6, 2026
9fed1f0
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 6, 2026
0e3dbea
fix(serve): address extension runtime review findings
Sep 7, 2026
ac63bb4
Merge remote-tracking branch 'origin/main' into codex/daemon-workspac…
Sep 7, 2026
26ed5a5
fix(web-shell): keep split Extension runtime loaders off untrusted wo…
Sep 7, 2026
9ae66ef
Merge remote-tracking branch 'origin/main' into codex/daemon-workspac…
qwen-code-ci-bot Sep 7, 2026
c7030d9
fix(serve): address round-4 extension runtime review findings (#11086)
qwen-code-ci-bot Sep 7, 2026
403b254
Merge remote-tracking branch 'origin/main' into codex/daemon-workspac…
qwen-code-ci-bot Sep 7, 2026
dedac49
fix(web-shell): annotate composer action merge as AtMentionWorkspaceA…
qwen-code-ci-bot Sep 7, 2026
f1a4858
fix(serve): address round-5 extension runtime review findings (#11086)
qwen-code-ci-bot Sep 8, 2026
aae6c06
fix(web-shell): cancel MessageList scroll-settle timer on unmount (#1…
qwen-code-ci-bot Sep 8, 2026
93a7ae7
fix(web-shell): surface extension runtime readiness errors
Sep 8, 2026
e96a0ed
fix(serve): close extension readiness gaps
Sep 8, 2026
882a153
fix(web-shell): merge main, keeping upstream locate scroll timer
qwen-code-dev-bot Sep 8, 2026
69604a9
fix(serve): address round-6 extension runtime findings and merge main…
qwen-code-ci-bot Sep 8, 2026
b97231b
Merge remote-tracking branch 'origin/main' into codex/daemon-workspac…
qwen-code-ci-bot Sep 8, 2026
ca96071
fix(web-shell): address round-7 extension runtime findings (#11086)
qwen-code-ci-bot Sep 8, 2026
80d2ab8
test(web-shell): repair render indicator in split-session rerender te…
qwen-code-ci-bot Sep 8, 2026
1937afd
chore(web-shell): merge main into #11086, keep strengthened split-rer…
qwen-code-dev-bot Sep 9, 2026
6296997
fix(serve): address extension reconciliation and notice review
Sep 9, 2026
8fd4108
Merge remote-tracking branch 'origin/main' into codex/daemon-workspac…
Sep 9, 2026
29ea351
fix(serve): preserve cold-runtime extension install success
Sep 9, 2026
75f6b12
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 9, 2026
35bf4f6
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 9, 2026
c031c91
fix(serve): Preserve extension reconciliation and operation lifecycle…
Sep 10, 2026
c80017e
Merge origin/main into codex/daemon-workspace-runtime-extensions-main
Sep 10, 2026
abb6fef
fix(extensions): Allow slow reconciliation and show unknown activation
Sep 10, 2026
641804c
fix(extensions): detect reused store generations and harden recovery …
Sep 10, 2026
0774d33
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 10, 2026
c246135
Merge remote-tracking branch 'origin/main' into codex/daemon-workspac…
qwen-code-ci-bot Sep 10, 2026
faefc6c
fix(extensions): hash receipts, scope update supersession, flag drain…
qwen-code-ci-bot Sep 10, 2026
26aafd9
fix(extensions): track recovered store identity during reconciliation
Sep 11, 2026
4e35093
Merge remote-tracking branch 'origin/main' into codex/daemon-workspac…
Sep 11, 2026
5fc7d91
fix(extensions): normalize source-addressed update operations
Sep 11, 2026
44983f7
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
ytahdn Sep 11, 2026
8c027e5
fix(extensions): address round-15 extension runtime review findings (…
qwen-code-ci-bot Sep 11, 2026
878b891
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 12, 2026
4913ac9
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 12, 2026
167621f
Merge remote-tracking branch 'origin/main' into codex/daemon-workspac…
qwen-code-dev-bot Sep 12, 2026
357979f
fix(cli): close review-round reconciliation and interaction gaps (#11…
qwen-code-dev-bot Sep 12, 2026
22da331
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 12, 2026
3e48daa
fix(cli): keep a late install sweep from cancelling newer parked oper…
qwen-code-dev-bot Sep 13, 2026
8285097
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
wenshao Sep 13, 2026
8e4e3c8
fix(cli): re-check extension readiness in-queue and order the install…
qwen-code-dev-bot Sep 13, 2026
4c1733f
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 13, 2026
0d75dee
Merge remote-tracking branch 'origin/main' into pr-11086-takeover
wenshao Sep 13, 2026
ef6b267
test(serve): pin extension interaction re-entry and fix activationSou…
wenshao Sep 13, 2026
b231153
fix(cli): close extension-generation certification gaps on ensure and…
qwen-code-dev-bot Sep 14, 2026
e756254
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 14, 2026
bd6077c
Merge branch 'main' into codex/daemon-workspace-runtime-extensions-main
qwen-code-dev-bot Sep 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions docs/design/daemon-workspace-runtime-extensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Daemon Workspace Runtime Extensions

## Goal

Move Extension management onto workspace-owned runtimes without requiring a
chat session. Keep the existing Extension Store as the durable global owner and
use the selected runtime only for the live catalog and reconciliation.

## Ownership

- `GET /extensions` remains the daemon-local global artifact catalog.
- `GET /workspaces/:workspace/extensions` remains the durable activation
projection for one workspace.
- `GET /workspaces/:workspace/runtime/extensions` returns the selected live
runtime catalog and its runtime epoch.
- `WorkspaceRuntimeCoordinator` owns desired/applied Extension generation,
capability readiness, runtime refresh, and stale-result rejection.
- Global mutations invalidate every managed runtime. Workspace activation and
resource-state mutations invalidate only the selected runtime.

The coordinator is the only writable owner of runtime Extension readiness.
The route controller continues to own operation history and durable mutation
sequencing, but reports committed generations to each affected coordinator.

## Reconciliation

An Extension commit is successful once the Extension Store commit succeeds.
For each affected trusted live runtime, the coordinator refreshes the bootstrap
configuration, discovery configuration, and active sessions, then reads the
live Extension catalog. It marks the capability ready only when the response
comes from the current runtime epoch and the applied generation equals the
latest desired generation. Cold runtimes remain deferred and converge on the
Comment thread
ytahdn marked this conversation as resolved.
Resolved
next `ensureRuntime()`.

Extension invalidation also invalidates the selected runtime's Skills and MCP
capabilities because both catalogs include Extension contributions. A late
refresh or catalog response from a replaced runtime cannot advance readiness.

## API and SDK

Runtime status adds an `extensions` capability with `state`, `revision`,
`runtimeEpoch`, `desiredGeneration`, and `appliedGeneration`. Extension runtime
catalog responses add `runtimeEpoch`.

`WorkspaceDaemonClient` exposes the runtime catalog. Global install, update,
uninstall, update-check, and default activation remain on `DaemonClient`;
workspace activation, Extension Skill state, projection reads, and runtime
catalog reads remain on `WorkspaceDaemonClient`.

Source installs use the V2 global route. Archive uploads remain on the legacy
workspace route until a V2 archive endpoint exists, so they retain the legacy
default-activation behavior.

## Web Shell

When the daemon advertises `workspace_extensions_config_runtime`, the
Extensions page:

1. loads the global catalog and selected workspace projection without starting
ACP;
2. calls the shared parameterless runtime ensure;
3. merges live details and `isActive` only when capability and catalog epochs
match the current runtime and applied generation equals desired generation;
4. shows the workspace selector on the list page and the disabled selector in
detail view.

Older daemons keep the existing primary-workspace flow.

When the daemon also advertises `workspace_extension_mentions`, the composer
uses the selected workspace runtime for both the `+` and `@` Extension menus.
Without that feature, it keeps the legacy primary-workspace loader.

## Downstream consumers

- runtime status and workspace management routes;
- Extension V2 operation reconciliation and external-generation polling;
- Skills and MCP capability invalidation;
- TypeScript daemon SDK;
- Web Shell Plugin manager and Extensions manager.
64 changes: 32 additions & 32 deletions docs/design/workspace-runtime-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
Workspace-runtime-centric 的目标设计与堆叠交付契约。该设计由四个可独立合并的
PR 渐进落地;本文描述最终形态,不表示 foundation PR 已实现所有 capability。

> **当前落地进度(Foundation + Skills + MCP)**:已实现 Bridge 权威的五态 lifecycle snapshot、
> **当前落地进度(Foundation + Extensions + Skills + MCP)**:已实现 Bridge 权威的五态 lifecycle snapshot、
> workspace 级单调 epoch、完整物理 work lease、绝对启动 deadline、无参数
> `ensure/status`、10 分钟可续期保活、drain/removal/shutdown admission,以及
> SDK 的 primary/qualified runtime 方法。Skills 与 MCP 的 revision/epoch、
> config/runtime Catalog、capability status 与 reconcile 均已落地,`ensure` 会在
> 同一观察预算内继续准备 Skills 与 MCP;Extensions、Tools 等其余领域的
> capability generation/revision、Catalog 投影和 operation 状态机仍属于后续阶段。
> SDK 的 primary/qualified runtime 方法。Extensions、Skills 与 MCP 的
> generation/revision、config/runtime Catalog、capability status 与 reconcile 均已落地,
> `ensure` 会在同一观察预算内依次准备 Extensions 以及 Skills/MCP;Tools 等其余领域的
> capability、Catalog 投影和 operation 状态机仍属于后续阶段。

### 1.1 当前实现与目标设计

Expand All @@ -22,14 +22,14 @@ PR 渐进落地;本文描述最终形态,不表示 foundation PR 已实现
- **Target(未实现)**:后续 PR 的目标契约,当前调用方不得依赖;
- **Legacy(兼容)**:迁移期间保留的旧入口,新调用方不应采用。

| 领域 | Foundation(已实现) | Target(后续阶段) |
| ----------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| Runtime lifecycle | Bridge 权威五态、workspace 单调 epoch、物理 work lease、启动 deadline、drain/removal admission | capability 健康状态参与统一对外投影 |
| `ensure` | 无参数;确保 ACP Channel 完成 initialize,并在同一观察预算内准备 Skills 与 MCP;成功后续期 10 分钟 | 继续准备 Extensions、Tools,并通过 capability status 表达收敛 |
| `status` | lifecycle、`runtimeLive`、`runtimeEpoch` 与 Skills、MCP capability 快照 | 其余 capability、generation、error 和 operation 投影 |
| SDK | primary/qualified `ensure`/`status` REST 方法,Skills 与 MCP 的 config/runtime Catalog 方法 | 其他 Catalog、operation 和统一 deadline 的完整 owner-aware API |
| 领域 | Foundation(已实现) | Target(后续阶段) |
| ----------------- | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| Runtime lifecycle | Bridge 权威五态、workspace 单调 epoch、物理 work lease、启动 deadline、drain/removal admission | capability 健康状态参与统一对外投影 |
| `ensure` | 无参数;确保 ACP Channel 完成 initialize,并在同一观察预算内依次准备 Extensions 以及 Skills/MCP;成功后续期 10 分钟 | 继续准备 Tools,并通过 capability status 表达收敛 |
| `status` | lifecycle、`runtimeLive`、`runtimeEpoch` 与 Extensions、Skills、MCP capability 快照 | 其余 capability、error 和 operation 投影 |
| SDK | primary/qualified `ensure`/`status` REST 方法及 Extensions、Skills、MCP 的 config/runtime Catalog 方法 | 其他 Catalog、operation 和统一 deadline 的完整 owner-aware API |

除明确标为 Foundation、Skills 或 MCP 已落地的段落外,第 9~14 节中 capability、
除明确标为 Foundation、Extensions、Skills 或 MCP 已落地的段落外,第 9~14 节中 capability、
Catalog、generation、revision 和 operation 的详细状态机均是 Target 契约。

核心目标只有一个:
Expand Down Expand Up @@ -315,8 +315,8 @@ MCP discovery 标记和 server-name 级 MCP auth 集合表示物理 work。已
status、Catalog、Extension refresh、Skills refresh、MCP discovery/auth、普通 runtime
mutation 以及 Session create/load/resume/close 都在对应物理工作期间持 lease。
物理 startup 本身也受启动 lease 和 deadline 保护。当前 `ensure` 覆盖
preheat/initialize 与 Skills prepare,并在成功后登记 keepalive;其余 capability
仍由后续阶段接入。
preheat/initialize 与 Extensions、Skills、MCP prepare,并在成功后登记 keepalive;
各阶段之间的外层 command-wide lease 仍由后续阶段接入。

Foundation 在 OAuth 返回 pending 后保留 owning Channel 的 auth lease。明确观察到
同一 Channel 上的 server 已变为 non-pending 时释放;Catalog 中缺少 server 不是完成
Expand Down Expand Up @@ -512,48 +512,47 @@ POST /workspaces/:workspace/runtime/ensure
primary workspace 使用等价的 `POST /workspace/runtime/ensure`。两个入口都拒绝非空
body;调用方不选择 capability,也不传 timeout、keepalive 或初始化顺序。

#### Foundation + Skills + MCP(已实现)
#### Foundation + Extensions + Skills + MCP(已实现)

当前 Coordinator 的职责:

1. 校验 workspace 已准确解析、受信任且未 draining;
2. 调用 Bridge 的物理 preheat/initialize,等待 ACP Channel handshake 完成;
3. 将本次成功转换为 workspace 级 10 分钟 keepalive;并发调用保留最长窗口;
4. 在同一观察预算内准备当前 revision 的 Skills 与 MCP catalog,并返回对应
4. 在同一观察预算内依次准备 Extension generation 以及当前 revision 的 Skills/MCP catalog,并返回对应
capability 状态;
5. 从 Bridge 读取 lifecycle snapshot 并返回。

`ensure` 成功证明 ACP Channel 已完成 initialize 且可由后续请求复用;Skills 与 MCP
`ensure` 成功证明 ACP Channel 已完成 initialize 且可由后续请求复用;Extensions、Skills 与 MCP
capability 会返回 `starting`、`ready`、`stale` 或 `error`,调用方必须按状态和 epoch
判断 catalog 是否可用。只有 `capabilities.<name>.state === 'ready'`、epoch 与
lifecycle 一致且 status 来自 live runtime 时,调用方才可读取对应 Catalog。它不证明
Extension refresh 或其他未迁移 capability 已 ready。若同一物理启动正在进行,并发
Tools 等其他未迁移 capability 已 ready。若同一物理启动正在进行,并发
`ensure` 复用 Bridge 的启动 Promise;每个成功调用都从自己的成功时刻续期 keepalive。
若启动卡住,Bridge 的绝对启动 deadline 会中止并清理该次启动,后续显式 `ensure`
可以发起新的尝试。

服务端观察预算为 60 秒。物理启动在预算内未完成时,请求以可重试的
`runtime_still_starting` 错误结束;Channel 已就绪但 Skills 或 MCP 尚未完成时,返回
`runtime_still_starting` 错误结束;Channel 已就绪但 Extensions、Skills 或 MCP 尚未完成时,返回
live runtime 和非 ready capability,后台工作继续有界收敛。底层物理启动仍由独立的
绝对启动 deadline 约束。`GET /runtime/status` 只观察 lifecycle 和 capability,不启动
或重试 runtime。

#### Target(部分实现)
#### Foundation(Extensions + Skills + MCP 已实现,外层 lease 仍为 Target)

后续 Coordinator 将把其余标准能力纳入同一次 workspace runtime command,目标顺序为
`extensions -> (mcp, skills, tools)`:
Coordinator 已按 `extensions -> (mcp, skills)` 准备标准能力;Tools 后续接入相同流程:
Comment thread
ytahdn marked this conversation as resolved.
Resolved

1. 获取覆盖整个命令的外层 runtime-control lease;
1. 获取覆盖整个命令的外层 runtime-control lease(Target,见 §8.2);
2. 确保 Workspace ACP Runtime 已完成 handshake;
3. 在当前 epoch 加载 Extension desired generation,或捕获 MCP/Skills revision;
4. 初始化标准 capability 集合并更新可轮询状态;
5. 命令完成、失败或安全排空后释放 lease。
5. 命令完成、失败或安全排空后释放 lease(Target,见 §8.2)。

MCP 已按 revision + epoch 实现上述收敛;Extensions、Skills 与 Tools 尚未迁移。
Target 中 Coordinator 先 prepare Extensions,再并行处理其派生能力;同一 capability
Extensions 已按 generation + epoch、MCP/Skills 已按 revision + epoch 实现上述收敛;Tools 尚未迁移。
Coordinator 先 prepare Extensions,再并行处理其派生能力;同一 capability
的并发工作合并。HTTP 观察预算耗尽可以先返回 capability `starting`,后台收敛受另一
个固定 deadline 约束,客户端通过 `/runtime/status` 观察终态。此语义在 capability
Coordinator 落地前不得由 SDK/UI 假设;当前只适用于已接入的 MCP。
Coordinator 落地前不得由 SDK/UI 假设;当前适用于已接入的 Extensions、Skills 与 MCP。

按 capability 的 prepare 只是 Coordinator 的内部实现,不暴露 HTTP 或 SDK 接口。
新增 capability 时只修改 Coordinator 的标准能力集合和初始化逻辑。
Expand Down Expand Up @@ -961,11 +960,12 @@ Catalog GET 始终保持只读,不以“页面加载”为理由启动 ACP。
- 保持现有领域 mutation 路由不变,不在 foundation 中引入 MCP、Extension 或 Skills
专属状态。

### 阶段二:收口状态与 operation(Skills + MCP 已完成)
### 阶段二:收口状态与 operation(Extensions + Skills + MCP 已完成)

- 已完成:Coordinator 增加 Skills 与 MCP 的 capability、revision 和 epoch 投影;
- 已完成:MCP 与 Skills 均清除跨 epoch ready 合并,状态绑定 live epoch;
- 待完成:其余 capability、Extension generation 和 operation 投影;
- 已完成:Extension desired/applied generation、revision 和 epoch 投影;
- 待完成:其余 capability 和 operation collection 投影;
- 所有已迁移 capability 状态绑定 epoch;
- 将 Extension desired/applied generation 更新改为同一 runtime 回执,MCP/Skills 使用
revision + epoch 丢弃迟到结果;
Expand All @@ -980,9 +980,9 @@ Catalog GET 始终保持只读,不以“页面加载”为理由启动 ACP。
的 SDK 契约;
- 已完成:Skills 与 MCP 管理页和新会话消费方接入 primary/qualified ensure 与统一
config/runtime 模型;
- 待完成:其余领域(Extensions、Tools)的 config/runtime Catalog 与 operation SDK
契约;
- 待完成:Extensions 页面迁移到统一 config/runtime/operation 模型;
- 已完成:Extensions 的 config/runtime Catalog 与 generation/epoch SDK 契约;
- 已完成:Extensions 页面迁移到 workspace 选择与统一 config/runtime 模型;
- 待完成:Tools 的 config/runtime Catalog 与 operation SDK 契约;
- 管理区域以无参数 runtime ensure 启动完整标准能力,各页面不再传 capability;
- Extensions 页面从 runtime Catalog 取得实际状态,不从 config refresh 调 Bridge;
- User scope 状态失效覆盖所有受影响工作区;可选事件也要 fan out;
Expand Down
2 changes: 1 addition & 1 deletion docs/developers/daemon/00-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Use these anchors when moving from the docs into the latest `main` code:
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| HTTP routes | The route catalog lives in `qwen-serve-protocol.md`; this daemon set only references it and explains implementation ownership. | [`../qwen-serve-protocol.md`](../qwen-serve-protocol.md), [`20`](./20-quickstart-operations.md) |
| Event schema | `EVENT_SCHEMA_VERSION = 1`; 53 known event types; id-less subscriber synthetic frames; `_meta.serverTimestamp` stamped by `EventBus.publish()` (with `formatSseFrame()` fallback for synthetic frames). | [`09`](./09-event-schema.md), [`10`](./10-event-bus.md) |
| Capabilities | `SERVE_PROTOCOL_VERSION = 'v1'`; 158 registered tags; 45 conditional tags. | [`11`](./11-capabilities-versioning.md) |
| Capabilities | `SERVE_PROTOCOL_VERSION = 'v1'`; 160 registered tags; 47 conditional tags. | [`11`](./11-capabilities-versioning.md) |
| Session shell | `POST /session/:id/shell` exists behind `--enable-session-shell`, bearer or trusted-loopback authority, and session-bound `X-Qwen-Client-Id`; capability tag is conditional. | [`11`](./11-capabilities-versioning.md), [`17`](./17-configuration.md), [`20`](./20-quickstart-operations.md) |
| Rate limiting | Optional per-tier HTTP rate limit is exposed by CLI flags/env and conditional capability tag. | [`11`](./11-capabilities-versioning.md), [`17`](./17-configuration.md) |

Expand Down
2 changes: 2 additions & 0 deletions docs/developers/daemon/13-sdk-daemon-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ const workspaceHandle = await client
const operation = await client.waitForExtensionOperation(workspaceHandle);
```

For live Extension details, pre-flight `workspace_extensions_config_runtime`, then call `workspace.ensureRuntime()`, `workspace.workspaceRuntimeExtensions()`, `workspace.workspaceExtensions()`, and `client.extensionCatalog()`. Runtime rows may override the durable catalog only when the Extension capability is `ready`, the runtime catalog is initialized, the capability and catalog epochs equal the coordinator epoch, the capability desired/applied generations equal the durable catalog generation, and the workspace activation projection's desired/applied generations also equal the durable catalog generation; on a mismatch, re-read the catalog and projection rather than treating the state as terminal.

The terminal operation result contains ordered `results`. Targets do not need to be installed when setting `enabled` or `disabled`: the daemon stores a name declaration and preserves that activation policy when an Extension with that name is installed later. All changed targets share one Extension Store generation and one reconciliation pass. Global default batches reconcile every registered runtime; workspace batches resolve and reconcile only the selected trusted runtime. Workspace `inherit` clears the exact override but does not create a declaration for an unknown name; an all-unknown clear succeeds as a no-op without reconciliation. Singular activation methods remain installed-only.

For workspace-internal Extension Skill switches, preflight `extension_state` and use the resource-grouped REST methods. These do not write Skill settings or activate a disabled parent Extension:
Expand Down
Loading
Loading