Files
Endoleap/headless/STEP4_ACCEPTANCE.md

8.4 KiB
Raw Permalink Blame History

Step 4:渐进功能与呈现验收

状态:第4步原定功能、合作调度及规模输入验收已通过;整体进度 4/7。长任务与非抢占边界见下文,不宣称生产实时性能保证。此文件随实现提交;完整目标仍包含后续真实服务、迁移和集成验收。

范围与直接证据

原要求 代码与验证入口 本次结果
导入、深复制逐步加入并允许编辑 imports.ts、canvas-runtime/duplicate.ts;imports.test.mjs、imports-engine.test.mjs、import-document-stream.test.mjs、duplicate*.test.mjs;实际页面文件选择/工具栏 Node 与页面检查通过。SHA 完成前可显示和编辑;完整校验完成且对应 Root 持久化后才发送。单项失败保留已加入内容并报告 partial。复制保留原图、新建身份,父层新增连线,复用合法资源且不自动启动 run。
loader 旧捕获与后续编辑/ACK 协调 loading.ts、engine.ts;loading-engine.test.mjs、浏览器存储和实际页面 当前 loading v1–v6 路径、未读 tail、undo/redo、重开、取消及源校验检查通过。旧数据不覆盖后来的编辑/ACK;已声明的 partial 状态保留。
公共 hooks 和局部订阅 canvas-bindings/react.ts、canvas-bindings;react-hooks-fixture.tsx、renderer.integration.mjs --hooks-only 同一最终源码的 StrictMode 入口 10 项通过;包括 owner 切换、engine close、资源句柄与 unloaded/absent。普通字段与 ACK 的无关投影复用由实际页面计数验证。
输入、呈现与合作调度 frame queue、scene/paint projection、retained projection;frame-queue.test.mjs、retained-projection.test.mjs、实际页面与生产规模入口 页面验证拖动最终位置、IME、Portal、detach、未知焦点与订阅取消。生产万元素早/中/尾段输入与副本捕获隔离通过;性能仍有限制,见下文。

所有 *.test.mjs 均位于 tests/headless/,源码位于 src/lib/ 或 src/components/canvas/。每个测试文件中的断言决定其覆盖范围;通过总数不代表 Draft 的 T01–T36 或整个项目已经完成。

编码与发布边界

  1. writePrefix 是有序单 writer,逐个保存 Root,异步编码不会跳过中间 Root。
  2. 外部对象、getter、custom toJSON 和浅冻结值在第一次让出前按原 codec 捕获;私有容器只证明成员固定,内部未知值仍需捕获。
  3. core 的 detachJsonData 为元素和复制规划 checkpoint 提供 JSON 脱离、深冻结事实,可以延后逐字段编码。需要标准 Object/Array 原型且没有继承的 toJSON;每次未知值捕获后重新检查环境。外部回调不能改变已经捕获的前项,也不能让后项错误沿用旧环境。
  4. 标量归一化、UTF-8 计数、history/import/pending 容器与首次元素遍历共用软预算。已完成的深不可变编码可复用,但不能省略 unsafe occurrence 的求值。
  5. 编码、调度或存储失败保留待存 Root;持久化没有确认,不解除网络发送屏障。旧 Root 与编码期间的新编辑保持各自内容。
  6. journal 比较先判断子值是否相同,再为变化项分配路径,避免为共享的整个前缀创建临时数组。patch 顺序与字节语义不变。

json-data.test.mjs 验证事实不能从外部冻结对象或结构克隆伪造;duplicate-checkpoint.test.mjs 验证首次 checkpoint 的真实字段编码在 yield 间发生,后续 planner.step 不改变已捕获值;imports-engine.test.mjs 验证真实 preparation/source envelope、字节和重开映射。ready plan 已先持久化时允许缓存复用,不要求空 yield。recovery-encoding.test.mjs 验证首次归一化、继承行为、外部回调、Proxy trap 次数、UTF-8、冷/热深度边界;engine.test.mjs 以 17000 元素验证暂停编码期间编辑、逐 Root 落盘和发送屏障。journal-delta.test.mjs 验证精确重放及属性顺序;浏览器检查验证真实 IndexedDB 重开。

可复现命令

