dsh-deeppilot 0.9.11 → 0.9.13

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/COMPATIBILITY.md CHANGED
@@ -1,17 +1,18 @@
1
1
  # Compatibility
2
2
 
3
- This branch targets exactly **six DSH releases**: `0.2.0-rc.2`; the `alpha`
4
- channel releases `0.2.1-alpha.3`, `0.2.1-alpha.4`, and `0.2.1-alpha.5`; and the
5
- `next` channel releases `0.2.1-rc.2` and `0.2.1-rc.3`. The npm channels have
6
- moved since: `latest` now points at `0.2.1-rc.2`, promoted from `next`, and
7
- `next` at `0.2.1-rc.3`. All six are
3
+ This branch targets exactly **eight DSH releases**: `0.2.0-rc.2`; the `alpha`
4
+ channel releases `0.2.1-alpha.3`, `0.2.1-alpha.4`, `0.2.1-alpha.5`, and
5
+ `0.2.2-alpha.2`; and the `next` channel releases `0.2.1-rc.2`, `0.2.1-rc.3`, and
6
+ `0.2.1-rc.4`. The npm channels have
7
+ moved since: `latest` now points at `0.2.1-rc.2`, promoted from `next`, `next`
8
+ at `0.2.1-rc.4`, and `alpha` at `0.2.2-alpha.2`. All eight are
8
9
  named in both `engines.dsh` and `peerDependencies`; no other version is accepted.
9
10
  DSH evaluates that declaration before composing a profile — on every start, not
10
11
  only on install — so a newly published DSH release deactivates this plugin until
11
12
  the list is widened deliberately. That is the intended trade: a plugin that
12
13
  cannot run on an unaudited host fails visibly instead of misbehaving quietly.
13
14
  The decision and the reversal it represents are recorded in
14
- [`docs/决策记录.md`](./docs/决策记录.md) (章节一), with the supporting audit in
15
+ the maintainers' local decision record `docs/adr/0001-dsh-compatibility-policy.md`, with the supporting audit in
15
16
  [`docs/DSH_RELEASE_MEMORY.md`](./docs/DSH_RELEASE_MEMORY.md).
16
17
 
17
18
  The development packages this branch builds and typechecks against stay pinned
@@ -22,7 +23,8 @@ recorded in the release memory.
22
23
  | Component | Current contract | Evidence |
23
24
  |---|---|---|
24
25
  | Node.js | 22 or newer | Package engine and CI |
25
- | DSH CLI and Host API | `engines.dsh` and `peerDependencies` both name `0.2.0-rc.2 \|\| 0.2.1-alpha.3 \|\| 0.2.1-alpha.4 \|\| 0.2.1-alpha.5 \|\| 0.2.1-rc.2 \|\| 0.2.1-rc.3` (dev pins `0.2.0-rc.2`) | Peer metadata, source typecheck, unit tests, bundle build, and config schema projection against a real 0.2.0-rc.2 CLI, plus isolated composes and live phone-protocol runs with the published 0.2.1-alpha.2, 0.2.1-alpha.3, and 0.2.1-alpha.4 CLIs, an isolated 0.2.1-alpha.5 host where this plugin now composes, starts, and answers `/phone/health` with 200 on its own LAN listener, a pre-widening 0.2.1-rc.2 host run where the unchanged declaration is refused at compose time, and an isolated 0.2.1-rc.3 host where the widened declaration composes, starts, and answers `/phone/health` with 200 (audits below) |
26
+ | DSH CLI and Host API | `engines.dsh` and `peerDependencies` both name `0.2.0-rc.2 \|\| 0.2.1-alpha.3 \|\| 0.2.1-alpha.4 \|\| 0.2.1-alpha.5 \|\| 0.2.1-rc.2 \|\| 0.2.1-rc.3 \|\| 0.2.1-rc.4 \|\| 0.2.2-alpha.2` (dev pins `0.2.0-rc.2`) | Peer metadata, source typecheck, unit tests, bundle build, and config schema projection against a real 0.2.0-rc.2 CLI, plus isolated composes and live phone-protocol runs with the published 0.2.1-alpha.2, 0.2.1-alpha.3, and 0.2.1-alpha.4 CLIs, an isolated 0.2.1-alpha.5 host where this plugin now composes, starts, and answers `/phone/health` with 200 on its own LAN listener, a pre-widening 0.2.1-rc.2 host run where the unchanged declaration is refused at compose time, an isolated 0.2.1-rc.3 host where the widened declaration composes, starts, and answers `/phone/health` with 200, and isolated 0.2.1-rc.4 and 0.2.2-alpha.2 hosts where the eight-release declaration does the same (audits below) |
27
+ | DSH history read | `SessionController.inspect` when the host has it, `SessionController.page` otherwise | DSH 0.2.2-alpha.2 removed `inspect`; the adapter branches on its presence and maps the host page's `{type:'event',event}` records onto the bridge's `{event}` contract, expressing the phone's exclusive `beforeSeq` as the inclusive `throughSeq` cut. Unit tests cover both branches (audits below) |
26
28
  | iOS bridge | DeepPilot protocol v2 | Bridge protocol tests; device behavior must be checked with the running Host and app |
27
29
  | Remote access | Tailscale Funnel on ports 443, 8443, or 10000 | Helper and supervisor tests |
28
30
  | Funnel helper platforms | macOS 13 Ventura or later, Linux, and Windows, each on amd64/arm64; built with Go 1.27, which dropped macOS 12 | CI starts the committed helper on a native runner for each of the six targets (`helper-smoke`); no runner covers macOS 13 itself |
@@ -75,6 +77,65 @@ carries the old top-level `debug: true` is accepted but that value is ignored:
75
77
  verbose logging must be turned on again from the settings page. No other config
76
78
  field changed shape, and the old key is not read anywhere in this version.
77
79
 
