dsh-prompt-customizer 0.9.2 → 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.
Files changed (64) hide show
  1. package/README.en.md +49 -234
  2. package/README.md +45 -310
  3. package/build.mjs +27 -10
  4. package/client/client.js +2446 -1364
  5. package/client/client.js.map +4 -4
  6. package/docs/adr/0001-remove-catalog-pool.md +27 -0
  7. package/docs/adr/0002-hide-identity-name-source.md +23 -0
  8. package/docs/adr/0003-destructive-updates-allowed.md +18 -0
  9. package/docs/adr/0004-generalized-filter-model.md +17 -0
  10. package/docs/adr/0005-universal-prompt-takeover.md +109 -0
  11. package/docs/design/prompt-control-consensus.md +103 -0
  12. package/docs/guide.md +280 -0
  13. package/docs/images/prompt.png +0 -0
  14. package/docs/images/tool.png +0 -0
  15. package/docs/testing/feature-matrix.md +142 -0
  16. package/docs/upgrades/1.0.0-sqlite-breaking.md +26 -0
  17. package/docs/upgrades/1.4.0-generalized-model.md +23 -0
  18. package/docs/upgrades/1.4.1-web-preview-fixes.md +15 -0
  19. package/docs/upgrades/2.0.0-remove-workspace-level.md +16 -0
  20. package/docs/upgrades/2.0.1-context-fixes.md +6 -0
  21. package/docs/upgrades/2.0.10-import-and-skill.md +6 -0
  22. package/docs/upgrades/2.0.11-regression-fixes.md +7 -0
  23. package/docs/upgrades/2.0.12-generative-tool-tests.md +5 -0
  24. package/docs/upgrades/2.0.13-runtime-contract.md +8 -0
  25. package/docs/upgrades/2.0.14-tool-execution-guard.md +5 -0
  26. package/docs/upgrades/2.0.15-mask-pool-regression.md +5 -0
  27. package/docs/upgrades/2.0.16-regression-cleanup.md +6 -0
  28. package/docs/upgrades/2.0.17-unhide-source.md +5 -0
  29. package/docs/upgrades/2.0.18-unhide-cleanup.md +4 -0
  30. package/docs/upgrades/2.0.19-mcp-json-edit.md +4 -0
  31. package/docs/upgrades/2.0.2-generic-context-filter.md +6 -0
  32. package/docs/upgrades/2.0.20-preset-isolation.md +4 -0
  33. package/docs/upgrades/2.0.21-isolation-restore-test.md +4 -0
  34. package/docs/upgrades/2.0.22-source-immutability.md +3 -0
  35. package/docs/upgrades/2.0.3-skill-summary.md +6 -0
  36. package/docs/upgrades/2.0.4-tool-draft.md +5 -0
  37. package/docs/upgrades/2.0.5-tool-catalog-robustness.md +13 -0
  38. package/docs/upgrades/2.0.6-tool-restrict.md +6 -0
  39. package/docs/upgrades/2.0.7-tool-stability.md +5 -0
  40. package/docs/upgrades/2.0.8-catalog-row-stability.md +4 -0
  41. package/docs/upgrades/2.0.9-tool-and-write.md +8 -0
  42. package/docs/upgrades/2.1.0-universal-prompt-takeover.md +41 -0
  43. package/docs/upgrades/2.1.1-tool-shadow-detection.md +48 -0
  44. package/docs/upgrades/2.1.2-tool-catalog-scope.md +55 -0
  45. package/docs/upgrades/README.md +298 -0
  46. package/docs/upgrades/dsh-0.2.2-rc1.md +49 -0
  47. package/docs/upgrades/rc2-migration.md +70 -0
  48. package/lib/index.js +4697 -1701
  49. package/lib/index.js.map +4 -4
  50. package/package.json +7 -5
  51. package/scripts/e2e-report.json +221 -0
  52. package/scripts/e2e-terminal.mjs +210 -0
  53. package/scripts/simulate-rescan.mjs +184 -0
  54. package/scripts/smoke-host.mjs +1 -1
  55. package/scripts/verify-apply-all.mjs +64 -0
  56. package/scripts/verify-effect.mjs +153 -0
  57. package/scripts/verify-mcp-edit-ext.mjs +48 -0
  58. package/scripts/verify-mcp-edit.mjs +45 -0
  59. package/scripts/verify-panel-browser.mjs +298 -0
  60. package/scripts/verify-workspace-mcp.mjs +62 -0
  61. package/scripts/test-mcp-layering.mjs +0 -441
  62. package/scripts/test-mcp-tool-disable.mjs +0 -420
  63. package/scripts/test-rc2-runtime.mjs +0 -42
  64. package/scripts/test-skill-toggles.mjs +0 -100
