feat(plugin-inventory): group by enabled state and allow re-enabling disabled plugins

The plugin-list tab now splits by current state: disabled plugins sit in the
main list with an enable button (so a bundle-default-disabled plugin can be
re-enabled), while enabled plugins sit in the collapsible system section —
a user-added enabled plugin keeps a disable toggle, a required one shows
none. setEnabled refuses to disable a required plugin but allows re-enabling
a disabled one, verifying the fiber activates and reverting a
dependency-missing enable.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Pine
2026-08-14 14:30:13 +08:00
parent d385b7cf05
commit cbec8cd6a9
7 changed files with 46 additions and 24 deletions
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-08-14-plugin-enable-disable-in-page.md
2026-08-14-plugin-enable-disable-in-page.md: b868a8e4f84357e944c184cb80d58ea40858f7b8
2026-08-14-plugin-enable-disable-in-page.zh.md: c53187fd067f3e208e62ecc09d361548ba61bda1
2026-08-14-plugin-enable-disable-in-page.md: 9616cc207f8032faf61d17e5211e64ce4253dee9
2026-08-14-plugin-enable-disable-in-page.zh.md: 1251c0aa7e57fce2364d99119c52d68540e728ae
@@ -38,13 +38,15 @@ The list is grouped: toggleable plugins carry the button in the main list, while
the required system plugins sit in a separate collapsible "system plugins"
section with no controls.
**Guard:** every entry carries a `protected` flag. The rule is default-protect —
disabling a plugin that another plugin injects breaks the dependent, and
enabling one whose service is unavailable fails the boot (both surfaced as
`dsh-tool-ralph: pending (waiting for service: workflowEngine)` after a bad
toggle). So `setEnabled` refuses and the UI hides the toggle for every shipped
plugin; only plugins added through an opt-in bundle (`USER_TOGGLEABLE_PLUGINS`
in `src/required.ts`) are toggleable.
**Guard:** every entry carries a `protected` flag. Disabling a plugin that
another plugin injects breaks the dependent, and enabling one whose service is
unavailable fails the boot (both surfaced as `dsh-tool-ralph: pending (waiting
for service: workflowEngine)` after a bad toggle). So `setEnabled` refuses to
**disable** a required plugin, and after **enabling** a plugin it verifies the
fiber became active (reverting a dependency-missing enable). The plugin-list tab
groups by current state: disabled plugins sit in the main list with an enable
button, while enabled plugins sit in a collapsible system section (a user-added
enabled plugin keeps a disable toggle, a required one shows none).
## Persistence caveat
@@ -29,11 +29,12 @@ Web 插件列表 tab`ui-settings-plugin-inventory`)在每张展开卡片的
绑定该 Remote,切换后重新拉取列表。列表分组:可切换插件在主列表带按钮,必需的系统插件
放在一个可折叠的"系统插件"区,无任何开关。
**门卫:** 每条条目带 `protected` 标记。规则默认保护——停用一个被其他插件注入的插件会破坏
依赖者,启用一个服务不可用的插件会导致启动失败(坏切换后都会表现为
**门卫:** 每条条目带 `protected` 标记。停用一个被其他插件注入的插件会破坏依赖者,
启用一个服务不可用的插件会导致启动失败(坏切换后都会表现为
`dsh-tool-ralph: pending (waiting for service: workflowEngine)`)。所以 `setEnabled`
拒绝、UI 隐藏所有随包插件的开关;只有通过 opt-in bundle 添加的插件
`src/required.ts``USER_TOGGLEABLE_PLUGINS`)可切换。
拒绝**停用**必需插件;**启用**后校验 fiber 变为 active(依赖缺失的启用会回滚)。
插件列表 tab 按当前状态分组:已停用插件在主列表带"启用"按钮,已启用插件放在可折叠的
"系统插件"区(用户自加的已启用插件保留"停用"按钮,必需插件无任何开关)。
## 持久化注意