80
+ ## 0.2.2-alpha.2 audit outcome
81
+
82
+ The artifact-level audit of `dsh-v0.2.2-alpha.2` (published to the npm registry
83
+ 2026-10-28T02:50:54Z, the `alpha` channel release; `latest` is still
84
+ `0.2.1-rc.2` and `next` moved to `0.2.1-rc.4`) against `dsh-v0.2.1-rc.3` found
85
+ **one break, confined to the history read**. The tree grows 307 → 332 packages.
86
+
87
+ - **The break.** `@deepseek-ai/dsh-api-session-controller` removed
88
+ `SessionController.inspect(sessionId, signal?)` — absent from both
89
+ `lib/types/index.d.ts` and the runtime `lib/index.js`. `sessions.history`
90
+ called it to read a whole log, so on this host the phone's history pagination
91
+ threw `TypeError`, while pairing, listing, prompting, the settings page, and
92
+ the plugin page kept working. The phone protocol itself is unchanged: the
93
+ `HistoryResult` shape is identical, only the host-side source moved.
94
+ - **The fix, one file.** `src/dsh-api-proxy.ts` now treats `inspect` as optional
95
+ and falls back to `SessionController.page`. The branch keys off `inspect`, not
96
+ off `page`: `page` exists on all eight admitted hosts, but its
97
+ `SessionPageRequest.throughSeq` is mandatory and validated on the seven older
98
+ ones, and this adapter has no log cursor to pass. On the `page` path the
99
+ phone's exclusive `beforeSeq` travels as the inclusive `throughSeq`, and the
100
+ host's `{type:'event',event}` records are unwrapped to the bridge's `{event}`.
101
+ - **Nothing else reaches this plugin.** 24 packages and 358 modules were
102
+ compared; 20 modules changed export surfaces, but only two at entry level
103
+ (`dsh-api-session-controller` dropping `buildModelCatalog`, `dsh-app-boot`
104
+ dropping five bundle-list constants and adding three platform helpers), and a
105
+ repo-wide grep shows the plugin uses none of them. The three packages the
106
+ plugin actually imports (`cordis`, `dsh-typert-protocol`, `schemastery`) have
107
+ unchanged export surfaces.
108
+ - **Patch anchor still valid.** The upstream `dsh-web-app/cordis.patch.yml`
109
+ gained and lost three ids, and the block this plugin disables
110
+ (`directory-picker`) moved from line 113 to 105 and byte 4664 to 4309, but the
111
+ block itself is byte-identical and the shared id order is unchanged; both
112
+ hosts' `loadOverlayPatches` resolve this plugin's patch to the same fields.
113
+ - **Vendor peers.** This host vendors `cordis 4.0.6-alpha.1` and
114
+ `schemastery 3.18.6-alpha.1`, which the previous ranges did not admit under
115
+ npm's default prerelease rule. The ranges now append `~4.0.6-alpha.1` and
116
+ `~3.18.6-alpha.1` rather than replacing the GA clauses, because every earlier
117
+ admitted host still vendors `4.0.5` / `3.18.5`. DSH's compatibility evaluator
118
+ ignores both peers; only npm's install-time resolution reads them.
119
+ - **Activation.** Before the widening this host refused the plugin with a single
120
+ `engines.dsh` requirement and skipped the whole bundle; after it the matrix
121
+ accepts exactly `0.2.2-alpha.2` with no new rejection, while `0.2.2-alpha.1`,
122
+ `0.2.2-alpha.3`, `0.2.2`, `0.2.2-rc.1`, `0.2.1`, and `0.3.0` stay refused.
123
+ - **One install-side prerequisite.** This host's `dsh` package raised
124
+ `engines.node` to `>= 24.9.0`; the plugin's own `engines.node` stays `>=22`.
125
+
126
+ ## 0.2.1-rc.4 audit outcome
127
+
128
+ The artifact-level audit of `dsh-v0.2.1-rc.4` (published 2026-10-28T02:49:58Z,
129
+ the `next` channel release) against `dsh-v0.2.1-rc.3` found **no change that
130
+ reaches this plugin**: 307 packages on both sides, 42,415 of 42,731 shared files
131
+ byte-identical, and 316 differing paths made of 296 `package.json` files plus 20
132
+ files in eight packages (MCP capability gating, one log call moved to stderr, one
133
+ View tooltip, four version strings, and documentation) — none of them in this
134
+ plugin's declaration or call surface. Export surfaces are unchanged across 3,271
135
+ modules, the evaluator is the same file as rc.3, and the patch anchor file is
136
+ byte-identical. The declaration admits exactly `0.2.1-rc.4` more and nothing
137
+ else.
138
+
78
139
  ## 0.2.1-rc.3 audit outcome
79
140
 