@@ -0,0 +1,49 @@
1
+ # DSH 0.2.2-rc.1 适配记录(0.12.0)
2
+
3
+ 目标 tag `dsh-v0.2.2-rc.1`(`0.2.1-rc.2 → 0.2.2-rc.1`)。插件版本对应 `0.12.0`。
4
+
5
+ ## 结论:不兼容,已升级
6
+
7
+ 0.2.2-rc.1 把 `system-prompt/assemble` 的入参从 `PromptAssembly` 收窄为 `PromptPresentation`:**瀑布流不再携带 `tools`,监听器返回的 `tools` 也会被忽略**(官方升级指南 `v0.2.1-rc.2/conditional-tools`,另见 `v0.2.1-rc.2/tool-executor-plugins` 的执行器拆分)。
8
+
9
+ 本插件有三条工具目录过滤链路直接读取 `assembly.tools`,在 0.2.2-rc.1 上会**静默失效**:
10
+
11
+ | 功能 | 位置 | 旧行为 | 0.2.2-rc.1 现象 |
12
+ |---|---|---|---|
13
+ | 提示词定制的阶段化工具目录 | `vendor/prompt-customizer/index.js` | 在装配瀑布流里删除 `assembly.tools` | `assembly.tools` 为 `undefined`,过滤不生效 |
14
+ | MCP 工具级启停的装配兜底 | `src/mcp-tool-disable.ts` | 瀑布流过滤兜底 | 同左;全局工具仍由 `tools.restrict` 覆盖,预设自带工具失去兜底 |
15
+ | 工作区级 MCP 关闭 | `src/mcp-workspace-scope.ts` | 按会话 cwd 删除对应工具 | 同左,工作区关闭不生效 |
16
+
17
+ 其他已核对、无破坏的宿主面:
18
+
19
+ - `ctx.tools.schemas(scope?, toolSet?)` / `tools.restrict()` / `tools/change` 仍在;
20
+ - `ctx.skills.list()` 所在 `@deepseek-ai/dsh-skill` 源码零改动;
21
+ - `agentPresets` 的 `list` / `readDocument` / `composedPreset` / `acquireScope` 仍在,新增 `presetForSession(session)`;
22
+ - `sessionProjections.register()` 改为返回可 await 的 handle,`ProjectionHandle.stateOf(session)` 可用;注册表级 `stateOf(session, key)` 仍保留但已弃用;
23
+ - `ctx.webServer.register()` 新增 `WebResourceRoute` 重载,原有 `WebRoute` 不变;
24
+ - `ui-primitives` 中本插件使用的 13 个图标、`Button` / `Modal` / `Tooltip` / `Menu` 全部保留;
25
+ - `locale.register` / `bind`、`ui-slots`、`ui-input-trigger` 的公开签名不变;
26
+ - 侧边栏锚点 `[data-slot="sidebar.workspaces"]` 与 `[data-sidebar-collapsed]` 仍存在。
27
+
28
+ ## 改动
29
+
30
+ 1. **提示词阶段化工具目录改用 agent 作用域 `tools.restrict({ deny })`**:新增 `vendor/prompt-customizer/tool-visibility.js`,在 `agent/created` / `session/event`(`tool/call`、`assistant/message`、`compaction/end`、`turn/start`、`agent-preset/selected`)/ `tools/change` 时重算该 agent 当前阶段应隐藏的工具并更新 restrict。配置写入路由在落盘后立即重算。
31
+ 2. **预览与清单的工具目录改读注册表**:`buildPreview` / `collectScopeBase` / `promptCustomizerBaseView` 不再读取 `assembled.tools`,改用 `ctx.tools.schemas(scope)`(作用域优先,回退全局);`baseTools` 继续携带每阶段 `hidden` 标记。
32
+ 3. **工作区级 MCP 关闭补上 agent 作用域 restrict**:`src/mcp-workspace-scope.ts` 在 `agent/created` / `tools/change` / 账本写入后按会话 cwd 计算被关闭 Server 的 `mcp__<server>__*` 工具并安装 restrict;旧装配过滤保留为旧宿主兜底。
33
+ 4. **升级记录与版本元数据**:`package.json` 版本 `0.12.0`,`peerDependencies` 升到 `^0.2.2-rc.1`,新增 `engines.dsh` 与 Node `>=24.9`。
34
+
35
+ ## 验证
36
+
37
+ - `npm run build`:通过;宿主产物无 `@deepseek-ai/*` 裸导入(`assertHostExternals` 通过)。
38
+ - `npm test`:119/119 通过(新增 `test/tool-visibility.test.mjs` 覆盖阶段 restrict)。
39
+ - `npm run smoke`:宿主半身 21 条路由、客户端半身 loader / primitives 检查通过。
40
+ - **真实 0.2.2-rc.1 Web 冷启动**:用默认 `web` 模板新建隔离 profile,`dsh plugin add` 链接本插件 `0.12.0` 后启动。
41
+ - `/api/prompt-customizer/config`、`/inventory`、`/preview?scope=standard&phase=bootstrap|active|compaction` 全部 200;预览工具目录来自注册表(37 个),不再是空数组。
42
+ - 浏览器实际打开侧边栏「能力」面板:SKILL / MCP / 提示词三个 tab 正常渲染;提示词面板显示当前预设的段列表、模型视角预览与工具目录。
43
+ - 临时写入 `bootstrap.exclude: [read]` / `exclude: [write]` / `compaction.exclude: [grep]` 后,三个阶段的预览分别只剩对应项被隐藏(36/37),验证通过后恢复原配置。
44
+ - 静态 API 对照:按 `dsh-v0.2.1-rc.2 → dsh-v0.2.2-rc.1` 逐包 diff 核对上述宿主面。
45
+
46
+ ## 已知限制
47
+
48
+ - `tools.restrict` 只能收窄 agent 继承的**全局工具**;预设自带(作用域内注册)的工具无法通过 restrict 隐藏。提示词定制的工具目录与工作区 MCP 关闭对这类工具不生效(旧版装配过滤可以,但 0.2.2 已无该接缝)。
49
+ - `mcp-tool-disable` 的预设自带工具兜底同样受限;全局工具与继承 MCP 工具不受影响。
@@ -0,0 +1,70 @@
1
+ # DSH 0.2.1-rc.2 适配记录(0.9.3)
2
+
3
+ 目标 tag `dsh-v0.2.1-rc.2`(区间 `dsh-v0.2.0-rc.2` → `dsh-v0.2.1-rc.2`,1925 commits,merge-base 纯)。实际 CLI `0.2.1-rc.2`,Node `24.18.0`。保留用户原有改动,不修改 DSH 源码。
4
+
5
+ **结论:三个功能面(skills / MCP / 提示词)的服务契约在区间内零破坏**。本轮两处改动:用户数据根解析对齐内核新规则;修复「存为预设」调用了并不存在的宿主 API。
6
+
7
+ ## 修复:「存为预设」调用了不存在的 API
8
+
9
+ **现象**:保存预设时报 `宿主未提供 agent 预设服务(dsh-agent-presets),无法创建预设`。
10
+
11
+ **根因**:路由判 `typeof roster.copy === 'function'`,但宿主 `agentPresets` 只暴露 `list` / `read` / `select` 三个 RPC —— `copy` 与 `authorable` 在 0.1.6 到 0.2.1 的**所有 tag 里都不存在**(逐 tag `git show` 验证,零命中)。这条路径从写下起就是死的。
12
+
13
+ **顺带发现**:`test/presets-route.test.mjs` 用假 roster `{ copy: async () => {} }` 覆盖了这条路由,所以测试一直"通过"——测试跟着错误假设一起编,掩盖了真实缺口。
14
+
15
+ **改法**:DSH 里预设是声明式的,创建 = 往 profile patch 追加一条 `@deepseek-ai/dsh-agent-preset` 行(HMR 监听该文件后热加载)。新实现:
16
+
17
+ 1. `agentPresets.readDocument(from)` 取来源预设的组成原文
18
+ 2. 以 yaml 文档 API 解析成自己的文档(`!!js` 条件保持为标签节点,不先 `toJSON`)
19
+ 3. 克隆来源节点到新行的 `config.plugins`,追加一条 `insert`,原子写回 `profileContext.patchPath`
20
+ 4. 再把提交来的定制写进 `overrides[新名]`
21
+
22
+ 失败语义:id 不合法 400、同名 409、来源不存在 404(按 `error.code === 'agent-preset/not-found'`,符合宿主「按 code 判别不用 instanceof」的契约)、无 `readDocument` 501、无 `profileContext` 400。每种失败都不写盘。
23
+
24
+ **验证**:`test/presets-route.test.mjs` 重写为 9 条断言,覆盖写入内容、注释保留、`!!js` 标签保形、各失败码不写盘;另在真实 `~/.dsh/profiles/web/cordis.patch.yml` 上验证写入后注释全在、原有 2 个 `!!js` 全在、新行可被 Loader 解析。全量 149/149 通过。
25
+
26
+
27
+ ## 唯一代码改动(其二):用户数据根解析对齐
28
+
29
+ 内核 0.2.1-rc.2 把 env 解析收进 `@deepseek-ai/dsh-home-paths` 的 `resolveDshHome` / `resolveAgentsHome`,规则比插件原来的内联写法更严:
30
+
31
+ | 规则 | 旧内联写法 | 内核 rc.2 | 实际后果 |
32
+ |---|---|---|---|
33
+ | `DSH_AGENTS_HOME=''` / 纯空白 | 当作路径 → `resolve('')` = 进程 cwd | 按未设置 → `~/.agents` | 面板列 `cwd/skills`,开关写进无人读的目录 |
34
+ | `DSH_HOME='~/x'` | 不展开 → `cwd/~/x` | 展开 → `~/x` | 同上,整片面板读错根 |
35
+
36
+ 插件是 vendor 进宿主的运行时插件,不能 import 内核包,所以**照抄规则而不是复用实现**:新增 `src/home-paths.ts` 作为唯一真源,`src/skill-health.ts`、`src/skill-toggles.ts` 改为消费它;`vendor/skill-manager/skills-host.js` 内联同规则并导出 `__managedRoot`/`__dshRoot` 供等值断言。
37
+
38
+ 验证:`test/home-paths.test.mjs` 4 条断言,含 vendor 与 src 三组 env(空串 / `~` / 绝对路径)下的逐项等值比较。全量 `npm test` 148/148、`npm run smoke` 全过。
39
+
40
+ ## 三个功能面的核对结果
41
+
42
+ | 功能面 | 接触点 | 区间变化 | 结论 |
43
+ |---|---|---|---|
44
+ | skills | `ctx.skills.registerProvider/list/get/snapshot` | `packages/skill/skill/src` 零改动 | 预设级闸门 provider 语义不变 |
45
+ | skills | 技能开关 frontmatter 字段 | `disable-model-invocation` / `user-invocable` 解析段逐字节相同 | 全局层开关字段名与语义未变 |
46
+ | skills | `.preset-skills.json` 账本 | `discoverRoot` 只认目录与 `*.md` | 点号文件不会被当技能,也不触发告警/重扫 |
47
+ | skills | 客户端避让三键 | locale `skill` / `tool.call.toolview#skill` / `/` 触发源均未改名 | 避让策略仍正确;新增的 `conversation.user.text.node#skill` 由内核独占,插件不碰 |
48
+ | MCP | `tools.schemas/get/register`、`tools/change` | 字段与无参事件载荷未变 | 工具目录与装配过滤写法不变 |
49
+ | MCP | `configEditor.entries/edit`、`loader.entries` | config-editor `src/` 零改动 | 预设行读写与原子写不变 |
50
+ | MCP | `agentPresets.readDocument/list/composedPreset` | 仍在(内部改 `generationFor`) | 插件对被删的 `livePresetMounts`/`serviceForAgent`/`standingMountFor` 零引用 |
51
+ | MCP | `mcpResources.register` | `mcp-resources/src` 两侧同构 | 资源遮蔽桩不变 |
52
+ | 提示词 | `system-prompt/assemble` waterfall | 声明逐字节相同 | 装配包装与段策略不变 |
53
+ | 提示词 | `section` / `context` / `getSectionOrder` / `variable` / `layers.merge` | 全在;`merge` 实现两侧相同 | forceSections 探测与变量注册不变 |
54
+ | 提示词 | 段重建是否丢新字段 | `applySectionPolicy` 用 `{...section}` 展开 | `interpolate` / `required` / `complete` 均保留,无回归 |
55
+ | 通道 | `connection.requestRejection` | 签名与 `ConnectionTrustRequest` 一致 | fail-closed 信任闸写法不变 |
56
+
57
+ ## 需要知道但不属于插件责任的变化
58
+
59
+ 1. **`tools.mode: both` 被移除**(`ToolPresentationMode` = `'native' | 'ptc'`)。profile/preset 里仍写 `both` 会在启动校验抛错。插件不产出该值。
60
+ 2. **`webServer` 的 `host` 不再接受 `0.0.0.0`**,必须是具体本机 IP 字面量,wildcard 直接抛错。用户 profile 若仍写该项,web 层启动失败——与插件无关但会一起不可用。
61
+ 3. **`includeRuntimeContext=false` 时预览 contexts 会变多**:rc.2 保留 `required: true` 的上下文(如 `working-directory:current`),旧版整表清空。这是宿主的正确行为,插件只如示。
62
+ 4. **`harness:source` / `app:web-surface` 改为 `interpolate: false`**:用户替换这两段文本后 `{{var}}` 不再插值。
63
+ 5. **`skill` 工具的 cwd 改走 `workingDirectory.ensure()`**(rc.2 新增服务):会话目录被删时 cwd 会被重新校验,技能的项目根可能随之改变。
64
+ 6. **base bundle 撤掉 `skill-badge` 行**(改由 `badge-skill-bundle` 独立声明):按该行 id 覆盖它的配置升级后失效。插件零引用。
65
+
66
+ ## 未覆盖 / 验证缺口
67
+
68
+ - **真实 rc.2 冷启动链路的 turn 段未验证**:该链路原由 `scripts/test-rc2-runtime.mjs` 覆盖,它在 0.2.1-rc.2 上跑到第 77 行断言(`model.requests.length === 2`)实得 0。已用对照实验排除插件因素——同一组合**带插件与不带插件都得到 0**,且最小探针(无 mount / 带 mount / 带 85 工具)单独跑均得 2。会话事件显示 `turn/start → step/start → step/end → turn/end` 走完但未发模型请求,属 fixture 在新版下的行为漂移,非插件回归。该脚本内还硬编码 `version !== '0.2.0-rc.2'` 即抛错,需单独一轮修 fixture 才能跑通。**0.11.6 起该脚本已随测试精简移除**,rc.2 适配行为改由 `test/rc2-preview.test.mjs` 覆盖。
69
+ - 预览段(零对话双模式、工具数、段顺序、模板变量)在真实 0.2.1-rc.2 上**全部通过**。
70
+ - 真实外部模型、多平台、用户当前 GUI 的视觉验证未覆盖。