dsh-deeppilot 0.9.9 → 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.
@@ -3,7 +3,245 @@
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.2`
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`
143
+
144
+ - **Audited release:** `dsh-v0.2.1-rc.3`, published to the npm registry
145
+ 2026-10-23T07:54:30Z (GitHub Release 2026-10-23T15:26:39Z), and the **`next`**
146
+ channel release — `next` moved from `0.2.1-rc.2` to it, so this is the second
147
+ consecutive rc on that line to enter the supported list, each on its own audit.
148
+ It is **not** `latest`: the registry currently reads `latest = 0.2.1-rc.2`
149
+ (rc.2, promoted from `next`) and `alpha = 0.2.1-alpha.5`. This audit therefore also
150
+ corrected the older channel attribution that called `0.2.0-rc.2` the `latest`
151
+ channel in `AGENTS.md` and both READMEs — the list of six admitted hosts is
152
+ unchanged by that correction, only its description.
153
+ - **Comparison baseline:** `dsh-v0.2.1-rc.2` (the previous audited tag).
154
+ - **Plugin runtime verdict: no break, and no `src/` change was needed.**
155
+ Nineteen packages were compared **as whole trees, not by `lib/` alone** —
156
+ eighteen from the two installed trees plus `dsh-client-ui-slots` (the seventh
157
+ declared `dsh-*` peer, absent from both) through its registry tarball. Fourteen
158
+ differ only in `package.json`, three carry one further file each, and
159
+ `cordis 4.0.5` / `schemastery 3.18.5` are byte-identical including
160
+ `package.json`. Of 3,302 shared files, 3,275 are byte-identical and 20 differ.
161
+ The tree count moves 306 → 307 with the new
162
+ `@deepseek-ai/dsh-client-ui-entry-customization@0.2.1-rc.3`, the More-menu bundle
163
+ the web-app patch now references; this plugin neither references it nor depends
164
+ on it. Across 274 modules **no export symbol is added or removed** (18 entry
165
+ modules compared), so every earlier fix still holds unchanged. The manifest
166
+ delta over 19 packages covers 585 paths — 17 version bumps and 568
167
+ dependency-spec moves — with **zero structural differences**.
168
+ - **The three non-`package.json` files are additive or comment-only.**
169
+ `@deepseek-ai/dsh-api-remotes/lib/client.js` widens the client telemetry event
170
+ schema (`is_new_session`, `agent_preset`, and the More-menu / agent-preset
171
+ switch events), data this plugin neither emits nor validates.
172
+ `@deepseek-ai/dsh-api-session-controller`'s
173
+ `lib/types/client/sessions/service.d.ts` changes a doc comment only.
174
+ `@deepseek-ai/dsh-web-app/cordis.patch.yml` gains one hunk inserting the
175
+ `ui-entry-customization` bundle (the More menus named in the rc.3 release
176
+ notes); the patch anchor this plugin targets, `id: directory-picker`, is
177
+ byte-identical on both sides at the same offsets, and neither the new package
178
+ name nor `entry-customization` appears in this plugin's `cordis.patch.yml` or
179
+ `package.json`.
180
+ - **Activation verdict: the new release is admitted by both declarations, and the
181
+ earlier rc stays out.** rc.3, like rc.2, reads a declared `engines.dsh` alone,
182
+ so before the widening its refusal reported a **single** `engines.dsh`
183
+ requirement and `exempted: false` — no profile exemption file exists on this
184
+ machine — and a real rc.3 CLI reproduced it (`skipping profile bundle
185
+ "dsh-deeppilot"`) while the host itself still booted and served its web port.
186
+ Widening admits `0.2.1-rc.3` and nothing else: `0.2.1-rc.1` was never audited as
187
+ its own host, so it stays refused, as do `0.2.1-rc.3.1`, `0.2.1-rc.30`,
188
+ `0.2.1-RC.3`, `0.2.1`, `0.2.1-rc.2.1`, `0.2.0`, `0.3.0`, and `1.0.0`. Deleting
189
+ `engines.dsh` from a copy of the manifest falls back to the ten peers and admits
190
+ the same six hosts, so the short-circuit is unchanged.
191
+ - **Evidence: the published artifacts, the published evaluator, and a real rc.3
192
+ CLI run — all taken before any declaration changed.**
193
+ - **Change surface:** `.rc3-verify/CHANGE_SURFACE.md` and
194
+ `.rc3-verify/AUDIT.md`, with raw logs under `.rc3-verify/logs/`
195
+ (`master-table.txt`, `file-hash-compare.txt`, `diff-rq.all.txt`,
196
+ `patch-anchor-check.stdout.txt`), plus `tree-compare.out.json` (the
197
+ 16-package whole-tree comparison), `export-symbol-diff.out.json` (274
198
+ modules, zero surface deltas), `pkg-manifest-delta.out.json` (585 paths, all
199
+ version or dependency-spec values) and `patch-anchor-check.out.json` (the one
200
+ patch-file change and its anchor).
201
+ - **Activation decision, reproduced against rc.3's own published evaluator
202
+ before any edit:** `.rc3-verify/evaluator-repro.out.json` shows the unchanged
203
+ manifest refused with one `engines.dsh` requirement and `exempted: false`, and
204
+ the worktree manifest admitted; `.rc3-verify/matrix.out.json` projects the
205
+ widening over 15 candidates — before accepted 5, after accepted 6, **newly
206
+ accepted exactly `0.2.1-rc.3`, newly rejected 0**.
207
+ - **Real CLI refusal and real CLI load.** The refusal was captured from the
208
+ installed rc.3 CLI before the declaration changed; after the widening the same
209
+ CLI composes the plugin (`--dump-config`, exit 0, no skip line).
210
+ - **Positive load verified this time.** An isolated `0.2.1-rc.3` host — its own
211
+ `DSH_HOME` in a one-off scratch directory (since deleted), the plugin linked
212
+ from this working tree, and no other plugin — composed the plugin into the
213
+ tree, started it, and answered `https://127.0.0.1:3098/phone/health` with `200`:
214
+ `{"ok":true,"enabled":true,"protocolVersion":2,"serverVersion":"0.9.10","dataPlane":true}`
215
+ while the isolated home gained `deeppilot/host-id` and `deeppilot/lan-tls/`.
216
+ Evidence: `.rc3-verify/HOST-BOOT.md` (written after the audit directory was
217
+ handed over) with the raw log and probe output beside it.
218
+ - **Check set run (nothing published).** `npm test` (609 pass, 0 fail),
219
+ `typecheck`, `build` (committed `lib/` unchanged), `check:config-schema`, and
220
+ `smoke:helper` (darwin-arm64). One environment note carries forward: the
221
+ default npm cache on this machine holds root-owned files, so the
222
+ `check:config-schema` script's `npx` invocation fails with `EPERM` until
223
+ `npm_config_cache` points at a writable directory; with that variable set the
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.
238
+ - **Not covered / limits.** No real iPhone run, no Funnel end-to-end, no
239
+ model-backed turn against this host. `npm ci` and the helper-matrix rebuild
240
+ steps were skipped because no helper, dependency, or source input changed; CI
241
+ rebuilds the matrix and fails on any `bin/` drift. The widening is a metadata
242
+ and documentation change only.
243
+
244
+ ### Previous decision — `dsh-v0.2.1-rc.2`
7
245
 