80
141
  The artifact-level audit of `dsh-v0.2.1-rc.3` (published to the npm registry
@@ -342,7 +403,7 @@ needs a documentation update, not a peer-range widening.
342
403
 
343
404
  > **Superseded 2026-10-14.** That open-ended range was narrowed back to the two
344
405
  > versions actually audited, `0.2.0-rc.2` and `0.2.1-alpha.3`; see the
345
- > 0.2.1-alpha.3 outcome above and `docs/决策记录.md` (章节一). The paragraphs in
406
+ > 0.2.1-alpha.3 outcome above and `docs/adr/0001-dsh-compatibility-policy.md`. The paragraphs in
346
407
  > this historical entry describe the policy as it stood on 2026-09-29.
347
408
  > **This note is in turn superseded:** `0.2.1-alpha.4` was added the next day by
348
409
  > the same deliberate audit step, `0.2.1-alpha.5` on 2026-10-16, and
package/README.md CHANGED
@@ -19,6 +19,13 @@ Host on your own computer and does not replace or modify the DSH Web UI.
19
19
  ## What you get
20
20
 
21
21
  - Browse projects, sessions, history, and live agent output from iPhone.
22
+ - Stream assistant text and reasoning while viewing a session; reconnects recover
23
+ the durable history rather than treating partial output as a completed answer.
24
+ - Export a full ZIP log archive, or share the conversation body as Markdown when
25
+ the Host provides that optional route.
26
+ - Check plugin updates from the app and install an explicitly confirmed compatible
27
+ version. The Host handles hot replacement and rollback; without hot reload the
28
+ app reports that a DSH restart is required.
22
29
  - Send prompts, switch models, create sessions, and answer approvals/questions.
23
30
  - Pair with a five-minute single-use code and a per-device P-256 key; physical
24
31
  iPhones keep the private key in Secure Enclave.
@@ -32,17 +39,18 @@ Host on your own computer and does not replace or modify the DSH Web UI.
32
39
 
33
40
  ## Install from npm
34
41
 
35
- This source checkout targets Node.js 22+ and the six DSH releases it has been
42
+ This source checkout targets Node.js 22+ and the eight DSH releases it has been
36
43
  audited against — `0.2.0-rc.2`, the `alpha` channel releases `0.2.1-alpha.3`,
37
- `0.2.1-alpha.4`, and `0.2.1-alpha.5`, and the two `next` channel releases it has
38
- admitted in turn, `0.2.1-rc.2` and `0.2.1-rc.3` — with a `web` profile. (The
39
- npm channels move: `latest` now points at `0.2.1-rc.2`, which was promoted
40
- from `next`, and `next` at `0.2.1-rc.3`.) DSH checks a plugin's declared
44
+ `0.2.1-alpha.4`, `0.2.1-alpha.5`, and `0.2.2-alpha.2`, and the `next` channel
45
+ releases it has admitted in turn, `0.2.1-rc.2`, `0.2.1-rc.3`, and `0.2.1-rc.4` —
46
+ with a `web` profile. (The npm channels move: `latest` now points at
47
+ `0.2.1-rc.2`, which was promoted from `next`, `next` at `0.2.1-rc.4`, and
48
+ `alpha` at `0.2.2-alpha.2`.) DSH checks a plugin's declared
41
49
  requirements before composing a profile, on every start rather than only on
42
50
  install, so any other host version refuses to activate this plugin. From DSH
43
51
  `0.2.1-alpha.4` on, that check reads `engines.dsh` and ignores
44
52
  `peerDependencies`; older hosts know only the peer range, so both name the same
45
- six releases. The package includes Funnel helpers
53
+ eight releases. The package includes Funnel helpers
46
54
  for macOS, Linux, and Windows on amd64/arm64; trusted-LAN mode does not require
47
55
  the helper. The helper is built with Go 1.27, which requires **macOS 13 Ventura
48
56
  or later**: on macOS 12 and earlier, Funnel mode cannot start, while
package/README.zh-CN.md CHANGED
@@ -18,6 +18,10 @@
18
18
  ## 功能
19
19
 
20
20
  - 在 iPhone 查看项目、会话、历史记录和 Agent 实时输出;
21
+ - 打开会话时实时显示助手正文与思考,断线后以正式历史恢复,不把半截输出当成完整答复;
22
+ - 导出完整 ZIP 日志归档;宿主提供相应能力时,也可分享 Markdown 对话正文;
23
+ - 在 App 检查插件更新,明确确认后安装兼容版本。宿主负责热替换和失败回滚;
24
+ 未启用热重载时,App 明确提示需要重启 DSH;
21
25
  - 发送提示词、切换模型、创建会话,并处理审批与提问;
22
26
  - 使用 5 分钟有效的单次配对码与设备级 P-256 密钥;iPhone 真机私钥保存在
23
27
  Secure Enclave;
@@ -30,15 +34,15 @@
30
34
 
31
35
  ## 从 npm 安装
32
36
 
33
- 当前源码面向 Node.js 22+ 与带 `web` profile 的**六个已审计 DSH 版本**:
37
+ 当前源码面向 Node.js 22+ 与带 `web` profile 的**八个已审计 DSH 版本**:
34
38
  `0.2.0-rc.2`、`alpha` 通道的 `0.2.1-alpha.3`、
35
- `0.2.1-alpha.4` 与 `0.2.1-alpha.5`,以及先后两版 `next` 通道的
36
- `0.2.1-rc.2` 与 `0.2.1-rc.3`(npm 通道会移动:`latest` 现指向由 `next` 转正的
37
- `0.2.1-rc.2`,`next` 指向 `0.2.1-rc.3`)。
39
+ `0.2.1-alpha.4`、`0.2.1-alpha.5` 与 `0.2.2-alpha.2`,以及先后三版 `next` 通道的
40
+ `0.2.1-rc.2`、`0.2.1-rc.3` 与 `0.2.1-rc.4`(npm 通道会移动:`latest` 现指向由 `next` 转正的
41
+ `0.2.1-rc.2`,`next` 指向 `0.2.1-rc.4`,`alpha` 指向 `0.2.2-alpha.2`)。
38
42
  DSH 在组合 profile 前会校验插件声明的
39
43
  兼容要求,且**每次启动都会校验**(不只是安装时),因此其他宿主版本会拒绝
40
44
  激活本插件。从 DSH `0.2.1-alpha.4` 起,该校验只读 `engines.dsh` 并忽略
41
- `peerDependencies`;更早的宿主只认 peer 范围,因此两处列出同一组六个版本。
45
+ `peerDependencies`;更早的宿主只认 peer 范围,因此两处列出同一组八个版本。
42
46
  npm 包内置 macOS、Linux、Windows 的 amd64/arm64 Funnel helper;可信局域网
43
47
  模式不依赖 helper。helper 用 Go 1.27 编译,要求 **macOS 13 Ventura 或更高版本**:
44
48
  macOS 12 及更早版本无法启动 Funnel 模式,可信局域网模式不受影响。
package/bin/SHA256SUMS CHANGED
@@ -1,6 +1,6 @@
1
- 0e49860ffd7b6fd9ba5918481cbfa2fc0a788f0c16d500de69a162d31451d526 ./darwin-amd64/dsh-deeppilot-tunnel
2
- 16e0b6235cb097401dc52840f11c0dcf405925d23449934cdfea93ec89c071e9 ./darwin-arm64/dsh-deeppilot-tunnel
3
- ed3d60db2da2f3c17a5f7d04834faf4623a955ecc48a3aa0497c3903df8a2bce ./linux-amd64/dsh-deeppilot-tunnel
4
- b5e85cd9f9f928f4204cfc15067588d1c3dcdc683a5f5b85759d5454bce2110e ./linux-arm64/dsh-deeppilot-tunnel
5
- 836126376d0da12abc6bafb3ed163138436f812b201bd254eb1c7cae3f8a34c7 ./windows-amd64/dsh-deeppilot-tunnel.exe
6
- 6b74d0f4b73f9f53b01829a84abd178c17a64950c1e9949b8fae15ef274fb99f ./windows-arm64/dsh-deeppilot-tunnel.exe
1
+ cc7f9ae55c7a8b717a45cd83fd671e2c9b6993f91c09f33c44fd28ea459eeba0 ./darwin-amd64/dsh-deeppilot-tunnel
2
+ 37f7430994f6ad79a2a93573f79ea2a1b1a6108fac054117548d8268dca422db ./darwin-arm64/dsh-deeppilot-tunnel
3
+ 051ff06069db0f4ede5570a693811f380cf0740065df3969113b0b5d9ded3c0f ./linux-amd64/dsh-deeppilot-tunnel
4
+ f704a48365d952185e6b6c28d655db0e174cbf1b9557e3fe40493ca1f7c614fe ./linux-arm64/dsh-deeppilot-tunnel
5
+ ac2470db2843958af431de284212018ff8f2f9aa147a08359aada21e3a5a09b1 ./windows-amd64/dsh-deeppilot-tunnel.exe
6
+ 541da90383098daecda68f910058d8071439d07f2edd7726f0af6fdb3c778b7d ./windows-arm64/dsh-deeppilot-tunnel.exe
@@ -0,0 +1,43 @@
1
+ # DSH 0.2.2 能力接入
2
+
3
+ 本轮在既有协议 v2 上增加三个可选能力。正式 wire 契约以 [PROTOCOL.md](../PROTOCOL.md) 为准;[TypeScript 镜像](../src/protocol.ts) 与私有 App 的 Swift 镜像同步。能力缺失时保留原有行为,不要求重新配对。DSH 版本兼容性审计另见 [发布记忆](./DSH_RELEASE_MEMORY.md)。
4
+
5
+ ## 实际接口与阅读范围
6
+
7
+ 已扫描此次发布的能力清单,精读下列实际调用面。其余新 Web 插件、推荐、共享与工作树模块未接入,也不作为本次兼容性声明依据。
8
+
9
+ | 上游接口 | 方法或来源 | 本次阅读 | 桥接用途 |
10
+ |---|---|---|---|
11
+ | `/api/session.markdown` | GET,经 `connection.createSharedFetchHandler('/api')` 的 owner 调用 | 已读路由注册、处理器和依赖 | 复用现有导出分块,返回正文 `.md` |
12
+ | `/api/session.export` | GET,`includeDescendants=true` | 已读 | 缺省 ZIP 原 URL、分块及回执保持不变 |
13
+ | `connection.fetchRoutes` / `sessionQuery.readSession` | 已注册路由及非激活读取 | 已读 | 真正有 Markdown 路由和读取依赖时才声明能力 |
14
+ | `agent/assistant-stream` | `{agent,frame}`;start / chunk / end | 已读类型与实际发射次序 | 生成独立、无重放序号的 `s2c.session.delta` |
15
+ | `session/event` | 持久事件先于 committed stream end | 已读 | final 前发出窗口尾部,以 `streamId` 替换临时输出 |
16
+ | `typert.getPackage` | 公开 host face 类型反射 | 已读 | 识别 `SessionAssistantStreamFrame`;缺反射只降级流能力 |
17
+ | `pluginManager.listVersions` / `registries` | 公开版本目录及软件源配置 | 已读 | 显示候选版本,读取精确协议声明,确定实际候选源 |
18
+ | `pluginManager.updateBundle` / `listBundles` | 精确版本更新、实际安装清单 | 已读 | 由宿主完成 HMR 替换和失败回滚,再核对安装与运行版本 |
19
+ | `plugin-manager/registry.registryPlan` | 公开软件源选择规则 | 已读并建立对照测试 | 预检宿主可能回退到的全部来源,禁止不同协议或完整性摘要绕过闸门 |
20
+ | npm 精确版本 manifest | GET `{registry}/dsh-deeppilot/{version}` | 已读并限制响应大小及超时 | 核对包名、精确版本、bundle、`deepPilot.protocolVersion` 与强 SRI |
21
+ | 其他新模块 | 新增包及发布清单 | 仅盘点 | 未接入,不引入额外产品行为 |
22
+
23
+ ## 差异对照
24
+
25
+ | 类别 | 本轮范围内的状态 |
26
+ |---|---|
27
+ | 双方都有 | ZIP/Markdown 导出、瞬时流生命周期与正式事件关联、明确确认的更新及状态查询、兼容性闸门、宿主 HMR/回滚、断线后日志对账 |
28
+ | 上游有、我方未接 | 自动化任务批量清理、Web 引用交互、插件富文本详情及其他 Web 专属入口;本轮未扩展手机对应功能 |
29
+ | 我方有、上游没有 | 手机专用分块传输、独立瞬时 wire 帧、设备隔离的持久更新日志、App 协议版本闸门 |
30
+ | 双方都没有 | 不支持的宿主上强制重启进程、手机静默安装、替用户发布 npm/GitHub 版本 |
31
+
32
+ ## 关键默认值与边界
33
+
34
+ - 导出缺省仍是 ZIP。Markdown 需要 `sessionMarkdown`,不会把旧桥接忽略 `format` 后返回的 ZIP 当作正文。Markdown 不含思考过程、系统指令及注入上下文。
35
+ - 流能力使用 `assistantStream`。50 ms 窗口只合并相邻同类文字,正文与推理保持到达顺序;容量满时提前发出。瞬时帧不占重放序号、不进入 APNs 或持久缓存;断线、弃置尝试及取消均丢弃未完成临时输出。
36
+ - 自更新使用 `pluginUpdate`;check 需要 `sessions.read`,apply 需要 `sessions.manage`,widget 均不可使用。查询不会安装,安装只由手机确认触发,不随断线取消或自动重试。
37
+ - 候选来源使用宿主真正的回退规则。所有可达源的精确目标必须具有相同协议和强完整性摘要;不可核验或不一致时拒绝受理。不会修改用户全局软件源配置。
38
+ - 更新接受回执在目标校验和日志耐久写入后发送。最近结果保留供重连对账;同请求编号不能更换目标,也不能重复安装。日志不保存凭据或会话内容,设备归属仅保存摘要并只向所属设备返回。
39
+ - “恢复”指 HMR 后重连并恢复当前会话。宿主无 HMR 时返回 `restart-required`;不会强杀宿主,不能声称已经自动重启。安装失败由宿主恢复旧版本,桥接只核验并呈现结果。
40
+
41
+ ## 验证入口
42
+
43
+ 插件用例:`tests/markdown-export.test.ts`、`tests/assistant-stream.test.ts`、`tests/plugin-update.test.ts`,以及 wire 注册表、历史适配和命令回归。iOS 测试及实机边界见私有项目的对接说明。真机、实际 npm 安装和 Funnel 验证不得由模拟或语法检查替代。
@@ -3,7 +3,143 @@
3
3
  > This is the durable audit record for DeepPilot's public DSH plugin. Re-audit
4
4
  > the next DSH release instead of assuming that an rc upgrade is runtime-safe.
5
5
 
6
- ## Current decision — `dsh-v0.2.1-rc.3`
6
+ ## Current decision — `dsh-v0.2.2-alpha.2`
7
+
8
+ - **Audited release:** `dsh-v0.2.2-alpha.2`, published to the npm registry
9
+ 2026-10-28T02:50:54Z (GitHub Release 2026-10-28T02:50:54Z), and the **`alpha`**
10
+ channel release — `alpha` moved from `0.2.1-alpha.5` to it. It is **not**
11
+ `latest` (still `0.2.1-rc.2`) and not `next` (`0.2.1-rc.4`, audited below in the
12
+ same pass). This is the first `0.2.2` line release to enter the supported list,
13
+ and the first one to carry a real runtime break since `0.2.1-alpha.3`.
14
+ - **Comparison baseline:** `dsh-v0.2.1-rc.3` (the previous audited tag).
15
+ - **Plugin runtime verdict: one break, confined to the history read; fixed in
16
+ `src/dsh-api-proxy.ts`.** The tree grows 307 → 332 packages (26 added, 1
17
+ dropped). `@deepseek-ai/dsh-api-session-controller` removed
18
+ `SessionController.inspect(sessionId, signal?)` — absent from
19
+ `lib/types/index.d.ts` and from the runtime `lib/index.js` (the rc.3
20
+ `inspectApiSession` helper and the class method are both gone). This plugin's
21
+ `sessions.history` read a whole log through it, so on this host the phone's
22
+ history pagination threw `TypeError`; pairing, listing, prompting, the settings
23
+ page, and the plugin page all kept working, and the phone protocol itself is
24
+ unchanged because `HistoryResult` has the same shape.
25
+ - **The fix branches on `inspect`, not on `page`.** `page(request, signal)` exists
26
+ on all eight admitted hosts with an identical signature and a stable
27
+ `{records, hasMore}` result, but `SessionPageRequest.throughSeq` is **mandatory
28
+ and validated** on the seven older ones and this adapter has no log cursor to
29
+ pass, so a unified `page` path would have broken every host below
30
+ `0.2.2-alpha.2`. The adapter keeps `inspect` when present, and otherwise reads
31
+ `page` with the phone's exclusive `beforeSeq` expressed as the inclusive
32
+ `throughSeq` (`beforeSeq - 1`; `-1` is the host's empty page) and unwraps the
33
+ host's `{type:'event',event}` records to the bridge's `{event}` contract.
34
+ `host-bridge.ts` already re-checks the seq boundary, so the inclusive cut
35
+ cannot make a client loop on one page.
36
+ - **No other export change reaches the plugin.** 24 packages / 358 modules were
37
+ compared; 20 modules changed export surfaces but only two at entry level
38
+ (`dsh-api-session-controller` dropping `buildModelCatalog`; `dsh-app-boot`
39
+ dropping `DEFAULT_PROFILE_BUNDLES`, `OFFICIAL_ON_DEMAND_CATALOG`,
40
+ `ON_DEMAND_BUNDLES`, `OPTIONAL_BUNDLES`, `PROFILE_TEMPLATES` and adding three
41
+ platform helpers). A repo-wide grep shows the plugin uses none of them; the
42
+ three packages it actually imports (`cordis`, `dsh-typert-protocol`,
43
+ `schemastery`) have unchanged export surfaces. Two earlier script findings —
44
+ `connection` missing `createPeer` / `createSharedFetchHandler` and `typert`
45
+ missing `register` — were false positives from reading `rpc-host.d.ts` instead
46
+ of `rpc.d.ts`, and from comparing against a symbol neither version has; both are
47
+ recorded as corrections in `.alpha2-verify/AUDIT.md`.
48
+ - **Patch anchor still valid.** The upstream `dsh-web-app/cordis.patch.yml`
49
+ changed 3 ids in and 3 out; the block this plugin disables
50
+ (`directory-picker`) moved from line 113 to 105 and byte 4664 to 4309, but the
51
+ block bytes and sha256 are identical, the shared id order is unchanged, and both
52
+ hosts' `loadOverlayPatches` resolve this plugin's patch to the same fields.
53
+ - **Vendor peers: appended, not substituted.** This host vendors
54
+ `cordis 4.0.6-alpha.1` and `schemastery 3.18.6-alpha.1`, which the previous
55
+ ranges did not admit under npm's default prerelease rule (they did under
56
+ `includePrerelease`). The ranges now append `~4.0.6-alpha.1` / `~3.18.6-alpha.1`
57
+ after the GA clauses, because every earlier admitted host still vendors
58
+ `4.0.5` / `3.18.5`; replacing instead of appending would have been a
59
+ narrowing. DSH's evaluator ignores both peers (a manifest carrying only these
60
+ two passes), so this is an install-time and documentation concern. The
61
+ `cordis 4.0.5 → 4.0.6-alpha.1` diff is a pure refactor (`_resolveConfig` →
62
+ public `resolveConfig`, new `rawConfig`/`effectiveConfig`, `this.` →
63
+ `this.ctx.fiber.`) with an unchanged 26-symbol export surface;
64
+ `schemastery` changed only `package.json`.
65
+ - **Activation verdict: the new release is admitted by both declarations.**
66
+ Before the widening, this host refused the plugin with a **single**
67
+ `engines.dsh` requirement and `exempted: false`, skipping the whole bundle.
68
+ After it, `afterNewlyAccepted = ["0.2.2-alpha.2"]` and
69
+ `afterNewlyRejected = []`; `0.2.2-alpha.1`, `0.2.2-alpha.2.1`,
70
+ `0.2.2-alpha.20`, `0.2.2-ALPHA.2`, `0.2.2-rc.1`, `0.2.2`, `0.2.1`,
71
+ `0.2.3`, and `1.0.0` stay refused. The projection is append-only: every other
72
+ manifest field is untouched.
73
+ - **Evidence.** `.alpha2-verify/AUDIT.md` and `CHANGE_SURFACE.md`, with 12
74
+ re-runnable scripts (`tree-compare`, `export-symbol-diff`, `call-surface-check`,
75
+ `history-api-matrix`, `vendor-range-check`, `evaluator-repro`, `matrix`,
76
+ `patch-anchor-check`, `client-face-check`, `pkg-manifest-delta`,
77
+ `snapshot-state.sh`, `surface-evidence.sh`), 12 `*.out.json` results, 180
78
+ diffs, and 30+ raw logs. The history-API matrix
79
+ (`.alpha2-verify/history-api-matrix.out.json`) is what proves the branch
80
+ decision: `inspect` present on 7/8 hosts, `page` present on 8/8,
81
+ `SessionPage` shape stable on 8/8.
82
+ - **Not covered / limits.** No real iPhone run and no Funnel end-to-end. No live
83
+ host boot on `0.2.2-alpha.2` was performed for this entry (the isolated-host
84
+ boot is tracked separately below). `dsh-client-ui-slots` was not tarball-compared
85
+ because this machine has no outbound HTTPS for `npm pack`; the plugin never
86
+ imports or injects that package and its `slots` service comes from
87
+ `dsh-client-ui-renderer`, which changed only `package.json`. npm install-time
88
+ peer resolution was not exercised.
89
+ - **Install-side prerequisite.** This host's `dsh` package raised
90
+ `engines.node` to `>= 24.9.0` — the only structural `package.json` change among
91
+ the 19 declared peers. The plugin's own `engines.node` stays `>=22`; a `0.2.2`
92
+ host simply cannot run on Node below 24.9.
93
+
94
+ ### Three optional capabilities verified in the same pass (2026-10-29)
95
+
96
+ - **alpha.2 isolated host:** 32/32 checks, including `assistantStream`,
97
+ `sessionMarkdown` and `pluginUpdate` all advertised. A synthetic turn produced
98
+ `stream.start` → `message.delta` → matching `message.final` (`data.streamId`)
99
+ → committed `stream.end`; Markdown export returned 10 chunks / 484,669 bytes
100
+ with `text/markdown; charset=utf-8`; update `check` answered without ever
101
+ sending `apply`.
102
+ - **rc.4 isolated host:** 27/27 checks. `assistantStream=true`, while
103
+ `sessionMarkdown` and `pluginUpdate` correctly stay false: rc.4's
104
+ `dsh-session-log-export` has no `session.markdown` route and its
105
+ `dsh-plugin-manager` exposes neither `listVersions` nor `updateBundle`.
106
+ The old ZIP path and old-client behaviour are unchanged.
107
+ - **Automated:** plugin `npm test` 679 tests (677 pass, 1 intentional TODO,
108
+ 1 env-gated real-host comparison; the comparison passes 21/21 with
109
+ `DSH_ALPHA2_PLUGIN_MANAGER` set). iOS offline suite 513 tests, 0 failures,
110
+ 2 skips. Both committed trees build.
111
+ - **Not covered:** no real iPhone, no system share sheet, no real npm install
112
+ through `updateBundle`/HMR rollback, no Funnel. Those remain manual gates.
113
+
114
+ ### `dsh-v0.2.1-rc.4`, audited in the same pass
115
+
116
+ - **Audited release:** `dsh-v0.2.1-rc.4`, published 2026-10-28T02:49:58Z, the
117
+ **`next`** channel release (`next` moved from `0.2.1-rc.3`). Baseline:
118
+ `0.2.1-rc.3`.
119
+ - **Verdict: no change that reaches this plugin, no `src/` change.** 307 packages
120
+ on both sides; 42,415 of 42,731 shared files byte-identical; 316 differing paths
121
+ = 296 `package.json` + 20 files in eight packages (`dsh-mcp-client` capability
122
+ gating for `resources/list`, `dsh-llm-deepseek-account` moving one log call to
123
+ stderr, `dsh-client-ui-conversation` View tooltip plus one removed locale key,
124
+ four version/build strings, and documentation). None is in the plugin's
125
+ declaration or call surface. `package.json` structural changes: 0 across all
126
+ 307 packages; 3,706 dependency-spec changes are mechanical `rc.3 → rc.4`
127
+ substitutions. Export surfaces: 0 changes across 3,271 `lib/` modules and 681
128
+ entry modules. The evaluator is the same file as rc.3 (same sha256).
129
+ - **Patch anchor:** `dsh-web-app/cordis.patch.yml` is byte-identical to rc.3;
130
+ the `directory-picker` anchor keeps line 113, byte 4664, and the same block
131
+ sha256.
132
+ - **Activation:** before the widening this host refused the plugin (single
133
+ `engines.dsh` requirement); after it, exactly `0.2.1-rc.4` is newly accepted,
134
+ nothing is newly rejected, and `0.2.1-rc.5`, `0.2.1`, `0.2.1-rc.4.1`,
135
+ `0.2.1-rc.40`, `0.2.1-RC.4`, and `0.2.1-rc.10` stay refused. Vendor pair is
136
+ still `cordis 4.0.5` / `schemastery 3.18.5`, both byte-identical to rc.3.
137
+ - **Evidence:** `.rc4-verify/AUDIT.md`, `CHANGE_SURFACE.md`, 10 scripts, 9
138
+ `*.out.json` results, 316 diffs. The comparator carries a negative control (a
139
+ byte-identical package compared against itself yields 0 differences; the same
140
+ package with one bit flipped yields exactly 1).
141
+
142
+ ### Previous decision — `dsh-v0.2.1-rc.3`
7
143
 
