dsh-vision-router 2.1.4 → 2.1.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.
Files changed (36) hide show
  1. package/README.md +15 -6
  2. package/README.zh.md +15 -6
  3. package/cordis.patch.yml +12 -1
  4. package/docs/architecture/2x-contract-ledger.md +1 -1
  5. package/docs/architecture/compat-inventory.md +10 -9
  6. package/docs/architecture/dsh-compatibility-matrix.md +3 -3
  7. package/docs/architecture/dsh-support-window.md +5 -3
  8. package/docs/architecture/host-first-proxy-convergence.md +91 -0
  9. package/docs/architecture/p3-compat-retirement.md +1 -1
  10. package/docs/architecture/p3-host-native-seams.md +1 -1
  11. package/docs/releases/v2.1.5.md +41 -0
  12. package/docs/releases/v2.1.6.md +30 -0
  13. package/index.js +476 -3070
  14. package/lib/adversarial-hardening.js +0 -46
  15. package/lib/client-presentation-boundary-main.js +4 -4
  16. package/lib/client.js +11 -8
  17. package/lib/core-primitives.js +2757 -0
  18. package/lib/doctor-vision-limits.js +5 -5
  19. package/lib/doctor.js +17 -14
  20. package/lib/dsh-support-window.js +3 -3
  21. package/lib/file-logger.js +7 -7
  22. package/lib/legacy-global-proxy-boundary.js +181 -60
  23. package/lib/proxy-dispatcher-pool.js +96 -0
  24. package/lib/proxy-routing.js +76 -0
  25. package/lib/proxy-url-compat.js +12 -0
  26. package/lib/public-entry.js +14 -6
  27. package/lib/remote-settings-bridge.js +5 -1
  28. package/lib/runtime-reliability.js +0 -68
  29. package/lib/settings-ia-client-prelude.js +2 -2
  30. package/lib/sharp-runtime.js +236 -0
  31. package/lib/twin-image-capability-fallback.js +6 -6
  32. package/lib/vision-capability-benchmark-service.js +13 -8
  33. package/lib/vision-model-visibility-boundary-main.js +7 -4
  34. package/lib/vision-provider-transport.js +44 -37
  35. package/lib/vision-tool-runtime-boundary.js +0 -25
  36. package/package.json +7 -6
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
  </p>
18
18
 
19
19
  <p align="center">
20
- <a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v2.1.0"><img src="https://img.shields.io/badge/release-v2.1.0-5B4CF0?style=flat-square" alt="Release v2.1.0" /></a>
20
+ <a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v2.1.6"><img src="https://img.shields.io/badge/release-v2.1.6-5B4CF0?style=flat-square" alt="Release v2.1.6" /></a>
21
21
  <a href="tests"><img src="https://img.shields.io/badge/verified-Node%2022%20%2B%2024-2EA44F?style=flat-square" alt="Verified: Node 22 + 24" /></a>
22
22
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat-square" alt="License: MIT" /></a>
23
23
  <a href="package.json"><img src="https://img.shields.io/badge/Node.js-%3E%3D22-339933?style=flat-square&amp;logo=nodedotjs&amp;logoColor=white" alt="Node.js >=22" /></a>
@@ -39,9 +39,9 @@
39
39
  <p align="center">💬 <strong>QQ community group: 1105463028</strong></p>
40
40
 
41
41
  > [!WARNING]
42
- > 📌 **Announcement (v2.1.0)**
42
+ > 📌 **Announcement (v2.1.6)**
43
43
  >
44
- > **v2.1.0:** Native five-card Settings, explicit Vision mode, runtime i18n, hardened capability routing/benchmarks, and the DSH rc.8 support floor. [What’s new →](docs/releases/v2.1.0.md)
44
+ > **v2.1.6:** Advances exact stable support to DSH `0.1.5-rc.2`, fixes the remote-settings `webServer` startup error, and completes Host-first proxy isolation, lifecycle, redirect-boundary, HTTP CONNECT, and SOCKS5 hardening without raising the rc.8 Host floor. [What’s new →](docs/releases/v2.1.6.md)
45
45
 
46
46
  <p align="center">
47
47
  <img src="assets/vision-demo.gif" width="640" alt="Demo: paste an image, the agent locates the send button with vision_ground / vision_crop / vision_pixel_diff and answers with coordinates" />
@@ -356,7 +356,7 @@ Everything is optional; defaults work out of the box. Prefer **Settings → Visi
356
356
  | `wrappedProviders` | `[{ provider: 'deepseek-official', models: [] }]` | optional manual wrapper scope `{ provider, models[] }`, used after disabling auto-wrap or to restrict which models can enter an internal wrapper through “👁 Vision”; changes apply live, no restart |
357
357
  | `routing` | `false` | legacy whole-turn chain routing (one-shot answer). `false` = tools-first flow (recommended) |
358
358
  | `reverseRouting` | `true` | with `routing: true`, route text turns back to `textProvider` |
359
- | `wrapperRoute` / `chainRoute` | `deepseek-vision` / `vision-chain` | admission wrapper route name / fallback chain route name (empty disables) |
359
+ | `wrapperRoute` / `chainRoute` | `deepseek-vision` / `vision-chain` | developer route names. Leaving either field blank in current Settings clears the override and restores its default; explicitly blank values are retained only for legacy/manual persisted-config compatibility. |
360
360
  | `stealth` | `false` | take over the official `deepseek-official` route (official row only; custom routes are auto-wrapped by default) |
361
361
  | `textProvider` | `deepseek-official` / `deepseek-v4-pro` | the model that reasons (your daily model) |
362
362
  | `tool` / `progressiveTools` / `autoActivateOnImage` | `true` / `false` / `true` | vision tools on / progressive mounting (off by default for a stable tool schema) / image-turn auto-mount when progressive mode is enabled; `progressiveTools` is boot-time config |
@@ -370,9 +370,18 @@ Everything is optional; defaults work out of the box. Prefer **Settings → Visi
370
370
  | `cache` / `cacheTtlSeconds` / `cacheMaxEntries` | `true` / `3600` / `200` | vision answer cache |
371
371
  | `timeoutMs` | `120000` | per vision call deadline |
372
372
  | `artifactsDir` | `.dsh-vision-router/artifacts` | artifact directory (relative to the session workspace) |
373
- | `proxy` / `proxyHosts` | `''` / openrouter hosts | optional proxy for vision provider hosts only |
373
+ | `proxy` / `proxyHosts` | `''` / openrouter hosts | **advanced override**: empty follows the DSH/Host network path; only an explicit value proxies selected vision hosts through Vision Router |
374
374
  | `catalogCorrections` | `true` | built-in catalog-routing corrections for known upstream wire-protocol mismatches; each correction disarms itself once the catalog is fixed upstream |
375
375
 
