dsh-vision-router 2.3.0 → 3.0.1

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 (105) hide show
  1. package/README.md +18 -3
  2. package/README.zh.md +16 -3
  3. package/docs/architecture/3.0-architecture-plan.md +252 -0
  4. package/docs/architecture/3.0-r0-contract-ledger.md +137 -0
  5. package/docs/architecture/3.0-r1-source-artifact-boundary.md +98 -0
  6. package/docs/architecture/3.0-r10-final-correctness-closure.md +207 -0
  7. package/docs/architecture/3.0-r11-adversarial-review.md +447 -0
  8. package/docs/architecture/3.0-r5-browser-go-no-go.md +165 -0
  9. package/docs/architecture/3.0-r5-browser-typescript-gate.md +105 -0
  10. package/docs/architecture/3.0-r6-compat-retirement.md +203 -0
  11. package/docs/architecture/3.0-r7-public-api.md +151 -0
  12. package/docs/architecture/3.0-r8-ci-release.md +248 -0
  13. package/docs/architecture/3.0-r9-final-audit.md +370 -0
  14. package/docs/architecture/dsh-support-window.md +13 -3
  15. package/docs/releases/v3.0.0.md +85 -0
  16. package/docs/releases/v3.0.1.md +77 -0
  17. package/entry.js +1 -1
  18. package/index.js +110 -71
  19. package/lib/agent-request-route-authority.js +1 -20
  20. package/lib/core-apply-lifecycle.js +37 -43
  21. package/lib/core-cache.js +87 -0
  22. package/lib/core-primitives.js +11 -144
  23. package/lib/core-vision-surface-domain.js +63 -0
  24. package/lib/core-vision-surface.js +11 -77
  25. package/lib/delegated-call-config.js +15 -24
  26. package/lib/doctor-cli.js +0 -0
  27. package/lib/doctor-runtime.js +4 -1
  28. package/lib/dsh-contract-compat.js +26 -230
  29. package/lib/dsh-host-capabilities.js +3 -9
  30. package/lib/dsh-settings-017-compat.js +17 -10
  31. package/lib/file-logger.js +8 -3
  32. package/lib/grounding-coordinate-runtime.js +1 -2
  33. package/lib/http-body-limit.js +97 -79
  34. package/lib/image-offload-compat.js +30 -21
  35. package/lib/image-resource-governor.js +210 -228
  36. package/lib/legacy-global-proxy-boundary.js +46 -3
  37. package/lib/live-model-client-prelude.js +12 -4
  38. package/lib/live-model-discovery.js +134 -43
  39. package/lib/local-vision-stabilizer.js +33 -18
  40. package/lib/maintenance-routes.js +1 -3
  41. package/lib/native-image-coexistence.js +15 -3
  42. package/lib/ollama-cold-start.js +87 -23
  43. package/lib/pi-ai-bridge-wire-compat.js +3 -2
  44. package/lib/proxy-dispatcher-pool.js +151 -92
  45. package/lib/proxy-routing.js +75 -51
  46. package/lib/proxy-url-compat.js +3 -10
  47. package/lib/public-config.js +23 -44
  48. package/lib/public-entry.d.ts +148 -0
  49. package/lib/public-entry.js +17 -4
  50. package/lib/replay-delegation.js +12 -7
  51. package/lib/replay-envelope-v2-compat.js +12 -7
  52. package/lib/runtime-composition.js +30 -10
  53. package/lib/screenshot-source-boundary.js +2 -2
  54. package/lib/session-affinity-runtime.js +113 -97
  55. package/lib/session-affinity.js +89 -76
  56. package/lib/session-event-history-compat.js +30 -0
  57. package/lib/session-query-readers.js +263 -0
  58. package/lib/session-surface-compat.js +30 -31
  59. package/lib/session-surface-policy-domain.js +85 -0
  60. package/lib/session-surface-policy.js +2 -111
  61. package/lib/session-turn-resolver.js +2 -6
  62. package/lib/session-vision-attachment-index.js +143 -0
  63. package/lib/session-vision-delegation-boundary.js +34 -0
  64. package/lib/session-vision-delegation.js +22 -0
  65. package/lib/session-vision-index.js +25 -107
  66. package/lib/session-vision-mode-authority.js +229 -192
  67. package/lib/session-vision-mode-boundary.js +65 -22
  68. package/lib/session-vision-policy-domain.js +304 -0
  69. package/lib/session-vision-policy.js +104 -0
  70. package/lib/session-vision-state.js +368 -378
  71. package/lib/settings-client-017-compat.js +16 -10
  72. package/lib/structured-flow-hardening.js +22 -4
  73. package/lib/tesseract-exec-compat.js +9 -1
  74. package/lib/turn-budget-context.js +47 -41
  75. package/lib/update-check.js +11 -2
  76. package/lib/vision-attachment-handle-runtime.js +176 -156
  77. package/lib/vision-backend-runtime-policy.js +16 -0
  78. package/lib/vision-background-benchmark.js +55 -6
  79. package/lib/vision-background-failure-policy.js +41 -41
  80. package/lib/vision-background-stop-store-core.js +217 -0
  81. package/lib/vision-background-stop-store.js +8 -179
  82. package/lib/vision-capability-benchmark.js +11 -61
  83. package/lib/vision-capability-evidence.js +35 -0
  84. package/lib/vision-capability-fingerprint.js +72 -0
  85. package/lib/vision-capability-identity.js +116 -61
  86. package/lib/vision-capability-router.js +13 -33
  87. package/lib/vision-chunk-assembler.js +95 -0
  88. package/lib/vision-diagnostics-routes.js +42 -4
  89. package/lib/vision-execution-order-apply.js +45 -55
  90. package/lib/vision-execution-order.js +19 -19
  91. package/lib/vision-execution-policy.js +12 -7
  92. package/lib/vision-model-registry.js +30 -17
  93. package/lib/vision-model-visibility-boundary-main.js +15 -16
  94. package/lib/vision-provider-transport.js +137 -147
  95. package/lib/vision-routing-authority.js +47 -48
  96. package/lib/vision-routing-product.js +26 -29
  97. package/lib/vision-routing-settings-prelude.js +8 -3
  98. package/lib/vision-runtime-performance-store.js +166 -0
  99. package/lib/vision-runtime-performance.js +13 -142
  100. package/lib/vision-tool-runtime-boundary.js +99 -30
  101. package/lib/web/dsh-settings-017-root-transport.js +27 -12
  102. package/lib/web/remote-settings-client.js +4 -7
  103. package/lib/web-capability-boundary.js +17 -7
  104. package/lib/wrapper-directory.js +14 -23
  105. package/package.json +37 -11