8
144
  - **Audited release:** `dsh-v0.2.1-rc.3`, published to the npm registry
9
145
  2026-10-23T07:54:30Z (GitHub Release 2026-10-23T15:26:39Z), and the **`next`**
@@ -85,8 +221,20 @@
85
221
  default npm cache on this machine holds root-owned files, so the
86
222
  `check:config-schema` script's `npx` invocation fails with `EPERM` until
87
223
  `npm_config_cache` points at a writable directory; with that variable set the
88
- check passes. No `npm ci`, no commit, no push, no tag, and no npm publish: the
89
- release is prepared but not shipped.
224
+ check passes.
225
+ - **Shipped as `dsh-deeppilot@0.9.11`.** Release commit
226
+ `a12750c84f1c2ecd579f87f3b5d60507fa3a7112`, annotated tag `v0.9.11`; CI
227
+ (`40055850654`) and CodeQL (`40055850739`) are green, and `publish.yml` run
228
+ `40056208123` completed all 24 steps — including the final version, integrity
229
+ and provenance check that several earlier releases failed on. Registry reads
230
+ `latest = 0.9.11`, 68 entries, 131,040,038 unpacked bytes, and SLSA provenance
231
+ of type `https://slsa.dev/provenance/v1` whose `gitCommit` is that release
232
+ commit at `refs/tags/v0.9.11`. The tarball answered `HTTP 404` for roughly
233
+ three minutes after publication, so an install check needs retries. A clean
234
+ isolated `DSH_HOME` then installed the published package **from npm** (not from
235
+ the working tree) and a real `0.2.1-rc.3` host loaded it and answered
236
+ `/phone/health` with 200 and `serverVersion: "0.9.11"`; the GitHub Release was
237
+ made public and marked Latest only after that check.
90
238
  - **Not covered / limits.** No real iPhone run, no Funnel end-to-end, no