8
246
  - **Audited release:** `dsh-v0.2.1-rc.2`, published 2026-10-17T08:36:31.655Z. It is
9
247
  **not** `latest`: `latest` still points at `0.2.0-rc.2`, and `alpha` still points
@@ -81,7 +319,7 @@
81
319
  0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5 || 0.2.1-rc.2`, mirrored in
82
320
  `tests/compatibility-metadata.test.ts`, `package-lock.json` (root entry only),
83
321
  both READMEs, `COMPATIBILITY.md`, `AGENTS.md`, and the local
84
- `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
85
323
  `0.2.1-rc.3` as negative probes, so neither the skipped rc nor the next rc can be
86
324
  admitted by accident. The dev pins and `DSH_BASELINE` stay at the exact
87
325
  `0.2.0-rc.2` this branch builds and typechecks against.
@@ -115,6 +353,33 @@
115
353
  `200` and `serverVersion: "0.9.8"`; the GitHub Release was made public only after
116
354
  that install verification. The same release shipped the mobile skills, host
117
355
  commands, and catalog-cache work recorded below.
356
+ - **Published as 0.9.9 on 2026-10-21.** The annotated tag `v0.9.9` dereferences to
357
+ `feee5c5854cd598af7b7827c53ddffdec3199573` on `main`, with CI and CodeQL green on
358
+ that commit. The DSH compatibility declaration did not change (the same five
359
+ audited hosts). The first CI run on the release commit failed in the helper job:
360
+ `govulncheck` reported GO-2026-6809 in Go 1.26.9's `crypto/x509`, reachable
361
+ through `http.Server.Serve`; the helper moved to Go 1.26.10 and the
362
+ `build-helpers` workflow refreshed all six binaries (PR #30, six `go1.26.10`
363
+ binaries, `bin/SHA256SUMS` 6/6) before the tag was cut. `publish.yml` ran on the
364
+ tag (run `39612245054`): the upload and provenance steps succeeded, but its last
365
+ step (registry verification) exhausted its 24 retries with `HTTP 404` — the
366
+ registry-visibility delay already seen in 0.9.5 and 0.9.6, not an upload failure.
367
+ Checked by hand instead: `npm view --prefer-online` gives `latest: 0.9.9` with a
368
+ `https://slsa.dev/provenance/v1` attestation whose `gitCommit` is that commit and
369
+ whose workflow ref is `refs/tags/v0.9.9`; the published tarball's SHA1
370
+ `bfea9ade6be9eb07f209e0e76f5ea20326dc0ddb` and its SHA512 match the registry and
371
+ the attestation subject; it holds 68 entries (the pre-publication pack count) and
372
+ every packaged file compared byte-identically with the verified tree. A clean
373
+ isolated `DSH_HOME` then installed `dsh-deeppilot@0.9.9` from npm on a real
374
+ `0.2.1-rc.2` host (`dsh web --no-open --port 0`) and `/phone/health` answered `200`
375
+ with `serverVersion: "0.9.9"`, `protocolVersion: 2` and the data plane active.
376
+ The first start attempt failed because DSH's own web server could not bind
377
+ `127.0.0.1:3080`, which another running DSH instance held; that is an environment
378
+ conflict, not a plugin fault, and the plugin's own listener had come up. The
379
+ GitHub Release was made public only after that install verification. The release
380
+ ships connection-failure diagnostics, the `failed` Live Activity phase, the
381
+ optional `toolName` / `detail` approval fields and `mutable-content`; it must run
382
+ against a Relay that already accepts them.
118
383
 
