dsh-deeppilot 0.9.4 → 0.9.6
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 +83 -11
- package/PRIVACY.md +2 -2
- package/README.md +28 -33
- package/README.zh-CN.md +24 -26
- package/SECURITY.md +2 -1
- package/cordis.patch.yml +1 -1
- package/docs/DEVICE_REGISTRY_RECOVERY.md +87 -0
- package/docs/DEVICE_REGISTRY_RECOVERY.zh-CN.md +73 -0
- package/docs/DSH_RELEASE_MEMORY.md +544 -13
- package/docs/NPM_PUBLISHING.md +88 -0
- package/docs/SECURITY_ROADMAP.md +9 -4
- package/docs/SECURITY_ROADMAP.zh-CN.md +9 -4
- package/lib/client.js +5 -5
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +57 -6
- package/lib/index.js.map +1 -1
- package/locale/en.json +1 -1
- package/package.json +19 -15
|
@@ -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
|
|
6
|
+
## Current decision — `dsh-v0.2.1-alpha.4`
|
|
7
|
+
|
|
8
|
+
- **Audited release:** `dsh-v0.2.1-alpha.4` (official release page:
|
|
9
|
+
<https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.2.1-alpha.4>),
|
|
10
|
+
published to npm 2026-10-15T13:08:08Z on the `alpha` dist-tag. It is **not**
|
|
11
|
+
`latest`; `latest`/`next` still point at `0.2.0-rc.2`, exactly as at alpha.3.
|
|
12
|
+
- **Comparison baseline:** `dsh-v0.2.1-alpha.3` (the previous audited tag).
|
|
13
|
+
- **Plugin runtime verdict: no break, and no `src/` change was needed.** Eight of
|
|
14
|
+
the ten peer packages ship a byte-identical `lib/` tree; only their
|
|
15
|
+
`package.json` `version` fields moved. That set includes `dsh-api-gateway`,
|
|
16
|
+
where alpha.3's first two breaks lived, and all three Client faces the resident
|
|
17
|
+
interaction client loads (`dsh-typert-registry/client`,
|
|
18
|
+
`dsh-client-connection/client`, `dsh-api-gateway/client`). Every alpha.3 fix
|
|
19
|
+
therefore still holds unchanged.
|
|
20
|
+
- **Only `dsh-api-remotes` changed in code, additively.** One new Remote Events
|
|
21
|
+
entry (`plugin-market/changed`) and the rename of `IncompatiblePlugin.peers` to
|
|
22
|
+
`requirements`. The plugin reads neither: it subscribes to no Remote Events
|
|
23
|
+
entry of that name, and its own phone-wire frame registry is a separate
|
|
24
|
+
vocabulary from DSH Remote Events. Its `lib/client.js` shows a 750-line diff
|
|
25
|
+
that normalises to zero contract changes — the bulk is `TYPERT_REMOTE$N`
|
|
26
|
+
renumbering plus `sourceLocation` line drift from the one inserted remote.
|
|
27
|
+
- **Two packages exist for the first time** — `@deepseek-ai/dsh-plugin-market`
|
|
28
|
+
and `@deepseek-ai/dsh-experimental-plugin-market-bundle` — behind this
|
|
29
|
+
release's custom plugin index sources. Neither is a dependency of this plugin,
|
|
30
|
+
the plugin does not name either in `inject`, and the bundle is a purely
|
|
31
|
+
additive entry in `dsh-app-boot`'s default bundle list.
|
|
32
|
+
- **Activation verdict: one break, and it is the release's own stated
|
|
33
|
+
migration.** alpha.4 changed the compatibility rule so that a plugin's own
|
|
34
|
+
`engines.dsh` range **decides alone and `peerDependencies` are ignored**
|
|
35
|
+
whenever that field is present; only a manifest without `engines.dsh` falls
|
|
36
|
+
back to the old peer evaluation. This plugin declared no `engines.dsh`, so it
|
|
37
|
+
kept the peer path, and its exact two-version peer list rejected
|
|
38
|
+
`0.2.1-alpha.4` — the plugin would not have activated on that host.
|
|
39
|
+
- **Evidence: reproduced against the published bundles, not inferred.** The audit
|
|
40
|
+
ran each host's own published `evaluatePluginCompatibility` (alpha.3 and
|
|
41
|
+
alpha.4 installed into separate isolated directories) against this plugin's
|
|
42
|
+
real `package.json`, over one candidate list. Before any edit, both hosts
|
|
43
|
+
admitted `0.2.0-rc.2` and `0.2.1-alpha.3` and both refused `0.2.1-alpha.4`,
|
|
44
|
+
reporting all ten peers unmet. With the new `engines.dsh` range in place, both
|
|
45
|
+
hosts admit all three audited releases; alpha.4 reports a **single**
|
|
46
|
+
`engines.dsh` requirement instead of ten peers when it refuses; and
|
|
47
|
+
`0.2.1-alpha.2`, `0.2.1-alpha.5`, `0.2.1`, and `0.3.0` are still refused.
|
|
48
|
+
alpha.3 ignores `engines.dsh` entirely — the field did not exist yet — and
|
|
49
|
+
keeps deciding on `peerDependencies`, which is why both declarations must name
|
|
50
|
+
the same list.
|
|
51
|
+
- **Install verdict: the two declarations now agree.** `engines.dsh` and all ten
|
|
52
|
+
`@deepseek-ai/dsh*` peers name `0.2.0-rc.2 || 0.2.1-alpha.3 || 0.2.1-alpha.4`,
|
|
53
|
+
mirrored in `tests/compatibility-metadata.test.ts`, `package-lock.json`, both
|
|
54
|
+
READMEs, `COMPATIBILITY.md`, `AGENTS.md`, and the local `docs/决策记录.md`
|
|
55
|
+
(章节一, 条目3). The dev pins and `DSH_BASELINE` stay at the exact
|
|
56
|
+
`0.2.0-rc.2` this branch builds and typechecks against.
|
|
57
|
+
- **Vendor peers need no widening.** Both hosts still vendor `cordis
|
|
58
|
+
4.0.5-alpha.2` and `schemastery 3.18.5-alpha.2`; neither package published a
|
|
59
|
+
`dsh-0-2-1-alpha-4` dist-tag, and the existing `~4.0.5-alpha.1` /
|
|
60
|
+
`~3.18.5-alpha.1` ranges already admit them.
|
|
61
|
+
- **Protocol verdict: no phone-protocol change.** Protocol v2, pairing state, and
|
|
62
|
+
device records are untouched by this release; no phone needs to re-pair.
|
|
63
|
+
- **Unrelated to this plugin, recorded for completeness:** the release also
|
|
64
|
+
brought per-model reasoning levels for custom API models, discovery and
|
|
65
|
+
installation from custom plugin index sources, a command/argument input fix, an
|
|
66
|
+
Office file delivery change, a Developer Tools reload fix, lower Linux command
|
|
67
|
+
startup overhead, and failed-command status reporting. None of them touches a
|
|
68
|
+
surface this plugin calls.
|
|
69
|
+
|
|
70
|
+
### Previous decision — `dsh-v0.2.1-alpha.3`
|
|
71
|
+
|
|
72
|
+
- **Audited release:** `dsh-v0.2.1-alpha.3` (official release page:
|
|
73
|
+
<https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.2.1-alpha.3>),
|
|
74
|
+
published to npm 2026-10-14T13:32:15Z on the `alpha` dist-tag. It is **not**
|
|
75
|
+
`latest`; `latest`/`next` still point at `0.2.0-rc.2`. Baseline commit
|
|
76
|
+
`2fbf4359b82fb94c03dcce0b831660d87f12ea5c`, compared against alpha.2's
|
|
77
|
+
`d743267388641bc76f17c45ce8b4c231aed1d32c` (**852 commits, 3311 changed files,
|
|
78
|
+
120,978 insertions, 16,632 deletions**).
|
|
79
|
+
- **Comparison baseline:** `dsh-v0.2.1-alpha.2` (the previous audited tag).
|
|
80
|
+
- **Plugin runtime verdict: four confirmed breaks with one root cause — the
|
|
81
|
+
alpha.3 Peer model — and the resident interaction client does not start.**
|
|
82
|
+
**Fixed in this audit; see "The fix" below.**
|
|
83
|
+
This release makes every in-process carrier name a `PeerScope`
|
|
84
|
+
(`principal` / `signal` / `interactions`) explicitly; nothing defaults to the
|
|
85
|
+
operator any more. The four landing points, each with its own evidence:
|
|
86
|
+
|
|
87
|
+
| # | Upstream change | Plugin seam | Evidence |
|
|
88
|
+
| --- | --- | --- | --- |
|
|
89
|
+
| 1 | `TypertGatewayWireStream.open`'s 4th parameter `peer` is required; `assertPeerLive()` reads `peer.signal.aborted` before anything else | `src/dsh-remote-interactions.ts:180` passes `undefined, undefined` | Reproduced against the published bundles: alpha.2 returns normally, alpha.3 throws `TypeError: Cannot read properties of undefined (reading 'signal')` |
|
|
90
|
+
| 2 | `$events` additionally requires `peer.interactions === 'answer'` (`requireInteractions`) | same call | Reproduced: a peer with `interactions: 'none'` gets `gateway/interactions-forbidden`; a full owner/answer peer passes on **both** versions |
|
|
91
|
+
| 3 | `ConnectionFetchHandler.fetch(request, peer)` now takes a required Peer | `src/dsh-remote-interactions.ts:204` calls `fetchHandler.fetch(request)` | `lib/types/rpc.d.ts` declares `peer: PeerScope` required, "never defaulted" |
|
|
92
|
+
| 4 | `./client` gained `node`/`browser` conditions; Node now resolves `lib/client.node.js`, which carries **no** `window.__ModuleLoader__.load` banner | `loadClientFaces()` (`src/dsh-remote-interactions.ts:117`) builds its module table from that banner | `grep -c __ModuleLoader__` is 0 in `client.node.js`, 1 in `client.browser.js` and 1 in alpha.2's `client.js` |
|
|
93
|
+
|
|
94
|
+
A fifth, latent one: `installConnection` derives
|
|
95
|
+
`interactions ?? (location === undefined ? 'none' : 'answer')`, and the
|
|
96
|
+
plugin's Node context has no `location`, so `apply(ctx)` alone always selects
|
|
97
|
+
`'none'`. Passing an explicit Peer is not enough by itself — the install call
|
|
98
|
+
must name `interactions: 'answer'` too.
|
|
99
|
+
- **Failure mode is degradation, not a crash — but only partly contained.**
|
|
100
|
+
`src/dsh-api-proxy.ts:316` wraps `startDshRemoteInteractions` in `try/catch`
|
|
101
|
+
and logs `[deeppilot] DSH Remote interaction client unavailable`. Breaks 3 and
|
|
102
|
+
4 surface while the resident client is being assembled, so they land in that
|
|
103
|
+
catch. Whether break 1/2 (the Gateway opens its Remote Events generation
|
|
104
|
+
asynchronously) also lands there is **not confirmed** — an uncaught rejection
|
|
105
|
+
there would be fatal under Node's default `--unhandled-rejections=throw`.
|
|
106
|
+
The phone loses approval/question delivery either way.
|
|
107
|
+
- **Fix direction (verified compatible with both hosted versions):** build one
|
|
108
|
+
owner/answer Peer (`new Peer(ownerCtx, { principal: { kind: 'owner' },
|
|
109
|
+
interactions: 'answer' })`, falling back to `connection.operator` on alpha.2)
|
|
110
|
+
and name it in every carrier call — alpha.2 ignores a second `fetch` argument
|
|
111
|
+
and defaults an absent `open` peer to the operator, so one call form serves
|
|
112
|
+
both. `loadClientFaces` additionally has to accept the Node bundle's named
|
|
113
|
+
exports when the banner did not fire; both shapes export `apply`/`inject`
|
|
114
|
+
(`installConnection`/`transportError` are extra on Node).
|
|
115
|
+
- **Install verdict: the peer range now names this release explicitly.** It moved
|
|
116
|
+
from the open-ended `>=0.2.0-rc.2 <0.3.0-0` to `0.2.0-rc.2 || 0.2.1-alpha.3`
|
|
117
|
+
across all ten `@deepseek-ai/dsh*` peers, and the two vendor peers widened to
|
|
118
|
+
`~4.0.4 || ~4.0.5-alpha.1` and `~3.18.4 || ~3.18.5-alpha.1`. Because DSH
|
|
119
|
+
evaluates that range on every start, the next DSH release deactivates this
|
|
120
|
+
plugin until the list is widened deliberately — see `docs/决策记录.md`
|
|
121
|
+
(章节一, 条目2), which records this as a reversal of the 2026-09-29 policy.
|
|
122
|
+
The published CLI composed the plugin's patch cleanly before the change (see
|
|
123
|
+
the 2026-10-14 entry). The plugin's own `lib/client.js` shape was not
|
|
124
|
+
re-verified against the alpha.3 client-modules scanner.
|
|
125
|
+
- **Protocol verdict: no phone-protocol change.** Protocol v2, pairing state,
|
|
126
|
+
and device records are untouched by this release; no phone needs to re-pair.
|
|
127
|
+
- **Two host-side migrations this machine must apply** (independent of the
|
|
128
|
+
plugin): `~/.dsh/profiles/web/cordis.patch.yml` carries
|
|
129
|
+
`llm-deepseek-account.config.models: []`, and alpha.3 throws on any residual
|
|
130
|
+
`models` key — **including an empty array** (`resolveAccountOptions`). Also
|
|
131
|
+
`dsh --profile <name> --from-default-profile <template>` now *replaces* an
|
|
132
|
+
existing profile directory (it deletes the old `node_modules` and
|
|
133
|
+
`cordis.patch.yml`); the audit procedure recorded below used that flag.
|
|
134
|
+
- **Capability gaps, not regressions:** the `contextBreakdown` projection was
|
|
135
|
+
reshaped (`nodes[]` → `systems[]` + `surfaceTokens` + `claim`, stateVersion
|
|
136
|
+
5→6) and the plugin forwards it by key, so the phone may render empty values;
|
|
137
|
+
the model catalog shrank (account routes return only the version-gated
|
|
138
|
+
`offered` subset, pi-ai routes without a resolvable key return `[]`); and
|
|
139
|
+
`CLIENT_UPGRADE_REQUIRED` / `MODEL_UNSUPPORTED` are new codes with no mapping
|
|
140
|
+
in `src/wire-errors.ts` yet.
|
|
141
|
+
|
|
142
|
+
### Previous decision — `dsh-v0.2.1-alpha.2`
|
|
7
143
|
|
|
8
144
|
- **Audited release:** `dsh-v0.2.1-alpha.2` (official release page:
|
|
9
145
|
<https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.2.1-alpha.2>),
|
|
@@ -43,9 +179,40 @@
|
|
|
43
179
|
|
|
44
180
|
### Plugin release verdicts
|
|
45
181
|
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
182
|
+
- **发布结论(`0.9.5`,2026-10-15,`v0.9.5` @ `6517ad7`):** 包含 alpha.3
|
|
183
|
+
对端(Peer)与客户端兼容修复、两个宿主精确列举策略、跨语言认证向量与恢复说明,
|
|
184
|
+
以及手动 OIDC 身份认证与来源证明发布。包与锁文件两处根版本、基线快照一致。
|
|
185
|
+
- **发布前验证:** 干净依赖安装;562 项单元测试通过、零失败、一项既有待办;
|
|
186
|
+
类型检查、构建、固定宿主的真实配置模型加载、Go 测试、六个辅助程序校验和与
|
|
187
|
+
包内容检查通过。挑战篡改测试基于当前连接生成变更值,消除了时间碰撞,连续
|
|
188
|
+
20 次重点回归通过。发布提交的持续集成(CI)和 CodeQL 代码安全扫描通过。
|
|
189
|
+
- **注册表与来源证明:** npm 于 `2026-10-14T23:29:29.605Z` 发布该版本,
|
|
190
|
+
`latest`(稳定分发标签)指向 `0.9.5`。下载压缩包共 50,934,088 字节,
|
|
191
|
+
SHA1 `6a2f356efa1e48849d9bf713f88cd0fd67c7999c` 与工作流上传记录一致;
|
|
192
|
+
SHA512 与注册表及来源证明中的包摘要一致。来源证明精确对应 `v0.9.5`、
|
|
193
|
+
`6517ad7b6d7022afc9b3d81d6779b434282c9c56` 和 `.github/workflows/publish.yml`。
|
|
194
|
+
`npm audit signatures`(npm 签名审计)通过,包含本插件的注册表签名和来源证明;
|
|
195
|
+
npm 可信发布者绑定显示 `Valid`(有效)。压缩包发布不依赖可选的 `gitHead`
|
|
196
|
+
字段来确认源码,使用已验证签名的来源证明提交。
|
|
197
|
+
- **已发布包安装:** 两个独立的新 DSH 主目录分别使用 `0.2.0-rc.2` 与
|
|
198
|
+
`0.2.1-alpha.3`,从注册表执行 `dsh plugin --profile verify add dsh-deeppilot@0.9.5`。
|
|
199
|
+
三条插件配置组合成功,版本为 `0.9.5`,安装路径未引用源码工作区,六个辅助程序
|
|
200
|
+
校验和全部一致;实际配置模型导入未出现本插件相关错误。两个 Web 模板仍各有
|
|
201
|
+
四项宿主配置模型错误,与未安装插件的基线完全一致;不把整个模板核对说成全绿。
|
|
202
|
+
- **真实宿主边界:** 隔离的 alpha.3 冒烟检查为 24 项通过、1 项失败、3 项跳过。
|
|
203
|
+
失败项是未配置模型账号的全新主目录中,模型目录非空的断言;模型目录 RPC 正常
|
|
204
|
+
且可路由。模型切换、真实提问和模型触发的审批问答未验证,iPhone 真机未验证。
|
|
205
|
+
已认证连接重复提交认证证明的既有待办保留。
|
|
206
|
+
- **发布后缓存核对修正:** [首次发布运行](https://github.com/Mars-Sea/dsh-deeppilot/actions/runs/38653869533)
|
|
207
|
+
上传成功,末尾核对短暂命中缓存的 404 而失败。独立注册表、摘要、签名及安装
|
|
208
|
+
核验通过后才公开 [GitHub 发布页](https://github.com/Mars-Sea/dsh-deeppilot/releases/tag/v0.9.5)。
|
|
209
|
+
后续仓库修正为刷新查询、要求元数据重新校验并最多读取重试 12 次;修正后的
|
|
210
|
+
只读核对步骤已对真实注册表执行通过。未重跑上传、未修改已发布包或移动版本标签。
|
|
211
|
+
发布说明:`docs/RELEASE_NOTES-0.9.5.md`。
|
|
212
|
+
|
|
213
|
+
- **Release verdict (`0.9.4`, published 2026-10-10, tag `v0.9.4` @ `e2f77af`):**
|
|
214
|
+
carries the `projections` adapter fix and the Automation tasks documentation
|
|
215
|
+
correction described in the 2026-10-09 entry below. `package.json`, both root
|
|
49
216
|
`package-lock.json` version entries, and `tests/apply-baseline.snapshot.json`
|
|
50
217
|
are on `0.9.4`, and `lib/` is regenerated. The full checklist passed locally:
|
|
51
218
|
`npm ci`, 538 unit tests, typecheck, build, the config-schema check against a
|
|
@@ -53,9 +220,24 @@
|
|
|
53
220
|
`npm pack --dry-run` (65 files, 50,916,470 bytes packed). The fix was also
|
|
54
221
|
verified on a live `0.2.1-alpha.2` host against the published `0.9.3` as an
|
|
55
222
|
A/B control (25 pass / 0 fail either way, with the `sessions.projections
|
|
56
|
-
failed: internal` diagnostic present only on `0.9.3`).
|
|
57
|
-
|
|
58
|
-
|
|
223
|
+
failed: internal` diagnostic present only on `0.9.3`).
|
|
224
|
+
- **Registry verification after publishing.** `dist-tags.latest` moved off
|
|
225
|
+
`0.9.3`; `dist.shasum` `85b3c71a802e45e42f5fb1b23444ed2e396d39dc` is
|
|
226
|
+
byte-identical to the local `npm pack` output at the tag; 65 files,
|
|
227
|
+
`dist.unpackedSize` 130,789,604. **`gitHead` is `e2f77af`, the tag commit** —
|
|
228
|
+
the 0.9.3 ordering deviation did not repeat, because the release notes and
|
|
229
|
+
every other documentation change were committed before the pack. The publish
|
|
230
|
+
itself needed the maintainer's one-time password, as in 0.9.3; everything up
|
|
231
|
+
to and after it was done here.
|
|
232
|
+
- **Clean-profile verification.** A fresh isolated home, built from the shipped
|
|
233
|
+
Web template and installed with the published `0.2.1-alpha.2` CLI
|
|
234
|
+
(`dsh plugin --profile verify add dsh-deeppilot@0.9.4`), composed a real
|
|
235
|
+
profile: `--dump-config` printed the plugin's three rows
|
|
236
|
+
(`deeppilot-directory-picker-browse`, `…-browse-client`, `deeppilot`) with no
|
|
237
|
+
missing-module or load error, the installed package's six helper checksums
|
|
238
|
+
verified, every helper binary embedded `go1.26.9`, and the installed
|
|
239
|
+
`lib/index.js` carried the projections fix. Only then was the GitHub Release
|
|
240
|
+
taken out of draft and marked Latest.
|
|
59
241
|
- **The release also had to fix the helper's toolchain and its refresh
|
|
60
242
|
workflow.** CI's `govulncheck` job reported 11 reachable Go standard-library
|
|
61
243
|
vulnerabilities for the pinned `go 1.26.6`; this is time-triggered, not
|
|
@@ -207,6 +389,355 @@
|
|
|
207
389
|
bundle" below. The plugin needs no code change; the phone's copy now points
|
|
208
390
|
at the bundle.
|
|
209
391
|
|
|
392
|
+
## 2026-10-15 — audit of `dsh-v0.2.1-alpha.4`
|
|
393
|
+
|
|
394
|
+
`dsh-v0.2.1-alpha.4` reached npm on 2026-10-15T13:08:08Z, roughly 24 hours after
|
|
395
|
+
alpha.3, with the GitHub release following at 13:40:02Z. It is a small release —
|
|
396
|
+
two features, five fixes, and one compatibility-policy change — and
|
|
397
|
+
`latest`/`next` still point at `0.2.0-rc.2`.
|
|
398
|
+
|
|
399
|
+
### Method
|
|
400
|
+
|
|
401
|
+
This audit established the change surface from **released artifacts before
|
|
402
|
+
reading any source**, rather than from the release notes, because those notes are
|
|
403
|
+
under 2 KB and all four of alpha.3's breaks had been invisible in its notes.
|
|
404
|
+
Every `@deepseek-ai/dsh*` peer package was fetched from npm at both
|
|
405
|
+
`0.2.1-alpha.3` and `0.2.1-alpha.4`, unpacked into a scratch tree, and compared
|
|
406
|
+
file by file. The one large diff was then re-compared after normalising
|
|
407
|
+
`TYPERT_REMOTE$N` renumbering and `sourceLocation` line/column drift, so that
|
|
408
|
+
mechanical churn could not hide a contract change.
|
|
409
|
+
|
|
410
|
+
### Change surface
|
|
411
|
+
|
|
412
|
+
- **Eight of the ten peer packages carry a byte-identical `lib/` tree**:
|
|
413
|
+
`dsh-api-gateway`, `dsh-client-connection`, `dsh-client-locale`,
|
|
414
|
+
`dsh-client-ui-settings`, `dsh-client-ui-slots`, `dsh-settings`,
|
|
415
|
+
`dsh-typert-protocol`, `dsh-typert-registry`. Only their `package.json`
|
|
416
|
+
`version` fields moved. That set includes every module alpha.3 broke the
|
|
417
|
+
plugin through.
|
|
418
|
+
- **`dsh-api-remotes`** gained one Remote Events entry (`plugin-market/changed`),
|
|
419
|
+
renamed `IncompatiblePlugin.peers` to `requirements`, and added a
|
|
420
|
+
`pluginMarket` remote. Its `lib/client.js` diff spans 750 lines but normalises
|
|
421
|
+
to zero contract changes — `TYPERT_REMOTE$N` renumbering, `sourceLocation`
|
|
422
|
+
drift, and one rewritten `productAnalytics/report` description.
|
|
423
|
+
- **`dsh-app-boot`** rewrote the compatibility evaluator (below) and appended
|
|
424
|
+
`@deepseek-ai/dsh-experimental-plugin-market-bundle` to its default bundle
|
|
425
|
+
list, which is additive to `DEFAULT_BUNDLES`.
|
|
426
|
+
- **`dsh-plugin-manager`** carried the same `peers` → `requirements` rename
|
|
427
|
+
through `IncompatiblePlugin` and its diagnostics.
|
|
428
|
+
- **Two packages are new at this release**: `@deepseek-ai/dsh-plugin-market` and
|
|
429
|
+
`@deepseek-ai/dsh-experimental-plugin-market-bundle`. Neither resolves at
|
|
430
|
+
alpha.3. Neither is a dependency of this plugin, and neither appears in its
|
|
431
|
+
`inject`.
|
|
432
|
+
- The `dsh` CLI's own ten `@deepseek-ai/dsh*` dependencies all moved to alpha.4;
|
|
433
|
+
the vendor pins did **not** move. Both hosts still vendor `cordis
|
|
434
|
+
4.0.5-alpha.2` and `schemastery 3.18.5-alpha.2`, and neither vendor published a
|
|
435
|
+
`dsh-0-2-1-alpha-4` dist-tag, so the existing `~4.0.5-alpha.1` /
|
|
436
|
+
`~3.18.5-alpha.1` ranges already admit what both hosts ship.
|
|
437
|
+
|
|
438
|
+
### The one break: `engines.dsh` now decides alone
|
|
439
|
+
|
|
440
|
+
`dsh-app-boot`'s evaluator grew a requirements path that short-circuits the old
|
|
441
|
+
peer loop:
|
|
442
|
+
|
|
443
|
+
```js
|
|
444
|
+
function unmetRequirements(fields, runtimeVersion) {
|
|
445
|
+
const engines = Object.hasOwn(fields, "engines") ? objectOf$1(fields.engines, "Plugin manifest engines") : {};
|
|
446
|
+
if (Object.hasOwn(engines, "dsh")) {
|
|
447
|
+
const range = engines.dsh;
|
|
448
|
+
if (typeof range !== "string") throw new Error("Plugin manifest engines.dsh must be a string");
|
|
449
|
+
return satisfies(runtimeVersion, range) ? {} : { "engines.dsh": range };
|
|
450
|
+
}
|
|
451
|
+
if (!Object.hasOwn(fields, "peerDependencies")) return {};
|
|
452
|
+
// ...otherwise the previous per-peer loop, unchanged
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Three consequences matter here. A plugin that declares `engines.dsh` is judged
|
|
457
|
+
**only** by it, and its `peerDependencies` are never read. A plugin that does not
|
|
458
|
+
declare it keeps the previous behaviour — which is the state this plugin was in,
|
|
459
|
+
so its exact two-version peer list refused `0.2.1-alpha.4`. And `engines.dsh` is
|
|
460
|
+
taken verbatim, with none of the `workspace:^` / `workspace:~` / `workspace:*`
|
|
461
|
+
substitution the peer path performs, so any `workspace:` range there is unmet.
|
|
462
|
+
|
|
463
|
+
### Validation evidence
|
|
464
|
+
|
|
465
|
+
- **Compatibility decision, reproduced against the published evaluators — before
|
|
466
|
+
any edit.** Each host's own `evaluatePluginCompatibility` (alpha.3 and alpha.4,
|
|
467
|
+
installed into separate isolated directories) judged this plugin's real
|
|
468
|
+
`package.json` over one candidate list. Unchanged, both hosts admitted
|
|
469
|
+
`0.2.0-rc.2` and `0.2.1-alpha.3` and refused `0.2.1-alpha.4`, listing all ten
|
|
470
|
+
peers as unmet. With the added `engines.dsh` range, both hosts admit all three
|
|
471
|
+
audited releases; alpha.4 reports a **single** `engines.dsh` requirement
|
|
472
|
+
instead of ten peers when it refuses; and `0.2.1-alpha.2`, `0.2.1-alpha.5`,
|
|
473
|
+
`0.2.1`, and `0.3.0` remain refused. alpha.3 ignores `engines.dsh` entirely
|
|
474
|
+
and keeps deciding on `peerDependencies`, which is why both declarations must
|
|
475
|
+
name the same list.
|
|
476
|
+
- **Live A/B install on the published alpha.4 CLI — the evidence that matters.**
|
|
477
|
+
Under an isolated `DSH_HOME`, the **unchanged** package was rejected outright:
|
|
478
|
+
`dsh: installation rejected: Plugin dsh-deeppilot@0.9.5 is incompatible with
|
|
479
|
+
dsh 0.2.1-alpha.4: requirements {…ten peers…}`, `Exact-version exemption: not
|
|
480
|
+
active`, `dsh: nothing was installed`, exit 1. The **fixed** package installed
|
|
481
|
+
cleanly, exit 0, linked into the profile manifest's `dsh.profile.bundles`
|
|
482
|
+
alongside `@deepseek-ai/dsh-sdk-minimal`.
|
|
483
|
+
- **Composed tree:** the same CLI's `--dump-config` produced **162 rows with the
|
|
484
|
+
plugin and 153 without it**, the plugin's three rows present at
|
|
485
|
+
`deeppilot-directory-picker-browse`, `deeppilot-directory-picker-browse-client`,
|
|
486
|
+
and `deeppilot`, with no `skipped`/`incompatible` diagnostic. The single
|
|
487
|
+
warning is the `sdk-minimal` template's own missing `directory-picker` entry,
|
|
488
|
+
which alpha.3 recorded as well.
|
|
489
|
+
- **Live boot on a real alpha.4 Web host.** An isolated `DSH_HOME` profile built
|
|
490
|
+
from the shipped Web template and linked to this working tree booted under the
|
|
491
|
+
published alpha.4 CLI on `--port 3180` (the default 3080 is held by this
|
|
492
|
+
machine's own Host). The plugin started fully —
|
|
493
|
+
`[deeppilot] data plane active (mux + host streams)`,
|
|
494
|
+
`[deeppilot] LAN TLS identity created`,
|
|
495
|
+
`[deeppilot] local transport listening on https://0.0.0.0:3098` — and the
|
|
496
|
+
alpha.3 failure line `DSH Remote interaction client unavailable` **did not
|
|
497
|
+
appear**. A scan of the whole boot log for `incompatible`, `rejected`,
|
|
498
|
+
`requirements`, `unavailable`, or `error` returns nothing.
|
|
499
|
+
- **Plugin unit tests:** `npm test` → **564 tests, 563 pass, 0 fail, 1 todo**,
|
|
500
|
+
including the new `engines.dsh names the same closed host list as the peer
|
|
501
|
+
range` and the updated peer-range boundary test. `npm run typecheck` passes.
|
|
502
|
+
- **Build and schema:** `npm run build` passes and leaves `lib/` **byte-identical
|
|
503
|
+
to HEAD** — this fix changes no code, only declarations and documentation, so
|
|
504
|
+
no host's runtime behaviour can regress. `npm run check:config-schema` passes
|
|
505
|
+
against the pinned `0.2.0-rc.2` CLI (`/34 → $defs/config19`, volatile fields
|
|
506
|
+
pinned).
|
|
507
|
+
- **Environment note, not a defect:** `check:config-schema` shells out to
|
|
508
|
+
`npx --yes @deepseek-ai/dsh@0.2.0-rc.2`, and this machine's `~/.npm/_cacache`
|
|
509
|
+
contains root-owned files, so the default npm cache fails with `EPERM`. Running
|
|
510
|
+
it with `npm_config_cache` pointed at a writable directory passes, and the
|
|
511
|
+
unchanged HEAD build fails identically under the default cache, which is what
|
|
512
|
+
attributes the failure to the machine rather than to this change.
|
|
513
|
+
|
|
514
|
+
### Evidence limits
|
|
515
|
+
|
|
516
|
+
Verified: install admission on alpha.4, profile composition, plugin startup, and
|
|
517
|
+
the full unit/typecheck/build/schema suite. **Not** verified here: a real iPhone
|
|
518
|
+
against this alpha.4 host, the Funnel transport, and a real model turn. The
|
|
519
|
+
phone-side contract is unchanged by this release — protocol v2, pairing state,
|
|
520
|
+
and device records are untouched, so no paired phone needs to re-pair — but that
|
|
521
|
+
is a source-level verdict, not a device run.
|
|
522
|
+
|
|
523
|
+
## 2026-10-14 — audit of `dsh-v0.2.1-alpha.3`
|
|
524
|
+
|
|
525
|
+
### Scope and method
|
|
526
|
+
|
|
527
|
+
Compared `dsh-v0.2.1-alpha.2...dsh-v0.2.1-alpha.3` (**852 commits, 3311 changed
|
|
528
|
+
files, 120,978 insertions, 16,632 deletions**) by fetching the new tag into the
|
|
529
|
+
existing blobless clone (`.audit-dsh-alpha2`, whose HEAD was already the alpha.2
|
|
530
|
+
audit's target SHA `d7432673`), then `git diff --name-status` and per-path
|
|
531
|
+
content diffs into `.audit-alpha3/diffs/`. Four parallel read-only passes
|
|
532
|
+
covered `packages/api` + `apps/cli` + `packages/typert` + `packages/settings` +
|
|
533
|
+
`vendor`, `packages/client/{connection,locale,ui-settings,ui-slots}` +
|
|
534
|
+
`packages/boot` + `packages/bundle`, `packages/{credentials,subagent,session,
|
|
535
|
+
schedule}`, and `packages/{core,host,skill,llm}`. All **14** upgrade guides
|
|
536
|
+
added by this release (under `docs/upgrade-guide/v0.2.0-rc.2/`,
|
|
537
|
+
`v0.2.1-alpha.1/`, `v0.2.1-alpha.2/`) were read in Chinese in full.
|
|
538
|
+
|
|
539
|
+
The alpha.2 audit's lesson — judge the seams reached through `ctx.get`, not just
|
|
540
|
+
the peer list — is what caught this one: the peer list is *not* where the breaks
|
|
541
|
+
are. `@deepseek-ai/dsh-api-remote-access` is new, `packages/schedule/schedule`
|
|
542
|
+
has **zero** changed source files, and the peer packages' own exported surfaces
|
|
543
|
+
moved far less than the carrier contracts around them.
|
|
544
|
+
|
|
545
|
+
### The four confirmed breaks
|
|
546
|
+
|
|
547
|
+
Every one is the same root cause: alpha.3 makes the Peer explicit. `PeerScope`
|
|
548
|
+
(`@deepseek-ai/dsh-typert-protocol`) gained required `principal`, `signal`, and
|
|
549
|
+
`interactions`; `client/connection` added a `Peer` class and deleted
|
|
550
|
+
`OperatorPeer`; the Gateway deleted `operatorPeer()` and its
|
|
551
|
+
`request.peer ?? this.operatorPeer()` fallback.
|
|
552
|
+
|
|
553
|
+
Reproduction used the **published** bundles, the same technique as the alpha.2
|
|
554
|
+
`projections` break, with the plugin's exact argument list
|
|
555
|
+
(`open('$events', payload, undefined, peer, signal)`):
|
|
556
|
+
|
|
557
|
+
```sh
|
|
558
|
+
# .audit-alpha3/repro-peer-contract.mjs, against
|
|
559
|
+
# alpha.2: ~/.npm/_npx/b5c6312874079fe8/node_modules/@deepseek-ai/dsh-api-gateway/lib/index.js
|
|
560
|
+
# alpha.3: .audit-alpha3/cli-install/node_modules/@deepseek-ai/dsh-api-gateway/lib/index.js
|
|
561
|
+
# A. peer = undefined (what the plugin sends today)
|
|
562
|
+
alpha.2: 未抛错
|
|
563
|
+
alpha.3: 抛错 TypeError: Cannot read properties of undefined (reading 'signal')
|
|
564
|
+
# B. peer = { principal: owner, signal, interactions: 'none' }
|
|
565
|
+
alpha.2: 未抛错
|
|
566
|
+
alpha.3: 抛错 TypertGatewayError: $events: forwarded Remote events require interactions=answer
|
|
567
|
+
# C. peer = { principal: owner, signal, interactions: 'answer' }
|
|
568
|
+
alpha.2: 未抛错
|
|
569
|
+
alpha.3: 未抛错
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
Break 4 was settled by reading the shipped artifacts rather than by inference:
|
|
573
|
+
`@deepseek-ai/dsh-client-connection`'s `./client` now maps `node` →
|
|
574
|
+
`lib/client.node.js`, and that file contains **zero** `__ModuleLoader__`
|
|
575
|
+
occurrences while `client.browser.js` and alpha.2's `client.js` each contain
|
|
576
|
+
one. `loadClientFaces` builds its module table *only* from that banner, so on
|
|
577
|
+
Node the table stays empty. Both shapes export `apply` and `inject`, which is
|
|
578
|
+
what makes a banner-optional fallback possible.
|
|
579
|
+
|
|
580
|
+
### The fix
|
|
581
|
+
|
|
582
|
+
One call form serves both audited hosts, because alpha.2 ignores a second
|
|
583
|
+
`fetch` argument and defaults an absent `open` peer to the operator Peer it
|
|
584
|
+
holds:
|
|
585
|
+
|
|
586
|
+
- `src/dsh-remote-interactions.ts` mints one Peer through
|
|
587
|
+
`connection.createPeer({ principal: { kind: 'owner' }, interactions: 'answer' })`
|
|
588
|
+
and falls back to `connection.operator` on a Host without that entry point.
|
|
589
|
+
The same Peer is named on `fetch` and on `wireStream.open`.
|
|
590
|
+
- The Connection install prefers the explicit
|
|
591
|
+
`installConnection(ctx, { transport, interactions: 'answer' })`, because
|
|
592
|
+
`apply(ctx)` cannot name the participation and therefore always selects
|
|
593
|
+
`'none'` for this caller; `apply` remains the fallback for a host that predates
|
|
594
|
+
the installer.
|
|
595
|
+
- `loadClientFaces` accepts a Node bundle's named exports when the browser
|
|
596
|
+
banner did not register them. A banner registration still wins, because the
|
|
597
|
+
bundle's own internal `require()` resolves against it.
|
|
598
|
+
|
|
599
|
+
Six regression tests in `tests/dsh-wire-stream-contract.test.ts` pin the
|
|
600
|
+
contract: the operator fallback, the alpha.3 `createPeer` request shape and the
|
|
601
|
+
Peer reaching `wireStream.open`, both installer branches, and both module-table
|
|
602
|
+
branches. The file fails against the previous call form — verified by restoring
|
|
603
|
+
the source and re-running (1 failure) — and passes after the fix.
|
|
604
|
+
|
|
605
|
+
### Peer range narrowed to the two audited hosts
|
|
606
|
+
|
|
607
|
+
By explicit user direction the DSH peer range stopped being open-ended:
|
|
608
|
+
`>=0.2.0-rc.2 <0.3.0-0` became `0.2.0-rc.2 || 0.2.1-alpha.3` across all ten
|
|
609
|
+
`@deepseek-ai/dsh*` peers, with `@deepseek-ai/cordis` widened to
|
|
610
|
+
`~4.0.4 || ~4.0.5-alpha.1` and `@deepseek-ai/schemastery` to
|
|
611
|
+
`~3.18.4 || ~3.18.5-alpha.1`. The two vendor peers are outside DSH's own peer
|
|
612
|
+
check — it reads only `@deepseek-ai/dsh` and `@deepseek-ai/dsh-*` — so their
|
|
613
|
+
ranges matter only to npm's install-time resolution, which runs without
|
|
614
|
+
`includePrerelease`; naming both vendored prereleases keeps a clean install on
|
|
615
|
+
either host. `devDependencies` stay pinned to `0.2.0-rc.2`.
|
|
616
|
+
|
|
617
|
+
The consequence is deliberate: `evaluatePluginCompatibility` runs before a
|
|
618
|
+
profile is composed on every start, so the next DSH release will refuse to
|
|
619
|
+
activate this plugin until the list is widened by an audit. That reversal of the
|
|
620
|
+
2026-09-29 policy is recorded in `docs/决策记录.md` (章节一, 条目2).
|
|
621
|
+
`tests/compatibility-metadata.test.ts` now asserts both admissions, fifteen
|
|
622
|
+
rejections, and the two vendor ranges.
|
|
623
|
+
|
|
624
|
+
### Host-side changes with no plugin impact
|
|
625
|
+
|
|
626
|
+
`packages/schedule/schedule/**` has no changed source; the schedule error-code
|
|
627
|
+
table is identical, so `src/wire-errors.ts`'s twelve mappings (including
|
|
628
|
+
`subagent_session → E_PROTOCOL`) stay correct. No session-log format migration
|
|
629
|
+
exists — `session-format*`, `v0-to-v1`…`v3-to-v4`, `session-persistence`,
|
|
630
|
+
`session-projection*`, `session-log-deepseek` changed only their version and
|
|
631
|
+
locale files — so phone history rendering is unaffected. The subagent descriptor
|
|
632
|
+
is still version 3. `host/webserver`'s `port` widening, the macOS directory
|
|
633
|
+
picker, the PTC call registry, and the new `job/registered` / `job/settled`
|
|
634
|
+
events are all unreachable or safely skipped by this plugin (`projectEvent`'s
|
|
635
|
+
`default: return null`). Settings surfaces are unchanged at the contract level:
|
|
636
|
+
`ui-settings`'s `settings.section` slot has the same SHA as alpha.2, and
|
|
637
|
+
`configForms.get()` kept its name. The Web composition still mounts
|
|
638
|
+
`schedule`/`ui-schedule`, and `directory-picker` is still disabled in place, so
|
|
639
|
+
the plugin's three `cordis.patch.yml` rows still land.
|
|
640
|
+
|
|
641
|
+
### Validation evidence
|
|
642
|
+
|
|
643
|
+
- **Config schema on the published CLI:** isolated `DSH_HOME`, `dsh
|
|
644
|
+
--profile deeppilot-audit --from-default-profile sdk-minimal
|
|
645
|
+
--dump-config-schema --patch cordis.patch.yml` against
|
|
646
|
+
`@deepseek-ai/dsh@0.2.1-alpha.3` → exit 0, 179,851 bytes, the plugin entry at
|
|
647
|
+
`/37` reports `status: 'schema'` with `configRef: #/$defs/config24`, all seven
|
|
648
|
+
volatile assertions pass, no `deeppilot`-attributed diagnostic, and the only
|
|
649
|
+
warning is the `sdk-minimal` template's own missing `directory-picker` row.
|
|
650
|
+
- **Web composition:** the same CLI composed a real Web profile with the plugin
|
|
651
|
+
patch → **1225 rows versus 1214 without it**, the plugin's three rows present
|
|
652
|
+
at `deeppilot-directory-picker-browse` / `…-browse-client` / `deeppilot`, and
|
|
653
|
+
zero `unrecognized Loader tree carrier` entries on either side.
|
|
654
|
+
- **Plugin unit tests:** `npx tsx --test tests/*.test.ts` → **562 tests, 561
|
|
655
|
+
pass, 0 fail, 1 todo**, including the six new contract tests. `npm run
|
|
656
|
+
typecheck`, `npm run build`, and `npm run check:config-schema` (against the
|
|
657
|
+
pinned `0.2.0-rc.2` CLI) all pass with regenerated `lib/`.
|
|
658
|
+
- **Live A/B on a real `0.2.1-alpha.3` host — the evidence that matters.** An
|
|
659
|
+
isolated `DSH_HOME` profile built from the shipped Web template and linked to
|
|
660
|
+
this working tree booted under the published alpha.3 CLI (`--port 3180`; the
|
|
661
|
+
default 3080 was already held by this machine's own Host). The **unfixed**
|
|
662
|
+
`0.9.4` build printed
|
|
663
|
+
`[deeppilot] DSH Remote interaction client unavailable:
|
|
664
|
+
@deepseek-ai/dsh-typert-registry/client Client bundle returned no exports`
|
|
665
|
+
and the fixed build printed no such line. The checklist itself scored
|
|
666
|
+
**23 pass / 1 fail / 4 skipped in both runs** — see the blind spot below.
|
|
667
|
+
- **The regression checklist does not cover this seam.** `scripts/smoke-live.mts`
|
|
668
|
+
scored identically before and after the fix, because the resident Client it
|
|
669
|
+
exercises is only reachable through the approval/question waterfall, and step
|
|
670
|
+
10 is skipped without `--interactions`. The observable difference is the Host
|
|
671
|
+
log line and the phone's approval/question delivery, not a checklist step. A
|
|
672
|
+
future revision should assert on that diagnostic directly.
|
|
673
|
+
- **Backward compatibility, same working tree:** the same profile booted under
|
|
674
|
+
the published `0.2.1-alpha.2` CLI (`--port 3181`) scored **25 pass / 0 fail /
|
|
675
|
+
0 warn / 3 skipped** with no interaction-client diagnostic — the same result
|
|
676
|
+
the alpha.2 audit recorded, so the fix does not regress the host users run
|
|
677
|
+
today.
|
|
678
|
+
- **One checklist difference between the two host versions is real.**
|
|
679
|
+
`模型目录可读` passes on alpha.2 and fails on alpha.3 in the same isolated
|
|
680
|
+
home (`0 provider / 0 model, routable=true`): this release stops listing a
|
|
681
|
+
pi-ai route before its credential resolves and returns only the version-gated
|
|
682
|
+
subset for the account route. The home has no model credential, so the phone's
|
|
683
|
+
model list is empty there. That is the documented behavior change, not a
|
|
684
|
+
plugin defect.
|
|
685
|
+
- **Artifact inspection:** the `node`/`browser` conditional exports and the
|
|
686
|
+
banner counts above were read from the installed alpha.3 packages, not from
|
|
687
|
+
the diff.
|
|
688
|
+
|
|
689
|
+
### Host-side migrations this machine must apply
|
|
690
|
+
|
|
691
|
+
Neither is a plugin defect, and neither is fixed by the plugin change:
|
|
692
|
+
|
|
693
|
+
1. **`llm-deepseek-account`'s retired `models` key.**
|
|
694
|
+
`~/.dsh/profiles/web/cordis.patch.yml:77-79` sets `models: []`.
|
|
695
|
+
`resolveAccountOptions` throws for *any* own `models` key
|
|
696
|
+
(`llm-deepseek-account: models is no longer configurable…`), and the
|
|
697
|
+
upstream test pins `[{ models: [] }, /models is no longer configurable/]`.
|
|
698
|
+
The empty array is not exempt. The `desktop` profile's row carries no
|
|
699
|
+
`config` and is unaffected. Whether the throw takes the whole Host down or
|
|
700
|
+
only retires that route was **not** measured — the guide says the account
|
|
701
|
+
models stop appearing either way.
|
|
702
|
+
2. **`--from-default-profile` now replaces.** It stages a fresh copy over the
|
|
703
|
+
target and deletes the previous directory, including `node_modules` and the
|
|
704
|
+
user's own `cordis.patch.yml`. The re-audit procedure below and the alpha.2
|
|
705
|
+
entry's schema command both use that flag; from now on it must be pointed at
|
|
706
|
+
a scratch name.
|
|
707
|
+
|
|
708
|
+
Checked and **not** required: Azure provider rename (no `azure` /
|
|
709
|
+
`azure-openai-responses` key exists under `~/.dsh/profiles`), credential-file
|
|
710
|
+
extra keys (the file's top level is already `version`/`refs`/`records`), and
|
|
711
|
+
the stored-credential precedence flip (no `refs` name is exported in the shell,
|
|
712
|
+
and the stored value won precedence over `.env` on both sides of the change).
|
|
713
|
+
|
|
714
|
+
### Still unverified
|
|
715
|
+
|
|
716
|
+
- Whether breaks 1 and 2 surface inside `dsh-api-proxy.ts`'s catch or escape it
|
|
717
|
+
as an unhandled rejection — the Gateway opens its Remote Events generation
|
|
718
|
+
asynchronously, after `startDshRemoteInteractions` has already returned.
|
|
719
|
+
- Whether an old profile that predates `@deepseek-ai/dsh-api-remote-access`
|
|
720
|
+
still gets the row (the shipped Web template does; `dsh-base` carries it).
|
|
721
|
+
- How the reshaped `contextBreakdown` renders on iOS, and what the phone shows
|
|
722
|
+
for the unmapped `CLIENT_UPGRADE_REQUIRED` / `MODEL_UNSUPPORTED` codes.
|
|
723
|
+
- Whether the plugin's own `lib/client.js` (banner shape, `dsh.client.inject`,
|
|
724
|
+
`platform: web`) is still accepted by alpha.3's client-modules scanner; that
|
|
725
|
+
scanner lives in `packages/client/modules` and `packages/client/web`, which
|
|
726
|
+
were not read in full.
|
|
727
|
+
|
|
728
|
+
### Re-audit procedure used
|
|
729
|
+
|
|
730
|
+
Fetch the new tag into the existing blobless clone at `.audit-dsh-alpha2`
|
|
731
|
+
(`git fetch --filter=blob:none --no-tags origin
|
|
732
|
+
'+refs/tags/<tag>:refs/tags/<tag>'`, ~3 s), slice
|
|
733
|
+
`git diff --name-status` per package, and write each slice's content diff to a
|
|
734
|
+
file before parallel reading — blobless clones fetch blobs on demand, so one
|
|
735
|
+
`git diff` per region is far cheaper than many small reads. Reproduce a
|
|
736
|
+
suspected carrier break against the **published** `lib/` bundles with a stub
|
|
737
|
+
`this`, as above, rather than trusting either the diff or the release notes.
|
|
738
|
+
`npm --cache <workspace dir>` is still required; `~/.npm/_cacache` holds
|
|
739
|
+
root-owned files and fails `npm view` with `EPERM`.
|
|
740
|
+
|
|
210
741
|
## 2026-10-09 — audit of `dsh-v0.2.1-alpha.2`
|
|
211
742
|
|
|
212
743
|
### Scope and method
|
|
@@ -316,12 +847,12 @@ the mirror's `signal` is required, so the compiler keeps it that way.
|
|
|
316
847
|
own, so a dedicated long-lived controller is not warranted; following the
|
|
317
848
|
existing convention in the same file is enough. `lib/index.js` was regenerated.
|
|
318
849
|
|
|
319
|
-
The fix ships in `0.9.4`,
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
850
|
+
The fix ships in `0.9.4`, published 2026-10-10 (see "Plugin release verdicts").
|
|
851
|
+
A host on `0.2.1-alpha.2` left on the published `0.9.3` still loses the on-open
|
|
852
|
+
projection baseline. That was observed directly: on a live `0.2.1-alpha.2` host
|
|
853
|
+
running published `0.9.3` the diagnostic appeared, and on the same host version
|
|
854
|
+
running this build it did not (see "Live run on a real `0.2.1-alpha.2` host"
|
|
855
|
+
under Validation evidence).
|
|
325
856
|
|
|
326
857
|
`tests/dsh-api-proxy.test.ts` adds "projection baseline reads pass the
|
|
327
858
|
AbortSignal the Host now requires": a controller stub that calls
|