91
239
  model-backed turn against this host. `npm ci` and the helper-matrix rebuild
92
240
  steps were skipped because no helper, dependency, or source input changed; CI
@@ -171,7 +319,7 @@
171
319
  0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5 || 0.2.1-rc.2`, mirrored in
172
320
  `tests/compatibility-metadata.test.ts`, `package-lock.json` (root entry only),
173
321
  both READMEs, `COMPATIBILITY.md`, `AGENTS.md`, and the local
174
- `docs/决策记录.md` (章节一, 条目5). The tests now also pin `0.2.1-rc.1` and
322
+ `docs/adr/0001-dsh-compatibility-policy.md` (item 5). The tests now also pin `0.2.1-rc.1` and
175
323
  `0.2.1-rc.3` as negative probes, so neither the skipped rc nor the next rc can be
176
324
  admitted by accident. The dev pins and `DSH_BASELINE` stay at the exact
177
325
  `0.2.0-rc.2` this branch builds and typechecks against.
@@ -296,7 +444,7 @@
296
444
  0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5`, mirrored in
297
445
  `tests/compatibility-metadata.test.ts`, `package-lock.json` (root entry only),
298
446
  both READMEs, `COMPATIBILITY.md`, `AGENTS.md`, and the local
299
- `docs/决策记录.md` (章节一, 条目4). The dev pins and `DSH_BASELINE` stay at the
447
+ `docs/adr/0001-dsh-compatibility-policy.md` (item 4). The dev pins and `DSH_BASELINE` stay at the
300
448
  exact `0.2.0-rc.2` this branch builds and typechecks against.
