Repository navigation
fix(app-slide): restore latest media state after freezing - #80
Conversation
Horan-Ding
left a comment
There was a problem hiding this comment.
Cursor Agent
Reviewed head: 18d0f824a54ff0c3e93ba87959ae30fa1e33ceb3
Reviewed base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
正在独立审查该 PR:读取 diff、AGENTS.md 及相关变更文件。
审查范围
已通读 pr.diff(e09be874 → 18d0f824),并对照当前 pinned checkout 中的实现与跨仓只读参考(@netless/slide 的 receiveSyncEvents / SyncTaskManager.receiveBatch)。本 PR 的生产代码变更集中在 packages/app-slide/src/SlideController/index.ts 与 packages/app-slide/src/index.ts(enableWebAudio 透传);其余为 E2E 基建、单测与依赖版本。
发现项(P0 → P3)
No findings.
对以下路径做了针对性核对,未发现需作者在本 PR 内修复的、可复现的缺陷:
- 冻结恢复批处理时机(
pendingFrozenSyncBatch):仅在invisibleBehavior === "frozen"且unfreeze完成release+ 强制 storage restore 之后置位;lifecyclePending/restoringStorage/storageBlocked会阻止过早flushSyncEvents,与BootstrapStorage.test.ts中「release 完成前不刷批」「defer freeze / failed freeze」用例一致。 flushSyncEvents批路径 vs 兼容路径:有receiveSyncEvents时整批splice后coalesceMedia: true;无 API 时仅清标志,余量仍走原有emit(syncReceive)FIFO,与 README 声明一致。release第四参getCurrentState:在destroyed时返回undefined,否则读context.storage.state.state,与 Slide_doRelease用最新 snapshot 恢复的设计一致;本仓无单测 mock 第四参,属覆盖缺口而非已证实的逻辑错误。- 批处理失败:
receiveSyncEvents抛错时记录日志且不再重入队列,与单条emit失败处理一致;未看到比变更前更糟的唯一回归路径(在可触发条件下)。
总体评估
变更面小且与需求对齐:仅在完成一次冻结恢复(含 storage 对齐)后,对积压同步事件走 Slide 本地 receiveSyncEvents(..., { coalesceMedia: true });unfreeze 向 release 提供动态 getCurrentState;enableWebAudio 仅类型与构造透传。与 @netless/slide 1.4.64-alpha.3 的批语义(receiveBatch + compactRecoveryBatch)在静态层面一致。
覆盖与验收缺口(非本 PR 代码缺陷)
| 缺口 | 说明 |
|---|---|
getCurrentState → release |
无单测断言第四参绑定与 destroyed/storage 快照;依赖 E2E 与 Slide 侧行为。 |
| 发布门禁 | prepublishOnly 含 test:media:release,需私有 APP_SLIDE_E2E_CONFIG 与真实浏览器;未配置则无法 npm publish,属有意 fail-closed。 |
| Slide 制品 | 仍 pin @netless/slide@1.4.64-alpha.3;无 API 时批合并不生效,文档已说明。 |
| E2E 矩阵 | 作者称 WebKit 全矩阵与 app full profiles 仍在进行;静态审查不能替代该 head 的最终门禁。 |
| 媒体核心修复 | 意图/track、resumeSeek、原生故障注入等主要在 slide 包;本 PR app 侧为集成与验收,未在 diff 内单独实现。 |
结论:在仅针对本 PR 引入变更的静态审查下,未发现可列为 P0–P3 的 actionable 缺陷;合并/发布是否就绪仍取决于 slide 候选发布、pin 升级及完整 E2E/release 门禁结果,不宜由本次审查推断。
Horan-Ding
left a comment
There was a problem hiding this comment.
Codex Astra (gpt-6-astra)
Reviewed head: 18d0f824a54ff0c3e93ba87959ae30fa1e33ceb3
Reviewed base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
Codex Astra 独立审查 — app-slide PR #80
No findings.
未发现可归因于当前完整 PR、具有充分代码因果的 P0/P1/P2/P3 可操作缺陷。
- HEAD:
18d0f824a54ff0c3e93ba87959ae30fa1e33ceb3 - Base:
e09be874f0c2b46a1e0befcd32f10c9b6192156b - 范围:完整 base…head diff,20 个变更文件、3,234 行。逐文件核对当前隔离快照的 Git blob,全部匹配固定 HEAD;变更路径集合与完整 Git diff 一致。
- 按授权复用 12 个与此前独立审查内容完全相同的 blob;另 8 个文件重新核查全部差异和相关上下文。其中生产行为与新增测试集中在 controller/BootstrapStorage,其余 6 个文档/E2E 文件的更新为格式调整,没有观察到行为变化。没有读取其他 reviewer 或旧 review 报告。
重点核对
packages/app-slide/src/SlideController/index.ts:821-826在 release 完成、最新 storage 恢复完成后才设置pendingFrozenSyncBatch;ready 前仅记录延迟冻结请求的路径不再提前开启批次。enqueueLifecycle在恢复期间持续阻止同步事件交付;storage 恢复的 finally 即使调用flushSyncEvents,仍被lifecyclePending拦住。批次标记设置后由外层 lifecycle 收尾交付,因此不会在最新 snapshot 恢复前消费积压事件。- 冻结或恢复失败继续由
resourceStateUnknown/storageBlocked保持阻塞。后续成功恢复仍会设置批次标记并处理积压;重复 unfreeze、恢复中再次 freeze 和 destroy 的 guard 没有因标记后移而失效。普通 live 事件及缺少批次 API 的旧引擎继续走原 FIFO 路径。 packages/app-slide/test/BootstrapStorage.test.ts:337起的新增测试明确区分播放器创建、最新 storage 恢复和消息交付;:382起覆盖 ready 前冻结不调用批次、冻结失败后继续保留消息以及成功恢复后批次交付。该测试使用结构 fixture,不把它等同于真实播放器/房间验收。- 独立发布验收仍先校验 npm 精确版本、按选定输入重建 app,再记录哈希并启动浏览器;release 要求
appRebuilt=true、installed-npm、完整三轮矩阵及成功清理。格式变更未弱化这些条件,也没有恢复复用旧候选 dist 的路径。
验证边界
本轮仅做固定源码快照审查与只读 Git 内容核验,没有执行构建、安装、单测、浏览器/房间测试或发布操作,也没有读取凭据。任务上下文给出的 lint、unit/sync、runtime 及源端测试结果未作为本轮独立复验。
App 仍钉 @netless/slide@1.4.64-alpha.3。候选中的底层媒体执行与批次能力不能被视为已经进入该 npm 包;作为修复版本发布仍需新引擎发布、app 精确钉版及对应制品完整验收。当前 app 完整 profile 未完成的边界继续保留。
本审查不覆盖移动实机、RTC/PCM、录制回放或真实声卡输出,也不构成合并或正式发布保证。
Horan-Ding
left a comment
There was a problem hiding this comment.
Cursor Agent
Reviewed head: 8034bbcc9f0240d8a2c761897be94d3e60a4ce85
Reviewed base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
正在独立审查该 PR:读取 diff、相关源码与调用方。
审查范围
已完整阅读 pr.diff(e09be874 → 8034bbcc),并对照检出树中的生产改动与调用链:packages/app-slide/src/SlideController/index.ts、packages/app-slide/src/index.ts、packages/app-slide/test/BootstrapStorage.test.ts,以及 E2E harness(run.mjs / main.ts / coverage.mjs / boundaries.mjs / release.mjs)。跨仓只读参考了 source/packages/slide 中 receiveSyncEvents / receiveBatch / release(getCurrentState) 语义。仓库根 AGENTS.md 与本 PR 无关(发布约定在 monorepo 另一路径)。
缺陷(P0–P3)
No findings.
对本次 PR 引入的生产逻辑,未找到可复现、可交给作者修复的确定性缺陷。说明如下(便于理解「为何无项」,不构成放宽标准):
- 冻结恢复批次:
pendingFrozenSyncBatch仅在invisibleBehavior === "frozen"且 unfreeze 走完release+ 强制 storage restore 之后置位;flushSyncEvents在lifecyclePending/storageBlocked/restoringStorage期间不会提前冲队列,与BootstrapStorage.test.ts中「ready 前 freeze 不启用批次」「失败 freeze 后仍 FIFO」「成功 recovery 后coalesceMedia: true」一致。 getCurrentState:在release第 4 参数传入context.storage.state.state,与@netless/slide侧在重建 Player 时拉最新 snapshot 的契约一致;属有意集成,非遗漏。enableWebAudio:仅透传AppOptions,行为仍由 SlideinitSlideConfig归一化,无新增分支错误。- E2E 体量很大,但属验收与 harness;
second.mp4URL 仍映射到fixtures/media.mp4,属测试数据复用,不是缺文件 404。
未将「destroy 与 flush 竞态导致 receiveSyncEvents 空操作且 pending 已 splice」等极端 teardown 竞态列为缺陷,因在正常 unfreeze 完成路径上缺乏可证实的必现触发链,且不符合「非推测」要求。
总体评价
本 PR 对 app 产品字节 的改动面很小:核心是 SlideController 在 frozen 模式 unfreeze 成功后 用 receiveSyncEvents(..., { coalesceMedia: true }) 交付冻结期积压信令,并在 release 时提供 storage 驱动的 getCurrentState;其余主要是 Playwright 真实房间媒体 E2E、prepublishOnly 发布门禁与 @netless/slide@1.4.64-alpha.3 依赖抬升。设计与 slide 源侧 SyncTaskManager.receiveBatch / Slide.receiveSyncEvents 对齐,结构测试对批次开关的覆盖合理。
覆盖与测试缺口(材料性,非代码缺陷)
| 缺口 | 说明 |
|---|---|
| 生产集成 | getCurrentState 四参数 release 无单测,仅 E2E/真实引擎路径间接覆盖。 |
invisibleBehavior: "pause" |
批次仅挂在 frozen 销毁路径;pause 模式未在本 PR 测试矩阵中验收 coalesce。 |
| 发布门禁 | prepublishOnly 含 test:media:release,依赖外部 APP_SLIDE_E2E_CONFIG 与浏览器;静态审查不能替代三轮 release 矩阵。 |
| 依赖 | app 仍钉 alpha Slide;与源侧修复的完整闭环需发布并 pin 正式包(作者已说明,审查不推断 merge 就绪)。 |
| 平台 | README 已声明桌面 E2E 不覆盖移动端、录制回放、RTC/PCM。 |
结论:在仅审查本 diff 引入变更的前提下,未发现需作者立即修复的 P0–P3 项;合并与发布就绪仍依赖已声明的 E2E/release 与 npm 发布流程,而非本次静态结论。
Horan-Ding
left a comment
There was a problem hiding this comment.
Codex Astra (gpt-6-astra)
Reviewed head: 8034bbcc9f0240d8a2c761897be94d3e60a4ce85
Reviewed base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
Codex Astra 独立审查 — app-slide PR #80
No findings.
未发现可归因于当前完整 PR、具有充分代码因果的 P0/P1/P2/P3 可操作缺陷。
- HEAD:
8034bbcc9f0240d8a2c761897be94d3e60a4ce85 - Base:
e09be874f0c2b46a1e0befcd32f10c9b6192156b - 范围:完整 base…head diff,20 个变更文件、3,491 行。当前快照的 20 个 Git blob 全部匹配固定 HEAD,变更路径集合与完整 diff 一致。复用 15 个内容完全相同文件的独立核查结果,对另 5 个 E2E/文档文件核查全部增量与调用上下文;生产
src相对此前固定快照没有变化。 - 未读取其他 reviewer 或旧 review 报告,未修改源码、运行构建/安装/浏览器、读取凭据或操作 GitHub/房间。
核对结果
- 重播位置具有独立起点。
packages/app-slide/test/browser-media-e2e/boundaries.mjs:129-160同时确认音频和视频均已暂停在裁剪起点,并在 600ms 后再次检查;真实 play 点击返回发起时间窗口和当次发送状态,断言该时间基准为零裁剪偏移(与 0.2 秒位置误差一致的容差)。之后才调用实际播放检查、要求三端 engine/storage 与该状态完全相同,并按当前房间时间验证两轨位置。因此,状态和媒体共同携带错误旧偏移不再能仅靠自洽通过。release.mjs:95-110强制要求每个配置的视频/音频都有这份独立锚点证据。 - 动画不再只依赖步号增长。
run.mjs:1028-1094先等三端引擎/共享状态稳定且一致,再根据 idle/end 状态计算此次精确预期步号;每次 nextStep 都要求新增真实同步事件、对应 start/end 回调、三端相同步号和 end 状态,以及每端 Pixi 场景像素变化,连续执行两步。事件按 App 实例 epoch 和当前页过滤,并只检查本次点击后的新回调。release.mjs:112-132另行要求两步、三端结果及像素变化。 - 新的诊断选项不会缩减发布矩阵。
APP_SLIDE_E2E_DIAGNOSTIC_MODE只在 diagnostic 分支选择 1.0/1.5;完整模式仍遍历两种白板配置与两个媒体后端。release 继续拒绝诊断子集,要求完整三轮 profile、成功清理和同一制品。 - 其它已核查约束保留。 playing seek 仍独立验证请求时间编码、真实回送状态和 native 定位完成;暂停仍按实际权威 pause 状态检查严格位置和停止。恢复批次只在 release 与最新 snapshot 恢复完成后启用,普通 FIFO/旧引擎兼容路径保留。发布入口仍强制精确 npm pin、新构建以及
appRebuilt/installed-npm检查。
验证边界
本轮只做源码与断言逻辑审查,没有重跑 WebKit replay、Chrome 动画或完整 R7 矩阵。任务上下文提供的成功实测不是本轮独立执行结果;R7 仍进行中,不能把部分通过当作完整资格验收完成。
新增像素检查验证采样时真实 Pixi 场景发生变化,属于端点画面检查,不是逐帧动画质量、目标效果 golden 或屏幕呈现/帧率验收。
App 当前仍钉 @netless/slide@1.4.64-alpha.3。修复版本发布仍需要新引擎发布、app 精确钉版及对应制品完整验收;候选测试通过不能视为 npm pin 已包含新能力。移动实机、RTC/PCM、录制回放和声卡输出不在本轮范围,本结论不构成合并或正式发布保证。
Horan-Ding
left a comment
There was a problem hiding this comment.
Codex Astra (gpt-6-astra)
Reviewed head: 0323f93c7fe990debc3eeb5ace84c700666692c3
Reviewed base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
app PR #80:Astra 最终 pinned 复审
- 仓库:
/Users/dinghaoran/code/agora/conversion-agent/outputs/slide-media-controller-20261016/app - HEAD:
0323f93c7fe990debc3eeb5ace84c700666692c3 - base tip:
e09be874f0c2b46a1e0befcd32f10c9b6192156b - 实际 merge-base:
e09be874f0c2b46a1e0befcd32f10c9b6192156b - 审查范围:当前完整 merge-base..HEAD 的 20 个文件及生产调用链;本轮额外核对 4 个文件的最终门禁增量。开始及结束均核对指定 HEAD,工作树干净。
- 当前背景来自本目录
app-context.md;未读取 Cursor、其他或历史 review。未访问外部、未发布/委派、未运行测试或浏览器,只写本报告。
No findings. 当前 pinned diff 中未发现足以列为可操作 P0/P1/P2/P3 的新增缺陷。这是静态审查结论,不等于完整 app 验收或发布资格通过。
最终修复核对
客户整稿覆盖现在有完整的检查链:run.mjs 在创建房间之前要求完整验收具备客户和动画资源,并要求 pageCount 为正整数;客户首页加载并收敛后,读取三端真实 Slide.slideCount,要求一致且等于配置值。遍历以实际页数为上限,只有页面完成 render/storage/scene 收敛并记录 checkpoint 后才加入覆盖集合。release.mjs 按每个浏览器 profile、白板模式和后端检查页序列恰为 1..actualPageCount,并核对第 2 页起每页都有三端实际记录。遗漏、过小或过大的配置不再被静默接受为完整整稿。
发布汇总在任何配置断言或子 profile 执行之前,已经通过临时文件加 rename 写入本次 runId 的 passed:false/status:running。正常异常路径将状态改为 failed,并在 finally 保存;只有三个 profile 及制品一致性检查全部通过才写 passed。复用 APP_SLIDE_E2E_OUTPUT 不会再把上一轮 passed 留作本轮最终状态。运行中的异常终止最多留下本次 running/false,不保留旧成功含义。
生产与验收范围
已复核当前恢复 provider 读取最新 storage、恢复及 storage 串行屏障、恢复完成后一次性提交 frozen batch、普通 live FIFO 与旧 API 回退、异常日志和永久销毁边界,以及 enableWebAudio 的配置透传。共享状态/场景写入仍受既有作者权限条件限制,未发现本 PR 新增回写路径。
完整 E2E/发布接线检查包含:三角色、两种白板模式、HTML5/WebAudio 实际后端、三种浏览器配置、被动 CDP 采样与真实权限手势、原生 seek/时钟/BufferSource 观察、旧节点静音、冻结恢复/断线/作者切换、裁剪与重播、多媒体及受控 HTTP 失败、18 秒独立 MP3 延迟、客户逐页与两步动画像素、房间创建 journal 和最终停用回读。发布 gate 继续拒绝诊断子集及本地 Slide alias,并要求重建 app、精确 npm 版本和跨 profile 制品哈希一致。当前未发现最终门禁增量破坏这些条件。
尚未由本次审查证明的结果
- 作者背景称 missing/0 pageCount 和旧成功标记失效的真实命令负例已通过,语法/格式通过且 lint 无 error;本审查没有重新执行这些命令。
- 当前完整 app 三 profile 尚待运行。本报告不把旧提交构建、单测、13 项生命周期或 source 结果计为当前 app 浏览器通过。
- 当前 npm 依赖仍为
@netless/slide@1.4.64-alpha.3;本地 SLIDE_CANDIDATE_DIR 验证不等于目标 npm 修复包验收。source 修复完成后的实际 npm 依赖、最终 app 构建及完整门禁仍需重新核验。 - 桌面矩阵不覆盖移动实机、RTC/PCM、录制回放;两步动画像素用例不证明所有动画内媒体生命周期。客户逐页收敛也不等于每页人工视觉通过。
以上均为验收与覆盖边界,不另列作本 pinned app diff 的新增缺陷。
Horan-Ding
left a comment
There was a problem hiding this comment.
Cursor Agent
Reviewed head: 1702f188418e16c97e4dbae245b04a6cbd8f791c
Reviewed base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
正在独立审阅该 PR:读取 AGENTS.md、完整 diff 及相关源码与测试。
已通读 pr.diff(merge-base e09be874 → head 1702f188),并对照检出树中的 SlideController/index.ts、index.ts、BootstrapStorage.test.ts 及 E2E 入口逻辑做了交叉核对。工作区内无 AGENTS.md。
发现项(P0–P3)
无发现。
对本次 PR 引入的产品面变更,未列出需在合并前修复的可执行缺陷。
审阅摘要
变更范围
| 类别 | 内容 |
|---|---|
| 产品代码 | SlideController/index.ts:pendingFrozenSyncBatch、flushSyncEvents 中 receiveSyncEvents(..., { coalesceMedia: true })、release 第四参 getCurrentState、enableWebAudio 透传;index.ts 类型导出 |
| 其余 | 版本号、BootstrapStorage 单测、Playwright 媒体 E2E 与 prepublishOnly 门禁、锁文件等 |
核心路径核对(无缺陷结论依据)
- 批量恢复时机:
pendingFrozenSyncBatch仅在invisibleBehavior === "frozen"且unfreeze走完release、以requireSuccess完成 storage restore 之后置位(约821:826:packages/app-slide/src/SlideController/index.ts)。与注释「未完成恢复不启用 batching」一致。 - 与 lifecycle 的交互:
flushSyncEvents在lifecyclePending > 0时直接返回(约399:407),避免在unfreeze内await storageRestoreTask时以 FIFO 提前冲掉冻结积压;batch 在 lifecyclefinally或后续 restore 的finally中触发,与BootstrapStorage新用例一致。 - 延迟 freeze(
ready === false):不置storageBlocked、不启用 batching,信号仍 FIFO(第二段新测约200:213:pr.diff)。 getCurrentState:箭头函数在调用时读context.storage.state.state,destroyed时返回undefined(约786:787),与「恢复后以 storage 为准」一致。- 旧 Slide 无
receiveSyncEvents:清 flag 后走原 FIFOemit(syncReceive)(约410:438),属文档化的兼容路径,非本 PR 引入的回归。
未将「仅升 app-slide、宿主仍注册旧 Slide IIFE」视为代码缺陷:属配套发布策略;E2E README 已说明兼容路径不含此次修复。
覆盖与测试缺口(非缺陷,但影响合并信心)
- 完整 app 三 profile 矩阵:作者自述仍在重跑,不能视为已通过;
prepublishOnly依赖外部APP_SLIDE_E2E_CONFIG与真实房间,本地/CI 无配置时无法在本审阅中复现 release 门禁。 getCurrentState无单测:BootstrapStorage的releasestub 仍只有三参、未断言第四参或 storage 快照(约140:151:packages/app-slide/test/BootstrapStorage.test.ts);行为主要靠 E2E + Slide alpha 联调。receiveSyncEvents抛错:与 FIFO 一样只打日志、不重入队(约419:422);无针对性单测,属既有错误处理风格,非本 PR 独有。- 产物与源码 SHA:上下文称产品 SHA 未变、最新提交偏验收/诊断;若以制品为准,合并前应再确认 head 与待发布构建一致。
@netless/slide仍为1.4.64-alpha.3dev 钉扎:npm 正式 Slide 发包后需按run.mjs的 pin 校验再跑 release(约3567:3572:pr.diff)。
结论
就 本 PR diff 内的产品逻辑 而言,冻结恢复串行化、storage 优先、receiveSyncEvents 批量合并与 enableWebAudio 透传与新增 BootstrapStorage 用例自洽;未发现 P0–P3 可执行代码缺陷。合并/发布风险主要在 E2E 矩阵未完成 与 app-slide 与 Slide 版本配套,而非本次审到的 controller 实现错误。
Horan-Ding
left a comment
There was a problem hiding this comment.
Codex Astra (gpt-6-astra)
Reviewed head: 1702f188418e16c97e4dbae245b04a6cbd8f791c
Reviewed base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
app PR #80:Astra 播放观察改动最终 pinned 审查
- 仓库:
/Users/dinghaoran/code/agora/conversion-agent/outputs/slide-media-controller-20261016/app - HEAD:
1702f188418e16c97e4dbae245b04a6cbd8f791c - base tip:
e09be874f0c2b46a1e0befcd32f10c9b6192156b - 实际 merge-base:
e09be874f0c2b46a1e0befcd32f10c9b6192156b - 本地 ESM 制品只读核验:
packages/app-slide/dist/main.es.jsSHA-256 为40248840ccfc26151184c036c6786ad82dac0595d0cf62991f40d08c5ab5f038。 - 当前完整 PR 为 20 个文件;最新相对
0323f93c7fe990debc3eeb5ace84c700666692c3只改 4 个验收/诊断文件,已用 Git 确认产品 src 无差异。开始及结束均核对指定 HEAD,工作树干净。 - 当前背景来自本目录
app-context.md;未读取 Cursor、其他或历史 review。未运行测试/浏览器/构建,未访问外部、未委派或发布,只写本报告。
No findings. 在当前完整 pinned PR 及最新播放观察增量中,未发现可操作的新增 P0/P1/P2/P3。静态审查完成;不代表正在执行的 app 三 profile 已通过。
新播放判定核对
run.mjs:485-515 的有效采样要求仍包括实际后端匹配、播放模式、音频非暂停、无原生 seeking、无两轨执行 pending;HTML5 要求原生 audio 非暂停,WebAudio 要求当前 BufferSource 已启动且未终止、AudioContext running。视频额外要求原生视频非暂停、当前显示图层可见以及两轨时间差小于 1.25 秒。引擎和 storage 都必须是 play 且时间基准一致。
523 行在每个客户端的观察循环之外建立一次 15 秒 deadline。失去 ready 条件会丢弃基线;播放器 epoch、media id、sound id、WebAudio source id、执行 revision 或共享时间基准变化时,只重取 baseline/capturedAt,不重置 deadline。之后只有同一身份、同一稳定执行区间达到至少 300ms,且音频及视频各推进超过 0.1 秒,才认定播放成功。正常校准发生后允许观察新的稳定区间,避免永久绑定已失效 revision;校准本身的 seek 跳变不直接计入新的时钟增量。持续校准或始终无法形成稳定区间仍会在原截止时间失败。
main.ts 新暴露的 WebAudio sourceId 来自原生探针 Map 中每次 createBufferSource 分配的递增 id,与实际 sourceActive 判断配合,可以区分同一 sound 下 BufferSource 替换。探针依然调用原始 create/start/stop/load 方法,未模拟播放或改变原生 Promise。禁止自动播放配置的 sample() 继续经过现有 passive CDP evaluate,不因改为 Node 侧采样循环而授予用户激活。
新的 mediaFailure 检查仍在每次观察时失败退出;HTTP/传输和 console 门禁也保留。原生 error/Range 记录属于诊断增强,没有将错误码 4、metadata 超时或资源失败改成允许通过的条件。
诊断与完整 PR 核对
原生 load 包装在调用原方法前按节点注册一次 error 监听,保留 code/message、readyState/networkState 和当时位置;媒体响应记录角色、时间、路径、HTTP 状态与 Range/类型/长度。请求 URL 记录使用 pathname,不额外记录查询参数。该记录用于区分响应与解码阶段,不能单凭一次成功响应证明设备解码正常。
当前生产恢复 provider、storage/lifecycle 串行屏障、一次性 frozen batch、兼容 FIFO 回退与作者写入边界均纳入完整 PR 复核,未发现新增生产缺陷。客户真实页数及逐页覆盖检查、发布汇总 running/failed 状态、诊断/本地 alias 禁止发布、精确 npm 版本和跨 profile 制品哈希检查仍有效。真实房间 journal、清理回读,以及既有权限、冻结恢复、断线、裁剪、多媒体、客户页面和动画像素门禁未被本次增量削弱。
证据与未完成边界
- 作者背景报告 source 352 项与负例、72 intent 前置条件重验及 A/B 160 已通过;这些不替代 app 全矩阵,本审查也未独立运行或核验其报告。
- 当前 app 完整三 profile 正在执行。候选与正式包在相同宿主首播均成功、纯原生及 Howler 对照通过,是局部观察;不能据此将完整 app 验收标记为完成。
- 原生资源错误码 4 和 metadata 未到的独立失败记录仍需保留与解释。新的 oracle 修正只针对正常校准后旧基线失效,不能把这些资源/解码失败重分类为已修复的 oracle 问题。
- 300ms 稳定播放区间是功能起播证明,不代表长时无漂移、连续所有帧可见或实际扬声器输出。当前变更也不扩大移动实机、RTC/PCM、录制回放或全部动画内媒体的覆盖。
- 当前 app 仍锁定 npm Slide alpha.3,本地候选测试不能代替包含目标修复的最终 npm 实包验收;发布门禁继续要求在实际 npm 依赖上重跑。
本报告仅完成当前 pinned 静态审查,不宣称发布、合并或完整 app 放行。
Horan-Ding
left a comment
There was a problem hiding this comment.
Cursor Agent
Reviewed head: 16e310a0eb85f9cee999137de434e957ccfad907
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
正在独立审查该 PR:读取 diff、相关源码与调用方。
已完整审阅 pr.diff(e09be874 → 16e310a0)及钉住 head 下的 SlideController/index.ts、index.ts、BootstrapStorage.test.ts 与 E2E 入口;并对照同批次 Slide 源码中 receiveSyncEvents / release(getCurrentState) 的契约(只作依赖行为理解,不替代对本 PR diff 的审查范围)。
发现项
无符合 P0–P3 标准的、由本 PR 引入且可行动的生产缺陷。
以下路径经核对,与 BootstrapStorage.test.ts 新增用例及 Slide receiveSyncEvents / release 设计一致,未发现需作者在本 PR 内修复的断点:
- 冻结恢复批次:
pendingFrozenSyncBatch仅在invisibleBehavior === "frozen"且release+startStorageRestore(true)完成后置位;flushSyncEvents在lifecyclePending/storageBlocked期间不会提前冲队列,与「先恢复 storage、再coalesceMedia批次、之后 FIFO 实时投递」一致(SlideController/index.ts约 399–442、666–695、809–826)。 getCurrentState:release第四参从context.storage.state.state惰性读取,与 Slide_doRelease中cloneDeep(latest)用法匹配(SlideController/index.ts约 786–787)。enableWebAudio透传:仅扩展AppOptions/createSlide配置面,E2E 用enableWebAudio: false选 WebAudio 矩阵;Slide 侧对undefined仍有默认归一化,不构成本 PR 行为回退。
已排除、不记为缺陷项的边界(属依赖契约、既有 lazy 行为或作者上下文中的已知验收缺口):
receiveSyncEvents在lifecycle !== "alive"时无抛错即返回时,若 app 仍 splice 队列会静默丢事件——正常路径下flushSyncEvents受destroyed/ 生命周期门控,未构造出可复现的用户路径。invisibleBehavior: "pause"不做批次合并、lazy 激活失败时resourceStateUnknown阻塞 flush——基线行为,非本 diff 新增。- Slide 1.4.65-alpha.0 媒体执行层问题、WebKit 门禁失败等——不在本 app PR 生产 diff 内。
总体评估
本 PR 的生产面改动集中且意图清晰:把钉住的 Slide 与冻结恢复契约接到 app-slide(storage 驱动的 release(getCurrentState)、解冻后一次性 receiveSyncEvents(..., { coalesceMedia: true })、可选 enableWebAudio),其余大部分为 Playwright 真实房间 E2E 与 prepublishOnly 发布门禁。实现与新增 BootstrapStorage 场景(含 ready 前冻结不启用批次、失败 freeze 后重试仍批次 backlog)一致;未在仅审本 diff 的前提下发现独立可修的 app 逻辑错误。
覆盖与测试缺口(非缺陷,但影响发布信心)
| 缺口 | 说明 |
|---|---|
| 发布门禁 | 作者上下文:alpha.0 全矩阵 WebKit 约第 16 例失败;最新修正的 repeated-global-pause 等未跑完三轮完整门禁;无针对钉住 head 的已通过 test:media:release 结论。 |
| Slide 版本 | 依赖仍为 1.4.65-alpha.0;alpha.1 未在本 PR 中集成/验收。 |
| E2E vs 单测 | installLifecycle 的 mock release 未接第四参 getCurrentState(BootstrapStorage.test.ts 约 140–151),真实 getCurrentState 仅 E2E/集成覆盖。 |
| 场景矩阵 | native-seeking-unlocked-pause 在 coverage.mjs 仅 html5 执行;WebAudio 发布汇总不要求该场景。 |
| 行为模式 | invisibleBehavior: "pause" 无 pendingFrozenSyncBatch;与 frozen 销毁播放器路径不同,冻结积压媒体合并在单测/E2E 中未同等强调。 |
| 批次失败 | receiveSyncEvents 失败仅打日志(SlideController/index.ts 约 419–422),无单测断言重试/降级 FIFO;依赖 Slide receiveBatch 抛错前尽量交付的契约。 |
结论:就 netless-app PR #80 钉住 diff 内的 app 生产代码而言,未发现需分级修复的引入性缺陷;发布是否安全仍取决于 Slide alpha 与完整三轮 E2E 门禁,本审查不构成发布批准。
Horan-Ding
left a comment
There was a problem hiding this comment.
Codex Astra (gpt-6-astra)
Reviewed head: 16e310a0eb85f9cee999137de434e957ccfad907
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
LOCAL_REVIEW_COMPLETE
Codex Astra:App PR #80 最终 pinned 复审
- PR:
https://github.com/netless-io/netless-app/pull/80 - HEAD:
16e310a0eb85f9cee999137de434e957ccfad907 - base tip / 实际 merge-base:
e09be874f0c2b46a1e0befcd32f10c9b6192156b - 仓库:
/Users/dinghaoran/code/agora/conversion-agent/outputs/slide-media-controller-20261016/app - 已核对本地 commit 对象、提供的 PR 回读 metadata 和 merge-base;开始及结束 HEAD 一致、工作树干净。覆盖当前完整 20 文件 PR及调用路径。
- 仅通过 pinned
git show/git diff检查代码;未读取非追踪构建、Cursor/Sol/此前报告,未运行测试/浏览器/构建,未委派或发布。只写本报告。
No findings. 当前 app pinned PR 未发现可操作的新增 P0/P1/P2/P3。静态审查完成不代表当前 npm 输入或完整浏览器矩阵已取得发布资格。
原生窗口资格核对
main.ts:535-558 在真实 seek 后观察窗口:音频原生 seeking 必须为 true、Howler play lock 必须为 false;对于 video,还必须同时观察 videoElement.seeking=true。只有进入该窗口才记录 sample 并发起暂停;未进入则抛错,不能通过等待 seek 已完成来取得通过结果。
同一视频条件在 coverage.mjs 和 release.mjs 各有独立断言,纯音频保留原音频窗口条件。最终 stopped 观察仍要求两轨 pending 消失、video seeking=false、quiet lease 撤销、native paused、位置与共享 pause 一致以及 900ms 时钟静止;未完成定位期间的例外仍仅限受控 muted/volume=0 视频解码,独立音轨必须停止,任何 mediaFailure 都失败退出。新增条件加强了视频原生窗口证据,没有削弱最终暂停要求。
完整 PR 核对范围
已复核生产恢复时读取最新 storage、storage/lifecycle 串行、一次性 frozen batch、普通 live FIFO/旧 API 回退、作者写入边界和 enableWebAudio 透传;没有确认新的生产接线缺陷。
验收/发布范围包括三角色、两白板配置、两实际音频后端与三种浏览器配置、稳定基线时钟和权限观察、原生节点/BufferSource、冻结恢复与断线、裁剪/多媒体/HTTP 失败、慢 MP3、客户实际页数及逐页集合、两步动画像素、房间 journal/停用回读、精确 npm 输入与制品一致性、运行开始撤销旧成功汇总。当前完整 diff 未发现其他可操作新增缺陷。
尚未完成的资格
当前 app 仍固定已发布 @netless/slide@1.4.65-alpha.0,并未集成最终修复 alpha.1。context 中 alpha.0 的 Chromium allowed/blocked 各 396 通过和 WebKit 16 case 后失败仍按原结果保留;九房间清理不改变失败资格。
此前本地候选普通 pause 诊断 25 项没有执行此次加强的 native-seeking-unlocked-pause,不能作为该资格通过。最新完整 app/source gate 尚未完成,alpha.1 尚未按该版本正式构建、资格验证或发布;后续必须使用最终 npm 修复包重新执行三 profile。当前静态 No findings 不追认之前失败,不授权合并或稳定发布。
本审查没有独立执行 context 中的测试;桌面矩阵也不外推移动实机、RTC/PCM、录制回放、扬声器或完整人工视觉验收。外部 CI 限制须单独报告,不能当作代码缺陷或通过证据。
LOCAL_REVIEW_COMPLETE
Horan-Ding
left a comment
There was a problem hiding this comment.
Cursor Agent
Reviewed head: a98e8274b2002e0e6b39222973c346d975a3fb97
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
正在独立审查该 PR:读取完整 diff、AGENTS.md 及相关变更与调用方。
继续审查生产代码变更与关键逻辑路径。
已通读 pr.diff(merge-base e09be874 → head a98e8274),并对照 pinned checkout 中的生产代码、BootstrapStorage.test.ts 及 E2E 入口/门禁逻辑做了交叉核对。checkout 内无 AGENTS.md;node_modules/@netless/slide 未安装,未对 Slide 包内 receiveSyncEvents 实现做字节级对照。
发现项
No findings.
在 PR 引入的变更范围内,未发现可定位到具体文件/行、且有明确触发路径与可复现后果的新增缺陷。生产面变更集中在 SlideController 的冻结恢复批处理、release 的 getCurrentState 透传,以及 enableWebAudio 选项暴露;与 BootstrapStorage.test.ts 新增用例(含 ready=false 不批处理、恢复后 coalesceMedia、失败 freeze 后 backlog 等)一致。
审查范围摘要
| 区域 | 内容 |
|---|---|
| 生产代码 | packages/app-slide/src/SlideController/index.ts、packages/app-slide/src/index.ts |
| 依赖 | @netless/slide@1.4.65-alpha.1、@netless/app-slide@0.2.108-alpha.1 |
| 单测 | BootstrapStorage.test.ts 扩展 |
| 门禁/ E2E | browser-media-e2e/*、prepublishOnly → test:media:release、根目录 playwright@1.62.1 |
逻辑核对(无缺陷结论的依据)
pendingFrozenSyncBatch与flushSyncEvents(约 399–442、821–826 行):仅在unfreeze完成release+ 强制 storage restore 之后置位;lifecyclePending/restoringStorage/storageBlocked会挡住过早 flush;批处理走receiveSyncEvents(..., { coalesceMedia: true }),其后仍走原 FIFOemit(syncReceive)。ready=false的 deferred freeze 不置位,实时信号仍 FIFO(测试已覆盖)。getCurrentState(约 786 行):在destroyed时返回undefined,否则读当前context.storage.state.state,与「unfreeze 用最新共享态恢复、避免旧快照回写」的设计一致。enableWebAudio:AppOptions与createSlide透传,无额外分支逻辑。
receiveSyncEvents 抛错时 app 侧只打日志、不重入队列,与 README 中「Slide 先交付剩余事件再上抛」的约定一致;在未读 Slide 源码前,不将其列为本 PR 的独立缺陷。
评估
PR 在 app 层把 Slide 1.4.65-alpha 的冻结恢复契约(最新 storage、receiveSyncEvents 批合并、WebAudio 配置)接好,单测对序列化与批处理边界覆盖较好。整体属于有意的集成 + 重型 E2E 门禁,不是仅改 lockfile 的 trivial bump(与作者「最终仅改 package.json」的阶段性描述相比,本 pinned head 仍包含完整 SlideController 与 E2E 树)。
覆盖与测试缺口(非代码缺陷,但影响发布信心)
- 发布门禁 E2E:作者已说明基于精确安装的 npm
@netless/slide@1.4.65-alpha.1的三档(Chrome 默认 / Chrome 阻止自动播放 / WebKit)完整矩阵尚未跑完;不能沿用候选构建或 alpha.0 的通过结论作为本次 npm 制品的最终验收。 - 本环境:未执行 build/test/E2E;未安装 Slide 包,未独立验证
receiveSyncEvents与 app 批处理在异常路径上的行为是否与文档一致。 - E2E 范围:README 已声明不覆盖移动端、录制回放、RTC/PCM;lazy-setup 非活跃 host 路径在单测里主要用单条 signal 验证,多事件媒体合并在该路径上主要靠后续
reconcileActivity/unfreeze序列间接保证,而非单独批处理单测。
以上为代码审查结论,非发布批准;在完整三档 E2E 与 npm 制品矩阵完成前,发布风险仍主要取决于门禁执行结果,而非本次 diff 内可见的逻辑漏洞。
Horan-Ding
left a comment
There was a problem hiding this comment.
Codex Astra (gpt-6-astra)
Reviewed head: a98e8274b2002e0e6b39222973c346d975a3fb97
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
LOCAL_REVIEW_COMPLETE
Codex Astra:App PR #80 alpha.1 依赖集成 pinned 审查
- PR:
https://github.com/netless-io/netless-app/pull/80 - HEAD:
a98e8274b2002e0e6b39222973c346d975a3fb97 - base tip / 实际 merge-base:
e09be874f0c2b46a1e0befcd32f10c9b6192156b - 仓库:
/Users/dinghaoran/code/agora/conversion-agent/outputs/slide-media-controller-20261016/app - 已核对本地对象、提供的 PR metadata 和 merge-base;开始及结束 HEAD 一致,工作树干净。范围为当前完整 20 文件 PR及依赖调用合同。相对
16e310a0eb85f9cee999137de434e957ccfad907的最终增量仅 package.json 与 pnpm-lock.yaml,产品/测试源码无差异。 - 未读取其他 reviewer 报告,未改源码、未运行测试/构建/浏览器、未委派或发布评论,只写本报告。
No findings. 当前 pinned PR 和精确 npm 依赖更新未发现可操作的新增 P0/P1/P2/P3。静态审查完成不代表 installed-npm 三 profile 已通过,也不代表 app 获得发布资格。
依赖与构建合同
package.json 精确固定 @netless/slide@1.4.65-alpha.1;pnpm-lock 的 importer、package integrity 和 dependency snapshot 均一致更新,没有残留的 alpha.0 解析条目或范围升级。依赖仍通过既有 Vite 构建进入 app bundle,app 的普通安装无需由消费者另外提供该 devDependency。
本轮独立只读核对本地安装:版本为 1.4.65-alpha.1,lib/Slide.js SHA-256 为 d900b2f04271f856d0f5f5c160dd7fcc502bab07469023b0328957dd0130c8b5。安装声明包含 app 需要的 SyncEventOrigin、receiveSyncEvents、四参数 release/getCurrentState、enableWebAudio 和 resourceTimeout,未发现 app 与该依赖的调用签名不匹配。
registry tarball 及安装包全部 22 文件逐字节核验、与 source84058994 的内容对应,是指定 context 中的作者验证证据;本审查没有重新访问 registry 或重做全部文件比对。没有用指向外层 workspace 的 registry gitHead 推断包内源码身份。
发布门禁继续拒绝 SLIDE_CANDIDATE_DIR,核对实际安装版本与精确 pin,每个 profile 重建 app 并记录实际 Slide/app hash,三个 profile 必须一致且为 installed-npm/full/matrixComplete。新依赖 pin 不会把旧 local-candidate 结果直接变成正式 npm 输入通过。
完整 PR 核对
当前生产最新 storage 恢复 provider、storage/lifecycle 串行、恢复批次与普通 FIFO、作者共享写边界及音频后端透传均纳入完整范围。相应静音定位观测仅容许未完成定位中的 owned muted/volume=0 解码,最终仍要求双轨原生暂停、无 seeking/pending、正确共享位置及 900ms 静止。
同时核对实际 video 与 unlocked audio seeking 资格、稳定身份时钟推进及固定 deadline、原生错误/Range 诊断、权限、冻结与断线恢复、裁剪/多媒体、客户实际页数与逐页覆盖、动画、房间 journal/清理和发布汇总状态。未发现最终依赖升级破坏这些接线或门禁,也未确认其他可操作新增缺陷。
证据边界与剩余资格
context 称 source 完整 376 positive cases、alpha.2 单轮负控、1.4.64 固定十轮负控通过并清理四房间;local-candidate app WebKit 完整 396 也通过且四房间清理,安装后的 app 单测和 13 项生命周期通过。本审查未独立运行这些验证。
精确 installed-npm alpha.1 的 Chromium allowed、Chromium blocked、WebKit 三 profile 刚启动,尚未完成。candidate WebKit396、已知存在 WebKit 失败的旧 alpha.0 结果,以及 source 门禁均不能代替本次 npm 输入资格。须等待当前三个 profile 的最终报告、同制品哈希及清理结果后再判断 app 发布。
桌面自动验收不外推移动实机、RTC/PCM、录制回放、实际声卡或全部页面人工视觉结果。本报告不授权合并或发布 app。
LOCAL_REVIEW_COMPLETE
Horan-Ding
left a comment
There was a problem hiding this comment.
Cursor Agent
Reviewed head: 3a0ccca7b6f133a6ac6704e5fee053644a0a4d29
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
正在读取 PR diff、AGENTS.md 及变更相关源码以进行独立审查。
审查范围
已通读 pr.diff(e09be874 → 3a0ccca7)全量变更,并对照 pinned checkout 中的 packages/app-slide/src/SlideController/index.ts、BootstrapStorage.test.ts 及 E2E harness 关键路径;另以同版本 Slide 源码(source-cursor 中 1.4.65-alpha.1 对应实现)核对 receiveSyncEvents / release(getCurrentState) 契约,不将未纳入本 PR diff 的 Slide 引擎改动计为「本 PR 引入的代码缺陷」,但会在覆盖缺口中说明。
本 PR 生产面实质变更:SlideController 冻结恢复批次投递、release 第四参 getCurrentState、enableWebAudio 透传、@netless/slide 升至 1.4.65-alpha.1;其余为 E2E/发布门禁与依赖。
缺陷(P0 → P3)
No findings.
(在可审查的 app-slide 集成与 harness 范围内,未发现需作者修复的、由本 PR 引入且证据充分的 P0–P3 生产缺陷。)
集成与逻辑核对(无新增缺陷项)
-
pendingFrozenSyncBatch时序(SlideController/index.ts约 399–442、668–695、821–826):lifecyclePending/restoringStorage会挡住恢复完成前的flushSyncEvents;pendingFrozenSyncBatch在 storage restore 完成之后、unfreezeRuntime末尾置位,再由enqueueLifecycle的finally触发带coalesceMedia: true的receiveSyncEvents。与BootstrapStorage.test.ts中「restore 完成前不 flush 批次」「完成后一次性 [3,4]」「之后 signal 5 走 FIFO」一致。 -
getCurrentState(约 786–787):在release异步窗口内读取context.storage.state.state,与 Slide_doRelease中releaseStateProviders在setMediaState(..., seekNow)时再次取最新共享态的设计一致;destroyed时返回undefined属既有销毁语义。 -
receiveSyncEvents异常(约 417–423):Slide 侧receiveBatch在监听器抛错后仍会收尾并throw;app 侧catch仅记日志,与 FIFO 路径对单条syncReceive的吞错策略一致,且批次内事件已由 Slide 按契约投递,不构成「整批静默丢失」的额外 app 缺陷(对照SyncTaskManager.receiveBatch)。 -
旧版 Slide 无
receiveSyncEvents:走 FIFO 兼容路径,README 已声明不含此次媒体合并修复——属发布/版本约束,非本 diff 内逻辑错误。
总体评估
- 方向:app 层用「恢复完成后单次
receiveSyncEvents(..., { coalesceMedia: true })」+「release时getCurrentState」与 Slide1.4.65-alpha.1的冻结/释放媒体语义对齐,单元测试覆盖了批次与 deferred freeze / 失败 freeze 重试边界;E2E 矩阵与release.mjs发布门禁设计完整。 - 风险:核心「视频 pause 后原生音频仍响」等行为修复主要在
@netless/slide@1.4.65-alpha.1包内,本 PR diff 不可审其实现;仅升级 pin + 集成接线,合并后必须 app 与 slide 同版本发布。 - 2s 暂停落点容差:与作者声明一致,属验收合同而非代码缺陷。
覆盖与测试缺口(材料性)
| 项目 | 状态 |
|---|---|
BootstrapStorage 冻结批次 / ready=false / freeze 失败重试 |
在 PR 内,已读 |
| 作者称 focused 8/8(Chromium/WebKit × HTML5/WebAudio × paused-seek/live-clock) | 未在本环境复跑,仅作上下文 |
| Slide 源码 ~380 case gate | 作者称曾因 5.000075 !== 5 前置失败,已修;全量跑完未作为已通过证据 |
完整 app test:media:release 三轮矩阵 E2E |
pending,不能视为已过关 |
@netless/slide 包内媒体执行/合并实现 |
不在本 PR diff,本次未做引擎级缺陷签收 |
invisibleBehavior: "pause"(不 destroy player) |
未走 pendingFrozenSyncBatch;本 PR/E2E 默认 frozen,该路径未同等验收 |
| 移动端 / RTC / 录制回放 | README 明确排除 |
结论:在 pinned diff 与可读集成代码范围内无待修缺陷清单;是否可合并仍依赖 Slide 全量单测 + 完整 app 媒体 E2E 发布门禁 的最终绿灯,以及生产环境 app-slide 与 slide 版本齐升。
Horan-Ding
left a comment
There was a problem hiding this comment.
Codex Astra (gpt-6-astra)
Reviewed head: 3a0ccca7b6f133a6ac6704e5fee053644a0a4d29
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
Codex Astra (gpt-6-astra)
PR: #80
Head: 3a0ccca7b6f133a6ac6704e5fee053644a0a4d29
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
Verified merge base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
No actionable PR-introduced finding identified.
Reviewed the complete merge-base change set (22 files): frozen recovery batching and latest-storage callback, backend-option forwarding, dependency/package changes, bootstrap tests, E2E runner and release validator, native observation and diagnostics, playback/pause/trim/freeze/permission/cleanup assertions, documentation and fixture additions. Runtime call sites were checked against the source candidate's public integration contract. This was an independent read-only review without consulting the other reviewer's reports.
Verification and limits
- Both commit objects and the merge base were verified locally; the checkout matched the pinned head and was clean when reviewed.
git diff --checkpassed for the pinned range. - The committed app dependency and lockfile select
@netless/slide@1.4.65-alpha.1; they do not yet select the separately reviewed alpha.2 source candidate. The explicitly stated delivery order is candidate acceptance, alpha.2 publication, then dependency update and actual npm-package acceptance. This intentional intermediate pin is recorded as a delivery boundary, not an unintended defect in this review. - The runner rebuilds the selected dependency before execution, identifies local candidate versus installed npm mode, and the release entry rejects local aliases and diagnostic subsets. Candidate evidence must not be presented as actual alpha.2 npm-package acceptance at this head.
- No source files were edited and no browser/room tests were launched during this review. Final full app E2E was pending in the supplied context; no pass is claimed here. Four binary synthetic media fixtures were considered as test inputs, but were not independently decoded or replayed by this reviewer.
- Static review does not establish real-device/WebView, recording/replay, custom RTC/PCM or physical speaker behavior. No-findings is not release approval, and the source PR's separate acceptance finding remains relevant to the combined delivery.
- This report covers the exact pins above. Subsequent dependency or implementation updates require a review against their new head.
Horan-Ding
left a comment
There was a problem hiding this comment.
Cursor Agent
Reviewed head: 073bc74699f5203c67e6f922e83be1319348c37a
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
正在读取 PR 差异与相关上下文,开始独立代码审查。
审查范围
已对照 merge base e09be874 → head 073bc746 阅读完整 pr.diff,并在 pinned checkout 中核对生产改动(SlideController/index.ts、index.ts)、BootstrapStorage.test.ts 新增用例,以及 browser-media-e2e harness 与 coverage.mjs / run.mjs / release.mjs 中的关键断言与异步路径。仓库 checkout 内无 AGENTS.md;conversion-agent/AGENTS.md 与本次 app-slide 改动无关。
缺陷(按优先级)
P3 — passive-page.mjs 超时错误信息未插入实际毫秒数
- 位置:
packages/app-slide/test/browser-media-e2e/passive-page.mjs:38(外层模板字符串在run.mjs的 CDP 被动waitForFunction安装路径中使用) - 触发路径:
APP_SLIDE_E2E_AUTOPLAY=blocked→installPassiveEvaluation→ 被动page.waitForFunction在浏览器内等到 deadline 仍不满足 predicate - 后果:失败时 Error 文案为字面量
... after ${timeout}ms,无法从日志直接看出配置的 timeout(deadline 计算用的${timeout}在第 32 行已正确注入,仅错误消息错误) - 证据:
throw new Error("Passive waitForFunction timed out after ${timeout}ms");(应改为与第 32 行一致的拼接或改用可插值的引号形式。)
生产代码(app-slide 本体)
对 pendingFrozenSyncBatch + receiveSyncEvents(..., { coalesceMedia: true })、release(..., getCurrentState)、enableWebAudio 透传与 enqueueLifecycle / restoreStorageStates 的交互做了逐段核对:
- 冻结积压信令在
lifecyclePending > 0时不会被restoreStorageStates尾部的flushSyncEvents提前 FIFO 冲掉(flushSyncEvents在lifecyclePending时直接返回),与BootstrapStorage.test.ts新增批次用例一致。 ready === false的 deferred freeze 不启用 recovery batching、失败 freeze 后仅对 backlog 做 batch,行为与新增单测一致。receiveSyncEvents抛错时splice后仅打日志、不重投队列,与 README 中「不重复交付整批」的 intentional 设计一致,不作为缺陷上报。
在上述边界下,未发现 P0–P2 级、需作者在本 PR 内修复的生产逻辑缺陷。
总体评估
本 PR 生产面改动面小且聚焦:@netless/slide@1.4.65、冻结恢复时的批量同步投递、release 读取最新 storage snapshot、以及 enableWebAudio 选项暴露;单元层用 BootstrapStorage 覆盖了 batching 与 deferred/failed freeze 边界。主体风险与修复能力仍绑定 Slide 1.4.65+ 的 receiveSyncEvents 实现,旧引擎走 FIFO 兼容路径(README 已说明)。
E2E 门禁设计完整(release.mjs 三轮浏览器 × 全矩阵场景校验、制品哈希、房间清理),但结合作者提供的边界说明:完整 WebKit/installed-npm 约 400×profile 矩阵尚未全部通过;曾出现动画页 90s 三端不收敛及 WebGL context 告警,未能在本 diff 内建立与本次 app/slide 媒体改动的因果链,不能视为本 PR 已端到端验收完成。单测仍使用 SlideStub(无真实 receiveSyncEvents),媒体合批的语义保障主要依赖真实房间 E2E,而非 Node 单测。
覆盖与测试缺口(材料性)
| 领域 | 状态 |
|---|---|
冻结恢复 receiveSyncEvents 合批 |
BootstrapStorage 有覆盖;无真实 Slide 包的单元/集成测试 |
| 原生 seeking 中暂停(分轨窗口) | coverage.mjs + release.mjs 仅 html5 强制校验 nativeSeekWindows |
| WebAudio 后端 | 矩阵跑 webaudio,但无与 html5 对等的 native seeking-unlocked 发布断言 |
| 客户整稿 / 动画 | 依赖私有 APP_SLIDE_E2E_CONFIG;动画步骤与页收敛在作者环境中仍有失败记录 |
prepublishOnly → test:media:release |
无私有配置时发布必然失败( intentional 发布门禁) |
结论:生产改动与新增单测在审查范围内自洽;可修复的代码问题仅见上述 P3 诊断文案。是否合入应继续以作者方 完整 release 矩阵通过 为准,并单独跟踪动画/WebKit 环境类失败是否与媒体 PR 相关。
Horan-Ding
left a comment
There was a problem hiding this comment.
Codex Astra (gpt-6-astra)
Reviewed head: 073bc74699f5203c67e6f922e83be1319348c37a
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
Codex Astra (gpt-6-astra)
PR: #80
Head: 073bc74699f5203c67e6f922e83be1319348c37a
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
Verified merge base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
No actionable PR-introduced code finding identified. Full app runtime qualification remains incomplete; this is not a release or merge approval.
The review covers the complete 23-file merge-base change set: frozen-recovery batching and latest-storage restoration, backend configuration forwarding, bootstrap tests, E2E browser host and runner, native observation and diagnostics, separate audio/video seek cancellation windows, playback/pause/trim/stop/freeze/permission/cleanup assertions, release validation, dependency/lockfile/release notes, and binary fixture additions. The assessment reuses this reviewer's independent full implementation examination and subsequent native-window inspection, with fresh checks of the final tree. No other reviewer's reports were read for this app assessment.
Git comparison verified that only packages/app-slide/package.json, pnpm-lock.yaml and packages/app-slide/README-zh.md changed from the independently reviewed native-window head 41520a2b802802034a9d75ea72b5827e62fbe4d1. The merged tree preserves the reviewed runtime integration and all four native-window harness/documentation changes. The current version is @netless/app-slide@0.2.108 with exact @netless/slide@1.4.65 dependency and matching lockfile entries. Local package resolution independently confirms installed Slide 1.4.65; its declarations include enableWebAudio, receiveSyncEvents and the fourth release latest-state callback used by this PR.
The native-window tests continue to require the selected physical element to be seeking near 4 seconds with the Howler play lock released and the captured audio owner unchanged. Pause is invoked immediately in that observation callback; it is not delayed until the old seek finishes. Video media must pass separate audio and video windows, while audio-only media must pass the audio window. The helper bounds discovery and cleans its listener, interval and timeout in finally; the original seek and actual pause promises remain awaited. The three-client final checks and independent release validator retain their mandatory per-track coverage. Separating windows is consistent with the observed ordered audio-settlement then video-calibration behavior and does not relax final native pause, settled-position, retired-source or stationary-clock assertions.
Verification and qualification limits
- Local HEAD, base and merge base were verified. The checkout matched the pinned head and was clean when reviewed. The parent identifies this head as pushed; remote metadata was not independently queried by this sub-reviewer.
git diff --checkpassed across the complete pinned PR range. JavaScript syntax checks passed for the runner, coverage and release scripts. The final runtime diff and installed package API declarations were rechecked.- No source files were edited, no browser or room tests were launched, and no review was published during this assessment. The four binary fixtures were not independently decoded or replayed by this reviewer.
- The latest supplied context reports source acceptance completed with 380 native-player/real-room cases and two legacy negative controls. It also reports verification of all 22 published Slide package files and that the published bundle differs from the tested candidate only by its version string. These are supplied validation results, not reruns or registry verification performed by this reviewer.
- The candidate app WebKit run completed 199 checkpoint records before a 90-second animation-page convergence timeout: writer-b remained loading page 1 while shared state and the other roles were on page 9. The supplied context records 32 WebGL-context-limit and 28 already-lost warnings. This is an unresolved full-run failure. The evidence does not establish that this PR caused it, and it is neither dismissed as pre-existing nor counted as a pass.
- The formal installed-npm matrix is still running, with three browser profiles and 400 checkpoint records per profile / 1200 total planned. Early successful native-window trials do not establish the complete matrix. The current dependency supersedes the earlier alpha.1 intermediate pin; earlier candidate evidence alone is not final installed-npm app acceptance.
- Desktop tests and static review do not establish physical iOS/WebView, recording/replay, custom RTC/PCM or physical audio-device acceptance. No qualifying static finding does not close any of these gates or the unresolved full-app failure.
Horan-Ding
left a comment
There was a problem hiding this comment.
Cursor Agent
Reviewed head: 840fad86327890718d50fb972fb2e83db8c957a0
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
正在读取 PR diff、AGENTS.md 及变更相关源码以进行独立审查。
发现项
无发现。
在 pinned base e09be874 → head 840fad86 范围内,运行时改动仅涉及 packages/app-slide/src/SlideController/index.ts 与 packages/app-slide/src/index.ts;其余为依赖升级、版本号、E2E 与文档/锁文件。对完整 pr.diff、上述源码及 BootstrapStorage.test.ts 中新增用例的静态审查,未发现可归因于本 PR 的、需作者修复的 P0–P3 缺陷。
审查要点(证据与路径)
1. 冻结恢复后的同步批次(pendingFrozenSyncBatch + receiveSyncEvents)
调用链: unfreeze → enqueueLifecycle → unfreezeRuntime(invisibleBehavior === "frozen")→ release → 强制 startStorageRestore(true) 并 await storageRestoreTask → 设置 pendingFrozenSyncBatch = true → enqueueLifecycle 的 finally 在 lifecyclePending === 0 且未 destroyed 等条件下调用 flushSyncEvents。
批次逻辑:
if (this.pendingFrozenSyncBatch) {
this.pendingFrozenSyncBatch = false;
const receiveBatch = (
this.slide as Slide & {
receiveSyncEvents?: (events: SyncEvent[], options: { coalesceMedia: boolean }) => void;
}
).receiveSyncEvents;
if (typeof receiveBatch === "function" && this.pendingSyncEvents.length) {
const events = this.pendingSyncEvents.splice(0);
try {
receiveBatch.call(this.slide, events, { coalesceMedia: true });
} catch (error) {
logger.error("[Slide] recovery sync receive failed", this.context.appId, error);
}
}
}与需求对齐点:
flushSyncEvents在lifecyclePending/restoringStorage/storageBlocked时直接返回,避免在 WebGLrelease与 storage restore 完成前冲队列(与既有BootstrapStorage用例一致)。- 仅在 完整 frozen 恢复路径末尾置位
pendingFrozenSyncBatch(约 824–826 行);ready === false的 deferred freeze 不会走该路径,单测明确断言积压信令仍走原 FIFO(BootstrapStorage.test.ts第二段新增用例)。 - 无
receiveSyncEvents时清 flag 后落入原有while+emit(syncReceive),属文档声明的兼容路径。
未将「receiveSyncEvents 抛错且未按引擎契约交付」列为缺陷:checkout 内无 @netless/slide@1.4.65 源码,无法独立验证引擎契约;app 侧对单条 syncReceive 亦仅为 log,行为与既有模式一致。
2. release 第四参数 getCurrentState
() => (this.destroyed ? undefined : this.context.storage.state.state || undefined)路径: 仅 unfreezeRuntime → slide.release(..., getCurrentState)。只读 storage 快照、销毁后返回 undefined,不触发 setState;可写回写仍由 onStateChange + isOwnWritableEvent 约束(既有逻辑,本 diff 未改)。
3. enableWebAudio 透传
createSlide 与 AppOptions 增加 enableWebAudio,与 @netless/slide@1.4.65 配置面对齐;未传时为 undefined,与改前「未传入」等价。
总体评估
本 PR 将 PPT 引擎升至 1.4.65,并在 app-slide 层补齐三项集成:WebAudio 开关透传、release 时提供最新共享 storage 状态、冻结恢复且 storage 还原完成后再批量交付积压同步事件(coalesceMedia)。生产面 diff 小、与需求描述一致;BootstrapStorage 新增用例覆盖了批次时机、deferred freeze、失败 freeze 后重试等关键边界。head 840fad86 与 fe5af094 树相同,仅 CI 重触发提交,运行时语义与已跑矩阵的 commit 一致。
测试与覆盖缺口(材料性,非代码缺陷):
| 缺口 | 说明 |
|---|---|
| 静态审查 | 未在本地解包/阅读 @netless/slide@1.4.65 中 receiveSyncEvents 实现;批次语义依赖引擎与作者 E2E。 |
| Head 矩阵 | 作者称 1200 条记录在 d91ac16 跑过;840fad86 仅改 E2E native-seek helper 的 early rejection 日志,未声明重跑完整矩阵。 |
| 环境 | 无真实浏览器/房间执行;不覆盖移动 WebView、RTC/PCM、录制回放、真机出声。 |
| 单测 | 无「receiveSyncEvents 抛错 / 部分交付」的负例;prepublishOnly 的 test:media:release 依赖仓库外 APP_SLIDE_E2E_CONFIG,本审查未执行。 |
| CI | 审查开始时 cloud lint/build 结果未知,不能当作通过依据。 |
在以上限制下,未发现需在本 PR 内修复的确定性运行时缺陷;合并风险主要来自对外部 Slide 1.4.65 行为与大规模 E2E 证据的依赖,而非 app-slide 集成逻辑本身的静态矛盾。
Horan-Ding
left a comment
There was a problem hiding this comment.
Codex Astra (gpt-6-astra)
Reviewed head: 840fad86327890718d50fb972fb2e83db8c957a0
Base: e09be874f0c2b46a1e0befcd32f10c9b6192156b
Codex Astra 独立审查
结论:No findings。针对最终固定 head 与 base 的完整差异,未发现具有明确触发条件及代码证据的新增 P0–P3 缺陷。本结论为静态审查,不等同重新完成运行时验收或批准合并。
- PR:#80
- 最终 head:
840fad86327890718d50fb972fb2e83db8c957a0 - Base / merge-base:
e09be874f0c2b46a1e0befcd32f10c9b6192156b - 最终 Git tree:
a2581b94f08fa21bf4c5435d53846ec6d7d5372a
最终快照验证:在新隔离 checkout 独立核对 HEAD、merge-base 和 tree;840fad8 与此前本人完整审阅的 fe5af09 的 tree 完全相同,二者 diff 为空。对 base 仍为相同的 23 个文件、3920 行新增及 10 行删除,因此本报告复用本人对相同内容的独立检查,覆盖完整 PR,并非仅审查空的 CI 重触发提交。未读取其他 reviewer 报告,未访问 GitHub。
覆盖范围:生产 SlideController 生命周期与同步接线、AppOptions、精确依赖及锁文件、版本说明、BootstrapStorage 单测、浏览器宿主、原生探针、执行诊断、被动求值、主 runner、extended/boundary 场景、发布汇总门禁、运行说明及忽略规则。四个二进制 fixture 此前检查了文件格式,未解码或播放;相同 tree 确认本次内容未变化。另检查了 SceneSync 作者判定、App 挂载/焦点/销毁调用、focus transition 队列及构建配置。
重点核查:恢复批次在 release 和随后 storage 恢复完成后启用,事件仍受生命周期、恢复及销毁屏障约束;普通实时交付保持原路径,transport author 保留。新 release 回调读取当前共享状态,已有自身可写作者判定继续控制共享写入。执行诊断采用弱引用记录 track,并保留被包装方法的接收者、返回值和异常;原生退役节点保留用于明确要求的静音观察。发布门禁拒绝诊断子集及本地候选替换,并检查三个完整 profile、制品一致性及房间清理回读。
本轮最终快照实际执行的只读检查:git diff --check 通过,browser-media-e2e 下所有 .mjs 的 node --check 通过,checkout 无改动。未安装依赖、修改源码、运行单测/构建/浏览器测试,未操作外部房间。
执行证据边界:上下文提供的完整矩阵在 d91ac16 上运行,Chromium allowed、Chromium blocked、WebKit allowed 各 400 条,共 1200 条 case records,并非 1200 个独立房间;本人未重新执行这些测试或 registry 校验。已独立确认 d91ac16..最终 head 仅改变 native seek helper 的提前 rejection 日志及注释,原 promise 仍用于后续 await。上下文提供的全仓 ESLint/Prettier 通过属于 fe5af09;840 与之代码树一致,但这不能表述为在 840 重跑了本地 lint 或 1200 条 E2E。
最终 head 的两个云端 lint/build 任务在上下文准备时尚未取得终态,本 reviewer 未查询云端状态,因此不报告其通过。Slide 1.4.65 内部运行正确性、发布制品一致性、二进制媒体实际解码、移动 WebView、物理设备声音输出、RTC/PCM 及录制回放均未在本次静态审查中独立验证。
app-slide 冻结恢复后按最新storage恢复媒体,并合并恢复批次中已被新状态覆盖的执行。接收侧可写端和只读端均不回写旧位置,普通实时事件保持FIFO。
发布前完整E2E使用真实White SDK房间、白板1.0/1.5、HTML5Audio/WebAudio、三个客户端,以及Chromium允许/禁止自动播放和WebKit。检查共享/原生状态、定位与播放时钟、frozen/release、断线恢复、旧节点静音、裁剪/自然结束、延迟音轨、客户整稿和动画;房间立即记录归属,失败也清理回读。
当前精确集成已发布npm
@netless/slide@1.4.65-alpha.1,lockfile固定registry完整性;registry包和安装目录22文件均已核验。该修复版源端376项及两组负控通过,同制品app候选完整WebKit396项通过且4房间清理。最新实包验收(2026-10-21):alpha.1 的 Chromium allowed / blocked 各 396/396 通过;WebKit 通过 368 项后在1.5/webaudio/customer-video-release-pause失败。三端共享暂停位置一致,音轨均停在16秒且无活动音源;只读端原生video停在15秒,其他两端16秒,三端均无pending/seeking。12间测试房间全部清理。完整矩阵未通过,保留原始失败,正在固定10轮专项记录定位写入与原生事件;静态双审查及候选通过不替代此失败。原alpha.0的WebKit失败保持为失败记录。暂停验收要求视频用例实际进入video seeking及原生audio seeking/unlocked窗口;定位期间仅允许当前静音视频解码,音轨始终暂停。最终两轨须无pending、native seeking=false、位置正确并静止900ms。当前HEAD
a98e8274b2002e0e6b39222973c346d975a3fb97的Cursor/Astra COMMENT均已发布回读且No findings;安装后单测与13项生命周期通过。尚未合并或发布app包。