dsh-prompt-customizer 0.12.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.en.md +7 -6
- package/README.i18n.yaml +2 -2
- package/README.md +7 -6
- package/build.mjs +236 -236
- package/client/client.js +2226 -1395
- package/client/client.js.map +4 -4
- package/cordis.patch.yml +11 -11
- package/docs/adr/0001-remove-catalog-pool.md +27 -0
- package/docs/adr/0002-hide-identity-name-source.md +23 -0
- package/docs/adr/0003-destructive-updates-allowed.md +18 -0
- package/docs/adr/0004-generalized-filter-model.md +17 -0
- package/docs/adr/0005-universal-prompt-takeover.md +109 -0
- package/docs/design/prompt-control-consensus.md +103 -0
- package/docs/guide.md +25 -11
- package/docs/testing/feature-matrix.md +142 -0
- package/docs/upgrades/1.0.0-sqlite-breaking.md +26 -0
- package/docs/upgrades/1.4.0-generalized-model.md +23 -0
- package/docs/upgrades/1.4.1-web-preview-fixes.md +15 -0
- package/docs/upgrades/2.0.0-remove-workspace-level.md +16 -0
- package/docs/upgrades/2.0.1-context-fixes.md +6 -0
- package/docs/upgrades/2.0.10-import-and-skill.md +6 -0
- package/docs/upgrades/2.0.11-regression-fixes.md +7 -0
- package/docs/upgrades/2.0.12-generative-tool-tests.md +5 -0
- package/docs/upgrades/2.0.13-runtime-contract.md +8 -0
- package/docs/upgrades/2.0.14-tool-execution-guard.md +5 -0
- package/docs/upgrades/2.0.15-mask-pool-regression.md +5 -0
- package/docs/upgrades/2.0.16-regression-cleanup.md +6 -0
- package/docs/upgrades/2.0.17-unhide-source.md +5 -0
- package/docs/upgrades/2.0.18-unhide-cleanup.md +4 -0
- package/docs/upgrades/2.0.19-mcp-json-edit.md +4 -0
- package/docs/upgrades/2.0.2-generic-context-filter.md +6 -0
- package/docs/upgrades/2.0.20-preset-isolation.md +4 -0
- package/docs/upgrades/2.0.21-isolation-restore-test.md +4 -0
- package/docs/upgrades/2.0.22-source-immutability.md +3 -0
- package/docs/upgrades/2.0.3-skill-summary.md +6 -0
- package/docs/upgrades/2.0.4-tool-draft.md +5 -0
- package/docs/upgrades/2.0.5-tool-catalog-robustness.md +13 -0
- package/docs/upgrades/2.0.6-tool-restrict.md +6 -0
- package/docs/upgrades/2.0.7-tool-stability.md +5 -0
- package/docs/upgrades/2.0.8-catalog-row-stability.md +4 -0
- package/docs/upgrades/2.0.9-tool-and-write.md +8 -0
- package/docs/upgrades/2.1.0-universal-prompt-takeover.md +41 -0
- package/docs/upgrades/2.1.1-tool-shadow-detection.md +48 -0
- package/docs/upgrades/2.1.2-tool-catalog-scope.md +55 -0
- package/docs/upgrades/README.md +145 -1
- package/docs/upgrades/rc2-migration.md +70 -70
- package/lib/index.js +5474 -3041
- package/lib/index.js.map +4 -4
- package/package.json +97 -97
- package/scripts/e2e-report.json +221 -0
- package/scripts/e2e-terminal.mjs +210 -0
- package/scripts/fixtures/rc2-mode.mjs +12 -12
- package/scripts/fixtures/rc2-preview.snapshot.json +35 -35
- package/scripts/fixtures/rc2-runtime.mjs +85 -85
- package/scripts/fixtures/rc2.cordis.yml +31 -31
- package/scripts/fixtures/rc2.overlay.yml +9 -9
- package/scripts/simulate-rescan.mjs +184 -180
- package/scripts/smoke-client.mjs +382 -382
- package/scripts/smoke-host.mjs +130 -130
- package/scripts/test-skill-manager.mjs +170 -170
- package/scripts/verify-apply-all.mjs +64 -0
- package/scripts/verify-effect.mjs +153 -0
- package/scripts/verify-mcp-edit-ext.mjs +48 -0
- package/scripts/verify-mcp-edit.mjs +45 -0
- package/scripts/verify-workspace-mcp.mjs +62 -0
package/cordis.patch.yml
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
# dsh-prompt-customizer bundle patch: inserts the dual-face plugin row into
|
|
2
|
-
# the web profile roster. Applied as a profile bundle layer (the
|
|
3
|
-
# `dsh.bundle.patch` manifest field). The node half (exports ".") runs in the
|
|
4
|
-
# host process: prompt filtering (block / replace / inject / ordering, inventory
|
|
5
|
-
# & preview routes), skill bundle management + toggles + health, and MCP status /
|
|
6
|
-
# presets / masking / tool-level enable-disable. The `dsh.client` declaration in
|
|
7
|
-
# package.json loads the browser half (exports "./client", served at
|
|
8
|
-
# /plugins/prompt-customizer/client.js): the capability panel (SKILL / MCP /
|
|
9
|
-
# 提示词 tabs) plus the `/` skill source.
|
|
10
|
-
- insert:
|
|
11
|
-
- id: prompt-customizer
|
|
1
|
+
# dsh-prompt-customizer bundle patch: inserts the dual-face plugin row into
|
|
2
|
+
# the web profile roster. Applied as a profile bundle layer (the
|
|
3
|
+
# `dsh.bundle.patch` manifest field). The node half (exports ".") runs in the
|
|
4
|
+
# host process: prompt filtering (block / replace / inject / ordering, inventory
|
|
5
|
+
# & preview routes), skill bundle management + toggles + health, and MCP status /
|
|
6
|
+
# presets / masking / tool-level enable-disable. The `dsh.client` declaration in
|
|
7
|
+
# package.json loads the browser half (exports "./client", served at
|
|
8
|
+
# /plugins/prompt-customizer/client.js): the capability panel (SKILL / MCP /
|
|
9
|
+
# 提示词 tabs) plus the `/` skill source.
|
|
10
|
+
- insert:
|
|
11
|
+
- id: prompt-customizer
|
|
12
12
|
name: 'dsh-prompt-customizer'
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# ADR-0001:移除目录累积池与手动重扫
|
|
2
|
+
|
|
3
|
+
- 状态:已采纳(2026-11-08)
|
|
4
|
+
|
|
5
|
+
## 背景
|
|
6
|
+
早期无法一次性拿到“全部提示词段/工具”,于是用“目录累积池(catalog_*)+ 手动重扫”来凑全量:
|
|
7
|
+
每次装配把见到的段/工具并入池子,重扫时整体替换。池子只增不减,且是**跨预设全局**的。
|
|
8
|
+
|
|
9
|
+
## 问题
|
|
10
|
+
- 全局池会把**别的预设独有**的段/工具串进当前预设(如 `tools:ptc-only` 串到一般预设)。
|
|
11
|
+
- 池子里的历史条目可能早已不存在,需要手动重扫清理。
|
|
12
|
+
- 清单/预览不再等于该预设的真实装配(“有就有”退化为“见过就有”)。
|
|
13
|
+
|
|
14
|
+
## 决策
|
|
15
|
+
- 删除“目录累积池 + 手动重扫”。清单只来自**当前预设真实装配**(动态枚举;2.1.0 起 + 同预设活动 agent,见 ADR-0005),有就有、没有就没有;
|
|
16
|
+
首次运行/插件后注册的段同样通过真实装配枚举得到。
|
|
17
|
+
|
|
18
|
+
> **2.1.0 修订(ADR-0005)**:这里的“当前预设真实装配”已被修订为「当前预设 **+ 同预设活动 agent** 的真实装配」——插件在 `agent/created` 里注册到 agent 作用域的段,只有用该 agent 自己的 scope 再跑一次真实装配才能枚举到。本 ADR 的其余结论(删除累积池 / 手动重扫、预设隔离、动态枚举、不保留跨预设历史条目)全部保留;只是不再用「跨预设历史池」凑齐全量,而是用同预设活动 agent 的真实装配。
|
|
19
|
+
|
|
20
|
+
## 后果
|
|
21
|
+
- 好处:预设天然隔离;清单与模型输入一致;无需手动维护。
|
|
22
|
+
- 代价:不再保留“跨预设历史条目”这种能力(本就是权宜)。
|
|
23
|
+
- 彻底移除:DB 迁移 `DROP TABLE IF EXISTS catalog_section / catalog_tool`;备份/恢复不再含 catalog 字段;
|
|
24
|
+
删除 `catalog.js` 及其测试(单用户,无兼容补丁)。
|
|
25
|
+
|
|
26
|
+
## 备选
|
|
27
|
+
- 给池子加“预设归属”过滤:仍保留全局池复杂度,且运行时归属不可靠 → 弃用。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# ADR-0002:段/工具的隐藏身份采用“名字 + 来源”
|
|
2
|
+
|
|
3
|
+
- 状态:已采纳(2026-11-08)
|
|
4
|
+
|
|
5
|
+
## 背景
|
|
6
|
+
同名不同源很常见:某插件遮蔽了原生 `apply_patch` 并注册同名工具;提示词段也可能由不同 provider 注册同名项。
|
|
7
|
+
原先按“名字”去重/隐藏,会把不同来源的同名条目当成一个。
|
|
8
|
+
|
|
9
|
+
## 决策
|
|
10
|
+
- 段与工具的隐藏/显隐身份 = **名字 + 来源(source/provider)**。
|
|
11
|
+
- 工具页按来源分列同名工具:**遮蔽池显示原生**条目、**启用列表显示插件自带**条目。
|
|
12
|
+
- 旧配置中只有名字的隐藏名单**不迁移、忽略**(D9)。
|
|
13
|
+
|
|
14
|
+
> **2.1.0 注(ADR-0005)**:本 ADR 的「名字 + 来源」身份与「同名不同源分列」在 2.1.0 首次真正落到**提示词段**(此前只在工具页分列):插件在 agent 作用域用与宿主 global 段同名的 `tool:read` 遮蔽时,清单会分「global / agent」两行,各自独立屏蔽。「来源缺失需降级标注」仍是已知限制。
|
|
15
|
+
|
|
16
|
+
## 后果
|
|
17
|
+
- 好处:同名不同源可分别控制与展示;遮盖关系清晰。
|
|
18
|
+
- 代价:需要来源信息;若某处来源缺失,需降级并标注“来源未知”。
|
|
19
|
+
- 兼容:旧名单忽略,可能使旧定制失效。
|
|
20
|
+
|
|
21
|
+
## 备选
|
|
22
|
+
- 仅按名字:无法区分同名不同源 → 否。
|
|
23
|
+
- 仅按 provider 内部 id:宿主未必稳定暴露 → 用“名字+来源”折中。
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# ADR-0003:允许破坏式更新,不保留前向兼容
|
|
2
|
+
|
|
3
|
+
- 状态:已采纳(2026-11-08)
|
|
4
|
+
|
|
5
|
+
## 背景
|
|
6
|
+
本插件为单用户自用;历史遗留形状(如仅按名字的隐藏名单、目录池 catalog、旧快照结构)
|
|
7
|
+
对“按来源区分同名工具/段、预览=真实装配”等正确性目标形成阻碍。
|
|
8
|
+
|
|
9
|
+
## 决策
|
|
10
|
+
- **不为前向兼容写迁移/兼容补丁**。必要时可直接改变数据形状与语义;升级后可丢弃旧数据。
|
|
11
|
+
- 已按此执行:彻底移除 catalog;后续“名字+来源”身份、预览=真实装配均按最优形状实现,
|
|
12
|
+
不兼容旧配置(旧隐藏名单忽略)。
|
|
13
|
+
|
|
14
|
+
> **2.1.0 注**:继续沿用破坏式、不迁移旧数据的决策;「预览 = 真实装配」的数据源口径由 [ADR-0005](0005-universal-prompt-takeover.md) 修订为「该预设 + 同预设活动 agent 的真实装配」。
|
|
15
|
+
|
|
16
|
+
## 后果
|
|
17
|
+
- 好处:实现更简单、语义更正确;无需维护多套兼容分支。
|
|
18
|
+
- 代价:升级后旧定制可能失效(可接受,单用户)。
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ADR-0004:通用过滤模型(PHASES + name+source)
|
|
2
|
+
|
|
3
|
+
- 状态:已采纳(2026-11-08)
|
|
4
|
+
|
|
5
|
+
## 决策
|
|
6
|
+
1. 三阶段只由 `model.js` 的 `PHASES` 描述表定义;字段名、状态映射、工具字段全部派生,禁止三处手写。
|
|
7
|
+
2. 段/工具/运行时上下文的身份统一为 `{name, source}`;`source` 是注册层(global / preset(id) / agent(session) / executor / workspace),宿主能提供 provider 时再附带。
|
|
8
|
+
3. 配置名单存结构化条目;旧 name-only 名单忽略。
|
|
9
|
+
4. 预设级 = 所选预设逐阶段真实装配 + 同预设活动 agent 的 agent 作用域真实装配(2.1.0 / ADR-0005);工作区级已于 2.0.0 移除。
|
|
10
|
+
|
|
11
|
+
> **2.1.0 修订(ADR-0005)**:决策 4 的「通用会话项」口径已改为「**同预设活动 agent** 的真实装配条目」——只有编辑目标所属预设的活动 agent 的会话级段 / 上下文才并入清单与预览,切到别的预设不混入;工作区级已在 2.0.0 移除。本 ADR 的其余决策(三阶段唯一描述表、`{name, source}` 身份、旧 name-only 名单忽略、`replacements` 阶段化)全部保留。
|
|
12
|
+
5. `replace` 改为阶段化 `replacements`(只替换已存在段)。
|
|
13
|
+
|
|
14
|
+
## 后果
|
|
15
|
+
- 旧配置不兼容,直接丢弃(ADR-0003)。
|
|
16
|
+
- 宿主不暴露段/上下文的 provider;来源只能按 global/预设/agent 装配差异推导为“注册层”。
|
|
17
|
+
- 同名不同源可分行显示与独立操作。
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# ADR-0005:全域系统提示词接管(会话级段纳入可编辑清单)
|
|
2
|
+
|
|
3
|
+
- 状态:已采纳(2026-11-09)
|
|
4
|
+
- 版本:2.1.0
|
|
5
|
+
- 修订:ADR-0001 的「清单只来自当前预设真实装配」口径;`docs/design/prompt-control-consensus.md` 的 D1 / D3 / D4 预览口径
|
|
6
|
+
- 依赖:ADR-0002(名字 + 来源)、ADR-0004(PHASES + `{name, source}` 通用过滤模型)、2.0.13 运行时契约(agent 来源按 kind 跨会话匹配)
|
|
7
|
+
|
|
8
|
+
## 背景
|
|
9
|
+
|
|
10
|
+
### 宿主契约(事实,不是本插件的选择)
|
|
11
|
+
|
|
12
|
+
- `ctx.systemPrompt.section(section)` / `context(context)` 把内容注册在**调用方的 scope**:「Register an ordered prompt section in the calling context's scope. A scoped section shadows a global section with the same name」(`deepseek-harness/docs/subsystems/system-prompt.md`)。
|
|
13
|
+
- `PromptSection` / `PromptContext` 的字段只有 `name`、`order`、`text`(静态串或每次装配求值的 provider)、`interpolate`、`complete` / `required`;**没有 `source` / `provider` / `phase`**。宿主不把「这段是哪个插件注册的」暴露给 waterfall 消费方。
|
|
14
|
+
- `system-prompt/assemble` 瀑布流从 0.2.1-rc.2 起只携带 `sections` / `contexts` / `variables`(`PromptPresentation`),「tool declarations remain provider-owned」;工具 `description` 走 `GenerateOptions.tools`,不是系统提示词 token。
|
|
15
|
+
- `systemPrompt.layers` 是单向作用域链(`global` / `peek(scope)` / `chainLayers(scope)` / `merge(scope, ...)`),**没有「列出所有已注册作用域」的 API**。
|
|
16
|
+
|
|
17
|
+
### 缺陷(2.0.22 现状)
|
|
18
|
+
|
|
19
|
+
工具插件可以在 `agent/created` 里用 `agent.ctx.systemPrompt.section()` 把指引注册到 **agent 自有作用域**。实测 `dsh-hashline-edit@0.2.0` 就在 `dsh/index.ts` 的 `installAgentTools` 里注册了三段动态 `text` provider 的命名段:`tool:read`(1100) / `tool:apply_patch`(1350) / `tool:undo_last_edit`(1360),前两段还遮蔽宿主的全局同名段。
|
|
20
|
+
|
|
21
|
+
2.0.22 的 `/api/prompt-customizer/inventory` 与 `/preview` 走 `buildPreview`,只跑**纯预设 scope** 装配,并且把 live 段写成空数组:
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
mergeAgentScopedSections(baseView.sections ?? [], [], previewDenied, previewReplacements, sectionOrder)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
这是 ADR-0001 删除累积池后为「预设隔离」做的取舍,`test/runtime-catalog.test.mjs`、`test/source-model.test.mjs` 还把它钉成了断言(后者直接用 `tool:undo_last_edit` 当 agent-only 段的例子)。后果:
|
|
28
|
+
|
|
29
|
+
1. 只在该 agent 作用域注册的段(如 `tool:undo_last_edit`)在**可编辑清单里根本不存在**;只读 `/session` 才列得出来,而客户端从不请求它。
|
|
30
|
+
2. 同名段(`tool:read` / `tool:apply_patch`)清单里显示的是宿主 global/preset 的原文,不是插件文本。
|
|
31
|
+
3. 即使勾了屏蔽:UI 写 `{name, source:{kind:'global'|'preset'}}`,运行时该段被 `sourceForEntry` 标成 `{kind:'agent', id:<sessionId>}`;`model.js:entryMatches` 要求 `sourceKey` 相等,只对 `agent ↔ agent` 按 kind 放行 —— **名单命不中,模型照样收到插件的指引**。
|
|
32
|
+
4. 工具 schema 的 `description` 是另一条独立通道,段级隐藏原则上看不见;禁用整工具也不会删掉这三段(两条注册互相独立)。
|
|
33
|
+
|
|
34
|
+
结论:2.0.22 **不能**捕获并隐藏这类插件的提示词。这不是运行时过滤能力缺失——`applySectionPolicy` 对带 agent 来源的段同样按 `{name, source}` 过滤,`forceSections` 包装也会把过滤结果覆盖回最终 `sections`——缺的只是「UI 发现 / 枚举」这一环。
|
|
35
|
+
|
|
36
|
+
## 目标 / 非目标
|
|
37
|
+
|
|
38
|
+
**目标**
|
|
39
|
+
|
|
40
|
+
- 只要贡献者把内容注入系统提示词(global / preset / agent / executor 任意作用域、静态串或动态 provider、首次运行或插件后注册),就要能在**预设编辑面板**里被枚举,并屏蔽 / 替换 / 注入 / 排序。
|
|
41
|
+
- 屏蔽后,真实会话装配里该段确实消失(最终 `system/message` 正文不含它),达到对每一个系统提示词 token 的精确掌控。
|
|
42
|
+
- 泛例:按契约对任意注册项求解,不硬编码段名、不认插件名(延续 ADR-0004 / 2.0.2 / 2.0.9 / 2.0.13 的方向)。
|
|
43
|
+
|
|
44
|
+
**非目标**
|
|
45
|
+
|
|
46
|
+
- 不接管工具 schema 的 `description` / 参数 JSON Schema:它们走 `GenerateOptions.tools`,不是系统提示词 token;本插件仍只做「工具显隐」,不做签名编辑。
|
|
47
|
+
- 不接管不并入系统提示词的 user-role 消息、工具结果、LLM 请求体里另加的文本。
|
|
48
|
+
- 不提供「无活动会话时枚举 agent 作用域段」——宿主没有这个 API,插件必须自己把段注册在预设 / 全局层才能无会话也可控。
|
|
49
|
+
- 不改动工具目录 / `tools.restrict` / 遮蔽池链路(2.0.5–2.0.18 的回归约束),不恢复跨预设累积池。
|
|
50
|
+
|
|
51
|
+
## 决策
|
|
52
|
+
|
|
53
|
+
- **D1 双数据源**:`buildPreview` 在「编辑目标 == 同预设活动 agent」时,额外跑一次该 agent 自己 scope 的真实装配(`collectLivePromptView`)。复用同一份 `hint`(含 `promptCustomizerPatch` 草稿、名义阶段、`promptCustomizerPreset` / `PromptScope`),只覆盖 `scope` / `agent`,保证两份装配走同一份生效配置、同一阶段、同一草稿。一次 `promptCustomizerBase: true` 装配同时给出预过滤清单(`promptCustomizerBaseView`)与过滤后的正文(`sections`)。
|
|
54
|
+
- **D2 清单 = 预设 base ∪ agent base**:经 `mergePromptEntries` 按 `{name, source}` 去重,agent 视图优先;同名不同源**分两行**(ADR-0002),由 `mergeAgentScopedSections` 装饰 `blocked` / `replaced` 并给 agent 来源打 `scope: 'agent'`(客户端「会话级」徽标)。`sectionOrder` 取「预设作用域链 ∪ 同预设 agent 作用域链」,否则 agent 段的规范 order 取不到会被排到清单尾部。
|
|
55
|
+
- **D3 预览正文同源**:有 live 视图时,`sections` / `text` / `contexts` / `emitted` / `takenOverBy` 都取自 agent 真实装配(过滤后),右栏显示的就是模型此刻真正看到的系统提示词;`baseSections` / `baseContexts` 取两份 base 视图的并集。无活动会话时整体退回纯预设装配。
|
|
56
|
+
- **D4 身份稳定化**:运行时 `sourceForEntry` 给 agent 来源带 session id,但配置按预设存、必须跨会话命中。`stableSourceOf` 把**清单与预览里**的 agent 来源统一收敛成 `{ kind: 'agent' }`(不带 id);`entryMatches` 已对 `agent ↔ agent` 按 kind 匹配(2.0.13),所以 UI 写入的名单、草稿 `entryKey`、运行时候选三者身份一致且跨会话稳定。
|
|
57
|
+
- **D5 隔离不破**:只用 `liveAgentForPreset(ctx, 编辑预设 id)`,绝不拿 `latestRootAgent` 顶替;编辑 A 预设不会混入 B 预设会话的会话级段。`latestRootAgent` 仍只用于工具 catalog 与无会话兜底。
|
|
58
|
+
- **D6 工具数据源分离**:`finalTools` / `buildToolUnion` / `catalogTools` 仍按纯预设装配计算;提示词与工具两条链路互不干扰,避免推翻 2.0.x 的工具目录回归约束。
|
|
59
|
+
|
|
60
|
+
> **2.1.2 修订**:D6 的「右栏工具目录按纯预设装配」已被证明是错的——宿主真实会话装配的 `scope` 是 live Agent 自身([2.1.2 升级记录](../upgrades/2.1.2-tool-catalog-scope.md)),预设装配只显示预设层工具(实测 38 vs 真实 50)。右栏 `tools` / `registryTools` / `registryTotal` 已改为 `ctx.tools.schemas(agent)` 与 `/session` 同源;`buildToolUnion` / `tools.restrict` / 阶段过滤 / 遮蔽池结构仍不变,D6 的「不动工具目录回归约束」这部分继续成立。
|
|
61
|
+
- **D7 失败回退**:agent 装配抛错时 `warnOnce` 并退回纯预设装配,绝不因可选视图让 `/inventory` / `/preview` 500。
|
|
62
|
+
- **D8 `/session` 定位**:`/session`(`buildSessionPreview`)与 `buildPreview` 的 live 视图是**两条并列的真实装配入口**——前者回答「模型此刻真正看到什么」(只读),后者是编辑目标预设的清单 / 预览数据源。两者都把 agent 来源稳定化为 `{kind:'agent'}`。
|
|
63
|
+
|
|
64
|
+
## 行为规格
|
|
65
|
+
|
|
66
|
+
| 场景 | 行为 |
|
|
67
|
+
|---|---|
|
|
68
|
+
| 有同预设活动 agent | 清单列出预设段 + 该 agent 作用域段;agent 段带 `source:{kind:'agent'}` 与「会话级」徽标;右栏预览 = 该 agent 真实装配的系统提示词正文 |
|
|
69
|
+
| 同名不同源 | 分两行(宿主 global 行 + 插件 agent 行),各自独立屏蔽 / 替换 / 排序 |
|
|
70
|
+
| 屏蔽一个 agent 段 | 配置写 `overrides[preset].sections = [{name, source:{kind:'agent'}}]` → `applySectionPolicy` 在装配瀑布流里过滤 → `forceSections` 包装覆盖回最终 `sections` → 真实会话 / `/session` 的 `sections` 与 `text` 都不含它 |
|
|
71
|
+
| 切到别的预设 | 不混入其它预设会话的会话级段(纯预设列表) |
|
|
72
|
+
| 无活动会话 / agent 装配失败 | 退回纯预设装配;此时只能控制预设 / 全局层注册的段 |
|
|
73
|
+
| 三阶段 | 三份名单互不继承;`buildPreview` 的名义阶段同时作用于两份装配,草稿 patch 也同时叠加 |
|
|
74
|
+
| 工具 description | 不在段清单里,不单独隐藏;只能整工具显隐(既有能力) |
|
|
75
|
+
| `forceSections: false` + `complete:true` | 宿主整段接管会压制段级定制(既有已知限制,不因本 ADR 改变) |
|
|
76
|
+
|
|
77
|
+
## 影响模块
|
|
78
|
+
|
|
79
|
+
- `vendor/prompt-customizer/index.js`:`stableSourceOf` / `mergePromptEntries` / `collectLivePromptView`(新增);`buildPreview`(D1–D6)、`buildInventory`(清单注释)、`buildSessionPreview`(D8 身份稳定化)、路由与文件头注释。
|
|
80
|
+
- `src/client/`:零逻辑改动——`SectionsPane` 已有「会话级」徽标与 `agentScopedHint`,`phase-ops.ts:phaseRows` 会把 `baseSections` ∩ `sections` 的行渲染成可交互行。
|
|
81
|
+
- `src/client/prompt/locales.ts`:`agentScopedHint` 文案随本 ADR 更新(「预览装配看不到它」不再成立)。
|
|
82
|
+
- 测试:`test/runtime-catalog.test.mjs`、`test/source-model.test.mjs` 反转旧断言并新增「枚举 → 屏蔽 → 真实装配消失」组合用例。
|
|
83
|
+
- 文档:本 ADR、`docs/design/prompt-control-consensus.md`、`docs/guide.md`、`docs/upgrades/README.md` + `2.1.0-*.md`、`README.md`、`GLOSSARY.md`、`docs/testing/feature-matrix.md`。
|
|
84
|
+
|
|
85
|
+
## 已知限制
|
|
86
|
+
|
|
87
|
+
1. **无活动会话**:宿主没有枚举任意作用域的 API,插件在 `agent/created` 注册的段只能等会话存在后才可枚举。这是宿主契约边界,不是可实现而暂未实现的缺口。
|
|
88
|
+
2. **宿主 `layers` 缺席**:`sourceForEntry` 退化为按名字差异近似推导,配置里带 source 而候选 source 为 `undefined` 或不同 kind 时不命中(ADR-0004:14 的既有代价)。
|
|
89
|
+
3. **动态 `text` provider**:清单 / 预览用宿主已求值的文本,不二次调用 provider(避免 `forceSections` 重复执行);替换 / 注入会冻结动态文本(guide 已知限制)。
|
|
90
|
+
4. **contexts 口径**:`PromptContext` 在宿主里是 user-role 快照,本插件按「并入系统提示词的可控部分」处理(设计共识 D7);预览的 contexts 仍按 `previewContextsDenied` 手动过滤。
|
|
91
|
+
5. **工具 description 通道未纳入**:若日后要「保留工具但隐藏说明」,需新接缝改写 `result.tools[].description` 或接管 `systemPrompt.tools(provider)`,并重新评估模型调用契约;本次明确不做。
|
|
92
|
+
|
|
93
|
+
## 验证与反例
|
|
94
|
+
|
|
95
|
+
- **反例(会让本 ADR 的实现判定为失败)**:把 `buildPreview` 里 `liveBase.sections` 换回空数组,或把 `stableSourceOf` 改成返回原始带 id 的 agent source,新增用例必须失败。
|
|
96
|
+
- 必测组合:① 同预设活动 agent 的会话级段出现在 `/inventory.sections` 且 `source.kind === 'agent'` / `scope === 'agent'`;② 同名不同源分两行;③ 对 agent 段写入带 `{kind:'agent'}` 的屏蔽名单后,`/preview.text` 与 `/session.sections` 都不含它,撤销后恢复;④ 换一个不同名字 / 不同插件的 agent 段同样可枚举(证明不是样例特判);⑤ 切到别的预设不串台;⑥ 无活 agent 时退回纯预设且不抛错;⑦ 工具目录的行数 / 状态与变更前一致(证明 D6)。
|
|
97
|
+
|
|
98
|
+
## 与既有 ADR 的关系
|
|
99
|
+
|
|
100
|
+
- **ADR-0001**:删除累积池 / 手动重扫、预设隔离、动态枚举,全部保留;仅把「清单只来自**当前预设**真实装配」修订为「当前预设 **+ 同预设活动 agent** 的真实装配」。代价(不再保留跨预设历史条目)不变。
|
|
101
|
+
- **ADR-0002 / ADR-0004**:身份 `{name, source}`、同名不同源分列、PHASES 唯一表、不按名字硬编码——本次全部沿用,正是靠它们才能泛化。
|
|
102
|
+
- **2.0.13 运行时契约**:agent 来源按 `source.kind` 跨会话匹配,是 D4 能成立的前提。
|
|
103
|
+
|
|
104
|
+
## 备选
|
|
105
|
+
|
|
106
|
+
- 恢复「跨预设累积池 + 手动重扫」来凑齐全量:会把别的预设串进当前预设、池子只增不减、清单不再等于真实装配 → 否(ADR-0001 已否)。
|
|
107
|
+
- 让插件改在全局 / 预设层注册段:需要改所有第三方插件,不属本插件职责 → 否。
|
|
108
|
+
- 把整个 `buildPreview` 的 scope 直接换成 agent:会连带改变 `sourceForTool` 与 `result.tools` 过滤,推翻 2.0.5–2.0.18 的工具目录回归约束 → 否(改选 D6 双数据源分离)。
|
|
109
|
+
- 按固定段名清单(`tool:*`)特判捕获:只对当前样例成立,换插件 / 换段名即失效 → 否(违反 ADR-0004:31 与「修的是类,不是样例」)。
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# 提示词 / 工具 / 上下文 控制模型 — 设计共识
|
|
2
|
+
|
|
3
|
+
> 状态:设计共识(实现前)。日期:2026-11-08。术语见根目录 `GLOSSARY.md`。
|
|
4
|
+
> 兼容性:**允许破坏式更新,不保留前向兼容**(见 ADR-0003)。
|
|
5
|
+
|
|
6
|
+
> **2.1.0 修订(ADR-0005)**:本文件是实现前的设计共识,保留作历史材料。其中 D1「预览 = 该预设(+工作区)实际发给模型的系统提示词」、D3「严格预设隔离:清单与预览只来自该预设真实装配,禁止并集/跨预设混入」、D4「动态枚举」的**预览数据源口径**已由 [ADR-0005](../adr/0005-universal-prompt-takeover.md) 修订为「该预设 + 同预设活动 agent 的真实装配」;「工作区级」已在 2.0.0 移除。其余决策(D2 只渲染 sections、D5 名字+来源、D6 工具页/提示词页职责独立、D7–D10)不变。当前实现以 `vendor/prompt-customizer/index.js` 与 ADR-0005 为准,本文件不再描述现状。
|
|
7
|
+
|
|
8
|
+
## 1. 背景与问题
|
|
9
|
+
|
|
10
|
+
面板现能定制“预设级/工作区级”的提示词段与工具显隐,但存在若干问题:
|
|
11
|
+
|
|
12
|
+
1. **禁用技能卡片信息丢失**:被“全局/预设/工作区”禁用的技能,在面板里显示成桩信息
|
|
13
|
+
(`disabled by dsh-prompt-customizer for preset "..."`、`0 文件`),而不是原有内容。
|
|
14
|
+
2. **提示词预览混入工具格式**:右侧“提示词预览”把工具声明/schema/签名也渲染进去。
|
|
15
|
+
3. **跨预设串台(未彻底)**:一般预设里仍能出现 ptc 专属的**系统提示词段**(列表与正文都有),
|
|
16
|
+
但实际并未注入模型——说明预览/清单不是该预设的“真实装配”。
|
|
17
|
+
4. **同名不同源工具无法区分**:某个插件遮蔽了原生 `apply_patch` 并注册同名工具后,面板把它们
|
|
18
|
+
当成同一个;期望“遮蔽池显示原生、启用列表显示插件自带”。
|
|
19
|
+
5. **重复的权宜设计**:历史上用“目录累积池 + 手动重扫”来凑齐全量,现已可从真实装配动态枚举,
|
|
20
|
+
该设计应删除(已在 1.1.3 移除,本设计确认其为正式方向)。
|
|
21
|
+
|
|
22
|
+
## 2. 目标 / 非目标
|
|
23
|
+
|
|
24
|
+
**目标**
|
|
25
|
+
- 面板对“系统提示词段(含并入系统提示词的 host contexts)”与“工具”的展示与控制,严格反映
|
|
26
|
+
**当前预设(叠加工作区)的真实装配**:有就有、没有就没有,不多不少。
|
|
27
|
+
- 禁用技能卡片与启用时**信息完全一致**,仅状态为“已停用”。
|
|
28
|
+
- 同名不同源的段/工具按“名字+来源”分别展示与控制。
|
|
29
|
+
- 动态枚举:首次运行/插件后注册的段,出现即可控,无需手动重扫。
|
|
30
|
+
|
|
31
|
+
**非目标**
|
|
32
|
+
- 不接管“不并入系统提示词”的真正运行时上下文(会话消息、工具结果等)。
|
|
33
|
+
- 不提供工具签名/schema 的编辑(只能控工具显隐)。
|
|
34
|
+
- 不做“按固定名单匹配段”的实现(不硬编码段名)。
|
|
35
|
+
|
|
36
|
+
## 3. 决策(Decisions)
|
|
37
|
+
|
|
38
|
+
- **D1 真实装配预览**:所有级别的“提示词预览”= 该预设(+工作区)实际发给模型的**系统提示词**,
|
|
39
|
+
只含系统提示词段,不含工具声明/schema/签名。无活动会话时,跑一次该预设的真实装配作为预览。
|
|
40
|
+
- **D2 预览只渲染 sections**:以**段形式**注册的工具指引文本(如 `tool:read` 段)属提示词内容并进预览;工具声明里的 `description` 走 `GenerateOptions.tools`,不是系统提示词 token,不进预览;工具签名/声明不进预览。(2.1.0 消歧,见 ADR-0005)
|
|
41
|
+
- **D3 严格预设隔离**:清单与预览只来自该预设真实装配,禁止并集/跨预设混入(修复 ptc 段串台)。
|
|
42
|
+
- **D4 动态枚举、不按名字匹配**:从真实装配动态枚举所有段(含首次运行注册/插件注册),基于实际结果,
|
|
43
|
+
不依赖固定名单。
|
|
44
|
+
- **D5 身份 = 名字 + 来源**:段与工具的隐藏/显隐以“名字+来源”为标识;同名不同源区分对待。
|
|
45
|
+
- **D6 工具页 vs 提示词页职责独立**:工具页只控“工具是否可用”;提示词页只控“段(含工具描述文本)”
|
|
46
|
+
显隐。禁用工具不自动隐藏其描述段。
|
|
47
|
+
- **D7 运行时上下文(并入系统提示词的部分)可显隐**:允许拦截 host `contexts` 中并入系统提示词的部分;
|
|
48
|
+
真正 user-role 上下文不管。范围与提示词段一致:预设级+工作区级、三阶段独立、受“三态同步”。
|
|
49
|
+
- **D8 技能禁用卡片全量还原**:描述/文件数/路径/正文与启用时一致,仅状态为“已停用”。
|
|
50
|
+
- **D9 旧隐藏名单忽略**:改为“名字+来源”后,旧配置中只有名字的隐藏名单不迁移、忽略。
|
|
51
|
+
- **D10 移除目录池/重扫**:不再累积、不再手动重扫;清单只来自真实装配。并**彻底移除** `catalog_*` 表与
|
|
52
|
+
备份/恢复中的 catalog 字段(无兼容补丁)。
|
|
53
|
+
|
|
54
|
+
## 4. 行为规格
|
|
55
|
+
|
|
56
|
+
### 4.1 技能卡片(SKILL)
|
|
57
|
+
- 启用与禁用卡片除“开关/已停用”外,描述、文件数、路径/来源、可查看正文等**完全一致**。
|
|
58
|
+
- 禁用仅表示“模型侧不可用 + 开关为关”,不影响面板展示的真实元数据。
|
|
59
|
+
|
|
60
|
+
### 4.2 提示词页(段)
|
|
61
|
+
- 左栏:动态枚举当前预设真实装配里的系统提示词段(含并入系统提示词的 contexts),每条带来源标签、
|
|
62
|
+
可勾选显隐;同名不同源分列。
|
|
63
|
+
- 右栏:该预设真实系统提示词正文(仅 sections,不含工具 schema/签名)。
|
|
64
|
+
- 首次运行/插件后注册的段:出现即可控(动态枚举,无需重扫)。
|
|
65
|
+
|
|
66
|
+
### 4.3 工具页
|
|
67
|
+
- 按“名字+来源”列出工具:遮蔽池显示被隐藏/禁用的条目(含被遮蔽的**原生** `apply_patch`),
|
|
68
|
+
启用列表显示当前可见条目(含插件自带的同名 `apply_patch`)。
|
|
69
|
+
- 只控工具可用性;不涉及 schema 编辑。
|
|
70
|
+
|
|
71
|
+
### 4.4 预览
|
|
72
|
+
- 预览 = 真实装配结果(该预设 + 工作区);有活动会话用会话真实结果,无会话跑一次该预设装配。
|
|
73
|
+
- 只渲染系统提示词段;上下文中的 user-role 快照不计入系统提示词正文(但其中并入系统提示词的部分可控)。
|
|
74
|
+
|
|
75
|
+
### 4.5 三态与层级
|
|
76
|
+
- 段、工具、运行时上下文的显隐在 bootstrap/compaction/active 三阶段独立;
|
|
77
|
+
- “三态同步”开启时,三者改动均三阶段一起生效。
|
|
78
|
+
- 预设级 + 工作区级都可控;工作区级覆盖预设级。
|
|
79
|
+
|
|
80
|
+
## 5. 影响模块(预估)
|
|
81
|
+
- `vendor/prompt-customizer/index.js`:装配过滤(sections/contexts/tools)、inventory、preview 数据源改为真实装配;
|
|
82
|
+
移除剩余目录池耦合;引入“名字+来源”身份。
|
|
83
|
+
- `src/kernel-skills.ts`:禁用技能的真实元数据还原(不被闸门桩替换)。
|
|
84
|
+
- `src/skill-toggles.ts`:闸门桩与真实元数据的关系(面板展示用真实源)。
|
|
85
|
+
- `src/client/prompt/*`(Panel / PreviewPane / PresetsPane / types):段/工具/上下文清单与预览渲染、三态同步。
|
|
86
|
+
- `src/client/skills/*`(SkillsView / 卡片):禁用技能卡片渲染真实元数据。
|
|
87
|
+
|
|
88
|
+
## 6. 待实现时核实的技术问题(事实,不属用户决策)
|
|
89
|
+
- host `system-prompt/assemble` 返回的 `sections` / `contexts` 是否携带 `source/provider/scope`,
|
|
90
|
+
以及“并入系统提示词”的 contexts 的可识别方式。
|
|
91
|
+
- 工具注册表是否暴露 provider/source,用于“名字+来源”区分同名工具。
|
|
92
|
+
- 闸门 provider 桩条目如何在不影响模型可用性的前提下,为面板提供“真实技能元数据”。
|
|
93
|
+
|
|
94
|
+
## 7. 测试计划
|
|
95
|
+
- 单测:预设隔离(ptc 段不出现在一般预设清单/正文);预览只含 sections(无工具 schema/签名);
|
|
96
|
+
同名不同源工具分别列出;禁用技能卡片还原真实元数据;上下文显隐与三态同步。
|
|
97
|
+
- 实机:切换 standard/ptc/minimal,核对预览=真实系统提示词;禁用技能卡片信息;同名工具遮蔽展示。
|
|
98
|
+
|
|
99
|
+
## 8. 分阶段落地
|
|
100
|
+
1. 预览/清单真实化 + 严格预设隔离 + 预览只 sections(修 ptc 串台、混入工具格式)。
|
|
101
|
+
2. 技能禁用卡片全量还原。
|
|
102
|
+
3. 身份“名字+来源”(工具先做,段同名后补)+ 同名工具分源展示。
|
|
103
|
+
4. 运行时上下文(并入系统提示词部分)显隐 + 三态同步涵盖。
|
package/docs/guide.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# 使用与实现指南
|
|
2
2
|
|
|
3
3
|
> 本文件保留原 README 的详细说明(会话阶段、界面、功能特性、工作原理、使用说明、配置位置、已知限制与开发)。产品概览见根目录 [README](../README.md),版本升级记录见 [docs/upgrades/README.md](upgrades/README.md)。
|
|
4
|
+
>
|
|
5
|
+
> **状态(2.1.2)**:本文是历史文档,与当前实现有漂移 —— ① 统一为单文件 SQLite `~/.dsh/prompt-customizer/prompt-customizer.db`,`config.yaml` / `catalog.yaml` 不读不迁移;② 工作区级提示词 / 工具层已移除(2.0.0);③ 跨预设累积池与手动重扫已删除(ADR-0001),下文「池子是见过才知道的并集」「catalog/rescan」等段落均已过时;④ **2.1.0 起清单与预览并入「同预设活动 agent」的真实装配**(ADR-0005),因此「预设预览按纯预设 scope 装配、不读取 agent 作用域条目」「预设预览右栏不会混入会话级内容」不再成立;⑤ 2.1.1 起同名遮蔽进只读遮蔽池;⑥ **2.1.2 起右栏可见工具目录改用 `ctx.tools.schemas(agent)`(与真实会话同源),不再只显示预设层工具**,只读池也如实列出插件纯新增的会话级工具。当前行为以 [ADR-0005](../adr/0005-universal-prompt-takeover.md) 与 [2.1.0](upgrades/2.1.0-universal-prompt-takeover.md) / [2.1.1](upgrades/2.1.1-tool-shadow-detection.md) / [2.1.2](upgrades/2.1.2-tool-catalog-scope.md) 升级记录为准。
|
|
4
6
|
|
|
5
7
|
## 会话阶段怎么流转
|
|
6
8
|
|
|
@@ -85,13 +87,14 @@
|
|
|
85
87
|
|
|
86
88
|
### 提示词段
|
|
87
89
|
|
|
88
|
-
-
|
|
90
|
+
- **屏蔽**:按名字 + 来源从装配结果里移除该段。被屏蔽的行不会消失,仍可编辑、恢复 —— 屏蔽只意味着不注入模型。
|
|
89
91
|
- **替换**:编辑该段文本,编辑框预填当前生效文本(动态段会尽力解析出真实内容再回显)。
|
|
90
92
|
- **注入**:每个阶段里「+ 注入」展开表单,按名称 + 文本新建一段,带 `手动` 徽标,随时可删除。
|
|
91
|
-
- **排序**:行首抓手拖动排序,或用行内 ↑/↓ 箭头逐格挪。顺序以 0 起始的连续虚拟下标存储,不会出现重复或小数 order
|
|
93
|
+
- **排序**:行首抓手拖动排序,或用行内 ↑/↓ 箭头逐格挪。顺序以 0 起始的连续虚拟下标存储,不会出现重复或小数 order,也不需要手填数字。**未手动排序时默认按宿主注册的规范 `order` 排列**(与模型实收顺序一致,如 `tool:apply_patch` 落在 `tool:edit` 之后),新见到的段按 order 落位、不再追加到尾部。
|
|
92
94
|
- **拖拽**:把「本系统全部提示词」池里的行拖进列表 = 加入当前阶段(带上池里原文);把行拖回池 = 从当前阶段移除(注入进来的撤销注入,原生段转为屏蔽);把行拖到头部某个**阶段按钮**上 = 复制到那个阶段。拖动中有插入位置提示(行上下的蓝色线),投放区高亮;列表比视口长时,把指针拖到列表上/下边缘会自动滚动(越靠边越快),所以池在折叠区里、目标行在视口外也照样能拖到。
|
|
93
95
|
- **每阶段独立**:引导期屏蔽写 `sectionsBootstrap`,压缩受控期写 `sectionsCompaction`,常驻期写 `sections`;三份名单互不继承、互不影响,排序空间也互不干扰,因此「引导期只留 5 段、常驻期全开」可以分别表达 —— 在一个阶段屏蔽 / 恢复某段,绝不会改变它在其它阶段的状态。从「本系统全部提示词」池把段**拖入**当前阶段即成为当前阶段的独立副本(带原文写入本阶段注入条目)—— 加入阶段只有拖拽这一条路径,池里的行不再挂按钮,界面因此干净一半。(勾选「三态同步」后三态共用同一份列表,见下。)
|
|
94
|
-
- **强制覆盖(`forceSections
|
|
96
|
+
- **强制覆盖(`forceSections`,默认开)**:只有当前预设 / 当前阶段存在实际段策略(屏蔽 / 替换 / 注入 / 排序)时才包装宿主装配入口,按本插件结果重建最终 sections —— 此时预设插件自身的阶段裁段(如 liangshen 引导期 20→1)与 persona 的 `complete: true` 整段接管会被绕过;没有段定制时保持宿主原样(包括 minimal 的 complete persona)。设为 `false` 退回瀑布流内过滤(此时完整段接管仍会压制段级定制)。
|
|
97
|
+
- **工具提示词段(`tool:*`)**:工具的第一部分是注册在 `systemPrompt` 里的工具提示词段,会以普通段的形式出现在提示词清单里,可照常屏蔽 / 替换 / 排序;工具页的 `description` 是第二部分(只读),参数 JSON Schema 是第三部分(不可编辑)。一个 `tool:*` 段可能服务多个工具(如 `tool:jobs` 对应 `job_kill/job_list/job_output`),工具页会给出关联提示。
|
|
95
98
|
- **中文提示词开关(面板头部工具栏,刷新按钮旁)**:开启 = 把名字对得上内置译本(`lib/zh/`,25 条目)的段一次性覆盖为中文;关闭 = 清掉这些段的替换文本,回归英文原文。两个方向都写入编辑草稿,与手动编辑同一条保存路径;开关状态从配置探测,不新增字段。自定义段与对不上名字的段不受影响,段数与注入不增不减。`{{...}}` 提示词变量(如 persona 的 `{{model}}` / `{{cwd}}`)、机器路径与代码块逐字保留;`tools:sdk` 只替换前导散文,TS 代码块取自原文。**`tools:sdk` 与 `context:file-reference` 是函数译本**:按该行原文决定译不译(原文为空 = 该段的守卫已把它抹掉,就放弃替换,绝不用译本把一段被守卫消掉的内容复活);开关开启时从「本系统全部提示词」池把段拖进某阶段,也优先取译本 —— 加入即中文,一步接管。
|
|
96
99
|
- **三态同步(头部开关,默认关)**:勾选瞬间即把另外两态覆写为**常驻期的并集行集**(写入编辑草稿,点「保存」生效),之后三个阶段共用同一份段列表与文本 —— 增加 / 删除 / 排序 / 勾选 / 编辑文本都一次写全三个阶段,不再逐阶段各点一遍。行序以常驻期为骨架,只存在于另外两态的段追加在尾部并补进常驻期(同名段以它原生所在那一阶段的行为准);三份屏蔽名单也统一为同一份。动态段(运行时才生成正文,取不到原文)无法凭空建进别的阶段,列表里会给出说明。工具两栏的隐藏 / 显示与加回同样对三个阶段一起生效(只作用于同名的那一项)。
|
|
97
100
|
|
|
@@ -102,11 +105,21 @@
|
|
|
102
105
|
- **阶段目录**:引导期与压缩受控期各有独立的 exclude / add 名单,运行时优先级为 **压缩受控期 > 引导期 > 静态** —— 压缩后仍未晋级且配了压缩目录就用它,否则未晋级时用引导目录,其余情况用静态过滤。
|
|
103
106
|
- **拖拽**:把池里的工具拖进列表 = 让它在当前阶段出现(加回或从黑名单放出来);把行拖回池 = 从当前阶段拿掉(已加回的撤销加回,原生工具则该阶段隐藏);拖到头部某个**阶段按钮**上 = 复制到那个阶段,**隐藏 / 启用状态一起带过去**,源阶段不动。加回阶段同样只有拖拽这一条路径。
|
|
104
107
|
- **扩充的天花板是注册表**:只能把注册表里已有的工具加回某个阶段;要让一个全新工具出现,得改预设的组成,不是这里。
|
|
108
|
+
- **顺序**:左栏启用列表、「本系统全部工具」池、右栏模型可见目录都按**宿主最终目录顺序**排列(预设配了 `toolOrder` 就用它,否则字母序)—— 不再按注册表枚举序 / 浏览先后乱排。
|
|
109
|
+
- **同名工具分开显示**:若别的插件在会话作用域注册了与原生同名的工具(如 better-edit 的 `read` / `edit`、apply-patch-edit 的 `apply_patch`),列表会出现**同名两行**:插件提供的那个在启用列表(标「会话级」,**可勾选开关** —— 取消即真正从模型目录移除,靠装配后过滤 `assembly.tools` 实现,因为 `restrict` 管不到作用域内注册的工具),原生那个进只读「已遮蔽」池(标「插件遮蔽」,**无法反开**)。
|
|
110
|
+
- **执行器包装(PTC 的 `run_code`)**:作为「执行器包装」锁定行出现在启用列表,勾选框禁用(它不是可单独开关的普通工具)。
|
|
111
|
+
- **只读「已遮蔽」池**:只放注册表里有、但当前不可见的 —— 被别的插件 `restrict` 掉的、被别的插件同名顶掉的原生工具、被本插件 MCP 账本遮蔽的。不可勾选、不可反开(要恢复请回到对应插件 / MCP Tab)。
|
|
112
|
+
- **工具的三部分分开**:提示词段(`tool:*`,在提示词 Tab 编辑)、工具描述(工具页只读展示)、参数 JSON Schema(不可编辑);工具页只负责工具显隐,不把 description / Schema 混入提示词编辑。
|
|
105
113
|
- 只影响面向模型的目录;工具本身与路由照常工作。
|
|
106
114
|
|
|
107
115
|
### 模型视角预览
|
|
108
116
|
|
|
109
|
-
|
|
117
|
+
预览分两种口径:
|
|
118
|
+
|
|
119
|
+
- **编辑目标预设预览**:提示词模式看最终系统提示词,工具模式看模型可见目录;随头部阶段 Tab 联动切换。2.1.0 起提示词清单与预览同时来自「该预设 + 同预设活动 agent」的真实装配(ADR-0005)——插件在 agent 作用域动态注册的段也会出现在清单与右栏;工具目录仍按纯预设装配计算。无活动会话 / 无同预设活动 agent 时退回纯预设装配。
|
|
120
|
+
- **当前会话(只读)**:`/session` 路由用最新活动根会话自己的 agent scope 跑真实装配,展示模型此刻真正看到的提示词、运行时上下文与工具目录。2.1.0 起它与预设编辑预览的 live 视图是**两条并列的真实装配入口**:预设预览只并入**同预设**活动 agent 的段,只读视图按最新根会话展示;两者都会列出 agent/created 时动态注册的段与 agent 作用域 `tools.restrict` 的遮蔽。
|
|
121
|
+
|
|
122
|
+
工具视图给出「模型可见 / 完整目录」的对照 —— PTC、Code Mode 这类预设会把整套目录包装成单个 `run_code`,只看注册表会误判。启用列表里的「会话级」(插件提供的工具)与「执行器包装」(`run_code`)是模型实际可见、本插件锁定的项;底部只读「已遮蔽」池放的是「注册表里有、当前不可见」的「插件遮蔽」「本插件遮蔽」项(无法反开)。同名工具会分别出现在启用列表(插件提供)与已遮蔽池(原生)两处。
|
|
110
123
|
|
|
111
124
|
### 提示词变量
|
|
112
125
|
|
|
@@ -132,13 +145,13 @@
|
|
|
132
145
|
|
|
133
146
|
「本系统全部提示词 / 本系统全部工具」不随编辑目标切换:它是一个**跨预设、只增不减的并集**(同名后见到者赢,新名追加),存放在 `catalog.yaml` 这个派生缓存里,删掉会自行重建。
|
|
134
147
|
|
|
135
|
-
|
|
148
|
+
池子的内容来自三处:
|
|
136
149
|
|
|
137
150
|
- **当前 scope 的注册表**(你正在编辑的那个预设);
|
|
138
|
-
-
|
|
151
|
+
- **同预设活动 agent 的会话级段 / 工具**:当编辑目标正好是同预设活动 agent 所属预设时,清单与预览在请求时按该 agent 的真实装配现 merge(`tool:subagent`、`context:file-reference`、`tool:undo_last_edit` 等任意段名),按 `{name, source}` 去重、同名不同源分列,并打「会话级」标记;切换到其它预设时保持纯预设列表,避免跨预设混入(ADR-0005);
|
|
139
152
|
- **浏览过的其它预设**:只在某个预设里注册的段 / 工具(如 `tools:ptc-only`、`raw-html-v2:vcp`)随你切换编辑目标逐步并进来 —— 这部分按需增长,是本插件的取舍(逐个挂载预设 tree 慢到十几秒,不值得每次开面板都跑)。
|
|
140
153
|
|
|
141
|
-
真实会话装配那次也会把看到的段 / 工具并进登记表,作为没有活 agent
|
|
154
|
+
真实会话装配那次也会把看到的段 / 工具并进登记表,作为没有活 agent 时的兜底。`catalog/rescan` 同样会读取同预设活动 agent 的视图,避免重扫把只在 agent 作用域注册的条目清掉。池里的段按宿主 `order` 排列(与模型实收一致);工具池只列能按阶段开关的预设工具,不可控项见工具页签的只读「完整目录 / 已遮蔽」。
|
|
142
155
|
|
|
143
156
|
## 工作原理
|
|
144
157
|
|
|
@@ -159,7 +172,7 @@
|
|
|
159
172
|
</tr>
|
|
160
173
|
<tr>
|
|
161
174
|
<td colspan="9" align="center">
|
|
162
|
-
<b>⑤ 交卷前还有一手</b>:宿主在瀑布流<b>之后</b>,若存在 <code>complete: true</code> 的段就把整份 sections 还原成那一条 ——
|
|
175
|
+
<b>⑤ 交卷前还有一手</b>:宿主在瀑布流<b>之后</b>,若存在 <code>complete: true</code> 的段就把整份 sections 还原成那一条 —— 这就是面板会对这类预设亮黄标的原因(工具目录不受影响;当前阶段有实际段策略且 <code>forceSections</code> 开启时,本插件已在装配入口重建 sections,接管被绕过,不再亮黄标;没有段策略时保持 complete 原样)
|
|
163
176
|
</td>
|
|
164
177
|
</tr>
|
|
165
178
|
<tr>
|
|
@@ -226,15 +239,16 @@
|
|
|
226
239
|
|
|
227
240
|
下面都是实测结论。面板在相关情况下会直接给出黄色警示,不需要你猜:
|
|
228
241
|
|
|
229
|
-
- **有些预设的提示词不由段组成。** 若某个段以 `complete: true` 注册(dsh-persona 的「整段接管」),宿主会在装配瀑布流**之后**把整份 sections
|
|
242
|
+
- **有些预设的提示词不由段组成。** 若某个段以 `complete: true` 注册(dsh-persona 的「整段接管」),宿主会在装配瀑布流**之后**把整份 sections 还原成那一条段。当前阶段有实际段策略且 `forceSections`(默认开)时,本插件在装配入口绕开该机制,段级定制照常生效;没有段策略时保持 complete 原样;设为 `false` 时,本插件的屏蔽 / 替换 / 注入 / 排序对这类预设无效(工具过滤不受影响),面板会写明「最终系统提示词由 `deployment:persona` 段整段接管」。
|
|
230
243
|
- **丢弃段的原因不止一种**。除了 `complete` 接管,也存在预设用自己的规则在特定阶段裁段(实测某预设引导期 20 段 → 1 段,而注册表里并没有 complete 段)。所以面板还做了一次机制无关的比对:把本插件产出的段名与最终装配逐名核对,不符时提示「产出 N 段,模型只见 M 段」。
|
|
231
244
|
- **预览的伪会话可能降级**。阶段视图由一次合成会话驱动,个别预设插件会在这种会话上抛错;此时该阶段回退为无会话装配并标注「已降级」,即那个阶段看到的是不带原生阶段裁剪的结果。
|
|
232
245
|
- **替换动态生成的段会固定其内容**。像 `app:web-surface` 这类段在装配时实时生成(嵌入当前 Web 端口等)。替换后文本冻结为你编辑时的值,不再跟随运行时变化;想保持跟随请改用屏蔽。
|
|
233
246
|
- **动态段文本解析是尽力而为**。面板读取动态段时会尝试调用其生成函数(只传最小上下文)来回显真实内容;依赖更复杂上下文、一调就抛的段会显示 `<动态生成>`,其余功能不受影响。另外,带 `{{model}}` / `{{cwd}}` 之类变量的段在列表里显示的是**未替换的模板**,右栏预览里才是替换后的最终文本。
|
|
234
247
|
- **导出依赖宿主允许下载**。Web 回退走浏览器下载:若宿主 webview 静默丢弃下载,面板仍会提示「导出成功」而文件没有落地。导入(文件选择)不受影响。
|
|
235
|
-
- **池子是「见过才知道」的并集**。当前 scope
|
|
248
|
+
- **池子是「见过才知道」的并集**。当前 scope 与**同预设活动 agent** 作用域的段 / 工具当场就能列出来;但**只在别的预设里注册**的段 / 工具要等你切到那个编辑目标才进池(逐个挂载预设 tree 太慢,不做预热)。池子对「某个名字属于哪个阶段」没有权威信息 —— 加入阶段时按当前 Tab 落,之后可以随意拖动改位置。
|
|
236
249
|
- **工具目录的扩充以注册表为天花板**,见前文「扩充的天花板是注册表」。
|
|
237
|
-
- **「当前会话」的判定**:面板是进程级单例,客户端拿不到渲染期的当前会话 id,因此以**最新创建的根会话**为准(`session.header.createdAt`
|
|
250
|
+
- **「当前会话」的判定**:面板是进程级单例,客户端拿不到渲染期的当前会话 id,因此以**最新创建的根会话**为准(`session.header.createdAt` 降序,子代理 `delegationDepth > 0` 不计入);多会话来回切换时,面板可能仍显示最新那个会话的技能集合与「当前会话」视图。无会话时退回启动 cwd 的全局视图。可写根集合仍只在「插件挂载时」与「新会话创建时(`agent/created`)」重算。
|
|
251
|
+
- **工具显隐的边界**:本插件的阶段工具过滤分两层 —— 继承的全局工具走 `tools.restrict`(只收窄、取交集),作用域内注册的工具(插件提供的 `read` / `edit` / `apply_patch` 等)走**装配后过滤 `assembly.tools`**(按名字从模型函数表移除),所以两类都能被本插件按阶段隐藏。但 ① 别的插件 `restrict` 掉的全局工具、② 被别的插件同名顶掉(遮蔽)的原生工具,本插件**无法反开**(restrict 不可反向、遮蔽由对方在会话作用域注册决定);这两类留在只读「已遮蔽」池。③ PTC / code-mode 下 `run_code` 程序内部可调工具来自 toolSet,本插件按名隐藏 `assembly.tools` 只影响模型可见的函数表,不影响程序内部绑定。
|
|
238
252
|
- **mcps 目录只读挂载**:面板不改写这些 `mcp.json`;要让某台 Server 成为持久全局配置,仍走「添加 MCP Server」(写 profile patch)。工作区层的 Server 工具名带 8 位路径哈希后缀(如 `mcp__codegraph-e5f6a7b8__*`),这是同名隔离的代价。
|
|
239
253
|
|
|
240
254
|
## 开发
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# 终测:功能点矩阵与自动化覆盖
|
|
2
|
+
|
|
3
|
+
> **状态(2.1.0)**:本文件记录的是 1.x / 2.0.x 时期的终端级与行为级验证结果(2026-11-07),**不作为 2.1.0 的当前验证结论**。当前门禁是 `npm run check`(构建 + 全量单测 + 宿主 / 客户端 smoke)与 `test/universal-prompt-takeover.test.mjs`(ADR-0005 组合场景)。`scripts/verify-effect.mjs` 的旧 `replace` 字典、`level=workspace`、`scripts/e2e-terminal.mjs` 的工作区级断言已与 1.4.0 / 2.0.0 之后的代码不相容,属历史脚本,运行前须按当前 `/config/apply` 契约更新;`docs/guide.md` 同样保留作历史材料,现状以 `docs/adr/0005-universal-prompt-takeover.md` 与 `docs/upgrades/2.1.0-universal-prompt-takeover.md` 为准。
|
|
4
|
+
|
|
5
|
+
> 自动化脚本:`scripts/e2e-terminal.mjs`(终端级,走真实 HTTP + dsh-auth 握手)。
|
|
6
|
+
> 运行:先起一个实例 `dsh web --no-open --port <N>`,再
|
|
7
|
+
> `node scripts/e2e-terminal.mjs --url "http://127.0.0.1:<N>/?token=<TOKEN>" [--destructive]`。
|
|
8
|
+
> `--destructive` 会先 `GET /backup` 整库备份、测试后 `POST /restore` 恢复,保护真实数据。
|
|
9
|
+
|
|
10
|
+
结果(2026-11-07,web profile,MCP `anysearch` + `codegraph`):
|
|
11
|
+
- 单测 `npm test`:**136 passed / 0 failed**。
|
|
12
|
+
- E2E(`--destructive`):**43/43 passed**,含备份→写入→恢复一致性。
|
|
13
|
+
|
|
14
|
+
## A. 提示词定制(预设级)
|
|
15
|
+
| 功能 | 覆盖 | 结果 |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| inventory 清单(段/工具/阶段) | `test/*` + E2E `GET /inventory` | PASS |
|
|
18
|
+
| config 读/写(forceSections、envBlocklist、presets) | `test/store` `test/reset-route` + E2E `GET /config`、`/config/set`、`/config/unset` | PASS |
|
|
19
|
+
| 三阶段 preview(bootstrap/compaction/active) | `test/ordering` `test/rc2-preview` + E2E `GET /preview?phase=` | PASS |
|
|
20
|
+
| 草稿预览 POST /preview | `test/session-preview` | PASS(单测) |
|
|
21
|
+
| 段 屏蔽/替换/注入/拖拽排序 | `test/ordering` `test/sectionOps` | PASS |
|
|
22
|
+
| 工具目录按阶段 隐藏/加回 | `test/tool-shadow` `test/tool-visibility` | PASS |
|
|
23
|
+
| config/apply 预设级写入 + 还原 | E2E `POST /config/apply`(target) | PASS |
|
|
24
|
+
| export 当前预设定制(只读) | `test/export-route` + E2E `GET /export` | PASS |
|
|
25
|
+
| 恢复初始 /config/reset | `test/reset-route` | PASS |
|
|
26
|
+
|
|
27
|
+
## B. 两级(预设级 / 工作区级)
|
|
28
|
+
| 功能 | 覆盖 | 结果 |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| config/apply `level=workspace` 写 `workspaceOverrides[cwd]` | `test/workspace-override` + E2E | PASS |
|
|
31
|
+
| 合并语义 工作区>预设(同名后者胜) | `test/workspace-override` `mergeOverrideLayers` | PASS |
|
|
32
|
+
| 运行时按会话 cwd 叠加工作区 override | `buildSessionPreview`/`resolveTarget`(单测 + 实机) | PASS |
|
|
33
|
+
| 顶部统一「预设级/工作区级」切换(三 tab 共用) | 实机 UI(截图) | PASS |
|
|
34
|
+
| 移除「当前会话」独立模式 | 实机 UI | PASS |
|
|
35
|
+
|
|
36
|
+
## C. SKILL 技能管理
|
|
37
|
+
| 功能 | 覆盖 | 结果 |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| list / bundles / loose 清单 | `test` skill 系列 + E2E `GET /api/skill-manager/list` | PASS |
|
|
40
|
+
| 全局 / 预设级开关 | `test/skill-toggles` + E2E `PUT /skill-toggles/presets/:id/skills/:name` | PASS |
|
|
41
|
+
| **工作区级开关(新)** | `test`(skill-toggles workspace)+ E2E `PUT /skill-toggles/workspaces/:cwd/skills/:name` + `GET /workspaces` | PASS |
|
|
42
|
+
| 技能健康检查 | E2E `GET /api/skill-health` | PASS |
|
|
43
|
+
| 技能包 CRUD / 安装 / 删除 | 单测(文件系统相关,E2E 未做破坏性文件操作) | 单测 PASS |
|
|
44
|
+
|
|
45
|
+
## D. MCP 管理
|
|
46
|
+
| 功能 | 覆盖 | 结果 |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| mcp-status(服务器/工具/遮蔽/工作区关闭/工具禁用镜像) | `test/mcp-*` + E2E `GET /api/triad/mcp-status` | PASS |
|
|
49
|
+
| 注册 Server 呈现(anysearch 4 工具、codegraph 1 工具) | 实机 UI 截图 + E2E | PASS |
|
|
50
|
+
| 预设级 遮蔽(mask) | `test` + E2E `PUT /mcp-masks/:preset/:server` | PASS |
|
|
51
|
+
| 预设级 工具级启停 | `test/mcp-tool-disable` + E2E | PASS |
|
|
52
|
+
| 工作区级 server 关闭 | `test/mcp-workspace-scope` + E2E `PUT .../workspace/:cwd/servers/:server` | PASS |
|
|
53
|
+
| **工作区级 工具级启停(新)** | `test/mcp-workspace-scope`(新增用例)+ E2E `PUT .../workspace/:cwd/tools` + `status` | PASS |
|
|
54
|
+
| mcp-config 启停 / 移除 | `test` + UI | PASS(单测/UI) |
|
|
55
|
+
| mcp-presets 添加/移除专属 Server | `test` + UI | PASS(单测/UI) |
|
|
56
|
+
| mcp-preview 粘贴校验 | `test` | PASS(单测) |
|
|
57
|
+
|
|
58
|
+
## E. 备份 / 恢复
|
|
59
|
+
| 功能 | 覆盖 | 结果 |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| 整库备份 `GET /backup`(docs + catalog) | `test/backup-route` + E2E | PASS |
|
|
62
|
+
| 整库恢复 `POST /restore` 且覆盖一致 | `test/backup-route` + E2E(恢复后 overrides 与备份一致) | PASS |
|
|
63
|
+
| 配置页「完整备份/恢复」卡片 | 实机 UI | PASS |
|
|
64
|
+
|
|
65
|
+
## F. 配置页
|
|
66
|
+
| 功能 | 覆盖 | 结果 |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| 环境变量黑名单(envBlocklist,`{{env:...}}`) | 实机 UI + 备份含该字段 | PASS |
|
|
69
|
+
| 强制覆盖 forceSections | E2E `config/set` + UI | PASS |
|
|
70
|
+
| 完整备份/恢复 | E2E + UI | PASS |
|
|
71
|
+
| 配置快照库(保存/应用/导入/导出/删除) | UI(保留,底层 presets/activePreset 不清理) | PASS |
|
|
72
|
+
| 恢复初始状态 | `test/reset-route` + UI | PASS |
|
|
73
|
+
| 自适应卡片网格排版 | 实机 UI | PASS |
|
|
74
|
+
|
|
75
|
+
## G. 存储 / 版本
|
|
76
|
+
| 功能 | 覆盖 | 结果 |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| 单文件 SQLite(WAL,node:sqlite) | `test/*`(DB 版) | PASS |
|
|
79
|
+
| 破坏式:旧 YAML/JSON 不读不迁移 | `test/include-migration` 等 | PASS |
|
|
80
|
+
| 版本 1.0.0 + 升级文档 | `docs/upgrades/1.0.0-sqlite-breaking.md` | PASS |
|
|
81
|
+
|
|
82
|
+
## 未纳入自动化(说明)
|
|
83
|
+
- 技能包安装/删除、MCP 添加专属 Server 会写真实文件系统(技能根、profile patch),E2E 不做破坏性文件操作,仅单测/手动覆盖。
|
|
84
|
+
- `codegraph` 依赖本机 `codegraph` 命令;某些启动环境 PATH 缺失时该 Server 显示「等待注册」,属环境问题,不影响插件逻辑。
|
|
85
|
+
|
|
86
|
+
## H. 行为级验证(真的生效,非只看接口 200)
|
|
87
|
+
脚本:`scripts/verify-effect.mjs`(对比宿主**真实装配**前后:`/preview` 的最终 `text`+`tools`、`/session` 活动会话真实视图;写入前备份、测后恢复)。
|
|
88
|
+
|
|
89
|
+
结果(web profile,活动会话 cwd=`D:\dsh-pulgn`):**13/13 通过**。
|
|
90
|
+
|
|
91
|
+
| 场景 | 观测 | 结果 |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| 预设级·隐藏段 | `/preview(active)` 最终 `sections` 去除该段;`text` 13522→13472 | PASS |
|
|
94
|
+
| 预设级·替换段文本 | 最终 `text` 含替换标记 `__E2E_MODIFIED_TEXT__` | PASS |
|
|
95
|
+
| 预设级·隐藏工具(MCP 工具级) | `/preview.tools`(=宿主交给模型的工具声明)不再含 `mcp__anysearch__batch_search` | PASS |
|
|
96
|
+
| 工作区级·隐藏段 | 活动会话 `/session` 最终 `sections` 27→26;`text` 15714→15664 | PASS |
|
|
97
|
+
| 工作区级·隐藏工具 | 活动会话 `/session.tools` 不再含该 MCP 工具 | PASS |
|
|
98
|
+
| 以上各项还原 | 隐藏/替换撤销后,段与工具均回到最终装配/会话视图 | PASS |
|
|
99
|
+
|
|
100
|
+
> 结论:在工作区隐藏/修改提示词、隐藏/启用工具,**确实改变了模型最终收到的系统提示词与工具声明**(隐藏即从最终装配移除;替换即进入最终文本;再次放回即恢复)。
|
|
101
|
+
|
|
102
|
+
## 2.1.0 当前验证(ADR-0005,全域系统提示词接管)
|
|
103
|
+
|
|
104
|
+
> 以下来自本机 `npm run check`(2026-11-09):全量单测 **164/164 通过**、构建产物重建、宿主 / 客户端 smoke 全绿。真宿主 E2E 由使用者自行校验;上节 A–H 的 2026-11-07 结果均为历史存档。
|
|
105
|
+
|
|
106
|
+
| 场景 | 覆盖 | 结果 |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| 会话级段进入 `/inventory` / `/preview`,同名不同源分列,`{kind:'agent'}` 身份稳定 | `test/universal-prompt-takeover.test.mjs` | PASS |
|
|
109
|
+
| 屏蔽会话级段后 `/preview.text` 与 `/session.sections` 都不含它,撤销恢复 | 同上 | PASS |
|
|
110
|
+
| 任意段名的 agent 段可枚举(非 `tool:*` 特判) | 同上 | PASS |
|
|
111
|
+
| 切到别的预设不串台;无活动 agent 退回纯预设不抛错 | 同上 | PASS |
|
|
112
|
+
| 工具目录不受 live 提示词视图影响(D6) | 同上 | PASS |
|
|
113
|
+
| 段按宿主规范 order 排序(含 agent 链 order) | `test/ordering.test.mjs` | PASS |
|
|
114
|
+
| 预览正文并入同预设活动 agent、工具目录仍纯预设 | `test/rc2-preview.test.mjs`、`test/source-model.test.mjs` | PASS |
|
|
115
|
+
| 无明确编辑目标时退回纯预设、不读累积池 | `test/runtime-catalog.test.mjs` | PASS |
|
|
116
|
+
| 反例 | 把 `liveBase.sections` 换回空数组、或让 `stableSourceOf` 返回带 session id 的原始 agent source,上述组合用例必须失败 | 已写入新测试文件头注释 |
|
|
117
|
+
|
|
118
|
+
## 2.1.1 当前验证(同名遮蔽探测)
|
|
119
|
+
|
|
120
|
+
> 来自本机 `npm run check`(2026-11-09):全量单测 **170/170 通过**、构建产物重建、宿主 / 客户端 smoke 全绿。真宿主 E2E 由使用者自行校验。
|
|
121
|
+
|
|
122
|
+
| 场景 | 覆盖 | 结果 |
|
|
123
|
+
|---|---|---|
|
|
124
|
+
| `definitions` 缺席 / agent `definitions` 缺该 name / `inPreset=false`(`schemas` 未挂原生)时同名遮蔽仍进池 | `test/tool-shadow-universal.test.mjs` ①②③ | PASS |
|
|
125
|
+
| 0.2.1 `restrict` 场景(agent 视图仍含插件工具)仍进池 | 同上 ④ | PASS |
|
|
126
|
+
| 任意工具名(`apply_patch` / `edit` / `plugin:custom`)都进池,非样例特判 | 同上 ⑤ | PASS |
|
|
127
|
+
| 遮蔽行 source 标继承层、`shadowedBy` 指向 agent 工具、`keySuffix='shadowed'` | 同上 ①③ + `test/tool-shadow.test.mjs` | PASS |
|
|
128
|
+
| 不误判 agent 新增 / 同一注册不拆行 / 跨预设不串台 / 无活动 agent 不抛错 / 工具目录状态不变 | 同上 ⑥ | PASS |
|
|
129
|
+
| 反例 | 判定换回单点 `presetDefs.get(name) !== liveDefs.get(name)` 时 ①②③ 必须失败;为 `read` 写死特判时 ⑤ 必须失败 | 已写入新测试文件头注释并实测 |
|
|
130
|
+
|
|
131
|
+
## 2.1.2 当前验证(工具目录与真实会话同源)
|
|
132
|
+
|
|
133
|
+
> 来自本机 `npm run check`(2026-11-09):全量单测 **175/175 通过**、构建产物重建、宿主 / 客户端 smoke 全绿。真宿主 E2E 由使用者自行校验。
|
|
134
|
+
|
|
135
|
+
| 场景 | 覆盖 | 结果 |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| 右栏可见工具目录 = agent scope 注册视图(含 `apply_patch` / `undo_last_edit`),计数与右栏同源 | `test/tool-catalog-scope.test.mjs` ① | PASS |
|
|
138
|
+
| 无 live agent 回落纯预设装配;右栏与 `/session` 同源 | 同上 ②③ | PASS |
|
|
139
|
+
| PTC 塌缩防护(`assemble().tools` 只剩 `run_code` 时仍用 `schemas(agent)`) | 同上 ④ | PASS |
|
|
140
|
+
| 纯新增 agent 工具不伪造 `masked-shadow`、`read` 仍是真同名遮蔽 | 同上 ⑤ | PASS |
|
|
141
|
+
| 只读池纳入 `locked-agent`(会话级徽标)、`stateBadge` 四态 | `test/tool-mask-pool.test.mjs` | PASS |
|
|
142
|
+
| 反例 | 主源换回 `toolSchemasOf(ctx, scopeKey, true)`(presetScopeKey)时 ①③④ 必须失败 | 实测 ①③④ 全红、②⑤ 仍绿 |
|