301
449
  - **Protocol verdict: no phone-protocol change.** Protocol v2, pairing state, and
302
450
  device records are untouched by this release; no phone needs to re-pair.
@@ -381,8 +529,8 @@
381
529
  `engines.dsh` and all ten `@deepseek-ai/dsh*` peers named `0.2.0-rc.2 ||
382
530
  0.2.1-alpha.3 || 0.2.1-alpha.4`, mirrored in
383
531
  `tests/compatibility-metadata.test.ts`, `package-lock.json`, both
384
- READMEs, `COMPATIBILITY.md`, `AGENTS.md`, and the local `docs/决策记录.md`
385
- (章节一, 条目3). The dev pins and `DSH_BASELINE` stay at the exact
532
+ READMEs, `COMPATIBILITY.md`, `AGENTS.md`, and the local `docs/adr/0001-dsh-compatibility-policy.md`
533
+ (item 3). The dev pins and `DSH_BASELINE` stay at the exact
386
534
  `0.2.0-rc.2` this branch builds and typechecks against. **Historical note:**
387
535
  `0.2.1-alpha.5` was appended to both lists on 2026-10-16 by the audit above,
388
536
  which now owns the current list; the four documentation mirrors that still
@@ -450,8 +598,8 @@
450
598
  across all ten `@deepseek-ai/dsh*` peers, and the two vendor peers widened to