119
384
  ### Previous decision — `dsh-v0.2.1-alpha.5`
120
385
 
@@ -179,7 +444,7 @@
179
444
  0.2.1-alpha.3 || 0.2.1-alpha.4 || 0.2.1-alpha.5`, mirrored in
180
445
  `tests/compatibility-metadata.test.ts`, `package-lock.json` (root entry only),
181
446
  both READMEs, `COMPATIBILITY.md`, `AGENTS.md`, and the local
182
- `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
183
448
  exact `0.2.0-rc.2` this branch builds and typechecks against.
184
449
  - **Protocol verdict: no phone-protocol change.** Protocol v2, pairing state, and
185
450
  device records are untouched by this release; no phone needs to re-pair.
@@ -264,8 +529,8 @@
264
529
  `engines.dsh` and all ten `@deepseek-ai/dsh*` peers named `0.2.0-rc.2 ||
265
530
  0.2.1-alpha.3 || 0.2.1-alpha.4`, mirrored in
266
531
  `tests/compatibility-metadata.test.ts`, `package-lock.json`, both
267
- READMEs, `COMPATIBILITY.md`, `AGENTS.md`, and the local `docs/决策记录.md`
268
- (章节一, 条目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
269
534
  `0.2.0-rc.2` this branch builds and typechecks against. **Historical note:**
270
535
  `0.2.1-alpha.5` was appended to both lists on 2026-10-16 by the audit above,
271
536
  which now owns the current list; the four documentation mirrors that still
@@ -333,8 +598,8 @@
333
598
  across all ten `@deepseek-ai/dsh*` peers, and the two vendor peers widened to
334
599
  `~4.0.4 || ~4.0.5-alpha.1` and `~3.18.4 || ~3.18.5-alpha.1`. Because DSH
335
600
  evaluates that range on every start, the next DSH release deactivates this
336
- plugin until the list is widened deliberately — see `docs/决策记录.md`
337
- (章节一, 条目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.
338
603
  The published CLI composed the plugin's patch cleanly before the change (see
339
604
  the 2026-10-14 entry). The plugin's own `lib/client.js` shape was not
340
605
  re-verified against the alpha.3 client-modules scanner.
@@ -586,7 +851,7 @@
586
851
  page instead of gating installability on it. The re-audit obligation below
587
852
  is unchanged: still source-diff and record every new DSH release; a `0.3.x`
588
853
  line still requires its own audit and its own range widening before it
589
- installs. Recorded in `docs/决策记录.md` (章节一, 条目1).
854
+ installs. Recorded in `docs/adr/0001-dsh-compatibility-policy.md` (item 1).
590
855
  - **Install/deployment verdict:** the peer range, the compatibility assertions,
591
856
  the registry lockfile, and generated `lib/` are updated for rc.2. `npm ci`,
592
857
  unit tests (304 passing), typecheck, build, the config-schema check against a
@@ -605,6 +870,135 @@
605
870
  bundle" below. The plugin needs no code change; the phone's copy now points
606
871
  at the bundle.
607
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
+
608
1002
  ## 2026-10-16 — audit of `dsh-v0.2.1-alpha.5`
609
1003
 
610
1004
  The first release on this line whose entire plugin-facing change surface is
@@ -948,7 +1342,7 @@ either host. `devDependencies` stay pinned to `0.2.0-rc.2`.
948
1342
  The consequence is deliberate: `evaluatePluginCompatibility` runs before a
949
1343
  profile is composed on every start, so the next DSH release will refuse to
950
1344
  activate this plugin until the list is widened by an audit. That reversal of the
951
- 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).
952
1346
  `tests/compatibility-metadata.test.ts` now asserts both admissions, fifteen