376
+
377
+ ### Network proxy: DSH/Host first
378
+
379
+ Vision Router does **not own network egress by default**. When `proxy` is empty, Router-owned vision HTTP injects no private dispatcher and the Host-owned compatibility wrapper stays transparent, so requests continue on the current DSH/Host network path. With an explicit override, Host-owned adapter traffic is intercepted only while Vision Router is actively executing that configured visual provider; unrelated concurrent Host traffic keeps the Host route.
380
+
381
+ On the DSH 0.1.5 line (rc.1+), the Host provides process-wide outbound proxy policy from `HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY` / `NO_PROXY`; TUN mode also works transparently below the process. DSH does not automatically read the macOS/Windows “system proxy” switch, so enabling only an app's System Proxy is not the same as proxying the CLI.
382
+
383
+ Set `proxy` only when you intentionally need a **vision-only proxy override**. It remains available for older Hosts, SOCKS5 users, and deployments that need selected vision domains to take a different route; `proxyHosts` scopes only this plugin override and does not redefine the Host's global proxy policy. Redirects cannot widen that scope: once a DVR-proxied request redirects to a host outside `proxyHosts`, that hop returns to the request's inherited Host/caller dispatcher. A request whose initial URL is outside `proxyHosts` stays fully Host-owned, even if a later redirect enters the list.
384
+
376
385
  ### Local Ollama vision backend (merged from dsh-vision)
377
386
 