451
599
  `~4.0.4 || ~4.0.5-alpha.1` and `~3.18.4 || ~3.18.5-alpha.1`. Because DSH
452
600
  evaluates that range on every start, the next DSH release deactivates this
453
- plugin until the list is widened deliberately — see `docs/决策记录.md`
454
- (章节一, 条目2), which records this as a reversal of the 2026-09-29 policy.
601
+ plugin until the list is widened deliberately — see `docs/adr/0001-dsh-compatibility-policy.md`
602
+ (item 2), which records this as a reversal of the 2026-09-29 policy.
455
603
  The published CLI composed the plugin's patch cleanly before the change (see
456
604
  the 2026-10-14 entry). The plugin's own `lib/client.js` shape was not
457
605
  re-verified against the alpha.3 client-modules scanner.
@@ -703,7 +851,7 @@
703
851
  page instead of gating installability on it. The re-audit obligation below
704
852
  is unchanged: still source-diff and record every new DSH release; a `0.3.x`
705
853
  line still requires its own audit and its own range widening before it
706
- installs. Recorded in `docs/决策记录.md` (章节一, 条目1).
854
+ installs. Recorded in `docs/adr/0001-dsh-compatibility-policy.md` (item 1).
707
855
  - **Install/deployment verdict:** the peer range, the compatibility assertions,
708
856
  the registry lockfile, and generated `lib/` are updated for rc.2. `npm ci`,
709
857
  unit tests (304 passing), typecheck, build, the config-schema check against a
@@ -722,6 +870,135 @@
722
870
  bundle" below. The plugin needs no code change; the phone's copy now points
723
871
  at the bundle.
724
872
 