953
1347
  rejections, and the two vendor ranges.
954
1348
 
@@ -117,6 +117,45 @@
117
117
  3098 的 `/phone/health` 返回 200 且 `serverVersion` 为 `0.9.8`;GitHub Release
118
118
  在这一步通过后才公开并标记 Latest。
119
119
 
120
+ 9. `0.9.9` 的实际发布结果(2026-10-21):附注标签 `v0.9.9` 指向
121
+ `feee5c5854cd598af7b7827c53ddffdec3199573`,该提交的 CI 与 CodeQL 均为绿。发布
122
+ 提交的首次 CI 曾因 helper 的 `govulncheck` 报 GO-2026-6809(Go 1.26.9 的
123
+ `crypto/x509`,调用链可达)而失败,处理方式是 helper 升到 Go 1.26.10,由
124
+ `build-helpers` 工作流重建六个二进制并合并刷新 PR(#30),之后才打标签。
125
+ `publish.yml` 在该标签上运行(运行号 `39612245054`):**上传与来源证明步骤成功,
126
+ 但最后的核对步骤在 24 次重试后仍抛 `读取 npm 发布信息失败(HTTP 404)`,整次运行
127
+ 结论为失败**——与 `0.9.5`、`0.9.6` 同一形态,说明 `0.9.7` 放宽的约 7 分钟窗口并非
128
+ 总是足够,注册表元数据的可见性延迟仍会超出它。事后人工核验:
129
+ `npm view --prefer-online` 得到 `latest = 0.9.9`;来源证明类型为
130
+ `https://slsa.dev/provenance/v1`,`gitCommit` 正是该提交,工作流引用为
131
+ `refs/tags/v0.9.9`;压缩包 SHA1 `bfea9ade6be9eb07f209e0e76f5ea20326dc0ddb` 与 SHA512
132
+ 同注册表和来源证明主体一致,共 68 个条目,包内每个文件与已验证的工作树逐字节相同。
133
+ 随后在全新隔离 `DSH_HOME` 中从 npm 安装 `dsh-deeppilot@0.9.9`,在真实
134
+ `0.2.1-rc.2` 宿主上用 `dsh web --no-open --port 0` 启动,`/phone/health` 返回 200,
135
+ `serverVersion` 为 `0.9.9`;首次启动因另一个正在运行的 DSH 占用了宿主自己的 3080
136
+ 端口而失败,属环境冲突,不是插件问题。GitHub Release 在这一步通过后才公开并标记
137
+ Latest。是否再放宽核对窗口,留待下次发布前决定,本次未改工作流。
138
+
139
+ 10. `0.9.11` 的实际发布结果(2026-10-24):附注标签 `v0.9.11` 指向
140
+ `a12750c84f1c2ecd579f87f3b5d60507fa3a7112`,该提交的 CI(运行号 `40055850654`,
141
+ 4 分 42 秒)与 CodeQL(运行号 `40055850739`,2 分 20 秒)均为绿。`publish.yml`
142
+ 在该标签上运行(运行号 `40056208123`),**24 个步骤全部成功**,包含最后的
143
+ 「核对发布版本、包完整性与来源证明」——这一步在 `0.9.5`~`0.9.9` 多次因注册表
144
+ 可见性延迟而失败,本次一次通过。注册表核验:`latest = 0.9.11`;tarball SHA1
145
+ `0a3e29b32beb393c7324d741602b5be1dc495d87`、SHA512 与来源证明主体一致、共
146
+ 68 个条目、解包 131,040,038 字节(与发布前 `npm pack --dry-run` 的
147
+ `unpackedSize` 完全一致);来源证明类型为 `https://slsa.dev/provenance/v1`,
148
+ `gitCommit` 正是该发布提交,工作流引用 `refs/tags/v0.9.11`。
149
+ **注册表可见性延迟仍然存在**:发布后约 3 分钟内
150
+ `dsh-deeppilot-0.9.11.tgz` 持续返回 `HTTP 404`(第 10 次探测才变 200),
151
+ 因此用它做安装验证必须带重试。随后在全新隔离 `DSH_HOME`
152
+ (`npm install dsh-deeppilot@0.9.11`,不是 link)中用真实 `0.2.1-rc.3` 宿主
153
+ 启动,插件日志出现 4 条 `[deeppilot]`,自有端口
154
+ `https://127.0.0.1:3098/phone/health` 返回 200 且 `serverVersion` 为 `0.9.11`;
155
+ GitHub Release 在这一步通过后才公开,并标记 Latest。
156
+ **遗留处理:** `0.9.10` 的 GitHub Release 原为 Draft,按用户决定于本轮**删除**
157
+ (远端标签 `v0.9.10` 与 npm 上的 `0.9.10` 包均保留,未做任何版本删除或回撤)。
158
+
120
159
  ## 五、官方资料
121
160
 
122
161
  1. [npm 可信发布配置与限制](https://docs.npmjs.com/trusted-publishers/)