@@ -0,0 +1,105 @@
1
+ # DVR 3.0 R5 Browser TypeScript gate
2
+
3
+ > Status: **No-Go for monolithic Browser TypeScript migration**
4
+ >
5
+ > Audited branch: `3.0`
6
+ >
7
+ > Evidence checkpoint: `20723c368433fcc628a09fe168ca4a9d221e55e1`
8
+
9
+ ## Decision
10
+
11
+ DVR 3.0 does **not** migrate `src/lib/client.js` wholesale to TypeScript at this stage.
12
+
13
+ This is not a rejection of TypeScript in Browser code. It is a boundary decision: the current Browser delivery topology does not provide enough architectural leverage to justify converting the monolith, and forcing the conversion would create new DTO/facade/type-maintenance debt without improving a stable ownership seam.
14
+
15
+ ## Current bundle constraint
16
+
17
+ The canonical Browser source and delivered artifact are currently identical in size:
18
+
19
+ - `src/lib/client.js`: **261,672 bytes**
20
+ - `lib/client.js`: **261,672 bytes**
21
+ - existing single-file review bound: **262,144 bytes**
22
+ - remaining headroom: **472 bytes**
23
+
24
+ The existing `tests/index-modularization.test.js` gate continues to enforce the 256 KiB bound. R5 does not raise, weaken, or bypass it.
25
+
26
+ `pnpm client:check` is green at this checkpoint.
27
+
28
+ ## Strict TypeScript characterization
29
+
30
+ A temporary, non-committed Client compiler spike added the existing `src/lib/client.js` to the current Client program with:
31
+
32
+ - `allowJs: true`
33
+ - `checkJs: true`
34
+ - inherited `strict: true`
35
+ - inherited `noUncheckedIndexedAccess`
36
+ - inherited `exactOptionalPropertyTypes`
37
+ - Client DOM libs
38
+ - `types: []`
39
+
40
+ The existing monolith produced **478 TypeScript diagnostics**.
41
+
42
+ Largest classes:
43
+
44
+ | Code | Count | Meaning |
45
+ | --- | ---: | --- |
46
+ | TS7006 | 258 | implicit-any parameters |
47
+ | TS2339 | 105 | dynamic/undeclared object properties |
48
+ | TS7005 | 60 | implicitly-any variables |
49
+ | TS7034 | 18 | variables whose array/object type cannot be inferred safely |
50
+ | TS7053 | 13 | dynamic indexed access |
51
+ | TS2367 | 13 | comparisons whose inferred domains do not overlap |
52
+
53
+ The first errors also expose real dynamic Browser/Host seams:
54
+
55
+ - `window.__ModuleLoader__`;
56
+ - injected `require()` values;
57
+ - React loaded through the Host module carrier;
58
+ - historical client attachment compatibility;
59
+ - mutable capability/state bags assembled at runtime.
60
+
61
+ Treating those surfaces as statically trustworthy would require either broad `any`, duplicated Host DTOs, or a large Browser facade. None reduces current ownership risk.
62
+
63
+ ## Why this is a No-Go
64
+
65
+ A direct `.js -> .ts` conversion would currently optimize for file extension rather than architecture.
66
+
67
+ It would tend to require one or more of the following, all rejected for 3.0:
68
+
69
+ - a large DVR Browser/Host facade;
70
+ - copied Host client DTOs;
71
+ - broad `any` or assertion-heavy adapters;
72
+ - a new bundler/transpilation layer solely to preserve the existing single-file delivery shape;
73
+ - generated TypeScript source embedded back into `client.js`;
74
+ - raising the 256 KiB review bound;
75
+ - minification as an architectural escape hatch.
76
+
77
+ The current Client compiler world therefore remains intentionally separate and narrow. Host TypeScript migration must not leak Node ambient types into it.
78
+
79
+ ## Existing source ownership remains valid
80
+
81
+ Browser behavior is already partially source-owned outside the monolith where a stable owner exists. For example, maintenance actions are authored in `client-maintenance-actions.js` and deterministically embedded into `client.js`; `pnpm client:check` verifies synchronization.
82
+
83
+ That pattern should not be mechanically converted to TypeScript either. In particular, a function serialized with `Function#toString()` cannot safely carry TypeScript-only syntax into the delivered browser source.
84
+
85
+ ## Re-open conditions
86
+
87
+ R5 Browser TypeScript should be reconsidered only when at least one of these becomes true:
88
+
89
+ 1. a substantial Browser responsibility gains an independent stable owner that can be typed without copying the monolith's dynamic Host surface;
90
+ 2. DSH exposes a public typed Client module/context contract that removes the need for DVR-owned facades;
91
+ 3. the Browser delivery topology gains an official build/bundle seam where TypeScript can compile without changing runtime ownership or weakening the size gate;
92
+ 4. source extraction creates enough review headroom that a typed owner can be introduced without hiding growth through minification;
93
+ 5. a concrete Browser bug class is shown to be prevented by a narrow type boundary.
94
+
95
+ ## Invariants retained
96
+
97
+ - no increase to the 262,144-byte client bound;
98
+ - no Node globals in the Client TypeScript program;
99
+ - no production dependency on DSH private `src/*` paths;
100
+ - no broad Host facade;
101
+ - no repository-wide Browser TypeScript rewrite;
102
+ - no minification-based architecture fix;
103
+ - runtime validation remains authoritative for dynamic Host/client data.
104
+
105
+ R5 therefore closes as **No-Go for monolithic migration, open for future owner-by-owner typed extraction when a real seam appears**.
@@ -0,0 +1,203 @@
1
+ # DVR 3.0 R6 — Compatibility retirement / Host-floor re-audit
2
+
3
+ Status: **complete — one stale package edge retired; Host floor unchanged**
4
+
5
+ Baseline:
6
+
7
+ - DVR branch: `3.0`
8
+ - DSH exact source: `deepseek-ai/deepseek-harness@639ed015397290b3745d163aafe02ffee4aa3f84`
9
+ - DSH version: `0.2.0-rc.2`
10
+ - public DVR Host window remains:
11
+ - `>=0.1.5-rc.1 <0.2.0-0`
12
+ - or `>=0.2.0-rc.2 <0.3.0-0`
13
+
14
+ R6 re-runs compatibility removal conditions. It does **not** treat age, a TypeScript
15
+ migration, or the current development pin as evidence that a compatibility owner is dead.
16
+
17
+ Durable user-data compatibility remains independent of the runtime Host floor.
18
+
19
+ ## Result
20
+
21
+ R6 found one real stale package-graph edge:
22
+
23
+ ```text
24
+ @deepseek-ai/dsh-client-runtime
25
+ ```
26
+
27
+ It was retired from both:
28
+
29
+ - `package.json#dsh.client.inject`;
30
+ - Doctor's Host-package diagnostic inventory.
31
+
32
+ No documented runtime compatibility seam met its removal condition, and the public Host
33
+ floor is not raised.
34
+
35
+ ## Retired: stale dsh-client-runtime client injection
36
+
37
+ ### Evidence
38
+
39
+ The exact DSH `0.2.0-rc.2` client architecture has no
40
+ `@deepseek-ai/dsh-client-runtime` package.
41
+
42
+ Repository review also found no DVR production consumer of a `ctx.runtime` or equivalent
43
+ client-runtime service. The only remaining DVR references before retirement were:
44
+
45
+ 1. `package.json#dsh.client.inject`;
46
+ 2. Doctor's diagnostic package list.
47
+
48
+ This matters because current DSH does not define `dsh.client.inject` as an optional
49
+ capability hint. Its client-module contract describes inject entries as package dependency
50
+ edges: injected package factories must arrive before the consuming row materializes, and
51
+ Cordis uses the same edges for entry composition.
52
+
53
+ A package name that no longer exists therefore has no supported ownership role as a
54
+ compatibility placeholder.
55
+
56
+ ### Retirement
57
+
58
+ R6 removes the stale row rather than replacing it with another guessed package.
59
+
60
+ The retained client inject list continues to use only the existing DVR-declared package
61
+ edges; no unrelated browser dependency is changed.
62
+
63
+ Doctor also stops reporting `@deepseek-ai/dsh-client-runtime` as a Host package. Keeping
64
+ the diagnostic after removing the graph edge would have produced false missing-package
65
+ evidence.
66
+
67
+ A regression gate in `tests/manifest-dependencies.test.js` now forbids the package name
68
+ from returning to either surface.
69
+
70
+ ### Validation
71
+
72
+ After retirement:
73
+
74
+ - canonical build succeeded;
75
+ - generated-artifact reproducibility succeeded;
76
+ - Host TypeScript program succeeded;
77
+ - Client TypeScript program succeeded;
78
+ - manifest, Doctor, browser-client and DSH-compatibility targeted tests passed
79
+ `193/193`.
80
+
81
+ ## Host floor: KEEP
82
+
83
+ R6 does not raise the minimum Host from `0.1.5-rc.1`.
84
+
85
+ A Host-floor increase requires evidence that dropping the admitted Host generation removes
86
+ real compatibility complexity without conflating runtime compatibility with persisted data.
87
+ That condition is not met.
88
+
89
+ Several retained seams remain reachable for current product/platform reasons even if older
90
+ Hosts were removed, while other seams still span genuine lifecycle differences inside the
91
+ declared support window.
92
+
93
+ Raising the floor would therefore reduce support without producing the architectural
94
+ simplification required by the 3.0 plan.
95
+
96
+ ## Retained: DSH Web modules -> webServer overlay
97
+
98
+ Verdict: **KEEP — shim-required**
99
+
100
+ Exact `0.2.0-rc.2` source still declares:
101
+
102
+ ```yaml
103
+ - id: modules
104
+ name: '@deepseek-ai/dsh-client-modules'
105
+ ```
106
+
107
+ with no activation `inject` field.
108
+
109
+ The existing retirement classifier therefore remains in `shim-required`, not
110
+ `retire-ready`.
111
+
112
+ DVR must keep the overlay until an admitted Host's official modules row owns
113
+ `webServer` itself.
114
+
115
+ ## Retained: DSH Web connection -> webServer overlay
116
+
117
+ Verdict: **KEEP — shim-required**
118
+
119
+ Exact `0.2.0-rc.2` source still declares:
120
+
121
+ ```yaml
122
+ - id: connection
123
+ name: '@deepseek-ai/dsh-client-connection'
124
+ inject: [webRuntime]
125
+ ```
126
+
127
+ The official row still does not own `webServer`.
128
+
129
+ The existing classifier correctly remains `shim-required`. If upstream later adds
130
+ `webServer`, the surveillance gate is already designed to change to
131
+ `retire-ready` and force an explicit DVR retirement before that Host train is admitted.
132
+
133
+ ## Retained: pi-ai / OpenCode Go session-affinity projection
134
+
135
+ Verdict: **KEEP — Host gap remains**
136
+
137
+ Exact DSH `0.2.0-rc.2` `PiAiAdapter` propagates the Harness session identity into
138
+ pi-ai:
139
+
140
+ ```text
141
+ GenerateOptions.sessionId
142
+ -> streamSimple(..., { sessionId: String(options.sessionId) })
143
+ ```
144
+
145
+ but the current DSH source contains no `x-opencode-session` carrier.
146
+
147
+ That is precisely the documented removal condition for DVR's scoped OpenCode Go wire
148
+ projection: generic `sessionId` propagation is not equivalent to the endpoint-required
149
+ header.
150
+
151
+ The DVR rule remains narrowly scoped to an active Vision Router affinity scope and the
152
+ official `https://opencode.ai/zen/go...` endpoint. It must not be retired until the
153
+ native header is emitted on every supported path.
154
+
155
+ ## Retained compatibility inventory
156
+
157
+ The remaining normative seams in `compat-inventory.md` continue to satisfy at least one
158
+ current removal blocker.
159
+
160
+ ### Host-gap owners
161
+
162
+ - `dsh-contract-compat` — Settings lifecycle still spans admitted Host generations;
163
+ durable historical attachment-policy overlays are a separate data-compatibility reason.
164
+ - `adapter-update-coalescer` — DVR still owns duck-typed adapters whose Host base
165
+ contracts and synchronous topology updates require normalization/coalescing.
166
+ - `pi-ai-bridge-wire-compat` — native OpenCode affinity remains absent as proved above;
167
+ legacy direct bridge removal is independently gated.
168
+ - `settings-client-loader-lifecycle` — the supported browser module lifecycle still
169
+ requires post-create reattachment across the declared Host window.
170
+ - `legacy-global-proxy-boundary` — explicit DVR proxy override for Host-owned visual
171
+ adapters remains a supported product capability with no scoped Host dispatcher seam.
172
+ - `legacy-core-vision-policy-bridge` — the Host still lacks the two exact pre-step
173
+ capabilities recorded by the inventory; the 3.0 typed Core-surface work did not create
174
+ an upstream substitute.
175
+
176
+ ### Product / durable-data / platform owners
177
+
178
+ These are not Host-floor retirement candidates:
179
+
180
+ - `replay-envelope-v2-compat` — durable replay data;
181
+ - `http-compat` — evidenced provider wire behavior;
182
+ - `tesseract-exec-compat` — Node/process and Windows DPI behavior;
183
+ - `abort-signal-compat` — partial runtime-realm capability compatibility.
184
+
185
+ Deleting any of these merely because the current Host pin is `0.2.0-rc.2` would mix
186
+ independent compatibility domains.
187
+
188
+ ## R6 exit state
189
+
190
+ ```text
191
+ Host floor unchanged
192
+ durable-data compatibility unchanged
193
+ stale client-runtime inject retired
194
+ stale Doctor package row retired
195
+ modules -> webServer overlay keep / shim-required
196
+ connection -> webServer keep / shim-required
197
+ OpenCode session projection keep / Host gap
198
+ other normative compat keep
199
+ ```
200
+
201
+ R6 is therefore a real retirement pass, not a blanket deletion pass: it removes the one
202
+ edge whose ownership and supplier both disappeared while preserving every seam whose
203
+ documented removal condition is still false.
@@ -0,0 +1,151 @@
1
+ # DVR 3.0 R7 — Public API closure
2
+
3
+ Status: **complete**
4
+
5
+ R7 replaces the package root's accidental mature-Core export graph with one explicit
6
+ plugin/compatibility contract and publishes a matching declaration surface.
7
+
8
+ ## Before R7
9
+
10
+ The package root was:
11
+
12
+ ```text
13
+ lib/public-entry.js
14
+ -> export * from ../entry.js
15
+ entry.js
16
+ -> export * from ./index.js
17
+ index.js
18
+ -> mature Core + algorithm/helper exports
19
+ ```
20
+
21
+ A runtime import of the built package exposed **122 names**. Most were implementation
22
+ details such as OCR helpers, pixel-diff utilities, cache primitives, HTTP/provider helpers,
23
+ SVG rendering helpers and routing internals.
24
+
25
+ Those names were public only because of transitive `export *`; they had no package-root
26
+ ownership contract.
27
+
28
+ Repository reachability review found no production or test consumer importing those Core
29
+ helpers through `dsh-vision-router` or through `entry.js`. Existing direct entry
30
+ consumers use the public Config/revision contract, while Core tests import `index.js`
31
+ or the owning module explicitly.
32
+
33
+ ## Deliberate runtime surface
34
+
35
+ R7 removes `export * from './index.js'` from `entry.js`.
36
+
37
+ The package root now exposes exactly:
38
+
39
+ ```text
40
+ Config
41
+ SETTINGS_CONTRACT_REVISION
42
+ apply
43
+ name
44
+ inject
45
+
46
+ sessionSurfaceReplacementIntent
47
+
48
+ ensureVisionAttachmentAdmissionPolicy
49
+ hasBatchAttachmentContract
50
+ hostOwnsOfficialDeepSeekProvider
51
+ installHostSettingsCompatibility
52
+ installVisionAttachmentAdmissionPolicy
53
+ protectHostProviderOwnership
54
+ ```
55
+
56
+ Classification:
57
+
58
+ - **plugin contract**
59
+ - `name`
60
+ - `inject`
61
+ - `Config`
62
+ - `apply`
63
+ - **supported DVR contract**
64
+ - `SETTINGS_CONTRACT_REVISION`
65
+ - **compatibility API**
66
+ - `sessionSurfaceReplacementIntent`
67
+ - the six explicit DSH compatibility helpers above
68
+ - **accidental internal**
69
+ - every former transitive mature-Core/helper export
70
+ - **test-only**
71
+ - none are published through the package root
72
+
73
+ The mature Core remains importable inside the repository from its owning source/artifact;
74
+ R7 does not delete or rename its internal exports.
75
+
76
+ ## Type surface
77
+
78
+ R7 adds one hand-owned declaration:
79
+
80
+ ```text
81
+ src/lib/public-entry.d.ts
82
+ -> build
83
+ lib/public-entry.d.ts
84
+ ```
85
+
86
+ It intentionally declares only the runtime faces above.
87
+
88
+ Dynamic Host values remain `unknown` at the package boundary instead of inventing a DVR
89
+ copy of the DSH Context graph. The Session replacement variants and the narrow
90
+ compatibility result/options that DVR actually owns are declared explicitly.
91
+
92
+ No internal typed owner is re-exported merely because it exists.
93
+
94
+ ## Package resolution
95
+
96
+ The package follows the current DSH publication shape:
97
+
98
+ ```json
99
+ {
100
+ "main": "lib/public-entry.js",
101
+ "types": "lib/public-entry.d.ts",
102
+ "exports": {
103
+ ".": {
104
+ "types": "./lib/public-entry.d.ts",
105
+ "default": "./lib/public-entry.js"
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ The existing `main` remains for runtime compatibility.
112
+
113
+ `./client` stays a DSH loader entry and is deliberately **not** promoted to an ordinary
114
+ typed consumer-library API.
115
+
116
+ ## Source/artifact ownership
117
+
118
+ The R1 builder now understands canonical `.d.ts` source files:
119
+
120
+ - `.js` canonical source is copied as runtime JavaScript;
121
+ - `.ts` canonical source is compiled to JavaScript;
122
+ - `.d.ts` canonical source is copied as a declaration artifact.
123
+
124
+ Generated declarations remain outside Git source-of-truth just like generated runtime JS.
125
+
126
+ ## Permanent gates
127
+
128
+ `tests/architecture-contract-baseline.test.js` now locks:
129
+
130
+ 1. root `main`, `types` and conditional `exports["."]`;
131
+ 2. absence of `export * from './index.js'` in the entry boundary;
132
+ 3. the exact twelve runtime export names;
133
+ 4. a deliberate declaration for every runtime export;
134
+ 5. no relative internal-module re-export from the root declaration;
135
+ 6. no DSH private `/src/` dependency in the public declaration.
136
+
137
+ This means a new Core export cannot silently become package API again.
138
+
139
+ ## Validation
140
+
141
+ At R7 closure:
142
+
143
+ - canonical build: success;
144
+ - generated-artifact check: **182 artifacts in sync**;
145
+ - Host TypeScript program: success;
146
+ - Client TypeScript program: success;
147
+ - built root runtime export count: **12**;
148
+ - public API / Config / DSH compatibility targeted tests: **66/66**.
149
+
150
+ R7 therefore closes both halves of the package boundary: runtime names and TypeScript
151
+ names are deliberate, narrow and independently owned.
@@ -0,0 +1,248 @@
1
+ # DVR 3.0 R8 — CI / release closure
2
+
3
+ Status: **complete**
4
+
5
+ R8 aligns the 3.0 canonical-source build with CI, packing and the existing trusted
6
+ release model. It does not replace the 2.3 pack-once / tarball-identity / OIDC /
7
+ provenance design; it closes the new source/type/declaration gaps around that design.
8
+
9
+ ## Release blocker found during R8
10
+
11
+ R1 intentionally removed generated runtime artifacts from Git:
12
+
13
+ ```text
14
+ src/**
15
+ -> build
16
+ entry.js
17
+ index.js
18
+ lib/**
19
+ ```
20
+
21
+ and added:
22
+
23
+ ```text
24
+ prepare = pnpm build
25
+ prepack = pnpm build
26
+ ```
27
+
28
+ The pre-3.0 release workflow still had two incompatible assumptions:
29
+
30
+ 1. release verification rejected `prepare` and `prepack` as forbidden lifecycle
31
+ scripts;
32
+ 2. the publish phase set `NPM_CONFIG_IGNORE_SCRIPTS=true`, checked out a clean tree,
33
+ did not install/build package artifacts, then executed `npm pack`.
34
+
35
+ Because generated JavaScript is no longer tracked, that publish path could have packed a
36
+ tarball without the canonical runtime artifacts.
37
+
38
+ R8 fixes the release path instead of weakening R1.
39
+
40
+ ## Canonical source ownership lint
41
+
42
+ R8 adds:
43
+
44
+ ```text
45
+ pnpm lint
46
+ -> scripts/lint-source-ownership.mjs
47
+ ```
48
+
49
+ The gate verifies:
50
+
51
+ - every canonical non-declaration `.ts` owner is present in `tsconfig.build.json`;
52
+ - every canonical Host `.ts` owner is present in `tsconfig.host.json`;
53
+ - stale TypeScript build includes fail closed;
54
+ - two canonical source files cannot claim the same package artifact;
55
+ - production source cannot contain `@ts-ignore` or `@ts-nocheck`;
56
+ - production source cannot import DSH private `/src/` entry points;
57
+ - `entry.js`, `index.js` and `lib/**` cannot return to Git source-of-truth.
58
+
59
+ At closure the gate reports:
60
+
61
+ ```text
62
+ 38 typed runtime owners
63
+ 182 canonical package artifacts
64
+ ```
65
+
66
+ ## Source-to-artifact evidence
67
+
68
+ R8 adds:
69
+
70
+ ```text
71
+ pnpm source:artifact:check
72
+ -> scripts/verify-source-artifact-map.mjs
73
+ ```
74
+
75
+ It proves one package artifact for every canonical JS/TS/declaration source and rejects:
76
+
77
+ - missing generated artifacts;
78
+ - orphan generated artifacts;
79
+ - canonical ownership collisions;
80
+ - copied JS/declaration byte drift.
81
+
82
+ For compiled TypeScript it records the canonical-source and emitted-artifact hashes rather
83
+ than pretending compilation is byte identity.
84
+
85
+ R8 closure evidence:
86
+
87
+ ```json
88
+ {
89
+ "canonicalSources": 182,
90
+ "typedSources": 38,
91
+ "declarationSources": 1,
92
+ "packageArtifacts": 182,
93
+ "mappingSha256": "8799b5363d809834b834676418583eb73aa969ab0d2f6808ed527120579f656a"
94
+ }
95
+ ```
96
+
97
+ ## Packed public API smoke
98
+
99
+ R8 adds:
100
+
101
+ ```text
102
+ scripts/verify-packed-public-api.mjs <existing-package.tgz>
103
+ ```
104
+
105
+ The script never repacks. It validates the exact candidate supplied by its caller:
106
+
107
+ - package `main`, `types`, root conditional exports and `./client`;
108
+ - required runtime/declaration artifacts;
109
+ - canonical `src/` is not shipped;
110
+ - exact twelve R7 runtime exports;
111
+ - a strict NodeNext TypeScript consumer resolves the packed declaration;
112
+ - an accidental mature-Core helper such as `createCache` is not package-root API.
113
+
114
+ This gives declarations a packed-package contract rather than validating only the
115
+ repository checkout.
116
+
117
+ ## CI
118
+
119
+ The Node 22 CI path now runs:
120
+
121
+ ```text
122
+ frozen install
123
+ build
124
+ build:check
125
+ build:reproducible
126
+ Host + Client typecheck
127
+ source ownership lint
128
+ source-to-artifact evidence
129
+ client generated-source check
130
+ full runtime suite
131
+ ```
132
+
133
+ A separate `packed public API` job:
134
+
135
+ 1. performs the canonical build;
136
+ 2. packs one candidate;
137
+ 3. runs the packed runtime/declaration smoke against that tarball.
138
+
139
+ Node 24 continues to run the full runtime suite, while Linux/macOS/Windows native Host
140
+ jobs retain their sharp/package installation checks.
141
+
142
+ At the final R8/R9 checkpoint, CI run `36855737017` for
143
+ `046fd10bc1e6eae9bb72bdf68f0a5e0580ae1efd` completed successfully across:
144
+
145
+ - packed public API;
146
+ - Node 22;
147
+ - Node 24;
148
+ - Linux Host/sharp;
149
+ - macOS Host/sharp;
150
+ - Windows Host/sharp.
151
+
152
+ ## Release verification phase
153
+
154
+ Release verification now explicitly validates the 3.0 source contract:
155
+
156
+ ```text
157
+ install locked dependencies
158
+ build
159
+ build:check
160
+ lint
161
+ source:artifact:check
162
+ build:reproducible
163
+ typecheck
164
+ full tests
165
+ client:check
166
+ Host support-window contract
167
+ ```
168
+
169
+ The lifecycle security check permits only the two required build hooks and pins their
170
+ contents exactly:
171
+
172
+ ```text
173
+ prepare = pnpm build
174
+ prepack = pnpm build
175
+ ```
176
+
177
+ Install/publish lifecycle hooks with unrelated execution authority remain forbidden.
178
+
179
+ ## Trusted publish phase
180
+
181
+ The publish phase deliberately keeps:
182
+
183
+ ```text
184
+ NPM_CONFIG_IGNORE_SCRIPTS=true
185
+ ```
186
+
187
+ It now performs:
188
+
189
+ ```text
190
+ pnpm install --frozen-lockfile --ignore-scripts
191
+ pnpm build
192
+ pnpm build:check
193
+ pnpm lint
194
+ pnpm source:artifact:check
195
+ npm pack --json # exactly once
196
+ verify-packed-public-api <that exact tarball>
197
+ registry identity / publish / provenance
198
+ ```
199
+
200
+ So a release no longer depends on npm lifecycle scripts to materialize package code.
201
+
202
+ The pre-existing supply-chain design is unchanged after the tarball is created:
203
+
204
+ - one exact tarball is hashed;
205
+ - the same tarball is probed/published;
206
+ - trusted OIDC publishing remains enabled;
207
+ - registry SHA identity is verified;
208
+ - SLSA/GitHub provenance binds the exact tarball;
209
+ - GitHub Release rehydrates and verifies the same npm artifact.
210
+
211
+ ## Clean publish simulation
212
+
213
+ R8 reproduced the trusted-publish shape from a clean checkout:
214
+
215
+ 1. `pnpm install --frozen-lockfile --ignore-scripts`;
216
+ 2. asserted `entry.js`, `index.js` and `lib/` were still absent;
217
+ 3. explicit canonical build;
218
+ 4. build/source ownership verification;
219
+ 5. one `npm pack`;
220
+ 6. packed runtime/declaration smoke.
221
+
222
+ Result:
223
+
224
+ ```text
225
+ PUBLISH_SIM_OK:dsh-vision-router-2.3.0.tgz
226
+ ```
227
+
228
+ The package version remains 2.3.0 because R8 is architecture/release-path validation,
229
+ not the 3.0 release/version-bump phase.
230
+
231
+ ## R8 exit state
232
+
233
+ ```text
234
+ canonical source src/**
235
+ generated repository artifacts untracked
236
+ typed runtime owners 38
237
+ public declaration owners 1
238
+ source/package artifacts 182 -> 182
239
+ Host + Client typecheck gated
240
+ clean reproducibility gated
241
+ packed declarations gated
242
+ browser generated sync gated
243
+ pack-once preserved
244
+ trusted publishing preserved
245
+ tarball identity preserved
246
+ provenance preserved
247
+ formal release not performed
248
+ ```