dsh-vision-router 2.2.7 → 2.3.0

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 (69) hide show
  1. package/README.md +8 -8
  2. package/README.zh.md +8 -8
  3. package/docs/architecture/2.3.0-compat-retirement.md +147 -0
  4. package/docs/architecture/2.3.0-execution-plan.md +410 -0
  5. package/docs/architecture/2.3.0-final-audit.md +279 -0
  6. package/docs/architecture/2.3.0-reopened-plan.md +720 -0
  7. package/docs/architecture/compat-inventory.md +26 -34
  8. package/docs/architecture/dsh-020-rc2-adaptation.md +23 -0
  9. package/docs/architecture/dsh-compatibility-matrix.md +65 -54
  10. package/docs/architecture/dsh-support-window.md +29 -21
  11. package/docs/architecture/final-closure-audit.md +2 -0
  12. package/docs/architecture/host-first-proxy-convergence.md +1 -1
  13. package/docs/releases/v2.2.8.md +25 -0
  14. package/docs/releases/v2.3.0.md +53 -0
  15. package/entry.js +8 -56
  16. package/index.js +161 -691
  17. package/lib/catalog-corrections.js +1 -2
  18. package/lib/client-host-compat-prelude.js +7 -12
  19. package/lib/client-maintenance-actions.js +145 -0
  20. package/lib/client-presentation-boundary-main.js +82 -32
  21. package/lib/client-presentation-boundary.js +60 -40
  22. package/lib/client-script-carrier.js +90 -0
  23. package/lib/client.js +248 -146
  24. package/lib/core-apply-lifecycle.js +47 -0
  25. package/lib/core-primitives.js +88 -135
  26. package/lib/desktop-screenshot-tool.js +262 -0
  27. package/lib/dsh-contract-compat.js +11 -26
  28. package/lib/dsh-support-window.js +4 -4
  29. package/lib/guide-vision-toggle-highlight.js +7 -10
  30. package/lib/http-compat.js +1 -2
  31. package/lib/live-model-client-prelude.js +7 -14
  32. package/lib/local-remote-settings-permission.js +41 -16
  33. package/lib/maintenance-routes.js +136 -0
  34. package/lib/public-config.js +57 -0
  35. package/lib/public-entry.js +2 -7
  36. package/lib/remote-settings-bridge.js +11 -0
  37. package/lib/remote-settings-risk-client-boundary.js +155 -0
  38. package/lib/remote-settings-risk-confirmation.js +17 -105
  39. package/lib/runtime-composition.js +105 -30
  40. package/lib/runtime-i18n-boundary.js +10 -11
  41. package/lib/session-message-source-compat.js +7 -3
  42. package/lib/session-vision-index.js +154 -9
  43. package/lib/session-vision-mode-boundary.js +43 -8
  44. package/lib/settings-client-loader-lifecycle.js +129 -0
  45. package/lib/settings-factory-lifecycle.js +25 -14
  46. package/lib/settings-ia-client-prelude.js +11 -11
  47. package/lib/settings-limit-client-prelude.js +7 -9
  48. package/lib/sharp-runtime.js +0 -7
  49. package/lib/strict-live-model-client-prelude.js +7 -10
  50. package/lib/structured-flow-hardening.js +3 -2
  51. package/lib/v2-settings-ia-integration.js +21 -6
  52. package/lib/vision-backend-runtime-policy.js +3 -2
  53. package/lib/vision-background-benchmark.js +3 -5
  54. package/lib/vision-capability-benchmark-client.js +7 -10
  55. package/lib/vision-capability-benchmark-service.js +1 -0
  56. package/lib/vision-diagnostics-routes.js +216 -0
  57. package/lib/vision-evidence-guidance.js +3 -1
  58. package/lib/vision-exact-check-client.js +11 -6
  59. package/lib/vision-model-visibility-boundary-main.js +7 -11
  60. package/lib/vision-model-visibility-boundary.js +7 -12
  61. package/lib/vision-provider-transport.js +0 -29
  62. package/lib/vision-routing-settings-prelude.js +7 -11
  63. package/lib/vision-toggle-root-hardening.js +50 -8
  64. package/lib/vision-tool-runtime-boundary.js +5 -1
  65. package/lib/vision-turn-budget-client-prelude.js +7 -10
  66. package/lib/web/remote-settings-client.js +9 -14
  67. package/package.json +23 -13
  68. package/lib/android-attachment-compat.js +0 -244
  69. package/lib/settings-client-rc8-lifecycle.js +0 -402