node --test tests/headless/*.test.mjs
npm run typecheck -- --incremental false
node tests/headless/renderer.integration.mjs
node tests/headless/renderer.integration.mjs --turbopack
node tests/headless/renderer.integration.mjs --hooks-only
node tests/headless/browser-storage.mjs
node tests/headless/package.integration.mjs
HEADLESS_PERFORMANCE_COUNT=10000 HEADLESS_PERFORMANCE_EDIT_DURING_COPY=1 HEADLESS_PERFORMANCE_REPORT=/private/tmp/headless-checkpoint-production-10000.json node tests/headless/renderer.integration.mjs --performance --production --turbopack

性能入口须在其它构建/测试结束后单独执行;功能检查可并行。这里验证真实 Chrome、IndexedDB、Web Locks 和实际前端,但 HTTP 为隔离 fixture,不能据此声称已完成真实 Foundry 集成。

本次运行结果(2026-11-11)

  • Node:783 项通过;全量前端 TypeScript 检查通过。
  • 实际页面:webpack 51 项、Turbopack 51 项通过;公共 hooks 10 项通过。
  • 浏览器存储:57 组通过;SDK:265 个打包文件,类型、独立消费和编译后的浏览器/Worker 检查通过。
  • Chrome 退出后的 stdio 清理保留。此次五组并行检查中,webpack 有一次原生双击未打开恢复编辑器;同源码单独复跑51项通过。随后测试增加同步完成、两次rAF和实际可命中点击点的前置条件,保留原生事件/编辑焦点断言;两种构建器各51项均通过。未据此推定产品逻辑有错或仅是CPU争用。
  • 生产规模环境:本机 arm64、macOS 15.6、Node 23.10.0、Chrome 157.0.8103.39,Next production Turbopack;无并行构建/测试、无计时代码插桩。
  • 10000-child 展开分区深复制:首副本呈现 784.1ms、本地完成帧 27949.7ms、加入并同步 28169.9ms;帧间隔 P95 33.4ms/max383.4ms;21 次 longtask,max386ms/total1663ms。
  • early 五次 input→两次 rAF:69.8/57.9/34.3/29.5/15.6ms;middle(5279 项)45.3ms、tail(9093 项)73.5ms。全部发生于复制活跃期间,DOM/focus 保留;中尾 CDP 往返约40.9/26.0ms。它们不含精确的派发前排队延迟。
  • 服务端最终 20005 元素/3 canvas;原/新父层边、原文后续输入、副本旧快照、pan 后副本挂载通过。样本呈现时挂载35节点,全过程最大137,pan 后28;屏幕外 IME/Portal 各保留1,独立应用面板不额外保活,runStartsDuringScenario=0。

原始报告 /private/tmp/headless-checkpoint-production-10000.json 和同名 PNG 为本次本机观察;命令与断言已保存在仓库,可独立复现。单次运行有不同 adaptive 批次、native/GC 与系统调度负载,不能以此与前轮36.26秒比较而宣称确定提速,更不能说所有停顿已解决,或未经归因把386ms全部称为GC。

收口审查

前轮唯一明确的编码缺口已经接通:createDuplicatePlanner().checkpoint() 与元素复用同一 JSON 脱离工厂,runtime 自建 job/source/preparation envelope 保留 shape 来源;分配列表、ready ID表和根列表不再丢失这项边界。首次 preparation 确实分段,最终 ready plan 先经过持久屏障后复用已有编码,重开后映射保持。

第4步验收按开工时的四类职责和6ms合作调度软目标完成,不把它改成“每次GC/native/原子发布均小于6ms”。此结论覆盖原定实现与列出的复现入口;它不代表无卡顿、低端设备SLA、任意selector皆O(1)或T01–T36全部完成。首项可见、输入保留、两侧快照正确、Root按序落盘及发送屏障均有直接断言;最终长任务观测作为已知限制保留,不假称已经消除。

调度限制与后续分工

6ms 是合作调度软目标。捕获成员引用、未知值的同步 JSON 语义、单个字符串/native 操作、原子模型发布和 GC 仍可能超过一个时间片。未知调用不能假冒不可变值以换取响应速度;也不能把普通循环停顿一概称为 GC。测试测量 input 到两次 rAF;CDP 往返另含传输和驱动时间,均不是精确的输入派发前排队延迟。

未登记的第三方 Portal/未知输入 owner 保留明确的兼容回退;任意全局 Root selector、结构变化和未知 ACK 不保证 O(1)。renderer 不保存第二份业务文档,不为裁剪丢弃完整模型。

下一阶段由服务/集成工作负责真实 Foundry 协议、权限、迁移、冻结请求幂等与恢复联调,并沿用现有远程 CI。分支推送不等于主线合并或部署,仍需单独报告。