873
+ ## 2026-10-24 — 插件链路实测:`dsh-v0.2.1-rc.3` 上的运行中排队与转向
874
+
875
+ 这不是版本审计:没有放行或下线任何版本。本节验证插件尚未提交的「运行中排队与转向」实现
876
+ (`promptQueue` 能力,见 `PROTOCOL.md`「运行中排队与转向扩展」),在真实宿主上能否按协议
877
+ 完整跑通:从手机帧,经 Bridge,到 Host 的 `prompt` / `updateQueue` 与 `inbox` 投影,再回到
878
+ 手机。
879
+
880
+ ### 方法
881
+
882
+ - 宿主 CLI:npx 缓存中的 `0.2.1-rc.3` 安装(`dsh --version` 输出 `0.2.1-rc.3`)。
883
+ - 插件:当前工作副本构建后用 `npm pack` 打成本地包,经
884
+ `dsh plugin --profile queue add <tgz>` 装入。装好后确认包内 `lib/index.js` 带有
885
+ `promptQueue`。
886
+ - 隔离 `DSH_HOME` 放在一次性临时目录(已删除),profile 用 `--from-default-profile web`
887
+ 创建。设备身份用 `scripts/smoke-live.mts register` 预先写入 `devices-v2.json`。连接走真实
888
+ 的 TLS 与签名挑战握手,不经过配对码。
889
+ - 额外挂载一个补丁,引入仅供测试的夹具,并用显式环境变量把关:本机 OpenAI 兼容模型,监听
890
+ `127.0.0.1:3388`,每个请求延迟 15 秒才回复。夹具只记录合成会话里用户消息的文本,用来核对
891
+ 转向插进了哪一轮。
892
+ - 测试客户端是临时脚本,每 15 秒发一次 `c2s.ping`,按清单逐项断言。宿主 Web 端口 3387,
893
+ 插件手机端 3398。结束后停掉宿主,确认三个端口都已无监听。
894
+
895
+ ### 结果
896
+
897
+ | 检查项 | 实际看到的 | 结论 |
898
+ | --- | --- | --- |
899
+ | 能力声明 | `welcome.capabilities.promptQueue=true` | 通过 |
900
+ | 打开会话 | 先收到 `s2c.session.tail`,再收到一帧空快照,这帧不带 seq | 通过 |
901
+ | 运行中排队 | 乙、丙依次进入 `queued`,各带自己的 `clientSendId`,帧带 seq | 通过 |
902
+ | 同 ID 重发 | 回执复用(`accepted`、原 `userSeq`),队列没有多出一项 | 通过 |
903
+ | 转向 | 收到 ack 后快照分两帧:先是丙离开,再是丙以 `steering` 出现 | 通过 |
904
+ | 删除 | ack 后快照里不再有乙;对乙再转向返回 `E_NOT_FOUND` | 通过 |
905
+ | 转向不可用 | 运行中把戊排进队列,再 `c2s.session.cancel`;取消后戊留在 `queued`,Host 没有自动领取;对戊转向返回 `E_STEER_UNAVAILABLE` | 通过 |
906
+
907
+ 模型侧的调用记录与快照一致:
908
+ - 转向后的丙,作为甲那一轮的第二步发给了模型,没有另起一轮。
909
+ - 丁单独作为一轮运行。
910
+ - 戊从未发给模型:取消后它留在排队区,随后被删除。
911
+
912
+ ### 发现
913
+
914
+ - **空闲会话上发 `mode:"steer"`**:Host 正常受理。该项先在快照里以 `steering` 出现一帧,
915
+ 随后被领取,按普通的一轮运行,不报错。
916
+ - **空闲时普通发送也经过排队区**:该项会以 `queued` 短暂出现一帧,下一帧即消失。这在插件
917
+ 链路上复现了 rc.2 探针的结论,客户端对账时必须容忍这类一闪而过的项。
918
+ - **`cancel` 不领取排队项**:取消后排队项仍然保留,会话停在空闲,直到有下一次发送或删除。
919
+ 这让 rc.2 探针里「无法构造」的 `session/steer-unavailable` 空闲场景,有了稳定的构造方法。
920
+ - **监听地址**:插件手机端监听在 `0.0.0.0:3398`,这是 LAN 传输的固定行为。验收时设备注册表
921
+ 里只有冒烟设备。
922
+
923
+ ### 局限
924
+
925
+ - 只跑了 `0.2.1-rc.3`。`0.2.0-rc.2` 上的插件链路没有实测,只有上次的宿主侧探针。
926
+ - 第一轮运行有两个问题:客户端没发心跳,约 100 秒后被插件断开;部分等待条件匹配到了更早的
927
+ 帧。修正客户端后,在新会话上重跑才得到上表。第一轮里丁没有出现在历史和模型记录里,当时
928
+ 没有检查它的发送回执,原因未查清。推测它是在上一轮结束的瞬间发出、被 Host 拒收,但没有
929
+ 证据。
930
+ - 只测了单台设备。快照「所有设备相同」与多设备并发操作都没有覆盖。
931
+ - 模型是合成的,固定输出不代表真实供应商的行为。
932
+
933
+ ## 2026-10-24 — 运行时探针:`dsh-v0.2.0-rc.2` 上的 `inbox` 投影
934
+
935
+ 这不是版本审计:没有放行或下线任何版本,插件代码也没有改动。本节只回答计划中手机端
936
+ 「运行中排队与转向」可选能力(`sessionController.updateQueue`,见下文「New rc.2
937
+ capabilities worth using」)背后唯一悬而未决的问题:最早放行的宿主版本,是否通过本插件
938
+ 已在使用的投影通道发布待处理收件箱(inbox)。
939
+
940
+ ### 静态证据
941
+
942
+ - `@deepseek-ai/dsh-agent-loop@0.2.0-rc.2`(`lib/index.js:27`)注册了带对外视图
943
+ (wire view)的标准 `inbox` 投影。其状态为
944
+ `{ "next-turn": Message[], "next-step": Message[] }`,由持久事件
945
+ `agent/inbox/spliced` 折叠而来;折叠会拒绝越界的 splice,以及同时出现在两个列表里的
946
+ 同一个 `MessageId`。
947
+ - `@deepseek-ai/dsh-api-session-controller` 的 `0.2.0-rc.2` 与 `0.2.1-rc.3`
948
+ (registry 包)带有相同的 `updateQueue` 实现:`edit`(只接受非空纯文本)、`remove`
949
+ (同时释放该提示词的上传附件)、`steer`(只接受 `next-turn` 中的项且 Agent 正在运行,
950
+ 否则返回 `session/steer-unavailable`)。项不存在时返回 `session/queue-item-not-found`。
951
+ 两个版本的 README 都说明:提示词的 `requestId` 会持久化为用户来源的 `rpcId`,待处理
952
+ 收件箱里的消息也保留这一来源。
953
+ - `0.2.1-rc.3` 在会话列表投影的类型定义里列出了 `inbox`,`0.2.0-rc.2` 没有列出,这正是
954
+ 需要做运行时探针的原因。
955
+
956
+ ### 方法
957
+
958
+ - 宿主 CLI:npx 缓存中的 `0.2.0-rc.2` 安装(`dsh --version` 输出 `0.2.0-rc.2`)。
959
+ - 隔离 `DSH_HOME` 位于一次性临时目录(已删除),profile 用 `--from-default-profile web`
960
+ 创建。`--dump-config` 退出码 0、stderr 为空、组合树中没有 `deeppilot` 行:刻意不加载
961
+ 插件。
962
+ - 额外挂载一个补丁,引入仅供测试的夹具,并用显式环境变量把关:
963
+ - 本机 OpenAI 兼容模型,监听 `127.0.0.1:3288`,经 `llm-pi-ai` 以占位密钥注册;每个
964
+ 请求延迟 40 秒才回复,让该轮一直处于运行中;
965
+ - 订阅 `sessionProjections.onChanged` 的探针,与 `src/dsh-api-proxy.ts` 使用的是同一
966
+ 接口。只对 `inbox` 键打印两个列表的长度、消息 ID 前 8 位、`source.kind`,以及是否带
967
+ `source.rpcId`,不打印任何消息正文。夹具必须声明 `inject: ['sessionProjections']`,
968
+ 否则 `apply` 时取不到该服务。
969
+ - 在宿主自带的 Web 界面(端口 3287)上操作:发送 A;A 运行期间发送 B 和 C;在排队区对
970
+ B 转向;删除 C;等 A 结束。结束后停掉宿主,确认 3287 与 3288 端口已无监听。
971
+
972
+ ### 结果
973
+
974
+ | 检查项 | 探针输出 | 结论 |
975
+ | --- | --- | --- |
976
+ | 投影存在且实时推送 | 发出 B、C 后:`next-turn=2`、`next-step=0` | 通过 |
977
+ | 能对应回发送 | 每一项均为 `kind=user` 且带 `rpcId` | 通过 |
978
+ | 转向 | 先是 `next-turn=1 [C] next-step=0`,再是 `next-turn=1 [C] next-step=1 [B]` | 通过 |
979
+ | 删除 | `next-turn=0`、`next-step=1 [B]` | 通过 |
980
+ | 被领取执行 | A 结束后:`next-step=0`,随后出现一次新的模型请求 | 通过 |
981
+
982
+ Web 界面表现一致:排队区标题为「2 条排队消息」,每项带编辑、删除与「插话发送」(转向)
983
+ 操作,被转向的 B 立即显示在会话尾部。
984
+
985
+ ### 对队列能力的影响
986
+
987
+ - 转向分两帧完成:B 先离开 `next-turn`,下一帧才进入 `next-step`。客户端必须按
988
+ `MessageId` 跨两个列表跟踪各项,不能把只缺席一帧当作被删除。
989
+ - 空闲会话上的提示词也会先经过 `next-turn` 再被领取,因此出现在收件箱里不能作为该轮正在
990
+ 运行的证据。
991
+ - 本次探针不要求插件做任何改动。该能力仍是可选能力,以 `updateQueue` 与 `inbox` 投影同时
992
+ 可用为前提。
993
+
994
+ ### 局限
995
+
996
+ - 没有运行 `0.2.1-rc.3`;其静态证据与本版一致。
997
+ - 没有加载插件。探针用的是同一个 `onChanged` 接口,但插件自身的折叠与手机帧仍未测试。
998
+ - 空闲会话上对排队项转向返回 `session/steer-unavailable` 只有源码证据:空闲会话会立即
999
+ 领取排队项,这种状态无法构造出来。
1000
+ - 模型是合成的,其固定输出不代表任何真实供应商的行为。
1001
+
725
1002
  ## 2026-10-16 — audit of `dsh-v0.2.1-alpha.5`
726
1003
 
727
1004
  The first release on this line whose entire plugin-facing change surface is
@@ -1065,7 +1342,7 @@ either host. `devDependencies` stay pinned to `0.2.0-rc.2`.
1065
1342
  The consequence is deliberate: `evaluatePluginCompatibility` runs before a
1066
1343
  profile is composed on every start, so the next DSH release will refuse to
1067
1344
  activate this plugin until the list is widened by an audit. That reversal of the
1068
- 2026-09-29 policy is recorded in `docs/决策记录.md` (章节一, 条目2).
1345
+ 2026-09-29 policy is recorded in `docs/adr/0001-dsh-compatibility-policy.md` (item 2).
1069
1346
  `tests/compatibility-metadata.test.ts` now asserts both admissions, fifteen
1070
1347
  rejections, and the two vendor ranges.
1071
1348