378
387
  > **Incremental author**: [shaoqiuyuavailable](https://github.com/shaoqiuyuavailable) (router local-vision increment)
@@ -413,7 +422,7 @@ ollama pull qwen2.5vl
413
422
  ## Requirements
414
423
 
415
424
  - DeepSeek Harness Web profile. Normal installs can use `npx @deepseek-ai/dsh ...`; source checkouts use `pnpm dsh ...`. A bare `dsh ...` command only works when the CLI is already on your shell `PATH`.
416
- - **DSH Host support policy:** DVR 2.1.x keeps DSH `0.1.0-rc.8` as the public minimum and currently supports the released stable channel through `0.1.2-rc.1`. Exact `0.1.3-alpha.2` coverage is **verification evidence only**, not a preview support promise; scheduled `latest`/`alpha` canaries monitor drift without changing the support policy. DVR 2.0.x was the final train with public support for rc.6/rc.7. See [DSH Host support window](docs/architecture/dsh-support-window.md).
425
+ - **DSH Host support policy:** DVR 2.1.x keeps DSH `0.1.0-rc.8` as the public minimum and currently supports the released stable channel through `0.1.5-rc.2`. Exact `0.1.5-alpha.2` coverage is **verification evidence only**, not a preview support promise; scheduled `latest`/`alpha` canaries monitor drift without changing the support policy. DVR 2.0.x was the final train with public support for rc.6/rc.7. See [DSH Host support window](docs/architecture/dsh-support-window.md).
417
426
  - Node ≥ 22 (host side).
418
427
  - No API key for the default free chain; a credential reference (`apiKeyEnv`) only for paid `httpProviders`.
419
428
  - Chrome / Chromium / Edge is needed only for `vision_html_screenshot`; every other tool works without a browser.
package/README.zh.md CHANGED
@@ -17,7 +17,7 @@
17
17
  </p>
18
18
 
19
19
  <p align="center">
20
- <a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v2.1.0"><img src="https://img.shields.io/badge/release-v2.1.0-5B4CF0?style=flat-square" alt="Release v2.1.0" /></a>
20
+ <a href="https://github.com/ysr666/dsh-vision-router/releases/tag/v2.1.6"><img src="https://img.shields.io/badge/release-v2.1.6-5B4CF0?style=flat-square" alt="Release v2.1.6" /></a>
21
21
  <a href="tests"><img src="https://img.shields.io/badge/verified-Node%2022%20%2B%2024-2EA44F?style=flat-square" alt="已验证 Node 22 + 24" /></a>
22
22
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat-square" alt="MIT 许可证" /></a>
23
23
  <a href="package.json"><img src="https://img.shields.io/badge/Node.js-%3E%3D22-339933?style=flat-square&amp;logo=nodedotjs&amp;logoColor=white" alt="Node.js >=22" /></a>
@@ -39,9 +39,9 @@
39
39
  <p align="center">💬 <strong>QQ 用户交流群:1105463028</strong></p>
40
40
 
41
41
  > [!WARNING]
42
- > 📌 **公告(v2.1.0)**
42
+ > 📌 **公告(v2.1.6)**
43
43
  >
44
- > **v2.1.0:原生五卡设置、输入框识图、运行时双语、能力路由/测评加固,并正式启用 DSH rc.8 最低支持线。** [查看完整更新 →](docs/releases/v2.1.0.md)
44
+ > **v2.1.6:正式验证 DSH `0.1.5-rc.2`,修复远程设置 `webServer` 启动报错,并完成 Host-first 代理隔离、生命周期、redirect 边界、HTTP CONNECT 与 SOCKS5 加固;公开最低 Host 仍为 rc.8。** [查看完整更新 →](docs/releases/v2.1.6.md)
45
45
 
46
46
  <p align="center">
47
47
  <img src="assets/vision-demo.gif" width="640" alt="演示:粘贴图片,Agent 用 vision_ground / vision_crop / vision_pixel_diff 定位发送按钮并给出坐标" />
@@ -354,7 +354,7 @@ Web profile 现在提供一级 **设置 → Vision Router** 页面。常规页
354
354
  | `wrappedProviders` | `[{ provider: 'deepseek-official', models: [] }]` | 可选手动包装范围 `{ provider, models[] }`;用于关闭自动包装后手动指定,或限制某个 provider 只有部分模型可通过「👁 识图」进入 wrapper |
355
355
  | `routing` | `false` | 旧版整轮链路由(一次性整轮回答)。`false` = 工具优先流程(推荐) |
356
356
  | `reverseRouting` | `true` | 开启 `routing` 时,文字轮路由回 `textProvider` |
357
- | `wrapperRoute` / `chainRoute` | `deepseek-vision` / `vision-chain` | 准入包装路由名 / 降级链路由名(置空关闭) |
357
+ | `wrapperRoute` / `chainRoute` | `deepseek-vision` / `vision-chain` | 开发者路由名。当前设置页留空会清除覆盖并恢复默认值;显式空字符串仅作为旧版/手工持久化配置兼容保留。 |
358
358
  | `stealth` | `false` | 接管官方 `deepseek-official` 路由(仅官方行;自定义路由默认由自动包装处理) |
359
359
  | `textProvider` | `deepseek-official` / `deepseek-v4-pro` | 负责思考的模型(你的日常模型) |
360
360
  | `tool` / `progressiveTools` / `autoActivateOnImage` | `true` / `false` / `true` | 视觉工具总开关 / 渐进式挂载(默认关闭以稳定工具 schema)/ 渐进模式下图片轮自动挂载;`progressiveTools` 为启动期配置 |
@@ -368,9 +368,18 @@ Web profile 现在提供一级 **设置 → Vision Router** 页面。常规页
368
368
  | `cache` / `cacheTtlSeconds` / `cacheMaxEntries` | `true` / `3600` / `200` | 视觉答案缓存 |
369
369
  | `timeoutMs` | `120000` | 单次视觉调用超时 |
370
370
  | `artifactsDir` | `.dsh-vision-router/artifacts` | 产物目录(相对会话工作区) |
371
- | `proxy` / `proxyHosts` | `''` / openrouter 域名 | 仅视觉供应商域名可选的本地代理 |
371
+ | `proxy` / `proxyHosts` | `''` / openrouter 域名 | **高级覆盖**:留空沿用 DSH/Host 网络路径;仅显式填写时让指定视觉域名使用插件代理 |
372
372
  | `catalogCorrections` | `true` | 内置目录纠错:当已安装目录把已知模型路由到错误协议时按正确协议应答;上游修复后对应纠错自动失效 |
373
373
 
374
+
375
+ ### 网络代理:默认跟随 DSH/Host
376
+
377
+ Vision Router 默认**不接管网络出口**。`proxy` 留空时,Router-owned 视觉 HTTP 不注入自有 dispatcher,Host-owned 兼容层也保持透明,因此请求继续沿用 DSH/Host 当前网络路径。显式填写覆盖时,Host-owned adapter 也只会在 Vision Router 正在执行该已配置视觉模型的调用作用域内被代理;并发的其他 Host 请求仍沿用 Host 路径。
378
+
379
+ 在 DSH 0.1.5 系列(rc.1+)中,Host 已提供统一出网代理:`HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY` / `NO_PROXY` 在启动时解析并应用;TUN 模式也会在更底层透明生效。DSH 本身不会自动读取 macOS/Windows 的“系统代理”开关,所以仅打开代理软件的 System Proxy 并不等价于 CLI 已经走代理。
380
+
381
+ 只有在你确实需要“**视觉请求单独走另一条代理**”时才填写 `proxy`。这仍保留给旧 Host、SOCKS5 用户和按视觉域名定向覆盖的高级场景;`proxyHosts` 只约束这一插件级覆盖,不会重定义 Host 的全局代理策略。 Redirect 也不会扩大这个范围:已进入 DVR 代理的请求一旦跳转到 `proxyHosts` 之外,该跳立即回到请求原本继承的 Host/caller dispatcher;首个 URL 不在 `proxyHosts` 的请求则全程保持 Host-owned,即使后续跳转进入名单也不会临时加载 DVR 代理。
382
+
374
383
  ### 本地 Ollama 视觉后端(并入自 dsh-vision)
375
384
 
376
385
  > **增量开发作者**:[shaoqiuyuavailable](https://github.com/shaoqiuyuavailable)(router 本地视觉增量)
@@ -411,7 +420,7 @@ ollama pull qwen2.5vl
411
420
  ## 环境要求
412
421
 
413
422
  - DeepSeek Harness 的 Web profile。普通安装可用 `npx @deepseek-ai/dsh ...`;从源码仓库运行时用 `pnpm dsh ...`。只有 CLI 已经进入系统 `PATH` 时才能直接写 `dsh ...`。
414
- - **DSH Host 支持策略:** DVR 2.1.x 的公开最低 Host 仍为 DSH `0.1.0-rc.8`,当前正式发布通道已验证并支持到 `0.1.2-rc.1`。对 `0.1.3-alpha.2` 的精确覆盖**只属于验证证据**,不代表对 preview 的公开支持承诺;定时 `latest`/`alpha` canary 只负责发现上游漂移,也不会自动改变支持策略。DVR 2.0.x 是最后公开支持 rc.6/rc.7 的版本线。详见 [DSH Host 支持窗口](docs/architecture/dsh-support-window.md)。
423
+ - **DSH Host 支持策略:** DVR 2.1.x 的公开最低 Host 仍为 DSH `0.1.0-rc.8`,当前正式发布通道已验证并支持到 `0.1.5-rc.2`。对 `0.1.5-alpha.2` 的精确覆盖**只属于验证证据**,不代表对 preview 的公开支持承诺;定时 `latest`/`alpha` canary 只负责发现上游漂移,也不会自动改变支持策略。DVR 2.0.x 是最后公开支持 rc.6/rc.7 的版本线。详见 [DSH Host 支持窗口](docs/architecture/dsh-support-window.md)。
415
424
  - Node ≥ 22(宿主侧)。
416
425
  - 默认免费链路无需 API Key;付费 `httpProviders` 只需一个凭据引用(`apiKeyEnv`)。
417
426
  - 只有 `vision_html_screenshot` 需要 Chrome / Chromium / Edge;其余工具无浏览器也能用。
package/cordis.patch.yml CHANGED
@@ -4,9 +4,20 @@
4
4
  # without any manual cordis.patch.yml edits. Later layers (the profile's own
5
5
  # cordis.patch.yml, --patch overlays) override these rows by id.
6
6
 
7
- # 纯增量补丁(issue #34):不碰核心行。最低支持 Host 仍保留旧兼容路径;
7
+ # 纯增量补丁(issue #34):不替换/禁用核心行。最低支持 Host 仍保留旧兼容路径;
8
8
  # batch-attachment 合同的 Host 始终拥有 deepseek-official,插件只提供
9
9
  # 「+ 自动识图」包装路由,因此这里永远不默认禁用官方 llm-deepseek 行。
10
+ #
11
+ # DSH 0.1.5 family(含当前 0.1.5-rc.1)的 client-modules Node half 在 webServer 尚未可用时会走
12
+ # ctx.inject() 延迟注册路径;Linux 并行 Loader 激活可在安装额外 client bundle 后
13
+ # 命中 Cordis 的 service-access 竞态("webServer without inject")。rc.8 至当前
14
+ # Web bundle 都使用同一个 modules row,因此只给该既有行追加显式 webServer
15
+ # activation dependency:不替换 row,不改变 client graph,只把官方已经需要的
16
+ # Web carrier 依赖从运行时探测收敛成 Loader 顺序。非 Web surface 缺少该 row 时
17
+ # Include 按官方 patch 语义仅跳过此 overlay。上游修复该竞态后可重新审计删除。
18
+ - id: modules
19
+ name: '@deepseek-ai/dsh-client-modules'
20
+ inject: [webServer]
10
21
 
11
22
  # 挂载插件行。默认保持完整视觉工具表常驻(issue #81):虽然渐进挂载可以
12
23
  # 少发一小段工具 schema,但图片轮首次扩展工具列表会改变请求前缀,可能让
@@ -40,7 +40,7 @@ A green test run while the old path can still silently rescue the new path is no
40
40
  | session surface repair | existing `surfaceOp: { op: 'replace' }` and `sourceEventSeqs` semantics remain compatible |
41
41
  | attachment identity | durable attachment ids remain Host/session identities; no cross-session lookup is introduced |
42
42
  | artifact publication | existing public derived-artifact paths/return values remain compatible; managed run cleanup remains confined to Router-owned provenance/namespaces |
43
- | proxy setting | existing proxy/proxyHosts behavior remains compatible; Router-owned HTTP stays independent of process-global fetch mutation |
43
+ | proxy setting | persisted `proxy` / `proxyHosts` remain compatible; blank `proxy` means Host-owned egress, while an explicit value remains a vision-only advanced override. Router-owned HTTP stays independent of process-global fetch mutation |
44
44
  | Doctor | Closure does not turn advisory architecture/support diagnostics into new failure exit codes |
45
45
  | support window | DVR 2.0.x continues to support the published minimum/previous/current DSH window; rc.6 support is not removed by a patch-level closure |
46
46
  | runtime platforms | Node 22/24 and the existing Ubuntu/macOS/Windows host-sharp contract remain supported |
@@ -70,18 +70,19 @@ P0 records why each major compatibility seam exists and the condition that permi
70
70
  - **Reason:** carry the Router-owned provider transport into compatibility callers whose mature function signatures still accept only a raw `fetch` or use an internal direct HTTP call, while keeping Router traffic off the process-global fetch patch.
71
71
  - **Host gap:** this is an internal composition gap rather than a DSH version persona: `fetchWithOpenAICompatibility(...)` and the Anthropic catalog-correction path do not yet receive a `VisionProviderTransport` parameter explicitly.
72
72
  - **First needed for:** provider-scoped transport ownership and proxy narrowing without rewriting the mature compatibility call signatures in the same migration.
73
- - **Feature detection:** explicit transport-aware callers bypass the registry; only compatibility paths that call `currentVisionProviderTransport()` consume the currently installed process/profile transport. The registry never patches `globalThis.fetch`.
74
- - **Removal condition:** every Router-owned compatibility caller receives `VisionProviderTransport` explicitly, production has zero reads of `currentVisionProviderTransport()`, and the install/release registry can be removed without changing proxy, credential, bounded-body or cancellation behavior.
75
- - **Tests:** `vision-provider-transport`, `http-compat`, `catalog-corrections`, P2 Data Boundary provider-transport Node 22/24, Host pack/install smoke.
73
+ - **Feature detection:** explicit transport-aware callers bypass the registry; only compatibility paths that call `currentVisionProviderTransport()` consume the currently installed process/profile transport. The registry never patches `globalThis.fetch`. Router-owned and scoped Host-owned explicit proxies share one lease/retire dispatcher pool. First-hop `proxyHosts` admission preserves the no-Undici Host path for non-matches; admitted requests use a request-scoped selector that re-checks every redirect origin and delegates non-matches to the request-start Host/caller dispatcher.
74
+ - **Removal condition:** every Router-owned compatibility caller receives `VisionProviderTransport` explicitly, production has zero reads of `currentVisionProviderTransport()`, and the install/release registry can be removed without changing proxy, redirect-hop authority, credential, bounded-body, cancellation, or dispatcher-lifecycle behavior.
75
+ - **Tests:** `vision-provider-transport` (A→B lifecycle, proxy clear, pending-construction unload, synchronous loader failure, real Fetch listed→unlisted redirect, initial-unlisted no-import and explicit-caller fallback), `legacy-global-proxy-boundary` (scoped Host-owned redirect and pool cleanup), `http-compat`, `catalog-corrections`, P2 Data Boundary provider-transport Node 22/24, Host pack/install smoke.
76
76
 
77
77
  ## `lib/legacy-global-proxy-boundary.js`
78
78
 
79
- - **Reason:** retain the process-global proxy patch only for Host-owned/raw-fetch visual providers that still lack a provider-scoped proxy seam. Router-owned `vision-http` and direct protocol-correction traffic already uses `VisionProviderTransport` with an explicit dispatcher.
80
- - **Host gap:** the supported Host window does not yet guarantee one provider-scoped/shared HTTP proxy seam that third-party Host-owned adapters can consume without a process-global fetch wrapper.
81
- - **First needed for:** legacy/custom Host-owned visual provider compatibility when users configure Vision Router proxy routing.
82
- - **Feature detection:** live visual-chain ownership. Router-owned routes bypass the legacy patch; any unknown/Host-owned provider conservatively keeps it available. This is capability/ownership detection, not a Host-version persona.
83
- - **Removal condition:** **the minimum supported DSH provides a provider-scoped/shared HTTP proxy seam** that covers the remaining Host-owned/raw-fetch provider compatibility requirement.
84
- - **Tests:** `legacy-global-proxy-boundary`, `vision-provider-transport`, `adversarial-hardening`, P2 Data Boundary Node 22/24.
79
+ - **Reason:** preserve the explicit Vision Router proxy override for Host-owned/raw-fetch visual providers without granting that configuration process-wide routing authority. Router-owned HTTP already uses `VisionProviderTransport`; blank `proxy` leaves the compatibility wrapper fully transparent.
80
+ - **Host gap:** DSH 0.1.5 owns ordinary process egress, but a Host adapter invoked through `ctx.llm.stream()` still exposes no DVR-owned request/dispatcher parameter for a vision-only SOCKS/selective override. A separate legacy direct whole-turn mode (`routing=true` plus blank `chainRoute`) also hands control to the Host after the DVR hook returns, leaving no adapter-iteration scope to authorize.
81
+ - **First needed for:** legacy/custom Host-owned visual provider compatibility when users configure a Vision Router-specific proxy override.
82
+ - **Feature detection:** live explicit proxy + exact configured Host-owned provider/model + AsyncLocalStorage visual-call scope. Router-owned routes, blank proxy, different pairs and concurrent ordinary Host traffic are pass-through. Only the explicit direct whole-turn blank-`chainRoute` configuration retains unscoped compatibility.
83
+ - **H3 product decision:** KEEP `proxy` / `proxyHosts` supported and non-deprecated as a local-only Advanced override; do not add a second legacy-proxy toggle. Explicit blank `chainRoute` is legacy persisted/manual compatibility, not a current Settings workflow.
84
+ - **Removal condition:** Host-owned adapter requests can receive the explicit DVR override through a scoped Host transport (or the override is intentionally retired under an announced product policy), and the direct whole-turn explicit-empty `chainRoute` state is migrated/retired by support-window policy.
85
+ - **Tests:** `legacy-global-proxy-boundary`, `vision-provider-transport`, exact Host proxy egress contract, Benchmark/Exact Check coverage, P2 Data Boundary Node 22/24.
85
86
 
86
87
  ## `lib/legacy-core-vision-policy-bridge.js`
87
88
 
@@ -10,8 +10,8 @@ The matrix is capability-based. Runtime code must feature-detect the seam it nee
10
10
  | --- | --- | --- |
11
11
  | `minimum-contract` | `0.1.0-rc.6` | Historical compatibility-retention fixture. The name is legacy; DVR 2.1.x public support starts at rc.8. |
12
12
  | `legacy-contract` | `0.1.0-rc.8` | Public support-floor fixture carrying batch attachments and dimension policy. |
13
- | `current-contract` | `0.1.2-rc.1` | Current stable Host contract baseline. Must remain green. |
14
- | exact preview gates | `0.1.3-alpha.2` | Required verification evidence only; not a public preview-support claim. |
13
+ | `current-contract` | `0.1.5-rc.2` | Current stable Host contract baseline. Must remain green. |
14
+ | exact preview gates | `0.1.5-alpha.2` | Required verification evidence only; not a public preview-support claim. |
15
15
  | `latest-dsh` / alpha canaries | resolved dynamically from npm dist-tags | Scheduled drift surveillance only. Never changes support policy by itself. |
16
16
 
17
17
  Node 22 and Node 24 remain the general required runtime matrix. The Host contract jobs are additive; they do not replace the normal test matrix.
@@ -20,7 +20,7 @@ Node 22 and Node 24 remain the general required runtime matrix. The Host contrac
20
20
 
21
21
  `yes` means the fixture has a direct positive test or feature probe. `no` means a direct negative probe exists. `compat` means the fixture proves Vision Router can safely carry the newer input/config through that Host, but does **not** claim the Host owns that capability. `probe` means the capability is intentionally not inferred from the version label and is verified at runtime/contract-test time.
22
22
 
23
- | Capability | minimum-contract rc.6 | legacy-contract rc.8 | current-contract rc.1 (0.1.2) | Evidence / detection |
23
+ | Capability | minimum-contract rc.6 | legacy-contract rc.8 | current-contract rc.2 (0.1.5) | Evidence / detection |
24
24
  | --- | --- | --- | --- | --- |
25
25
  | Batch attachment save | no | yes | yes | `hasBatchAttachmentContract()` checks the released `attachments.saveImages` prototype; `tests/rc6-rc7-compat.test.js`; contract CI. |
26
26
  | Max image dimension policy | compat | yes | yes | All fixtures parse the complete attachment-local row; rc.8/current positively retain the field and the established admission tests exercise the 10000/10001 boundary. Older Schemastery passthrough is not treated as ownership evidence. |
@@ -9,10 +9,12 @@ The public support policy contains only released Host semantics. Preview/canary
9
9
  | Role | DSH train | Meaning |
10
10
  |---|---|---|
11
11
  | Minimum Supported Host | `0.1.0-rc.8` | Oldest Host generation that DVR 2.1.x publicly supports. |
12
- | Current Stable Host | `0.1.2-rc.1` | Current npm stable-channel release covered by required exact Host and browser evidence. |
12
+ | Current Stable Host | `0.1.5-rc.2` | Current npm stable-channel release covered by required exact Host and browser evidence. |
13
13
 
14
14
  DVR `2.1.x` therefore keeps `0.1.0-rc.8` as its public floor and supports released Host trains through the current stable channel. Runtime branching remains capability-based rather than version-string-driven.
15
15
 
16
+ DSH `0.1.5-rc.1` remains explicitly admitted for existing installations; current exact stable evidence has advanced to `0.1.5-rc.2`. Advancing this evidence does not raise the public minimum.
17
+
16
18
  No later support-floor increase is currently announced.
17
19
 
18
20
  ## Verification evidence — not support policy
@@ -21,8 +23,8 @@ Compatibility evidence answers a different question: what exact upstream release
21
23
 
22
24
  | Evidence role | DSH source | Meaning |
23
25
  |---|---|---|
24
- | Exact stable evidence | `0.1.2-rc.1` | Required Host/wire and real Host + Chromium coverage for the current stable release. |
25
- | Exact preview evidence | `0.1.3-alpha.2` | Required preview Host/wire/lifecycle/browser evidence. This is not a preview support promise. |
26
+ | Exact stable evidence | `0.1.5-rc.2` | Required Host/wire and real Host + Chromium coverage for the current stable release. |
27
+ | Exact preview evidence | `0.1.5-alpha.2` | Required preview Host/wire/lifecycle/browser evidence. This is not a preview support promise. |
26
28
  | Stable drift canary | npm dist-tag `latest` | Scheduled, dynamically resolved surveillance. A failure starts compatibility investigation; it does not rewrite support policy. |
27
29
  | Preview drift canary | npm dist-tag `alpha` | Scheduled, dynamically resolved surveillance with preview-specific lifecycle coverage. A failure does not rewrite support policy. |
28
30
 
@@ -0,0 +1,91 @@
1
+ # Host-first Proxy Convergence
2
+
3
+ Status: **H0 + H1 + H2 + H3 complete without raising the DSH support floor**
4
+
5
+ H1 baseline: `main@9fb7f1736813f1f5c63c1f0e8214eb12a779f24e`
6
+
7
+ H2 merged: `main@40b43d78b7c105c19188059172c2883eea9e681c`
8
+
9
+ ## Decision
10
+
11
+ Network egress is a Host concern, not a vision-routing concern. Vision Router therefore treats DSH/Host as the default network authority and keeps its own proxy only as an explicit, vision-only compatibility/advanced override.
12
+
13
+ `proxy: ''` means **do not override transport**. Router-owned HTTP calls pass no private dispatcher, and the Host-owned compatibility wrapper stays transparent. Whatever path DSH/Host currently owns — direct, environment proxy, or a lower-level TUN — remains authoritative.
14
+
15
+ An explicit non-empty `proxy` keeps the existing Vision Router behavior for users who need a different route for selected `proxyHosts`, including legacy SOCKS5 configurations. Persisted settings are not migrated or rewritten.
16
+
17
+ ## Why this direction
18
+
19
+ DSH's 0.1.5 line introduced a process-wide outbound proxy subsystem (`@deepseek-ai/dsh-http-proxy`) with one Host policy and a public `proxyRouteFor()` transport seam. Keeping a second generic proxy authority inside Vision Router would duplicate routing, redirect, dispatcher-lifecycle, and ownership policy.
20
+
21
+ The production plugin does not import or require that Host package. The current public support window still includes older DSH releases, and the upstream package contract explicitly says ordinary `fetch()` callers should do nothing: the Host global dispatcher already owns routing. Calling `proxyRouteFor()` is reserved for consumers that must branch on proxy state or own a transport that cannot use normal fetch. H1 therefore adopts the Host capability by preserving plain fetch and proving the behavior against exact Host source, rather than adding a second route decision.
22
+
23
+ ## Compatibility matrix
24
+
25
+ | Host / user state | Authority after H0 | Vision Router behavior |
26
+ |---|---|---|
27
+ | Any supported Host, `proxy=''` | DSH/Host | inject no dispatcher; compatibility wrapper is transparent |
28
+ | Explicit `proxy` + Router-owned HTTP | Vision Router for matching vision hosts | provider-scoped dispatcher; no global interception |
29
+ | Explicit `proxy` + Host-owned visual adapter | Vision Router only inside that visual adapter call | AsyncLocalStorage-scoped dispatcher interception |
30
+ | `routing=true` + explicit blank `chainRoute` + Host-owned provider | Vision Router legacy compatibility | narrow unscoped direct whole-turn fallback retained until H3 |
31
+ | SOCKS5 / legacy `socks5h` override | Vision Router | preserved; `socks5h` is projected at the Undici boundary |
32
+ | Non-matching `proxyHosts` | DSH/Host | no plugin dispatcher and no Undici import |
33
+
34
+ ## H0 invariants
35
+
36
+ 1. Blank/whitespace `proxy` never authorizes the legacy proxy compatibility wrapper.
37
+ 2. Blank `proxy` never imports Vision Router's userland Undici ProxyAgent.
38
+ 3. Router-owned HTTP with blank `proxy` calls the captured Host fetch without an explicit dispatcher, so ambient Host dispatcher changes remain visible at request time.
39
+ 4. Explicit `proxy` remains live-editable and preserves `proxyHosts` narrowing.
40
+ 5. No schema migration, no setting rewrite, no DSH peer-range increase, and no new dependency on `@deepseek-ai/dsh-http-proxy`.
41
+ 6. The legacy compatibility seam is relevant only for the intersection: explicit plugin proxy **and** Host-owned/raw-fetch visual provider.
42
+
43
+ ## H1 — Host capability adoption
44
+
45
+ H1 is complete as an egress contract, not as a new production dependency. Exact DSH source gates now run a local fake proxy through the Host's real `installProxyFromEnvironment()` implementation and drive Vision Router's shipping provider transport with `proxy: ''`. The contract proves all of the following:
46
+
47
+ 1. Host proxy policy receives Vision Router egress while Vision Router reports no private override and never imports its ProxyAgent.
48
+ 2. Host `NO_PROXY` remains authoritative for a bypassed target.
49
+ 3. A redirect from a proxied origin to a `NO_PROXY` origin is re-evaluated by the Host dispatcher per hop; the first-hop proxy decision is not pinned across the redirect.
50
+ 4. The same contract runs against the exact current stable Host and exact preview evidence on Linux, macOS, and Windows through the existing source-contract matrix.
51
+ 5. Production code contains no `@deepseek-ai/dsh-http-proxy` dependency or import. `proxyRouteFor()` is used only by the exact-source test as an oracle for the Host decision.
52
+
53
+ The current stable evidence advances to DSH `0.1.5-rc.2`; `0.1.5-rc.1` remains explicitly peer-admitted, and the public minimum remains `0.1.0-rc.8`.
54
+
55
+ ## H2 — Scope Host-owned override authority
56
+
57
+ H2 retires the **configuration-wide proxy authority** without removing the compatibility feature. Core no longer constructs ProxyAgent instances or installs its own process proxy patch. One compatibility wrapper remains outside runtime composition, but its default behavior is an exact pass-through to the DSH/Host fetch chain that existed when it was installed.
58
+
59
+ For DVR-owned calls into a Host adapter, `streamWithLegacyGlobalProxyScope(provider, model, ...)` keeps an AsyncLocalStorage authorization alive across lazy AsyncIterable creation and every `next()` / `return()` / `throw()` operation. The wrapper injects a private dispatcher only when the live settings still contain an explicit proxy and the active scope exactly matches a configured Host-owned vision pair. Vision-chain adapter calls, `vision_describe`, capability Benchmark and Exact Check use this same boundary. Router-owned direct HTTP continues through `VisionProviderTransport` instead.
60
+
61
+ H2 regression proof includes a deliberately blocked Host-owned visual stream plus a concurrent same-origin ordinary Host fetch. The ordinary request receives no DVR dispatcher; only the visual request receives the marked ProxyAgent dispatcher after its stream resumes. Clearing the proxy while the visual stream is active immediately returns later requests to Host authority.
62
+
63
+ One unscoped compatibility case remains intentionally: `routing=true` with an explicitly blank `chainRoute` routes the whole image turn directly to the first Host provider after the DVR routing hook returns, so there is no DVR-owned adapter-iteration boundary to scope. H2 preserves that old configuration narrowly rather than silently breaking it in a patch release.
64
+
65
+ ## H3 — Product contract for the override and last wrapper
66
+
67
+ H3 decides to **keep `proxy` / `proxyHosts` supported and non-deprecated** as a local-only Advanced override. No extra “legacy proxy” toggle is added: blank `proxy` is already the opt-out/default, the controls are already behind Advanced and local-only, and another authority bit would make the settings contract harder to reason about without removing the compatibility boundary.
68
+
69
+ This is a current capability decision, not inertia. The H3 audit on 2026-09-11 checked DSH `0.1.5-rc.2` plus upstream `master@c291e7961a515f6d7af9304e7fd1d257929aef26`: `@deepseek-ai/dsh-http-proxy` still accepts only `http:` / `https:` and explicitly diagnoses SOCKS-family URLs as unsupported. The Host LLM adapter surface at that revision also still has no generic per-call dispatcher/transport input that a plugin can pass through `ctx.llm.stream()`. DVR issue #455 provides current Windows + DSH 0.1.5-rc.1 user evidence that `socks5://` plus selective `proxyHosts` is a real supported deployment shape. Removing the override now would therefore remove capability, not merely delete compatibility code.
70
+
71
+ The remaining unscoped `routing=true` + explicit `chainRoute=''` behavior is classified as **legacy persisted/manual-config compatibility only**. Current Settings does not create that state: leaving `chainRoute` blank clears the user-layer override, so the schema default `vision-chain` becomes effective again. Existing persisted/manual explicit-empty values continue to work in this support window; H3 neither migrates nor rewrites them. Public documentation must not teach “leave `chainRoute` blank to disable” as a current Settings workflow.
72
+
73
+ The final Host-owned compatibility wrapper remains justified until both conditions are satisfied: (1) Host-owned adapter calls can receive the DVR-specific override through a scoped Host transport/dispatcher seam, or the DVR override is intentionally removed under a future announced product policy; and (2) the legacy direct whole-turn explicit-empty `chainRoute` state has been migrated or retired under the applicable support-window policy. A Host release that merely has a global HTTP(S) proxy does not satisfy those conditions.
74
+
75
+ ### Post-H3 dispatcher lifecycle hardening
76
+
77
+ Both explicit DVR proxy paths now use one `createProxyDispatcherPool()` lease/retire owner. A live proxy identity change retires the previous dispatcher immediately as an authority decision, but request leases prevent graceful close until already-admitted fetch calls have handed control back. Clearing the plugin proxy retires the cached dispatcher without constructing a replacement, Router-owned plugin cleanup calls `transport.dispose()`, and the Host-owned compatibility boundary disposes its pool with its own fiber. Pending constructors that resolve after replacement or unload are still retired and closed; synchronous loader/fetch failures cannot strand leases or poison the cache.
78
+
79
+ ### Per-hop redirect authority
80
+
81
+ `proxyHosts` is an authorization upper bound, not merely a first-request filter. DVR first checks the original request URL before importing its userland Undici; if that URL is not listed, the entire request remains on the inherited Host path, including any later redirect into a listed domain. This deliberately preserves #149's no-Undici boundary for non-admitted traffic.
82
+
83
+ When the original URL is listed, DVR supplies Fetch with a tiny request-scoped dispatcher selector rather than a fixed ProxyAgent. Each Undici `dispatch()` re-checks `options.origin`: listed hops use the leased DVR ProxyAgent; non-listed or malformed origins use the dispatcher that the request inherited at admission time (an explicit caller dispatcher when present, otherwise Undici's current Host global dispatcher snapshot). The selector borrows that fallback and never owns or closes it. Fetch/Undici therefore remains authoritative for redirect status handling, method/body rewriting, replay, credential/header stripping, redirect limits, and cancellation.
84
+
85
+ This also preserves the DSH 0.1.5 Host policy across the repository's Undici-major split: Undici 8 publishes its Dispatcher v2 globally and a `Dispatcher1Wrapper` under the legacy global symbol; DVR's Undici 7 reads that legacy symbol, so a non-listed redirect hop can safely delegate back to the Host-owned dispatcher instead of manufacturing a direct connection.
86
+
87
+ After the shared pool became authoritative for both explicit-proxy paths, the older runtime-level `ProxyDispatcherTracker` and its `globalThis.fetch` observer were removed. Those components could no longer see the real ProxyAgent after per-hop selectors were introduced, and retaining them would create a third, ineffective dispatcher-lifecycle authority. The shared pool is now the only owner that closes DVR-created ProxyAgents; borrowed Host/caller dispatchers remain outside DVR ownership.
88
+
89
+ ## System proxy terminology
90
+
91
+ Vision Router must not implement OS-specific proxy discovery. DSH's 0.1.5 network guide distinguishes OS “system proxy” settings, standard proxy environment variables, and TUN mode; DSH itself follows the environment policy and does not automatically read macOS/Windows system-proxy switches. Host-first therefore means “follow DSH/Host”, not “reimplement operating-system proxy detection in this plugin”.
@@ -24,7 +24,7 @@ P3-B is intentionally a retirement audit, not a quota to delete files. Under the
24
24
  | replay envelope v2 compatibility | old durable histories remain valid inputs even when the live Host is newer | only when the supported history/runtime window no longer needs producer rebinding or Host provides an equivalent native replay identity seam |
25
25
  | adapter prepareCall/coalescing compatibility | the support matrix still spans Host generations with different adapter-registration/update behavior | only when the minimum Host and every DVR-owned adapter satisfy one stable registration/update contract |
26
26
  | pi-ai bridge wire compatibility | legacy direct-bridge traffic remains a supported route shape | only after the direct bridge is retired or all supported Hosts execute that path through an equivalent native wire seam |
27
- | process-global proxy compatibility | P2-E already reduced this to Host-owned/raw-fetch compatibility only; the minimum Host still lacks a provider-scoped/shared proxy seam | when the minimum supported Host provides a provider-scoped/shared HTTP proxy seam |
27
+ | scoped Host-owned proxy compatibility | H0/H1 makes DSH/Host the default authority; H2 removes configuration-wide interception; H3 keeps `proxy` / `proxyHosts` supported because current Host proxy still lacks SOCKS and arbitrary Host adapters expose no DVR per-call dispatcher seam. Explicit blank `chainRoute` is legacy persisted/manual compatibility only | when Host-owned adapter calls can carry the DVR override through a scoped Host transport (or an announced product policy retires the override) **and** the explicit-empty `chainRoute` state is migrated/retired |
28
28
 
29
29
  ## First planned deletion window
30
30
 
@@ -20,7 +20,7 @@ Current result: **NO NEW HOST-NATIVE MIGRATION IS AUTHORIZED IN DVR 2.0.x.**
20
20
  | Candidate | Current evidence | Decision |
21
21
  |---|---|---|
22
22
  | settings exposure | Newer Hosts expose stronger live settings seams, but rc.6 remains the minimum and existing compatibility is still required for the supported window | NO-GO in 2.0.x |
23
- | provider transport / proxy | P2-D moved Router-owned HTTP to `VisionProviderTransport`; P2-E reduced the global patch to Host-owned/raw-fetch compatibility. The minimum Host still has no proven provider-scoped/shared proxy seam | KEEP P2 boundary; no native migration |
23
+ | provider transport / proxy | P2-D moved Router-owned HTTP to `VisionProviderTransport`; H0/H1 proved Host-owned default egress; H2 scopes the explicit DVR override to exact Host-owned visual adapter execution. H3 verifies current DSH still supports only HTTP(S) proxy URLs, while real DVR users rely on SOCKS/selective overrides and arbitrary Host adapters expose no DVR per-call dispatcher seam | KEEP `proxy` / `proxyHosts` supported and KEEP the scoped compatibility boundary; no extra legacy toggle and no generic Host route duplication |
24
24
  | `ctx.jobs` | P2-F's ten-point spike found that Jobs does not replace DVR's priority, authority-revoke, topology-abort and evidence-publication fencing without retaining the custom scheduler | NO-GO; retain current scheduler |
25
25
  | adapter registration replacement | Current Host generations expose better replacement behavior, but a read-only capability probe cannot prove a stable returned handle across the full minimum/previous/current window | NO-GO until minimum Host contract and parity tests prove one handle contract |
26
26
  | scoped tool execution hooks | Current DSH has richer tool pipeline seams, but the rc.6 support floor and existing mature wrapper behavior mean a migration would be a split-path compatibility rewrite rather than simplification | NO-GO in 2.0.x |
@@ -0,0 +1,41 @@
1
+ # v2.1.5
2
+
3
+ DVR 2.1.5 is a compatibility, reliability, and release-hardening patch. It moves the fixed stable evidence to DSH `0.1.5-rc.1`, keeps exact preview evidence on `0.1.5-alpha.2`, fixes live Vision-twin reconciliation and wrapped-model switching, and modularizes the oversized Core runtime without changing the public 2.1.x routing model or minimum Host floor.
4
+
5
+ ## DSH 0.1.5 stable / preview compatibility
6
+
7
+ - Supports the current npm stable Host `0.1.5-rc.1` while keeping DSH `0.1.0-rc.8` as the public minimum for DVR 2.1.x. Exact `0.1.5-alpha.2` coverage remains preview verification evidence only, not a blanket preview-support promise.
8
+ - Admits the exact verified `0.1.5-alpha.1`, `0.1.5-alpha.2`, and `0.1.5-rc.1` Host peers without using a broad semver range that would silently promise compatibility with future untested DSH releases.
9
+ - Moves the required current Host contract, Node 22/24 release-family contracts, exact source checks, and real Host + Chromium browser gates onto `0.1.5-rc.1`; the exact preview gates move to `0.1.5-alpha.2`.
10
+ - Pins exact source evidence to immutable upstream commits and verifies the checkout SHA before running attachment normalization, LLM adapter, session/remotes, and Web compatibility contracts on Ubuntu, macOS, and Windows.
11
+ - Keeps the existing Web `@deepseek-ai/dsh-client-modules` row explicitly waiting for the official `webServer` carrier. Current `0.1.5-rc.1` and `0.1.5-alpha.2` still require this compatibility overlay.
12
+ - Adds a three-state overlay lifecycle contract plus moving upstream watch: `shim-required` keeps the overlay, `retire-ready` fails and requires deliberate retirement once DSH owns the dependency, and `dangerous-drift` fails closed if the upstream row changes incompatibly.
13
+
14
+ ## Vision-mode and live-provider reliability
15
+
16
+ - Preserves Vision mode when the user switches to another model that has a matching hidden Vision Router wrapper in the same visible source provider. Cross-provider switches or targets without a wrapper still leave Vision mode, and DSH's image-session model guards remain authoritative.
17
+ - Treats `wrappedProviders` as configuration intent rather than a snapshot of startup topology. Generated `<provider>-vision` twins are reconciled against the live provider registry: dormant sources do not materialize twins, newly mounted providers gain them, removed providers withdraw them, and provider/model presentation metadata refreshes atomically.
18
+ - Reuses the bounded adapter-update coalescer for synchronous registry events so live provider churn converges without duplicate registrations, re-entrant loops, or stale model filters.
19
+ - Keeps the lower twin-image capability compatibility boundary tolerant of out-of-order registration for older Host shapes while preserving fail-closed ownership checks for Vision Router-owned routes.
20
+
21
+ ## Runtime architecture
22
+
23
+ - Splits the oversized root runtime into `lib/core-primitives.js` and `lib/sharp-runtime.js` while keeping `Config`, `apply`, Host composition, and public exports owned by the existing entry point.
24
+ - The modularization is behavior-preserving: no settings migration, route rename, tool-schema change, or public API change is introduced. A permanent architecture contract prevents the extracted primitives from drifting back into a monolithic entry file or creating a second runtime owner.
25
+
26
+ ## Security and release hardening
27
+
28
+ - Updates the development `sharp` runtime past the libheif advisory while keeping the shared-Host peer contract at `sharp >=0.35.3 <1`, so the security fix does not raise the public Host floor.
29
+ - Reworks the trusted PR impact shadow so `pull_request_target` never checks out PR code. The classifier is fetched from the trusted base commit, size-bounded, and verified against its Git blob identity before execution; permissions remain read-only.
30
+ - Adds deterministic adversarial security fuzzing, dependency review, OpenSSF Scorecard coverage, Private Vulnerability Reporting guidance, and stronger immutable release verification.
31
+ - Expands audited browser-impact triggers so client preludes, model-visibility boundaries, Web modules, Settings client surfaces, and exact compatibility modules cannot change without the corresponding browser/source gates running.
32
+
33
+ ## Validation
34
+
35
+ - Release-candidate coverage includes Node 22/24, DSH rc.6/rc.7/rc.8 compatibility contracts, current stable `0.1.5-rc.1`, exact preview `0.1.5-alpha.2`, Ubuntu/macOS/Windows exact-source contracts, Windows screenshot runtime, host-sharp on all three desktop OSes, routing parity, native multimodal cold resume, large-image resource stress, deterministic hostile-input fuzz, dependency review, CodeQL, and real Chromium lifecycle gates for both exact stable and preview Hosts.
36
+ - The moving release-channel canary also resolves npm `latest` and `alpha` independently so a newly published DSH train is detected before the fixed release evidence is deliberately advanced.
37
+ - No Settings migration is required. Restart DSH Web/Desktop after upgrading so the updated Host and browser compatibility logic is loaded.
38
+
39
+ ## Upgrade
40
+
41
+ Upgrade to 2.1.5 and restart DSH Web/Desktop. Existing Vision Router settings remain compatible.
@@ -0,0 +1,30 @@
1
+ # v2.1.6
2
+
3
+ DVR 2.1.6 is a compatibility and network-hardening patch for the 2.1.x train. It advances exact stable validation to DSH `0.1.5-rc.2`, fixes the DSH 0.1.5 remote-settings startup error, and finishes the Host-first proxy convergence work without changing the public routing model, persisted settings schema, or minimum Host floor (`0.1.0-rc.8`).
4
+
5
+ ## DSH 0.1.5-rc.2 and remote Settings
6
+
7
+ - Advances the fixed stable/exact Host evidence to DSH `0.1.5-rc.2`; exact `0.1.5-alpha.2` coverage remains preview verification evidence only. `0.1.5-rc.1` remains explicitly peer-compatible and the public DVR 2.1.x floor stays at `0.1.0-rc.8`.
8
+ - Fixes #465 by declaring `settings`, `connection`, and `webServer` on the same Cordis caller fiber that invokes `connection.rpc.handle()`. This prevents `cannot get property "webServer" without inject` under DSH 0.1.5 strict service-access semantics.
9
+ - Keeps the remote Settings security model unchanged: the RPC channel remains `trusted-host`, sensitive network/credential/local-device fields stay local-only, and the explicit remote field allow-list plus risk-confirmation flow remain authoritative.
10
+ - Keeps the separate Web-bundle `modules -> webServer` compatibility overlay in place while current upstream DSH still lacks that Loader activation dependency; #448 continues to track its eventual retirement.
11
+
12
+ ## Host-first proxy convergence
13
+
14
+ - Makes the DSH/Host network path authoritative whenever Vision Router's `proxy` is blank. Ordinary Host traffic no longer passes through a second DVR proxy-routing decision.
15
+ - Keeps explicit `proxy` / `proxyHosts` as a supported, local-only Advanced override for visual traffic, including SOCKS5 and selective-host deployments that current DSH Host proxy policy cannot replace.
16
+ - Scopes Host-owned visual adapter overrides with AsyncLocalStorage, so concurrent same-origin Host requests do not inherit DVR proxy state. Vision chain, `vision_describe`, Benchmark, and Exact Check share the same scoped authority.
17
+ - Gives Router-owned and scoped Host-owned ProxyAgents one shared lease/retire lifecycle. Hot proxy replacement, clearing configuration, pending construction, synchronous failures, and plugin unload now retire Agents without leaking or closing in-flight work.
18
+ - Enforces `proxyHosts` on every redirect hop after the initial request is admitted. Redirects that leave the allow-list return to the request-start Host/caller dispatcher while Fetch/Undici remains responsible for redirect semantics, body replay, header stripping, limits, and abort behavior.
19
+ - Preserves historical `socks5h://` settings without rewriting persisted configuration: the compatibility projection to Undici-native `socks5://` happens only after a request is admitted by `proxyHosts`.
20
+ - Removes the obsolete process-wide dispatcher tracker/global-fetch observer after lifecycle ownership moved to the shared dispatcher pool.
21
+
22
+ ## Protocol and regression coverage
23
+
24
+ - Adds real loopback HTTP CONNECT and SOCKS5 protocol tests in addition to MockAgent/FakeProxyAgent coverage. The SOCKS case verifies proxy-side DNS by sending an unresolved domain name through the SOCKS5 tunnel.
25
+ - Exact-source stable/preview contracts continue to run on Ubuntu, macOS, and Windows; Node 22/24 CI, routing parity, adversarial fuzzing, dependency review, CodeQL, native multimodal cold resume, Windows screenshot runtime, and host-sharp integration remain release gates.
26
+ - Pre-release acceptance on macOS used the actual `npm pack` tarball installed through DSH `0.1.5-rc.2`, then exercised the real Chromium Settings UI, a settings write/readback round trip, cold Web restart, and a real headless vision turn. `vision_ocr`, `vision_describe`, and `vision_colors` correctly read a generated image using the machine's normal DSH model credentials.
27
+
28
+ ## Upgrade
29
+
30
+ Upgrade to 2.1.6 and restart DSH Web/Desktop. Existing 2.1.x settings remain compatible; no migration is required.