webloom-framework 0.1.0 → 0.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.
@@ -0,0 +1,533 @@
1
+ # WebLoom 浏览器双运行时施工单
2
+
3
+ > SharedWorker 的 `hello`、RemoteService `handshake`、`baseline/resync`、握手超时和
4
+ > 自动重连要求,已被[SharedWorker call-first 消融施工单](../shared-worker-call-first/implementation-plan.md)
5
+ > 覆盖。其余 Runtime、PluginHost、生命周期和安全边界继续有效。
6
+
7
+ ## 1. 施工目标
8
+
9
+ 把 WebLoom 从字符串运行标签和手工初始化装配,升级为真实的 `window-main + shared-worker` 浏览器双运行时;删除无执行语义的 `lifetime` 与插件分类 `kind`;用高层 API 封装 SharedWorker、MessagePort 和远程 capability。
10
+
11
+ 需求基线见[浏览器双运行时迭代需求](./requirements.md)。本施工单保留基础双运行时的
12
+ 历史实施顺序;SharedWorker 连接相关条款已由上方 call-first 施工单取代,不再作为
13
+ 当前 hello/handshake/baseline/reconnect 行为的真值。
14
+
15
+ ## 2. 施工边界
16
+
17
+ ### 2.1 本期包含
18
+
19
+ - WebLoom 核心契约精简;
20
+ - Window RuntimeHost;
21
+ - SharedWorker RuntimeHost;
22
+ - Window/Worker 高层连接 API;
23
+ - 初始化消融 API;
24
+ - 远程 capability 复用与收口;
25
+ - 测试工具、真实浏览器验收;
26
+ - DemoWebLoom 迁移;
27
+ - Keymaster 分阶段接入和旧装配删除。
28
+
29
+ ### 2.2 本期不包含
30
+
31
+ - Server、Node、Deno、Bun 或 Edge PluginHost;
32
+ - Service Worker Runtime;
33
+ - 普通后台 API 通用封装;
34
+ - Keymaster 钱包、密码学、存储格式或业务协议重写;
35
+ - 将 setup 函数动态发送到 Worker;
36
+ - 用自动重试重放具有外部副作用的请求。
37
+
38
+ ## 3. 实施原则
39
+
40
+ 1. 先固化行为测试,再删除旧字段。
41
+ 2. 真实 realm 建立必须早于旧 execution 标签删除。
42
+ 3. Window 和 SharedWorker 各自创建 Host,不能由 Window Host 假装拥有 Worker 单元。
43
+ 4. 多 Window 只增加连接,不增加 Worker RuntimeUnit 实例。
44
+ 5. 同步撤权先于异步清理。
45
+ 6. 旧代理永久失效,不静默重绑。
46
+ 7. 静态 descriptor 与本地 implementation 在内部继续分离。
47
+ 8. 初始化 helper 只隐藏机械装配,不隐藏安全错误。
48
+ 9. Keymaster 迁移保持真实 SharedWorker 和私钥隔离连续可用。
49
+ 10. Node 测试、MessageChannel 模拟与真实浏览器证据分开报告。
50
+
51
+ ## 4. 里程碑
52
+
53
+ ```text
54
+ M1 当前行为基线与消融量化
55
+ M2 契约精简和 Window Runtime
56
+ M3 SharedWorker Runtime 与连接封装
57
+ M4 跨 Runtime capability
58
+ M5 初始化简化与兼容清理
59
+ M6 DemoWebLoom 真实示例
60
+ M7 Keymaster 双 Host 接入
61
+ M8 完整验收与发布准备
62
+ ```
63
+
64
+ ## 5. 工单 WLBR-001:建立当前行为基线
65
+
66
+ ### 目标
67
+
68
+ 在修改 API 前固定当前有效安全行为,并量化初始化样板。
69
+
70
+ ### 修改范围
71
+
72
+ - `src/host/createPluginHost.test.ts`
73
+ - `src/host/pluginGraph.test.ts`
74
+ - `src/transport/*.test.ts`
75
+ - 新增初始化基线 fixture 或测试夹具
76
+ - 不修改生产行为
77
+
78
+ ### 工作
79
+
80
+ - 固化插件启用、停用、依赖阻塞、同步撤权、异步清理和实例重建行为;
81
+ - 固化旧服务引用在 provider instance、connection、revision 改变后失效;
82
+ - 记录最小示例所需 import、声明字段、初始化调用和手工映射;
83
+ - 明确现有 `lifetime` 在无 `scopeResolver` 时不产生差异化行为;
84
+ - 明确 `PluginMeta.kind` 在 WebLoom 核心中无消费点;
85
+ - 给同页面 MessageChannel 测试统一加上 transport simulation 命名或说明。
86
+
87
+ ### 验收
88
+
89
+ - 旧行为测试通过;
90
+ - 基线报告能区分“保留的安全行为”和“待删除的装饰字段”;
91
+ - 不把 Node 测试写成真实 Worker 证据。
92
+
93
+ ## 6. 工单 WLBR-002:精简公共契约
94
+
95
+ ### 目标
96
+
97
+ 删除无执行语义的字段,建立受限浏览器 Runtime 类型。
98
+
99
+ ### 修改范围
100
+
101
+ - `src/contracts/lifecycle.ts`
102
+ - `src/contracts/plugin.ts`
103
+ - `src/host/pluginGraph.ts`
104
+ - `src/host/createPluginHost.ts`
105
+ - `src/index.ts`
106
+ - `docs/api.md`
107
+
108
+ ### 工作
109
+
110
+ - 新增 `RuntimeKind = "window-main" | "shared-worker"`;
111
+ - 将运行单元的 `execution` 替换为 `runtime`;
112
+ - 删除 `PluginExecution = string`;
113
+ - 删除 `PluginLifetime = string`;
114
+ - 删除 `RuntimeUnitDescriptor.lifetime`;
115
+ - 删除 `PluginMeta.lifetime`、`defaultLifetime`;
116
+ - 删除 `RuntimeUnitDependency.scope` 和相关匹配逻辑;
117
+ - 删除 `PluginMeta.kind`、`PluginKind`;
118
+ - 从 WebLoom 核心删除 `displayGroup`;
119
+ - 保留 `PluginState.kind` 等真实判别字段;
120
+ - 保留内部 ResourceScope,但不再从 runtime unit 读取 scope kind;
121
+ - 未知 runtime 值在解析边界 fail closed。
122
+
123
+ ### 测试
124
+
125
+ - JS/JSON 导入非法 runtime;
126
+ - 单元只能被匹配的 RuntimeHost 选择;
127
+ - 依赖不再读取 scope/lifetime;
128
+ - 删除字段后生成的 `.d.ts` 不残留旧符号;
129
+ - ResourceScope 的撤权、迟到资源和清理聚合回归通过。
130
+
131
+ ### 验收
132
+
133
+ - `rg` 检查公开源码与声明中无旧 lifetime API;
134
+ - `PluginMeta.kind` 和 WebLoom `displayGroup` 完全移除;
135
+ - 删除分类字段不影响 PluginState 运行状态。
136
+
137
+ ## 7. 工单 WLBR-003:Window RuntimeHost
138
+
139
+ ### 目标
140
+
141
+ 让 `window-main` 对应当前真实 Window,而不是调用者自报字符串。
142
+
143
+ ### 修改范围
144
+
145
+ - 建议新增 `src/runtime/windowRuntime.ts`
146
+ - `src/host/createPluginHost.ts`
147
+ - `src/contracts/plugin.ts`
148
+ - `src/index.ts`
149
+
150
+ ### 工作
151
+
152
+ - 实现 `createWindowApp()`;
153
+ - 内部固定 RuntimeKind 为 `window-main`;
154
+ - 每次创建生成 `runtimeInstanceId`;
155
+ - 批量接收插件定义,内部构建 Implementation Registry;
156
+ - 自动注册并启动初始插件;
157
+ - 必需插件启动失败时拒绝初始化 Promise;
158
+ - 返回 App handle,提供状态、capability 和 `dispose()`;
159
+ - 页面销毁适配保持显式,核心不得擅自把所有 `pagehide` 当成永久销毁。
160
+
161
+ ### 验收
162
+
163
+ - 使用者不能把 Window Runtime 声称为 SharedWorker;
164
+ - 最小插件不创建 registry、不调用 `host.register()`;
165
+ - dispose 后旧 capability 同步不可取得;
166
+ - 再创建 App 得到新的 runtime/unit instance identity。
167
+
168
+ ## 8. 工单 WLBR-004:插件定义与内部实现注册
169
+
170
+ ### 目标
171
+
172
+ 消除普通插件的 Manifest/setup/registry 三段样板,同时保持跨 realm 可序列化边界。
173
+
174
+ ### 修改范围
175
+
176
+ - 建议新增 `src/authoring/definePlugin.ts`
177
+ - `src/host/runtimeUnitImplementationRegistry.ts`
178
+ - `src/contracts/plugin.ts`
179
+ - `src/index.ts`
180
+
181
+ ### 工作
182
+
183
+ - 实现面向单 Runtime 简单插件的 `definePlugin()`;
184
+ - 定义清晰的 descriptor 与 implementation 内部分离结构;
185
+ - 自动生成默认 unitId;
186
+ - 默认目标为调用方 Runtime,普通 Window 插件不填 `runtime`;
187
+ - 为默认启用、可禁用插件提供一致默认值;
188
+ - 为 required 插件提供单一无矛盾声明方式;
189
+ - 本地 capability contract 可由 helper 生成;
190
+ - 跨 Runtime capability 必须保留显式精确版本;
191
+ - 保留低层 API 供框架内部和复杂打包场景使用,但不作为入门主路径。
192
+
193
+ ### 必测场景
194
+
195
+ - 两个插件重复 id;
196
+ - 同一插件重复 unitId;
197
+ - descriptor 可序列化且不含 setup;
198
+ - Window bundle 不因静态描述导入 Worker-only 实现;
199
+ - 缺失本地 implementation 时结构化报错。
200
+
201
+ ### 验收
202
+
203
+ - 最小示例只导入 `definePlugin`、`createWindowApp`;
204
+ - 复杂插件仍能共享 descriptor、分开打包实现;
205
+ - 静态 Manifest 不成为可执行函数目录。
206
+
207
+ ## 9. 工单 WLBR-005:SharedWorker RuntimeHost
208
+
209
+ ### 目标
210
+
211
+ 在真实 `SharedWorkerGlobalScope` 内创建唯一 PluginHost,并管理多 Window 连接。
212
+
213
+ ### 修改范围
214
+
215
+ - 建议新增 `src/runtime/sharedWorkerHost.ts`
216
+ - 建议新增 `src/runtime/runtimeProtocol.ts`
217
+ - 复用 `src/transport/messagePortServiceProvider.ts`
218
+ - `src/index.ts`
219
+
220
+ ### 工作
221
+
222
+ - 实现 `startSharedWorkerApp()`;
223
+ - 安装并拥有 Worker 的 `onconnect`;
224
+ - 首个连接时创建或取得唯一 Worker Host;
225
+ - 后续连接复用同一 Host 和 RuntimeUnit 实例;
226
+ - 为每个端口生成 connectionId、请求空间和取消集合;
227
+ - Worker 每次启动生成新 runtimeInstanceId;
228
+ - 发布完整 Runtime/Unit/capability baseline;
229
+ - 单个端口断开只释放该连接资源;
230
+ - Host 显式 dispose 时同步撤销全部 capability 并关闭所有端口;
231
+ - 不假设 SharedWorker 提供可靠的终止回调。
232
+
233
+ ### 验收
234
+
235
+ - 浏览器中实际全局对象为 `SharedWorkerGlobalScope`;
236
+ - 两个页面连接后 Worker setup 只执行一次;
237
+ - 一个页面断开不停止 Worker 插件;
238
+ - Worker 重建后所有实例身份变化。
239
+
240
+ ## 10. 工单 WLBR-006:Window 连接封装
241
+
242
+ ### 目标
243
+
244
+ 让使用者通过 RuntimeHandle 使用 Worker,不直接操作 MessagePort。
245
+
246
+ ### 修改范围
247
+
248
+ - 建议新增 `src/runtime/connectSharedWorker.ts`
249
+ - `src/transport/messagePortServiceTransport.ts`
250
+ - `src/transport/serviceBridge.ts`
251
+ - `src/contracts/lifecycle.ts`
252
+ - `src/index.ts`
253
+
254
+ ### 工作
255
+
256
+ - 实现 `connectSharedWorker()`;
257
+ - 内部创建 module SharedWorker;
258
+ - 封装 `port.start()`、握手、baseline、增量 snapshot 和 disconnect;
259
+ - 提供 `ready/state/capability/subscribe/dispose`;
260
+ - 连接失败与协议不兼容返回结构化错误;
261
+ - 自动重连只能创建新连接与新代理;
262
+ - 页面永久 dispose 后禁止后台重连复活;
263
+ - 默认不暴露原始 MessagePort;
264
+ - 诊断中公开必要 identity/revision,但不公开授权 Secret。
265
+
266
+ ### 测试
267
+
268
+ - 握手前调用;
269
+ - baseline 缺失;
270
+ - revision gap、回退和重复;
271
+ - provider rebuild;
272
+ - dispose 与 reconnect 竞争;
273
+ - 两个 RuntimeHandle 连接同一 Worker;
274
+ - 一个 handle 销毁后另一个继续调用。
275
+
276
+ ### 验收
277
+
278
+ - 普通示例没有 MessageChannel/MessagePort 装配代码;
279
+ - 旧代理不会因重连恢复;
280
+ - 具有外部副作用的调用不被框架重放。
281
+
282
+ ## 11. 工单 WLBR-007:跨 Runtime 依赖与状态投影
283
+
284
+ ### 目标
285
+
286
+ 让 Window Host 使用 Worker 发布的真实状态,不根据静态 Manifest 猜测。
287
+
288
+ ### 修改范围
289
+
290
+ - `src/host/pluginGraph.ts`
291
+ - `src/host/createPluginHost.ts`
292
+ - `src/transport/serviceBridge.ts`
293
+ - Runtime snapshot contracts
294
+
295
+ ### 工作
296
+
297
+ - 跨 Runtime 依赖声明来源 runtime 和精确 contractVersion;
298
+ - Window 依赖远程 capability 时等待 Worker baseline;
299
+ - Worker 状态投影只用于产品聚合和诊断,不在 Window 创建 Worker unit 假实例;
300
+ - 远程引用绑定 connectionId、runtimeInstanceId、providerInstanceId、contractVersion、status、revision;
301
+ - `scopeId` 若保留,只代表框架生成的具体实例 Scope,不恢复 lifetime 分类;
302
+ - 支持产品自定义 attributes 透传,但核心不解释 owner/session 等领域字段。
303
+
304
+ ### 验收
305
+
306
+ - Worker 未连接时 Window 依赖保持 blocked;
307
+ - Worker ready 后只启动相关 Window 单元;
308
+ - 断线后 capability 即时撤销;
309
+ - 快照乱序不能让旧 Provider 恢复 ready。
310
+
311
+ ## 12. 工单 WLBR-008:测试工具与真实浏览器验收
312
+
313
+ ### 目标
314
+
315
+ 建立清晰的三层证据,避免模拟测试冒充真实运行空间。
316
+
317
+ ### 修改范围
318
+
319
+ - `src/testing.ts`
320
+ - `src/testing/fakes.ts`
321
+ - Vitest 配置
322
+ - 新增浏览器 fixture 和自动化脚本
323
+
324
+ ### 工作
325
+
326
+ - 提供 `createTestApp()` 或等价内存 helper;
327
+ - 提供明确命名的 MessagePort transport simulation;
328
+ - 建立真实 HTML Window + module SharedWorker fixture;
329
+ - fixture 返回 Window/Worker global marker、runtime identity、setup count 和连接数;
330
+ - 覆盖多页面、断开、重连、Worker URL 变更和版本不兼容;
331
+ - 浏览器不支持 SharedWorker 时明确报告 unsupported,不能回退为主线程并通过。
332
+
333
+ ### 验收
334
+
335
+ - Node 单测通过;
336
+ - transport simulation 通过;
337
+ - 真实浏览器确认代码执行在不同 realm;
338
+ - 验收报告分别列出三层结果。
339
+
340
+ ## 13. 工单 WLBR-009:DemoWebLoom 迁移
341
+
342
+ ### 目标
343
+
344
+ 用 Demo 证明简化 API 和真实双运行时,而不是展示内部装配样板。
345
+
346
+ ### 修改范围
347
+
348
+ - `/home/david/Workspaces/DemoWebLoom/examples/*`
349
+ - Demo README、课程说明和构建配置
350
+
351
+ ### 工作
352
+
353
+ - `01-hello` 改为 `definePlugin + createWindowApp`;
354
+ - 删除所有 Demo 中的 `lifetime` 和插件 `meta.kind`;
355
+ - 普通示例不手工创建 Implementation Registry;
356
+ - remote 课程改用真实 module SharedWorker 文件;
357
+ - 页面不再同时创建 MessageChannel 两端来冒充 Worker;
358
+ - 在 UI 中展示 runtimeInstanceId、unitInstanceId、connectionId 和实际 global 类型;
359
+ - 保留低层 transport 课程时必须标明“协议模拟”,与真实 Worker 课程分开。
360
+
361
+ ### 验收
362
+
363
+ - 所有课程 typecheck/build;
364
+ - 首页和各课程路由可访问;
365
+ - 真实浏览器交互验证 Worker setup 只执行一次;
366
+ - 文档不再把字符串 `execution: "worker"` 描述为物理 Worker 证据。
367
+
368
+ ## 14. 工单 WLBR-010:Keymaster Window 接入
369
+
370
+ ### 目标
371
+
372
+ 让 Keymaster 页面使用新 Window Runtime 和 SharedWorker RuntimeHandle,同时保持现有 Coordinator 安全边界。
373
+
374
+ ### 修改范围
375
+
376
+ - `/home/david/Workspaces/keymaster.cc/apps/web/src/bootstrapPlugins.ts`
377
+ - `keymasterSessionCoordinatorClient.ts`
378
+ - `packages/runtime/src/keymasterHostAdapter.ts`
379
+ - Keymaster Window plugin catalog/implementations
380
+
381
+ ### 工作
382
+
383
+ - 用 `createWindowApp()` 替换页面侧手工 Host/registry/register 样板;
384
+ - 用 `connectSharedWorker()` 封装 SharedWorker 客户端连接;
385
+ - 保留现有 Worker URL 版本隔离、永久 shutdown 和 BFCache 处理;
386
+ - 把 Keymaster 领域 facade 建立在 RuntimeHandle/capability 之上;
387
+ - 删除页面对远端 WorkerUnit 的静态猜测;
388
+ - Keymaster 的 UI `displayGroup` 留在 Keymaster 契约,不回写 WebLoom 核心。
389
+
390
+ ### 验收
391
+
392
+ - 页面插件实际运行在 Window;
393
+ - SharedWorker 不可用时 fail closed;
394
+ - 一个页面销毁不影响另一个页面;
395
+ - 页面不能取得明文私钥;
396
+ - 当前 Local `localStorage` 页面桥行为不被错误替换成其他存储技术。
397
+
398
+ ## 15. 工单 WLBR-011:Keymaster Coordinator Worker 接入
399
+
400
+ ### 目标
401
+
402
+ 在现有真实 SharedWorker 中创建 WebLoom Worker Host,逐步替代手工 WorkerUnitRegistry,不改写钱包领域安全状态机。
403
+
404
+ ### 修改范围
405
+
406
+ - `/home/david/Workspaces/keymaster.cc/apps/web/src/keymasterSessionCoordinator.worker.ts`
407
+ - `apps/web/src/coordinator/workerUnitCatalog.ts`
408
+ - `apps/web/src/coordinator/workerUnitRuntime.ts`
409
+ - 各 `packages/*/coordinator` 入口
410
+
411
+ ### 工作
412
+
413
+ - 先把现有 Worker 入口挂接 `startSharedWorkerApp()`;
414
+ - 将 Vault、Storage 和一个低风险后台单元提取为真实 Worker RuntimeUnit implementation;
415
+ - 证明 Worker Host 真实调用 setup、产生实例、撤销 capability 并清理;
416
+ - 再按领域分批迁移 P2PKH、token、contacts、WOC/JungleBus、MSFile、Sat/Channel;
417
+ - 保留 Keymaster `sessionEpoch`、keyspace generation、owner fence、authority CAS 和 final-I/O lease;
418
+ - Vault lock/unlock 继续由 Coordinator 领域控制器执行,不映射成 WebLoom lifetime;
419
+ - Worker Runtime 只负责插件启停、实例归属、依赖与通用资源清理;
420
+ - 只有当运行快照完全来自真实 Worker Host 后,才能删除手工 WorkerUnitRegistry。
421
+
422
+ ### 迁移顺序
423
+
424
+ ```text
425
+ Vault/Storage 管理外壳
426
+ → 无副作用服务单元
427
+ → 后台只读同步
428
+ → 写入/广播任务
429
+ → MSFile、Sat/Channel 与执行租约
430
+ → 删除旧手工目录和激活代码
431
+ ```
432
+
433
+ ### 安全验收
434
+
435
+ - Worker 重启必为 locked;
436
+ - 私钥只存在 Coordinator Worker 内存;
437
+ - lock 同步推进 epoch、撤销 grant、覆盖私钥;
438
+ - A → B → A 时旧代理和旧 store 不复活;
439
+ - 旧不可中断 I/O 通过既有 fence/lease 隔离;
440
+ - 多 Tab 只有一个 Coordinator Worker 业务实例;
441
+ - Local 桶仍通过页面 localStorage 桥,传输和权限边界不倒退。
442
+
443
+ ## 16. 工单 WLBR-012:删除兼容层与更新文档
444
+
445
+ ### 目标
446
+
447
+ 新机制成为唯一公开路径,避免两套初始化方式长期并存。
448
+
449
+ ### 修改范围
450
+
451
+ - WebLoom 全部源码、测试、README、API 文档
452
+ - DemoWebLoom
453
+ - Keymaster 已迁移调用点
454
+ - 发布配置与 consumer smoke
455
+
456
+ ### 工作
457
+
458
+ - 删除旧 `execution/lifetime/defaultLifetime/scopeResolver` API;
459
+ - 删除 `PluginMeta.kind/PluginKind`;
460
+ - 删除普通使用者可见的手工 Implementation Registry 主路径;
461
+ - 删除已无调用者的 Keymaster WorkerUnitRegistry;
462
+ - 更新 README 最小示例和双运行时示例;
463
+ - 更新包导出和发布文件白名单;
464
+ - 搜索旧符号、旧字段和误导性 Worker 文案;
465
+ - 若必须提供短期迁移 helper,必须标注 deprecated 和明确删除版本,不能保留双真值。
466
+
467
+ ### 验收
468
+
469
+ - 全仓精确搜索无预期外旧符号;
470
+ - package tarball 的 `.d.ts` 不泄漏旧 API;
471
+ - core-only、React、Window 和 SharedWorker consumer smoke 通过;
472
+ - 新用户只阅读 README 即可完成最小 Window 和 SharedWorker 示例。
473
+
474
+ ## 17. 验证顺序
475
+
476
+ 每个工单先执行目标测试,再逐步扩大:
477
+
478
+ ```text
479
+ targeted unit tests
480
+ → typecheck
481
+ → boundary checks
482
+ → full unit tests
483
+ → build
484
+ → package consumer smoke
485
+ → real browser SharedWorker fixture
486
+ → Demo browser interactions
487
+ → Keymaster browser/runtime regression
488
+ → git diff --check
489
+ ```
490
+
491
+ ### WebLoom 基础门禁
492
+
493
+ - `pnpm lint:boundaries`
494
+ - `pnpm typecheck`
495
+ - `pnpm test`
496
+ - `pnpm build`
497
+ - `pnpm run pack:consumer`
498
+ - 新增真实浏览器 Runtime 验收命令
499
+
500
+ ### Keymaster 集成门禁
501
+
502
+ - Keymaster typecheck、boundaries、targeted/full tests、build;
503
+ - Coordinator Client/Worker 的真实浏览器回归;
504
+ - 多 Tab 单 Worker 验证;
505
+ - lock/unlock、切 Key、Worker 重启、旧代理失效;
506
+ - Local 桶 cold start 与页面 localStorage 桥;
507
+ - 外部生产或真实 Provider 验收继续单独报告,不能由本地 fixture 替代。
508
+
509
+ ## 18. 停止条件与回滚原则
510
+
511
+ 遇到以下情况停止对应迁移批次,不继续删除旧路径:
512
+
513
+ - 新 SharedWorker Host 不能证明运行在独立 realm;
514
+ - 多页面产生重复 Worker RuntimeUnit 实例;
515
+ - 断线或重连使旧代理重新可用;
516
+ - Keymaster 私钥出现在 Window 或可序列化快照;
517
+ - lock 后旧签名/存储调用仍可进入最终 I/O;
518
+ - Local 桶因 Worker 无 localStorage 而失去可用页面桥;
519
+ - 新 helper 隐藏初始化失败或把 required 插件失败包装为成功。
520
+
521
+ 回滚只能恢复上一批仍通过安全门禁的装配路径。不得回滚 session epoch、owner generation、已经提交的外部副作用或持久删除操作。
522
+
523
+ ## 19. 最终交付物
524
+
525
+ - 精简后的 WebLoom 浏览器 Runtime API;
526
+ - `window-main` 和 `shared-worker` 真实 Host;
527
+ - SharedWorker RuntimeHandle 与自动连接协议;
528
+ - 初始化消融前后对比;
529
+ - 更新后的 API/README;
530
+ - DemoWebLoom 真实双运行时课程;
531
+ - Keymaster 双 Host 集成及旧手工注册表清理;
532
+ - 单元、模拟、真实浏览器和 Keymaster 集成四类独立验收记录;
533
+ - 未覆盖的外部环境与风险清单。