@@ -0,0 +1,720 @@
1
+ # DVR 2.3.0 reopened execution plan
2
+
3
+ Status: **completed through release preparation / publication and main integration pending explicit user decision**.
4
+
5
+ Branch: `2.3.0`.
6
+
7
+ Reopen baseline:
8
+
9
+ - 2.3 branch: `5ef41f2` (`chore(architecture): record remote settings contract and Desktop lineage`)
10
+ - current main: `6ebc30b` (`v2.2.8`)
11
+ - original 2.3 branch point: `74e3f019` (`v2.2.7`)
12
+
13
+ The earlier version of `2.3.0-final-audit.md` was a **first-pass audit snapshot**. The later review reopened 2.3 after finding a Session correctness hole, unresolved findings and substantial `main`/Desktop evolution.
14
+
15
+ That reopened work is now complete through R5 and release preparation. The current `2.3.0-final-audit.md` is the authoritative final architecture decision; only explicit main integration and publication remain pending.
16
+
17
+ ## 1. What 2.3.0 is now trying to achieve
18
+
19
+ 2.3.0 is not a large feature release and is not a rewrite of the Vision Router architecture.
20
+
21
+ Its final architecture objective is:
22
+
23
+ > **make the current single-owner design safe under composition, current DSH Desktop/Host behavior, long-session edge cases, and future extraction — then remove only the mature-Core/browser glue whose replacement boundary is clearly better than the current one.**
24
+
25
+ The order matters. Correctness and integration come before further extraction.
26
+
27
+ The remaining phase has five priorities, in this order:
28
+
29
+ 1. **Integrate the current v2.2.8 / Desktop / DSH 0.2-rc.2 mainline into the 2.3 branch.**
30
+ 2. **Close confirmed correctness and lifecycle gaps**, especially Session event-feed overflow and asynchronous Core bootstrap settlement.
31
+ 3. **Bring 2.3 compatibility evidence and developer baselines up to the current support reality.**
32
+ 4. **Continue mature-Core and browser extraction only at stable ownership seams with measurable structural benefit.**
33
+ 5. **Re-run an adversarial final audit on the integrated branch before release/version work begins.**
34
+
35
+ ## 2. Historical accounting: what belongs to which development line
36
+
37
+ A 2.3 task being "complete" means the final 2.3 branch satisfies its exit contract. It does **not** mean every prerequisite was first authored on the 2.3 branch.
38
+
39
+ ### 2.1 Inherited before the 2.3 branch was cut
40
+
41
+ The `v2.2.7@74e3f01` branch point already contained substantial Host/Desktop hardening, including:
42
+
43
+ - official Desktop-origin recognition (`58d2f21`);
44
+ - DSH 0.1.7 Settings/Session/Web lifecycle compatibility;
45
+ - Host-first proxy convergence and scoped proxy ownership;
46
+ - Web capability/authentication boundaries;
47
+ - Session event-feed repair introduced around #527/#533;
48
+ - the original descriptor-safe fetch lifecycle for proxy + pi-ai wrappers (#522);
49
+ - resource-governor, fuzz, property and architecture-closure infrastructure.
50
+
51
+ These are inherited foundations, not new 2.3 accomplishments.
52
+
53
+ ### 2.2 First-pass 2.3 work that remains valid
54
+
55
+ The first 2.3 pass added or completed:
56
+
57
+ - runtime-i18n migration onto the descriptor-safe fetch wrapper lifecycle;
58
+ - full i18n + wire + proxy composition coverage;
59
+ - five explicit runtime composition phases;
60
+ - a branch-local aggregated 2.3 critical architecture gate;
61
+ - removal of the `VisionProviderTransport` process-global/current registry in favor of explicit transport plumbing;
62
+ - compatibility inventory reclassification;
63
+ - explicit public Config composition;
64
+ - extraction of maintenance routes and the desktop screenshot implementation from the mature Core;
65
+ - source ownership for browser maintenance actions with deterministic `client.js` embedding;
66
+ - the explicit Remote Settings product contract: risk confirmation is reminder/acknowledgement only, not authentication.
67
+
68
+ These changes stay unless the integrated v2.2.8 branch proves a concrete regression.
69
+
70
+ ### 2.3 Mainline work after the branch cut that 2.3 must inherit
71
+
72
+ `main` continued independently after the 2.3 branch was cut. Current v2.2.8 includes, among other changes:
73
+
74
+ - shared Desktop/Web client-script carrier ownership (`b1bd5ec` lineage);
75
+ - stale Vision tool-mask release and HMR cleanup (`2c4c57d` lineage);
76
+ - DSH `0.2.0-rc.2` exact compatibility evidence;
77
+ - authenticated Desktop renderer/Host validation and multi-plugin isolation coverage;
78
+ - related Settings/client carrier changes.
79
+
80
+ A no-commit integration audit of `2.3.0 + origin/main(v2.2.8)` produced **no textual conflicts** and passed the focused integration set **121/121** plus the full suite **1552 tests / 1551 pass / 1 skip / 0 fail**.
81
+
82
+ That is strong evidence that the lines can converge cleanly, but it is not a substitute for actually merging/reconciling main into the 2.3 branch and rerunning the complete 2.3 gates there.
83
+
84
+ ### 2.4 Historical experimental `composition-hardening-stage1` branch
85
+
86
+ `feat/composition-hardening-stage1@bfea108` is a historical experiment, not an integration target.
87
+
88
+ It attempted several ideas later implemented differently in 2.3, including transport-registry removal and a `core-runtime-facade`. Its focused audit currently produces **44 pass / 2 fail** against the architecture contracts because its entry/composition changes were not fully reconciled with the existing P3 closure tests.
89
+
90
+ The `core-runtime-facade` approach is intentionally **not** adopted by 2.3. It uses `Object.create(core)` to produce a Core-like object with injected runtime behavior. Although convenient, this changes object identity/own-property semantics and adds another implicit facade layer. The explicit transport dependency used by current 2.3 is more verbose but keeps ownership and call-site dependencies visible.
91
+
92
+ Do not cherry-pick `bfea108` wholesale.
93
+
94
+ ## 3. Reopened finding ledger
95
+
96
+ This ledger is the checklist that the final 2.3 audit must reconcile. Completing a batch does not implicitly close unrelated findings.
97
+
98
+ | Finding | State at reopen | 2.3 disposition |
99
+ | --- | --- | --- |
100
+ | runtime-i18n direct `globalThis.fetch` accessor recursion | closed | first-pass 2.3 fix + full wrapper matrix remain required |
101
+ | proxy/pi-ai fetch wrapper composition | closed | inherited #522 lifecycle + expanded 2.3 matrix |
102
+ | `VisionProviderTransport` process-global/current registry | closed | explicit transport plumbing; must not regress |
103
+ | runtime composition ordering hidden in one flat installer chain | closed for 2.3 | five phases + async Core settlement contract; must not regress |
104
+ | Session event-feed pending overflow silently loses repair | **closed** | `669e445` bounded exact-event recovery; gate `36589418063` |
105
+ | Promise-returning Core apply ends schema bootstrap too early | **closed** | `8fee12e` settles bootstrap after async Core apply |
106
+ | v2.2.8/Desktop/rc.2 mainline absent from branch | **closed** | `d7b7415` integrated v2.2.8 mainline |
107
+ | 2.3 aggregate gate behind current rc.2/Desktop evidence | **closed** | reusable rc.2/Desktop evidence in aggregate gate; run `36592304318` |
108
+ | public Host floor still carries 0.1.0-era compatibility | **closed** | R2.2 publishes continuous `0.1.5+` support and removes pre-floor required Host fixtures |
109
+ | default dev DSH dependencies older than active development target | **closed** | root dev dependencies and lockfile pin exact `0.2.0-rc.2` |
110
+ | compatibility inventory evaluated on old branch/support baseline | **closed** | R2.3 retired pre-floor Android/provider/alias paths and finalized retained-seam evidence; aggregate run `36660877636` |
111
+ | `index.js` mature Core still owns non-algorithm product/Web glue | **closed for 2.3 R3 scope** | diagnostics Web ownership extracted; provider-call binding explicitly rejected because it would add an interface without reducing dependency fan-out |
112
+ | `core-primitives.js` large/shared | retained debt | do not split without a stable data-plane owner |
113
+ | current-product browser logic still lives in raw embedded preludes | partial | R4 source modularization over shared carrier |
114
+ | multiple independent browser delivery mechanisms | improved on main | inherit shared `client-script-carrier` in R0; forbid new direct owners |
115
+ | aggregate architecture gate not a protected-main required status | deferred | decide at final integration, not mid-branch |
116
+ | Remote Settings confirmation is not authentication | product decision | **no fix**; reminder-only behavior is intentional |
117
+ | DSH Web activation overlays remain | external Host gap | retain while exact source contract is `shim-required` |
118
+ | Host-first proxy ownership | closed/inherited | preserve; no global dispatcher re-ownership |
119
+ | Web capability boundary/auth inheritance | closed/inherited | preserve; continue closed-world route classification |
120
+
121
+ The final audit may add findings, but it may not remove an open row merely because the related code was reorganized. A row closes only when its stated exit evidence exists.
122
+
123
+ ## 4. Frozen product and architecture decisions
124
+
125
+ These decisions remain fixed for the rest of 2.3.0.
126
+
127
+ ### 4.1 Remote Settings is reminder-only
128
+
129
+ Remote Settings keeps the current product behavior:
130
+
131
+ - the browser may show a risk confirmation;
132
+ - `acceptedRisk` records acknowledgement of the warning flow;
133
+ - it is **not** a credential, authentication proof, administrator authorization, local-presence proof, challenge response or one-time secret;
134
+ - no 2.3 task adds a hidden second server-side confirmation gate;
135
+ - the actual capability boundary remains the remote mutable-field allow-list plus local-only fields.
136
+
137
+ The code now carries this product contract explicitly. Do not reinterpret historical `authorize*` RPC/function names as security-auth semantics.
138
+
139
+ ### 4.2 Existing semantic owners stay authoritative
140
+
141
+ 2.3 must not create a second owner for:
142
+
143
+ | Responsibility | Owner |
144
+ | --- | --- |
145
+ | routing/background authority | `vision-routing-authority.js` |
146
+ | routing evidence | `vision-routing-evidence.js` |
147
+ | planning/scoring | `vision-capability-router.js` |
148
+ | execution order | `vision-execution-order.js` |
149
+ | Session visual state/index | `session-vision-runtime.js` + state/index |
150
+ | managed artifacts | `vision-artifact-store.js` |
151
+ | Router-owned provider HTTP | `vision-provider-transport.js` |
152
+ | Host/product presentation state | server-side presentation/product boundaries |
153
+ | browser rendering | client/presentation layer |
154
+
155
+ No generic dependency-injection container, current-owner locator or Core-like service facade is introduced to reduce parameter plumbing.
156
+
157
+ ### 4.3 Host-first network behavior remains authoritative
158
+
159
+ A blank DVR proxy continues to inherit Host/Undici network policy. Explicit `proxy` / `proxyHosts` remain supported Advanced product overrides. 2.3 does not re-own global network dispatch.
160
+
161
+ ### 4.4 Compatibility retirement remains evidence-driven
162
+
163
+ No shim is removed merely because it is old or aesthetically awkward. The removal condition must be satisfied on the current integrated support matrix, including durable historical/session inputs where applicable.
164
+
165
+ The DSH Web activation overlays remain while exact supported/rc source contracts classify them as `shim-required`.
166
+
167
+ ### 4.5 DVR 2.3 resets the supported Host floor and the default development Host
168
+
169
+ This is a deliberate 2.3 minor-release policy change, not an incidental consequence of dependency cleanup.
170
+
171
+ For DVR `2.3.0`:
172
+
173
+ - **Minimum supported DSH Host:** `0.1.5` train (earliest admitted release `0.1.5-rc.1`).
174
+ - **Default development Host:** exact `0.2.0-rc.2`.
175
+ - **Unsupported by DVR 2.3:** all DSH Host trains older than `0.1.5`, including the entire `0.1.0-rc.6/rc.7/rc.8` line and the intermediate 0.1.x pre-stable trains previously admitted for older DVR releases.
176
+ - The default development version is pinned exactly; it must not float through a caret range to a different rc without an explicit evidence update.
177
+ - Runtime compatibility remains capability-based. Raising the support floor does not authorize widespread version-string branching.
178
+
179
+ The policy distinction is intentional:
180
+
181
+ ```text
182
+ public compatibility floor: DSH 0.1.5 train
183
+ ordinary 2.3 development: 0.2.0-rc.2 exact
184
+ older Host archaeology: not part of the 2.3 supported Host matrix
185
+ ```
186
+
187
+ Dropping an old Host does **not** automatically permit deleting compatibility code that protects durable data produced by older versions. Session logs, replay envelopes, persisted settings and other long-lived inputs are audited by data format/capability, not by the current Host version alone.
188
+
189
+ The 2.3 release notes, README/Doctor support messaging, peer admission and CI must all converge on this boundary before release.
190
+
191
+ ## 5. Phase R0 — integrate current main before further architecture work
192
+
193
+ Status: **completed** on `2.3.0`.
194
+
195
+ Evidence:
196
+
197
+ - `d7b7415` merged current `origin/main` / v2.2.8 into `2.3.0` with no textual conflicts;
198
+ - `279a3b0` added a manual trigger to the existing rc.2 validation workflow so the exact mainline fixture could be reused on the branch without opening a PR;
199
+ - local integrated branch: `client:check` green, focused Desktop/Session/composition set **121/121**, full suite **1552 tests / 1551 pass / 1 skip / 0 fail**, `pnpm pack` green;
200
+ - `2.3 Critical Architecture Gate` run `36586576101`: success on Node 22, Node 24 and current stable Host;
201
+ - `DSH 0.2.0-rc.2 validation` run `36586632659`: success across Windows/macOS/Linux exact-source evidence, real Host + Chromium, Windows Desktop Host Node 22/24, Node 24 multi-plugin adversary and real macOS/Windows Desktop renderer lifecycle.
202
+
203
+ R0 is closed. R1 correctness work is now permitted.
204
+
205
+ ### R0.1 Merge/reconcile `origin/main` v2.2.8 into `2.3.0`
206
+
207
+ Bring the 22 main-only commits into the 2.3 branch before making further 2.3 architecture changes.
208
+
209
+ Required retained mainline behavior includes:
210
+
211
+ - shared `client-script-carrier` ownership;
212
+ - Desktop structured carrier + Web HTML carrier coexistence;
213
+ - stale tool-mask/HMR cleanup;
214
+ - DSH 0.2.0-rc.2 evidence and fixtures;
215
+ - Desktop authenticated runtime coverage;
216
+ - current support-window documentation.
217
+
218
+ Do not resolve apparent overlap by deleting 2.3's explicit source modules or transport plumbing unless a failing contract proves the 2.3 implementation is wrong.
219
+
220
+ ### R0.2 Integration gate
221
+
222
+ After the merge, run at minimum:
223
+
224
+ - `pnpm client:check`;
225
+ - full default tests on Node 22 + 24;
226
+ - client-script-carrier and Settings/Desktop tests;
227
+ - Session event-feed tests;
228
+ - fetch wrapper composition tests;
229
+ - architecture closure tests;
230
+ - current stable Host fixture;
231
+ - DSH 0.2.0-rc.2 exact/desktop validation;
232
+ - package smoke.
233
+
234
+ **Exit condition:** the real `2.3.0` branch, not a temporary merge worktree, contains current main and is green before R1 begins.
235
+
236
+ ## 6. Phase R1 — correctness hardening
237
+
238
+ Correctness fixes take priority over additional extraction.
239
+
240
+ ### R1.1 Repair Session event-feed overflow without returning to full-history cloning
241
+
242
+ Status: **completed** by `669e445` (`fix(session): recover bounded event-feed overflow`).
243
+
244
+ Evidence: the original 257-event reproducer now repairs **257/257** with one exact recovery read; normal 256-event feed uses zero recovery reads; 400-event overflow recovers in capped 32-read batches; transient/unsupported readers retain dirty retry state; Session-focused suite **92/92**; full suite **1560 tests / 1559 pass / 1 skip / 0 fail**; remote gate `36589418063` success. Recovery stores only bounded seq ranges and uses `readSessionEvent()` — it does not return to whole-history cloning.
245
+
246
+ #### Confirmed defect
247
+
248
+ `session-vision-index.js` bounds each pending surface-repair map at 256 entries. When a 257th pending repair arrives, the oldest entry is currently deleted permanently.
249
+
250
+ A current-code reproducer with 257 pending guard-stop events yields:
251
+
252
+ ```text
253
+ events: 257
254
+ repaired: 256
255
+ oldestRepaired: false
256
+ ```
257
+
258
+ The warning is emitted, but no recovery path restores the dropped repair. This trades bounded memory for silent durable-surface correctness loss.
259
+
260
+ #### Required design
261
+
262
+ Do **not** fix this by returning to repeated whole-session clones/snapshots; #527/#533 existed specifically to remove that failure mode.
263
+
264
+ Preferred recovery model:
265
+
266
+ ```text
267
+ steady state
268
+ session/event -> bounded pending repair map -> next pre-step repair
269
+
270
+ on overflow
271
+ keep bounded fast-path map
272
+ + mark this Session repair feed as dirty
273
+ + remember the earliest/affected dropped repair range
274
+
275
+ next prepareDecision
276
+ inspect current surface nodes
277
+ recover missing repair events through Host-owned bounded SessionQuery.readEvent()
278
+ in bounded batches
279
+ apply only repairs that are still on the current surface
280
+ keep dirty state until the affected current surface has been completely reconciled
281
+ then return to event-feed steady state
282
+ ```
283
+
284
+ The current `createSessionEventReader()` already uses `sessionQuery.readEvent({sessionId, seq})` and does not materialize the entire Session log. Prefer that exact-event capability for overflow healing. A whole-log `readSessionLog()` must not become the normal overflow repair path merely because it is convenient.
285
+
286
+ If exact-event recovery is unavailable on a compatibility Host, fail visibly and retain dirty/retry state rather than silently clearing the lost-repair condition.
287
+
288
+ #### Required tests
289
+
290
+ Cover:
291
+
292
+ - 257 pending guard repairs: all still-current repairs eventually complete;
293
+ - 257 pending tool-result repairs;
294
+ - dropped events removed from `surface.nodes` are not resurrected;
295
+ - recovery proceeds in bounded batches rather than unbounded allocations/reads;
296
+ - a transient `readEvent()` failure retries later;
297
+ - unsupported exact-event capability never silently marks the dirty repair complete;
298
+ - normal <=256 event-feed steady state performs zero extra SessionQuery reads;
299
+ - replacement events never re-enqueue themselves.
300
+
301
+ **Exit condition:** bounded memory no longer implies silent loss of a repair still present on the current Session surface.
302
+
303
+ ### R1.2 Make Core schema-bootstrap completion follow the actual Core apply lifetime
304
+
305
+ Status: **completed** by `8fee12e` (`fix(runtime): settle Core bootstrap after async apply`).
306
+
307
+ The synchronous Core path remains synchronous, Promise-returning Core apply now keeps the schema-bootstrap window open until settlement, failure closes it exactly once, and post-Core installation follows the same settlement boundary.
308
+
309
+ #### Original latent gap
310
+
311
+ `runtime-composition.js` currently accepts a Promise-like return from `core.apply()`, but calls:
312
+
313
+ ```text
314
+ coreVisionSurfaceRuntime.finishSchemaBootstrap()
315
+ ```
316
+
317
+ immediately after invoking `core.apply()`, before a returned Promise settles.
318
+
319
+ Today the mature Core applies synchronously, so this is not a current production crash. However the composition contract is internally inconsistent: it claims async compatibility while ending the schema-bootstrap window synchronously.
320
+
321
+ #### Required design
322
+
323
+ Create one explicit Core-apply settlement path:
324
+
325
+ - synchronous return: finalize bootstrap exactly where it finalizes today;
326
+ - synchronous throw: close the bootstrap lifecycle and log/rethrow as today;
327
+ - Promise resolve: finalize bootstrap only after Core registration has completed;
328
+ - Promise reject: close the bootstrap lifecycle once, preserve the original rejection and bounded logging;
329
+ - post-Core installers that semantically require completed Core registration must run from the same settlement boundary.
330
+
331
+ Do not make all composition async solely to solve this. Preserve synchronous return behavior for the current Core.
332
+
333
+ #### Required tests
334
+
335
+ Use a stub Core for:
336
+
337
+ - synchronous success;
338
+ - synchronous throw;
339
+ - delayed Promise success with schema reads before/after settlement;
340
+ - delayed Promise rejection;
341
+ - exactly-once `finishSchemaBootstrap()`;
342
+ - wrapper/maintenance installation ordering relative to settlement.
343
+
344
+ **Exit condition:** the lifecycle behavior matches the return type the composition already claims to support.
345
+
346
+ ## 7. Phase R2 — support, compatibility and CI convergence
347
+
348
+ ### R2.1 Advance the 2.3 gate to current Host evidence
349
+
350
+ Status: **completed**.
351
+
352
+ The aggregate gate now reuses the current rc.2/Desktop workflow rather than copying its fixture. Reusable-workflow concurrency was isolated so the called workflow cannot contend with its caller. Aggregate run `36592304318` completed successfully across Node 22/24, stable Host `0.1.5-rc.3`, rc.2 exact-source on Ubuntu/macOS/Windows, real Host + Chromium, Windows Desktop Node 22/24, macOS Desktop lifecycle and the final `critical-gate`.
353
+
354
+ The first-pass 2.3 gate only embedded current stable `0.1.5-rc.3`; the completed R2.1 gate also reflects the admitted DSH `0.2.0-rc.2` evidence now present on main.
355
+
356
+ The final 2.3 aggregate gate should cover:
357
+
358
+ - Node 22 and Node 24 full regression;
359
+ - current stable `0.1.5-rc.3` exact Host contract;
360
+ - exact DSH `0.2.0-rc.2` contract/browser/Desktop evidence;
361
+ - shared client carrier ownership;
362
+ - fetch composition;
363
+ - Session overflow recovery;
364
+ - architecture closure;
365
+ - security/property fuzz contracts;
366
+ - package/public-entry smoke.
367
+
368
+ Prefer reusing current mainline workflows/scripts rather than duplicating rc.2 fixture construction inside the 2.3 gate.
369
+
370
+ ### R2.2 Raise the 2.3 Host floor and pin ordinary development to the latest verified Host
371
+
372
+ Status: **completed**.
373
+
374
+ Evidence:
375
+
376
+ - peer admission is train-shaped: `>=0.1.5-rc.1 <0.2.0-0 || >=0.2.0-rc.2 <0.3.0-0`;
377
+ - minimum `0.1.5-rc.1` and current `0.1.5-rc.3` isolated Host contracts are green;
378
+ - ordinary development dependencies and the pnpm lockfile pin exact `0.2.0-rc.2`;
379
+ - minimum-Host Settings persistence runs in its own self-contained fixture rather than borrowing root dependencies;
380
+ - README/Doctor/support-window contracts publish the 0.1.5 train rather than the old jagged 0.1.x list.
381
+
382
+ Policy is now frozen by §4.5.
383
+
384
+ R2.2 must change the repository so that:
385
+
386
+ - public DVR 2.3 Host support starts at the **DSH `0.1.5` train** (earliest admitted release `0.1.5-rc.1`);
387
+ - normal root development dependencies use **exact `0.2.0-rc.2`**;
388
+ - peer admission and public support messaging no longer advertise DSH trains below `0.1.5` for DVR 2.3;
389
+ - the `0.1.0-rc.6/rc.7/rc.8` Host matrix and other pre-`0.1.5` Host compatibility jobs are removed from the 2.3 required compatibility program rather than being preserved as release gates;
390
+ - tests whose only purpose is proving a pre-floor Host implementation may be deleted with their fixture;
391
+ - tests that exercise **durable historical data semantics** must be retained or rewritten against supported Hosts even if the Host that originally produced the data is no longer supported;
392
+ - the exact rc.2 development pin is reproducible and changes only through an explicit Host-evidence update.
393
+
394
+ The resulting development/support model is:
395
+
396
+ ```text
397
+ minimum supported Host DSH 0.1.5 train
398
+ ordinary development Host 0.2.0-rc.2 exact
399
+ current forward evidence 0.2.0-rc.2
400
+ pre-0.1.5 Host compatibility unsupported in DVR 2.3
401
+ ```
402
+
403
+ This is an intentional support-floor increase in a minor release. It **does** change the public 2.3 support contract; it must not be disguised as a devDependency-only cleanup.
404
+
405
+ Required verification:
406
+
407
+ - a clean `pnpm install --frozen-lockfile && pnpm test` uses the exact rc.2 development dependencies;
408
+ - minimum `0.1.5-rc.1` and current stable `0.1.5-rc.3` Host evidence stay green;
409
+ - exact `0.2.0-rc.2` Host/Desktop evidence stays green;
410
+ - peer-dependency tests assert the new 2.3 floor rather than the old rc.8 floor;
411
+ - Doctor/README/support-window tests report the new minimum;
412
+ - no default or required CI job claims pre-`0.1.5` Hosts are supported.
413
+
414
+ **Exit condition:** the package, lockfile, CI and support messaging all agree that DVR 2.3 supports the DSH `0.1.5` train plus explicitly verified later trains and develops against exact `0.2.0-rc.2`.
415
+
416
+ ### R2.3 Re-run compatibility retirement against the new `0.1.5` train floor
417
+
418
+ Status: **completed**.
419
+
420
+ Completed retirements:
421
+
422
+ - pre-floor Android/no-batch attachment fallback;
423
+ - legacy DeepSeek provider reconstruction/keep-alive takeover;
424
+ - rc.7-labelled public aliases in favor of capability-named APIs;
425
+ - pre-floor `0.1.5-alpha.2` removed from the normative exact-source support matrix (historical browser surveillance may remain explicitly non-support).
426
+
427
+ R2.3 is now a real retirement pass, not only a reclassification exercise.
428
+
429
+ After R2.2 raises the public minimum, rerun every `retain-host-gap` / `product-compat` seam and separate three questions:
430
+
431
+ 1. **Host-version compatibility:** is the seam needed by the supported `0.1.5` train or an explicitly admitted later train?
432
+ 2. **Current product compatibility:** is the seam still part of an intentional DVR product contract such as explicit proxy overrides?
433
+ 3. **Durable-data compatibility:** can persisted Session/settings/replay data created by older DVR/Host combinations still reach this path on a supported Host?
434
+
435
+ A seam that exists **only** to keep a pre-`0.1.5` Host running becomes a deletion candidate. It does not need to be preserved as a historical Host fixture.
436
+
437
+ Do not assume the first-pass 6 + 5 classification remains correct merely because the source files survived the merge.
438
+
439
+ For every retained seam record:
440
+
441
+ - minimum `0.1.5-rc.1` and current stable `0.1.5-rc.3` evidence;
442
+ - exact `0.2.0-rc.2` evidence;
443
+ - whether Desktop structured carrier changes the seam;
444
+ - whether rc.2 now owns the capability upstream;
445
+ - durable historical-data constraints independent of Host version;
446
+ - next concrete removal trigger.
447
+
448
+ For every deleted seam record the proof that no supported Host/current durable-data path still reaches it.
449
+
450
+ Only then may the compatibility inventory be called final for 2.3.
451
+
452
+ R2.3 is closed by current-branch evidence:
453
+
454
+ - exact supported 0.1.x source matrix: run `36659179011` — success;
455
+ - minimum/current Host contract after the retirement pass: run `36660877445` — success;
456
+ - final aggregate architecture/compat gate: run `36660877636` — success across Node 22/24, current `0.1.5-rc.3`, exact `0.2.0-rc.2` source on Ubuntu/macOS/Windows, real Host + Chromium, Windows Desktop Node 22/24, macOS Desktop renderer lifecycle, and final `critical-gate`.
457
+
458
+ No remaining retained seam is justified only by a pre-`0.1.5` Host. Remaining compatibility debt is current-Host, durable-data, product, or platform compatibility and therefore moves forward explicitly rather than being deleted for version-age alone.
459
+
460
+ ### R2.4 Promote the aggregate gate only after the branch is stable
461
+
462
+ Final repository-governance inspection does **not** confirm the older assumption that `main` requires `test (22)`, `test (24)` and `current-contract`. The readable active repository ruleset is **Main PR safety**: it requires PR-based integration and resolved review threads, but currently exposes no required status-check rule. The branch-protection endpoint itself is not readable through the GitHub App because it lacks repository-administration permission.
463
+
464
+ The 2.3 aggregate gate is therefore branch-local evidence, not a GitHub-enforced `main` required check. DVR 2.3 does not mutate repository governance from the development branch.
465
+
466
+ At explicit integration time, decide separately whether the aggregate architecture/compat gate should become a required `main` status and whether it replaces or supplements other checks. This is a repository-governance action, not something to fake through workflow naming alone.
467
+
468
+ ## 8. Phase R3 — mature-Core extraction, second pass
469
+
470
+ Status: **completed**.
471
+
472
+ Evidence:
473
+
474
+ - `7015c2e` extracted `/_dsh/vision-router/test-connection` and `/_dsh/vision-router/model-capabilities` into `lib/vision-diagnostics-routes.js`, so Core no longer owns those WebServer route registrations;
475
+ - `4317d5f` preserved partial-LLM diagnostics semantics after extraction;
476
+ - exact supported-source contract run `36661996135`: success;
477
+ - current-head DSH Contract run `36662031316`: success;
478
+ - aggregate `2.3 Critical Architecture Gate` run `36662031617`: success across Node 22/24, current stable Host, exact rc.2 source on Ubuntu/macOS/Windows, real Host + Chromium, Windows Desktop Node 22/24, macOS Desktop renderer lifecycle and final `critical-gate`;
479
+ - the secondary provider-call binding candidate was explicitly rejected after dependency review: `index.js` has only three one-line transport-binding closures (four OpenAI call sites, one local call site and one Anthropic call site), while `core-primitives.js` still has twelve real `providerTransport` data-plane references. Moving the three wrappers to a new module would not reduce primitive dependencies or Core fan-out, and would add a new interface solely to hide explicit plumbing.
480
+
481
+ The first pass proved that extraction is useful when the seam already has a stable owner (`maintenance-routes`, `desktop-screenshot-tool`, `public-config`). The second pass must use stricter acceptance criteria.
482
+
483
+ ### R3.1 Extraction acceptance rule
484
+
485
+ A candidate moves out of `index.js` only when all are true:
486
+
487
+ 1. it represents one coherent responsibility, not an arbitrary group of lines;
488
+ 2. the resulting module has a narrower dependency set than the code had implicitly inside Core;
489
+ 3. no module-global/current owner is introduced;
490
+ 4. no Core-like facade or generic service locator is introduced;
491
+ 5. the move can be behavior-preserving in its own commit;
492
+ 6. the extracted contract can be tested directly without reconstructing most of Core;
493
+ 7. composition/Core fan-out or product/lifecycle glue is measurably reduced.
494
+
495
+ If the extracted function needs a large bag of unrelated callbacks just to compile, the seam is not mature enough and remains in Core.
496
+
497
+ ### R3.2 Primary candidate: diagnostics/product Web ownership still inside Core
498
+
499
+ Status: **completed** by `7015c2e` (`refactor(core): extract vision diagnostics routes`), with `4317d5f` preserving partial-LLM diagnostics behavior.
500
+
501
+ `index.js` previously directly owned Web registrations for:
502
+
503
+ - `/_dsh/vision-router/test-connection`;
504
+ - `/_dsh/vision-router/model-capabilities`.
505
+
506
+ These are product diagnostics/settings support, not visual inference algorithms.
507
+
508
+ 2.3 should attempt to move them behind a narrow diagnostics owner **only if** the service boundary can be expressed cleanly, for example as explicit candidate/catalog/capability probes rather than passing most of Core into a route module.
509
+
510
+ Success means Core no longer owns WebServer registration for these endpoints.
511
+
512
+ That condition is now satisfied by `lib/vision-diagnostics-routes.js`. The extracted module receives three coherent diagnostics faces — connection candidates/probes, capability snapshot, and Host ownership state — rather than a Core facade.
513
+
514
+ Abort the extraction if the route module requires a broad Core facade or a dependency bag that simply reproduces `index.js` coupling elsewhere.
515
+
516
+ ### R3.3 Secondary candidate: provider-call transport binding
517
+
518
+ Status: **rejected for 2.3 after dependency review**.
519
+
520
+ Core currently creates local helper closures to attach the explicit `providerTransport` to OpenAI/local/Anthropic calls.
521
+
522
+ A small typed/narrow provider-call binding module may be worthwhile if it:
523
+
524
+ - accepts only the explicit transport + concrete call functions;
525
+ - returns only the three transport-bound call operations;
526
+ - does not pretend to be Core;
527
+ - removes repeated transport option plumbing across Core/primitives;
528
+ - preserves direct helper callers without an implicit current transport.
529
+
530
+ This is explicitly different from the rejected historical `core-runtime-facade` approach.
531
+
532
+ If the module does not reduce dependency repetition in practice, leave the explicit call-site plumbing as-is.
533
+
534
+ That is the current result. The proposed module would only relocate three one-line closures. The underlying primitives still need explicit transport data for local/OpenAI/Anthropic and request paths, so the extraction would not eliminate or narrow those dependencies. Explicit plumbing therefore remains preferable to a cosmetic binding layer.
535
+
536
+ ### R3.4 Do not make `core-primitives.js` line count a release criterion
537
+
538
+ `core-primitives.js` is still large, but 2.3 should not split it solely because it is ~3k lines.
539
+
540
+ A primitive group moves only when a clear data-plane owner emerges. OCR/image preprocessing/resource-governor code should remain together with its current owner until a move reduces coupling rather than adding interfaces.
541
+
542
+ **R3 exit condition:** met. Diagnostics/product Web ownership was cleanly extracted and the secondary transport-binding candidate was rejected with dependency evidence. The goal remains architectural clarity, not an arbitrary LOC target.
543
+
544
+ ## 9. Phase R4 — browser/source modularization on top of the shared carrier
545
+
546
+ Status: **completed**.
547
+
548
+ Evidence:
549
+
550
+ - `28cc21f` moved remote Settings risk/reminder behavior into `lib/remote-settings-risk-client-boundary.js`, so queue/Web and queue-to-live lifecycle paths consume one current-product semantic owner instead of maintaining duplicate authorization/reminder code;
551
+ - `3adc254` moved the local `allowRemoteSettings` browser normalization/write behavior into the capability owner in `lib/local-remote-settings-permission.js`, leaving the loader lifecycle bridge to compose owners rather than copy product semantics;
552
+ - `1debee0` renamed the retained loader bridge to `lib/settings-client-loader-lifecycle.js` and capability-named APIs. The historical in-page `data-vision-router-settings-rc8-lifecycle` marker and `__visionRouterSettingsRc8Lifecycle` sentinel are deliberately retained only for mixed-generation/HMR idempotency;
553
+ - DSH Contract run `36672168661`: success;
554
+ - exact supported-source run `36672168695`: success;
555
+ - aggregate `2.3 Critical Architecture Gate` run `36672168927`: success across Node 22/24, current stable Host, exact rc.2 source on Ubuntu/macOS/Windows, real Host + Chromium, Windows Desktop Node 22/24, macOS Desktop renderer lifecycle and final `critical-gate`;
556
+ - the standalone remote-risk `tapIndex()` path is intentionally retained as the queue-stage/served-Web compatibility fallback. Moving that fallback onto the structured Desktop carrier as well was rejected because the queue-to-live lifecycle carrier already covers Desktop/live attachment; duplicating the fallback there would add a second wrapper execution surface without adding product capability.
557
+
558
+ Main's shared `client-script-carrier` changes the correct direction for browser cleanup.
559
+
560
+ ### R4.1 One delivery mechanism, multiple source owners
561
+
562
+ Current-product browser code should increasingly follow:
563
+
564
+ ```text
565
+ real source module
566
+ -> deterministic generated/embedded script
567
+ -> shared client-script-carrier
568
+ -> Desktop structured row and/or Web HTML carrier
569
+ ```
570
+
571
+ Do not add new independent `tapIndex()` owners when the shared carrier can carry the same code.
572
+
573
+ ### R4.2 Move current-product logic before legacy compatibility shims
574
+
575
+ Prioritize source modularization for browser code that represents current product behavior, such as:
576
+
577
+ - current settings/product actions;
578
+ - current diagnostics/capability presentation;
579
+ - current routing/settings presentation;
580
+ - current model visibility/product presentation.
581
+
582
+ Legacy Host lifecycle shims may remain `String.raw` while the Host gaps they bridge still exist.
583
+
584
+ The target is **not** “zero `String.raw` in 2.3”. The target is that new/current product logic has a real source owner and compatibility injection code is visibly separated from it.
585
+
586
+ ### R4.3 Preserve deterministic bundle checks
587
+
588
+ Any embedded current-product source must have a generation/synchronization check analogous to `client-maintenance-actions.js` so the shipping `client.js` cannot silently diverge from its source owner.
589
+
590
+ **R4 exit condition:** met. Current remote-risk and local-permission behavior now have real source owners, while the retained loader/fallback shims contain lifecycle/delivery compatibility rather than duplicate product policy. Browser delivery continues to use the shared mainline carrier where it is the correct execution surface; the queue/Web fallback remains separate only where combining it would create duplicate execution.
591
+
592
+ ## 10. Phase R5 — final adversarial audit and release handoff
593
+
594
+ Status: **completed**.
595
+
596
+ ### Final finding ledger
597
+
598
+ | Severity | Unresolved |
599
+ | --- | ---: |
600
+ | High | 0 |
601
+ | Medium | 0 |
602
+
603
+ Closed during R5:
604
+
605
+ - the frozen Session/Core wiring contract still pointed at the pre-R3 diagnostics owner; `fd97e5e` now forbids Core from regaining that response ownership and verifies the extracted diagnostics module performs the live official-route check;
606
+ - `079781c` pruned retired/unused mature-Core import fan-out found by the final static review;
607
+ - the production ESM cycle audit was made durable in `scripts/esm-cycle-audit.mjs` plus the default test manifest.
608
+
609
+ ### Final evidence
610
+
611
+ - R5 deep audit run `36673859366`: success;
612
+ - Architecture Closure Node 22: 132/132;
613
+ - Architecture Closure Node 24: 132/132;
614
+ - 166 production ESM modules / 347 static relative edges / 0 cycles;
615
+ - deterministic and rotating property/adversarial fuzz passed;
616
+ - quality 12/12;
617
+ - 100MP stress passed on Ubuntu/macOS/Windows, maximum observed RSS delta 92.5 MiB;
618
+ - client source sync and package smoke passed.
619
+ - minimum/current Host run `36673859352`: success for `0.1.5-rc.1` and `0.1.5-rc.3`;
620
+ - supported 0.1.x exact-source run `36672168695`: success for `0.1.5-rc.1`, `0.1.5-rc.3` and `0.1.7-rc.2` on Ubuntu/macOS/Windows;
621
+ - aggregate run `36673859774`: success across Node 22/24 full regressions, current Host, exact rc.2 source on three OSes, real Host + Chromium, Windows Desktop Node 22/24, macOS Desktop renderer and final `critical-gate`;
622
+ - immediately before final housekeeping, `main@65415159` is the merge base and `2.3.0` is behind by 0 commits.
623
+
624
+ ### Quantitative closure snapshot
625
+
626
+ | File | Lines | UTF-8 bytes | Direct local import fan-out |
627
+ | --- | ---: | ---: | ---: |
628
+ | `index.js` | 4,787 | 223,815 | 28 |
629
+ | `lib/core-primitives.js` | 2,935 | 120,717 | 11 |
630
+ | `lib/runtime-composition.js` | 468 | 20,774 | 44 |
631
+ | `lib/client.js` | 4,961 | 261,672 | 0 ESM imports |
632
+
633
+ The client bundle has 472 bytes of headroom under the existing 262,144-byte single-file review bound. This is recorded as Low retained maintenance debt rather than “solved” by weakening the guard.
634
+
635
+ The full final audit is `2.3.0-final-audit.md`. It distinguishes inherited hardening, parallel main/Desktop integration, 2.3-authored work and retained debt.
636
+
637
+ ### Release preparation after architecture closure
638
+
639
+ Status: **preparation completed; integration/publication pending explicit user decision**.
640
+
641
+ Completed after the green final audit:
642
+
643
+ - package version `2.3.0`;
644
+ - bilingual changelog and curated release notes;
645
+ - README release/support messaging;
646
+ - release-ready support-policy/Doctor alignment;
647
+ - release workflow fail-closed checks for generated client synchronization and Host support policy;
648
+ - repository-governance review: no branch/ruleset mutation from `2.3.0`.
649
+
650
+ Still intentionally not performed:
651
+
652
+ - PR/main integration;
653
+ - `v2.3.0` tag creation;
654
+ - npm publication;
655
+ - GitHub Release/provenance publication.
656
+
657
+ The release workflow requires the release SHA to be on `main` and manual dispatch requires the exact current `origin/main` HEAD. A tag is therefore a publication action and must not be created merely as branch housekeeping.
658
+
659
+ No PR is opened merely because this plan exists.
660
+
661
+ ## 11. Revised batch order
662
+
663
+ | Batch | Work | Nature | Gate before next batch |
664
+ | --- | --- | --- | --- |
665
+ | R0 | merge current `main` / v2.2.8 into `2.3.0` | integration | full + Desktop/rc.2 green |
666
+ | R1.1 | Session feed overflow dirty/recovery path | correctness fix | 257+ regressions + normal feed unchanged |
667
+ | R1.2 | async Core apply/bootstrap settlement | lifecycle correctness | sync + async settlement tests |
668
+ | R2.1 | update 2.3 gate to stable + rc.2/Desktop | CI/support | aggregate gate green |
669
+ | R2.2 | raise minimum Host to the `0.1.5` train + pin dev Host to exact rc.2 | support/developer contract | package/CI/docs agree; stable + rc.2 green |
670
+ | R2.3 | retire pre-floor Host compatibility and re-audit remaining seams | compat deletion/evidence | inventory complete; durable-data paths proven |
671
+ | R3 | second mature-Core extraction pass | behavior-preserving refactor | targeted + full tests |
672
+ | R4 | second browser source modularization pass | behavior-preserving refactor | shared carrier + sync checks green |
673
+ | R5 | final adversarial audit | audit/docs | no unresolved High/Medium blocker |
674
+ | Release | version/changelog/tag/integration | release | separate user decision |
675
+
676
+ Each behavior fix/refactor gets its own commit. Do not combine Session recovery, mainline integration and Core extraction into one diff.
677
+
678
+ ## 12. What is explicitly not a 2.3 requirement
679
+
680
+ 2.3 does **not** require:
681
+
682
+ - changing Remote Settings into authenticated authorization;
683
+ - preserving DVR 2.3 Host compatibility with DSH trains older than `0.1.5`;
684
+ - deleting `proxy` / `proxyHosts`;
685
+ - deleting Web activation overlays while current exact Host evidence still requires them;
686
+ - replacing the routing/evidence/planning/execution architecture;
687
+ - splitting all of `core-primitives.js`;
688
+ - eliminating every browser `String.raw` compatibility prelude;
689
+ - physically splitting DSH's single delivered `client.js` bundle if the Host contract still consumes one bundle;
690
+ - adopting the historical `core-runtime-facade` experiment;
691
+ - adding feature work such as PDF/video/CAD/GUI agents.
692
+
693
+ ## 13. Final success definition
694
+
695
+ 2.3.0 is ready to close only when all of the following are true:
696
+
697
+ 1. the branch contains the then-current v2.2.8/main Desktop and rc.2 compatibility line;
698
+ 2. Session overflow cannot silently lose a still-current surface repair;
699
+ 3. Core schema bootstrap ends according to the actual Core apply settlement contract;
700
+ 4. fetch composition remains fully descriptor-safe across i18n/wire/proxy/Host accessors;
701
+ 5. no process-global/current provider transport locator returns;
702
+ 6. the public 2.3 Host floor is the DSH `0.1.5` train, ordinary development is pinned to exact `0.2.0-rc.2`, and package/lockfile/README/Doctor/CI agree;
703
+ 7. the aggregate branch gate covers the new minimum stable Host plus admitted rc/Desktop evidence;
704
+ 8. pre-floor Host-only compatibility is retired, while any retained seam has current-Host or durable-data evidence;
705
+ 9. the R3/R4 extraction candidates are either cleanly extracted or explicitly rejected with dependency evidence; no extraction is forced merely to reduce LOC;
706
+ 10. final full/fuzz/stress/quality/package validation is green;
707
+ 11. the final audit has no unresolved High or Medium architecture/correctness blocker;
708
+ 12. release/version work has not been conflated with architecture refactoring.
709
+
710
+ The intended end state is not “many more files”. It is:
711
+
712
+ ```text
713
+ 2.2.8 + first-pass 2.3
714
+ -> integrated current Desktop/Host line
715
+ -> no known Session/composition correctness hole
716
+ -> current support evidence and developer baseline
717
+ -> fewer mature-Core/browser product-glue responsibilities
718
+ -> explicit remaining compatibility debt
719
+ -> one trustworthy final gate/audit
720
+ ```