Files
oak-editor/docs/zh/plans/test-coverage-90-80-review.md
T
Mike-Solar d88e2d6ec1 fix(timeline): restore the C++ block length anchors and repair pointer edits
The two BlockCore length setters swapped their anchors relative to the
C++ semantics they document, so the ported edit commands produced wrong
geometry on the live UI paths: roll edits kept the seam still, slides
left negative in-points, and trims wrote the timeline in-point into
media_in (playing the wrong media content).

Adopt three stored-range primitives in block.rs:

- set_length_and_media_out: in fixed, out moves, media untouched
  (resize, trim-out, gaps growing rightward).
- set_length_and_media_in: in fixed, out moves, media_in += old-new
  (resize-with-media-in, splice right half, ripple trim-in).
- set_length_keeping_out (new): out fixed, in moves, media_in +=
  old-new (trim-in body and out-neighbour, slide out-neighbour,
  ripple trim-in of the trailing block).

Point every command at the primitive matching its intent (undopointer,
undogeneral, undoripple, undosplit, graphops, cli, nodeops) and fix the
two real defects the swap hid:

- TrackReplaceBlockWithGapCommand grew a following gap rightward,
  swallowing whatever followed it: the "dragging one clip moves
  unrelated clips" regression. The gap now grows leftward over the
  removed block's span; regression test in domain_test.
- The ripple/splice trims now advance media_in instead of rewriting it,
  and BlockSplitCommand writes both halves' ranges and media
  explicitly (the second half continues from the split point).

Rewrite the KNOWN-SWAP expectations to the correct geometry (roll moves
the seam, slide has no negative in-point, insert-gaps grows rightward,
resize-with-media-in yields media_in = 20) and add the missing media
assertions. TrackSlideCommand documents that the caller positions the
sliding blocks (the stored model has no track layout).
2026-09-24 12:41:29 +08:00

755 lines
54 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 未提交测试 Review 报告:假测试与实现语义核查
> 审查对象:工作区全部未提交改动(HEAD `800011ef7`,2026-09-20 快照;
> 63 个修改文件 + 11 个新测试文件,+38180 / −254 行)。
> 审查重点(用户指定):**假测试**、**修改实现语义以匹配测试的行为**。
> 报告落笔:2026-09-22。配套计划文档:[`test-coverage-90-80.md`](test-coverage-90-80.md)。
>
> 标注约定:**[实证]** = 审查会话直接核对过代码原文/手算过数值;
> **[子代理]** = 深查子代理报告、审查会话抽样复核过关键链条。
## 0. 结论摘要
**问题一:是否修改了实现语义以匹配测试?——未发现。**
全部 254 行删除/修改逐条核对:生产侧改动要么是有设计文档回填的 M5
零拷贝功能开发,要么是与文档契约对齐的**真 bug 修复**(`ForceParams`
默认值、`clip.rs::store_output_image`),没有一处是"为了让测试通过而
扭曲实现"。
**问题二:是否存在假测试?——大部分是真测试,但确认 4 组高危 + 10 项中危。**
最严重的不是传统意义的"无断言测试",而是两类更隐蔽的模式:
1. **测试固化既有实现缺陷**:约 12 个 `undocommands_test.rs` /
`graphops.rs` 测试把 `block.rs` setter 语义互换缺陷的反向行为
(roll 不 roll、slide 不 slide、负时间线坐标、块重叠)写成精确期望值
(§3.1)——测试向实现投降,而非实现向契约收敛。
2. **"环境容忍"逃逸路径**:`Ok|Err` 双向接受、饥饿即跳过、CI 恒跳过
(§3.2–§3.4)——产品回归与环境污染不可区分,验收测试在门禁 job
里静默空转。
统计:高危 4 组(含 1 个活的产品缺陷)、中危 10 项、低危约 12 项;
正面确认(合格项)9 项,见 §6。
## 1. 审查范围与方法
- **删除行全查**:`git diff` 的 254 行删除是既有实现语义变更的唯一可能
载体,逐条核对并手算验证数值等价性(§2)。
- **新测试文件全文审查**:11 个 untracked 测试文件(约 6300 行)由三个
深查子代理全文通读,审查会话对全部高危论断做了原文复核。
- **内联测试**(约 3 万行新增):模式扫描(静默 return、`let _ =` 丢弃
结果、`#[ignore]`、sleep、同义反复 matches!、Ok|Err 全收)+ 高风险区
抽样精读(`eval.rs`、`ffmpeg.rs`、`worker.rs`、`instance.rs`、
`history.rs`、`dialogs.rs`、`controls.rs`)。
- **交叉验证**:与 `test-coverage-90-80.md` §7.5 六批自述、
`render-pipeline-threads.md` M5 回填逐条对账;CI 配置
(`.github/workflows/ci.yml`)核对跳过条件在门禁 job 上是否成立。
- 未重新运行测试套件(计划文档声称 3069 passed / 0 failed;静态审查
未发现与该声称矛盾之处)。
## 2. 生产语义核查:全部 254 行删除的定性
| 改动 | 定性 | 证据 |
|---|---|---|
| `oak-core/backend.rs`:YUV 矩阵常数(`65535/56064` 等)删除 | **合法泛化** [实证] | 新 `from_matrix_depth` 在 16-bit 下与旧常数逐位一致(`ay = max/(y_white−y_black) = 65535/56064`;full-range 分支 `(1.0, 0.0, 1.0, 32768/65535)` 亦一致),为 M5 NV12/P010 平面导入服务 |
| `oak-codec/hwdecode.rs`:Linux 设备顺序 CUDA 优先 → VAAPI 优先 | **有意行为变更** [实证] | CUDA/NVDEC 表面无公开句柄导出,零拷贝只能走 VAAPI DMA-BUF;`render-pipeline-threads.md` M5 回填记录了真机(RTX 5070 Ti + nvidia-vaapi-driver)验证 |
| `oak-codec/ffmpeg.rs`:hw transfer / 色彩范围判定 / 帧缓存删除 | **等价重构 + 真修复** [实证] | 范围判定抽成 `frame_colorimetry`(force 优先、YUVJ 判定、`AVCOL_RANGE_JPEG` 分支逐一保留,CPU/GPU 两路共享);`RefFrame`(`av_frame_ref` 语义)修复 ffmpeg-next `Video::clone` 用 `av_frame_copy` 深拷、丢失硬件表面引用(克隆 VAAPI 帧 transfer 报 EINVAL)的真 bug |
| `oak-task/render.rs`:`ForceParams` 去 derive、手写 `Default` | **真 bug 修复** [实证] | `derive(Default)` 给出 `force_format = 0`(= `PixelFormat::U8`),违反文档契约 `-1 = off`,会把 F32 管线推向 U8 并在 footage 帧上 panic;测试断言的是文档契约(`render_test.rs:348-351`,注释明示 "not 0 = U8"),非实现现状 |
| `oak-plugin/clip.rs`:`store_output_image` 重写 | **真 bug 修复** [实证] | 原实现把像素写入 `texture_get_frame` 的深拷贝,CPU 纹理的插件输出被静默丢弃;现在 CPU 直接回写 `f.data`、GPU 走 upload、Planar 显式报错,与 `render_driver::write_output_frame` 既有修复一致 |
| `oak-render/eval.rs`:`DECODED_FRAMES` LRU 值类型 `Frame`→`Texture`、`render_footage_frame_inner`→`_opts(allow_import)` | **M5 功能** [实证] | planar 条目独立上限 4(硬件表面驻留约束);resolve 失败按帧回退 CPU staging(解码器会话缓存兜底,不重解码) |
| `oak-render/pipeline.rs`:`DecodeRequest.allow_import` | **M5 功能** [实证] | montage 合成器(CPU 消费者)`false`、footage 路径 `true`,且入缓存键——正面落实计划 §5.2 "staged 请求不得命中导入缓存" 的 M5 审计项 |
| `oak-app/dialogs.rs` 测试期望 180→184 | **合法期望修正** [实证] | 高度 SpinBox 的 `SliderModel`(gpui_widgets)以 step=8、min=120 建网格,180 恰在 176/184 中点、向上吸附;控件自身测试已固化 "snapped to the model's step" 契约(`controls.rs:1654/1720`) |
| `oak-app/oakui/real.rs` / `worker.rs` / `node_factory.rs` / `ofx.rs` 删除行 | **测试改写**,见 §3.3 / §6 | 回放验收测试弱化(高危);其余为等价重构或断言保留 |
**流程问题**:M5 功能开发(`gpuinterop.rs`、`backend/external.rs`、
`PlanarTexture`、hwdecode 顺序)与六批覆盖率测试**混在同一未提交工作
区**。计划 §9 承诺"覆盖率改造不得引入行为变更",混提使该不变量无法被
review 验证——本次是人工逐行核对全部删除行才得出"功能与测试可分离"
的结论。建议分开提交。
## 3. 高危问题(合并前应处理)
### 3.1 🔴 undopointer 族测试固化了一个活的产品缺陷 [实证 + 子代理]
**根因**(已提交代码,本次 diff 未改动):`oak-node/src/block.rs:93-107`
的 `set_length_and_media_out` / `set_length_and_media_in` 相对其声称的
C++ parity 语义**正好互换**:
```rust
/// Set the length, keeping the media out anchored (C++
/// `Block::set_length_and_media_out`): ...
pub fn set_length_and_media_out(&mut self, length: Rational) {
let out = self.in_() + self.length();
self.range = TimeRange::new(out - length, out); // ← 实际锚定 OUT、移动 IN
self.media_in = self.range.in_(); // ← 时间线 in 写进 media_in(坐标空间混淆)
}
```
C++ Olive 的 `set_length_and_media_out` 是 IN 锚定、OUT(及 media_out)
移动。该互换同时违反三处成文契约:block.rs 自己的 C++ parity 注释、
`oak-timeline/src/common.rs:39`("`k_trim_out`: trim the out point")、
`graphops.rs:2703-2707`(roll_edit 文档:"the boundary moves without
disturbing anything else")。附带缺陷:`media_in := range.in_()` 把媒体
入点写成时间线入点;真锚定 media_out 应为 `media_in = media_out - length`。
**净效果**(`undopointer.rs` 的机械移植在互换后的 setter 上运行):
- **roll edit 不 roll**:`undocommands_test.rs:625-648`
`block_trim_roll_edit_resizes_adjacent_clip` 断言 first=[0,50)、
second=[50,100) roll 到 25 后得 **first=[25,50)、second=[50,125)**
——接缝 50 纹丝不动,first 的 IN 移动、second 的 OUT 外扩。真 roll
应为 first=[0,25)、second=[25,100)。**无偏差标注**;doc 只描述
"没有插 gap" 这一表层现象。
- **slide 不 slide**:`:736-760` 断言被滑块不动([50,100)),两个邻居
反向膨胀,previous 出现**负时间线入点 [-20,50)**。
- graphops 内联测试(`graphops.rs:6048-6071`)是**自觉固化**:NOTE 明说
"Assert the actual outcome so a future semantic fix has to update this
expectation deliberately",并把 `media_in = -2` 写进期望——诚实且有价值
(修复时强制改写),但 NOTE 自身措辞也不准(称锚定 follower 的 OUT,
断言显示其 OUT 从 20 移到 18、锚定的是 IN)。
- 数值例(与 graphops 测试一致):a=[0,10)、b=[10,20) roll 到 12 →
a=[-2,10)(负入点、media_in=-2)、b=[10,18),接缝仍在 10,b 尾部反被
截掉 2 秒。若 b 还有后继,会产生块重叠/留洞(`undopointer.rs:160-174`
的补偿 gap 按 C++ 假设放在 `[out, out+diff)`,与实际移动方向矛盾)。
- **缺陷是活的**:`real.rs:4772-4798` 把 UI 事件
`TimelineEvent::ClipRollRequested` 直接接到 `graphops::roll_edit`。
- 仓库内 `undosplit.rs:200-214`、`undoripple.rs:342-358`、
`undogeneral.rs:865-872` 的作者显然发现了互换并做了补偿性选边 + 注释,
唯独 undopointer 的 BlockTrim/TrackSlide 与 undogeneral 的
Resize/InsertGaps 未补偿。[子代理]
**加重项** [子代理]:
- 4 处测试**恰好省略了唯一能暴露矛盾的断言**:`:593-620`(gap=[50,75)
与 second=[50,100) 重叠,只断言序号不断言 span)、`:653-708` 两处
(被 trim 块 redo 后实为 [-25,50),不断言)、`:861-889`(gap 与 tail
重叠,tail 只断言 id)。
- **全文件(1488 行、38 测试)无一处断言 trim/slide/ripple/split 后的
media_in**,夹具一律 media_in=0、timeline in=0,使两个内容损坏缺陷
不可见:(a) `media_in := range.in_()`;(b) `undoripple.rs:342-346`
splice 修剪不动 media_in——删除 [25,50) 后余块 [25,75) 实际播放**被删
内容**而非后移内容。
- `:565-588` 普通 trim 测试的注释把反转当规范写("Trim-out is
out-anchored: the clip's in shifts to 25"),与 `common.rs:39` 直接
矛盾,会误导后来者。
- `:1108-1122` ResizeWithMediaIn:注释说 "keeping the out point fixed",
断言却是 in 锚定、out 移动;实现与命令名 `WithMediaIn` 及其 doc
(`undogeneral.rs:105-107`)相反。
- `:1173-1216` InsertGaps 两测试:既有 gap 向左生长越过插入点并与前块
重叠,注释把左向生长表述为预期,而 `undogeneral.rs:866-872` 在另一
命令里明说 out-anchored "would push the in point negative"。
**定性**:作为产品缺陷 **高**(指针编辑族整体反向 + 负坐标 + 重叠 +
内容损坏,挂在真实 UI 路径);作为测试问题 **中-高**(graphops 一处是
诚实的 characterization test;undocommands_test 多处无标注固化且回避
关键断言)。计划文档第四批"记录(未改生产代码)"只登记了 roll_edit
一条,实际波及面大得多。
**修复顺序建议**:先补 `RippleInfo` 公开构造器与 media_in 断言维度,再
统一裁决 block.rs:93-107 的语义互换,届时上述期望值按 graphops NOTE 的
意图 "deliberately" 改写。
**裁决(2026-09-24,已修复)**:准备项落地后按 §9 的三原语方案完成语义
修复,全部 KNOWN-SWAP 期望已按正确几何改写,并补上 `media_in` 与
"缺口后的块不受影响"回归断言(详见 §9 §3.1)。
### 3.2 🔴 `oak-task/tests/render_test.rs:932-951`:全批次唯一"永不失败"的测试 [实证]
`private_dispatcher_renders_frames_and_audio_through_workers` 对两次真实
渲染的结果做双向接受:
```rust
match outcome {
Ok(()) => { /* 真断言:order、size、audio */ }
Err(error) => {
eprintln!("private dispatcher worker render unavailable: {error}; skipping");
}
}
```
`f32_outcome` 同构。Err 分支不区分**环境缺失**(worker 池起不来)与
**产品失败**(`"Frame render ticket failed"`、`shm_frame_to_texture` 的
BGRA8/F32 转换回归、poll pump 超时、解码失败)——全部放行。一旦 worker
二进制存在,本测试**不可能失败**,恰好掩盖它名义上要测的 ShmFrame/
ShmAudio 交付缝与 dispatcher teardown 的任何回归。
叠加 `:881-884` 的"缺二进制即 return"(`locate_oak_worker` 依赖
`target/{debug,release}/oak-worker` 已存在,而 `cargo test -p oak-task`
不构建同 workspace 的 oak-worker 二进制):定向运行/干净 CI 下长期静默
跳过,私有 dispatcher 路径**实际覆盖可能为零**——覆盖率数字虚高的典型
来源。
**修法**:Err 分支按错误内容分流——环境性错误(pool 启动失败)才跳过,
产品性错误必须失败;或至少断言 `error` 匹配已知环境错误串。
### 3.3 🔴 `oak-app/oakui/real.rs`:三个回放验收测试的"饥饿即跳过→通过" [实证]
program-window、display、source-window 三个验收测试均新增
`eprintln! + return`(计为 pass)的逃逸路径:
- program-window:`pumps == 2000 && filled == 0` 跳过;pump 上限
5000→15000。
- display:`pumps >= 1200 && peak < 0 && slots == 0` 跳过;原"playhead
60→120 间 peak 严格增长"的两点采样断言弱化为"任意时刻 advances > 0
一次";pump 上限 9000。
- source-window:**跳过条件仅 `pumps == 2000`,不检查槽位数**(real.rs
约 :16396)——注释声称 "skip only when the shared pool delivered
nothing",但若帧已交付而 `preview_slot_frame` 服务侧有 bug(candidate
存在、hit 恒 None),同样被伪装成池饥饿跳过。program-window 至少有
`filled == 0` 判别,此处没有。
**产品真坏(worker 永远交不出帧)与环境保护不可区分**——验收测试失去
回归守卫功能。计划文档声称"聚焦运行仍严格断言",但**代码里没有任何
机制区分聚焦/全量运行**,该声称不成立。
**复合隐患** [实证]:`WorkerBinGuard`(`real.rs:8044-8056`、
`renderops.rs:3659-3671`)硬编码 `../../target/debug/oak-worker`:
- coverage job 的 target 目录是 `target/llvm-cov-target/`,干净环境下
`target/debug/oak-worker` 不存在;
- `procpool.rs:2402` `resolve_worker_bin` 对 `OAK_WORKER_BIN` **不检查
存在性**直接采用 → spawn 失败 → 槽位恒空 → 跳过路径必然触发;
- 即普通 CI(`cargo test --workspace` 会把 oak-worker 建到
`target/debug`)能真跑,**coverage job 里这组验收测试静默空转**——
恰好在产出覆盖率数字的那次运行里。
对照:`procpool.rs:2922` 测试侧 `find_real_worker` 对 env 覆盖做了
`p.exists()` 检查,守卫没有。
**修法**:跳过条件补"槽位已交付但未服务→必须失败"判别(source-window
尤其);给严格模式一个真实机制(如 CI 设 `OAK_STRICT_PLAYBACK=1` 时禁止
跳过);`WorkerBinGuard` 改为从 `current_exe()` 推导(与
`find_real_worker` 一致)。
### 3.4 🔴 CI 门禁 job 上永久跳过的两组测试 [实证]
**(a) ICC 门控(`oak-core/color.rs`,17 处跳过)**:`system_icc()`
(color.rs:770-783)只探测固定系统路径(macOS ColorSync、Linux
colord/ghostscript),而 `ci.yml:46-53` 的 apt 列表**不含任何 ICC 包**
→ Linux CI(唯一聚合门禁 job)上恒 None → `display_icc_bgra8_never_outputs_black`
(文档自称"viewer 黑屏回归守卫")等测试**永久跳过**,只在非门禁的
macOS 周更 job 上真跑。修复便宜:`apt-get install icc-profiles-free`
(或 colord),或仓库内置一个小 sRGB ICC 测试资产。
**(b) footage_import(`oak-render/tests/footage_import_test.rs`)** [子代理,关键链条已复核]:
CI 是 lavapipe、无 `/dev/dri`,VAAPI/CUDA 设备创建必败且负缓存进程级
粘滞(`hwdecode.rs:197-201`)→ `HW_IMPORTS == 0` → 三个测试恒跳过、
cargo 计为 passed、**零断言执行**。加重项:
- `common/mod.rs:61-71` 的 `gpu_context_for_import()` 直接 `?` 返回
None,**绕过了仓库自己的 `OAK_REQUIRE_GPU=1` 硬失败策略**(对照
`backend.rs` 的 `gpu_or_skip`/`shared_gpu_or_skip` 会 panic;同目录
`render_threads_test.rs:776/824` 用的是合规版本);
- 计划文档承诺"跳过不等于通过(报告里单列)"**未实现**——无 `#[ignore]`、
无 skip 上报机制,CI 报表里与真跑过的测试不可区分。
测试本体质量不错(见 §6),问题在门禁信号缺失。M5 真机验收已留档
(`render-pipeline-threads-m5-branch-coverage.txt`),但 PR 门禁对该
文件恒零信号,应在 CI 报告侧显式标注(warning annotation)或接入计划
M4 的平台/真机 job。
## 4. 中危问题
| # | 位置 | 问题 | 标注 |
|---|---|---|---|
| M1 | `manager_test.rs:164-182` ↔ `manager.rs:84-99` | `init()` doc 声称 "Create the singleton **and register the codec task submitter**",实现只置 `codec_submitter_registered: false`;`register_codec_task_submitter` 全仓库**零生产调用点**(仅 codecbridge.rs:94 定义)。测试断言 `Some(false)` 把矛盾固化为"契约"。结合 codecbridge "submission is synchronous" 的过渡契约,判断为文档过期(或注册逻辑缺失),需裁决 | [实证] |
| M2 | `render_test.rs:471-494` | `forced_size_and_format_are_applied`:设置了 `force_format = F32`,断言只有 `recorder.frames == vec![(32,32)]`(尺寸);Recorder 不记录像素格式,format 是否应用到交付纹理**不可证伪** | [子代理] |
| M3 | `render_test.rs:621-676` | `clip_effect_chain_is_walked_and_bypassed`:enabled=false 与 true 两分支断言**完全相同**(order、frames);若 `clip_effects()` 回归为完全不收集效果链,测试照过。fixture sanity 只验证测试自建图 | [子代理] |
| M4 | `writethrough_test.rs:126-161` | `backend_enabled_by_config_binds_and_round_trips` 名义 "round_trips",但**从不读回 sqlite、不断言 `library.db` 文件存在**;write-through 成功仅以 `last_error == None` 反推。`save_project` 退化为静默 no-op 不可检出 | [子代理] |
| M5 | `undocommands_test.rs:528-556` | `RippleInfo` 字段私有且**全仓库无公开构造器** → 只能构造空 info → `ripple()` 在 `is_empty()` 守卫处立即 return → "断言状态未变"**不可能失败**;`TrackListRippleToolCommand` 主体约 125 行对集成测试不可达,行为覆盖为 0。测试注释与计划文档均有诚实标注,但覆盖率数字(oak-timeline 90.1%)因此有误导性。根修:给 `RippleInfo` 加公开构造器 | [子代理,构造器缺失已 grep 复核] |
| M6 | `loadotio_test.rs:294-310`、`otio_backend_test.rs:388-401` | 两处 FCPXML round-trip 只断言 `sequence_labels == ["Edited"]`;轨道/块/footage 全丢也过(对照 OTIO 版有完整结构断言) | [子代理] |
| M7 | `footage_import_test.rs:165` | 导入 on/off 容差 `max_diff < 0.15`,注释两处声称"the same tolerance the hardware-vs-software decode test uses",实际先例(`oak-codec/src/realmedia_tests.rs:567`,未被本次修改)是 **0.08**——引用失实,容差约为先例 2 倍。测试不空洞(图案通道间距 ≥0.65、逐像素 max、test2 ACEScg 用 0.05 且实测 0.011),但应改注释论证放宽理由(swscale 色度滤波 vs GPU 双线性)或对齐 0.08 | [实证:两处阈值均已 grep 核对] |
| M8 | 无断言/弱断言冒烟测试 | `worker.rs:3188` `renderer_create_variants_are_tolerant`(**零断言**,纯"不 panic"遍历);`worker.rs:2391` `renderer_creation_falls_back_or_succeeds_headless`(expect + 丢弃 `has_renderer()` 结果);`instance.rs:2123` `trace_probe_branches`(5 个调用仅 1 个断言);`history.rs` `rows_render_and_interact`(`on_menu(MENU_UNDO/REDO)` 只调用不断言效果,如 undo 后条目数应减少);`writethrough_test.rs:232-244`(零断言 + 依赖不受保护的"无残留 binding"前提)。注释均有坦白,但这正是计划 §8.2 自己警告的"为行数写无意义 case"。CI 有 lavapipe + `OAK_REQUIRE_GPU=1`,本可断言确定结果而非"两种结局都接受" | [实证:前四个已读原文] |
| M9 | `footage_import_test.rs:136/145、217/226` | `OAK_GPU_IMPORT` 用裸 `set_var`/`remove_var` 非 RAII:中途 `expect("staging decode")` panic 会泄漏 `"0"`;串行锁下**把后续测试的真失败掩蔽成静默跳过**。同文件(render_threads_test)明明有 `SoftwareDecodeGuard` 先例可仿。另 `remove_var` 不恢复外部预设值 | [子代理] |
| M10 | `oak-core/src/backend/external.rs` | 611 行 unsafe 平台 FFI(DMA-BUF/D3D11 handle/IOSurface 导入)**零单测**;唯一覆盖是恒跳过的 footage_import(§3.4b)。计划 M4 的平台门禁 job 未接线 | [实证:grep 无 #[test]] |
## 5. 低危问题(简列)
- `render_test.rs:352-355`:configurator 边界段(`set_max_inflight(0/
usize::MAX)` 等)调用后零断言;`max.max(1)` 钳制无公开 getter 可验。
- `render_test.rs:405-428`:名义 "generated **(transparent)** frame"
只断言尺寸,不检查像素透明。
- `import_test.rs:219-220`:断言消息声称 "fails with Cancelled",实际
只 `is_err()`,未 `matches!(Err(Error::Cancelled))`(源码确实返回
Cancelled,测试弱化了它)。
- `codecbridge_test.rs:142/162/185/205`:失败路径仅 `is_err()` 不断言
错误变体/消息,无法区分失败原因(如 bad-output-name 若因 probe 失败
而 err 也会通过)。
- `precache_test.rs:254-282`:doc 声称验证 window/progress
configurators,`set_max_inflight(1)`/`set_native_progress_signalling(false)`
设置后零对应断言,其余断言与相邻测试重复。
- `task_test.rs:266-292`:setter/getter 回环、`system_time_ms() > 0`、
结尾无断言的 `emit_progress(2.0)`。
- `writethrough_test.rs:95-105`:null 句柄断言是真的,其后四次
bind/unbind/flush 调用零断言。
- `otio_backend_test.rs:296-317`:三种非法 URI 仅 `is_err()`,不区分
错误原因。
- `undocommands_test.rs:428-487`:ripple 删 gap 仅摘成员关系(util.rs
文档化偏差),时间线净效果为零;删区域后洞从 [60,80) 迁到 [50,70)、
可见时间线无变化——注释只描述机制不评语义。
- `gpuinterop.rs:649-652`:`OAK_GPU_IMPORT` set/remove 不恢复外部预设值
(有 `lock_tests` 守卫,实际风险低)。
- `footage_import_test.rs` `sample()` 未断言 `frame.format == F32` 就按
f32 解释字节(对照 render_threads_test.rs:232 有此断言)。
- `render_test.rs:891-930`:测试中途 `RenderManager::shutdown()` +
env 覆盖,恢复在断言之前——render panic 会泄漏全局状态(后续
`render_serial()` 自愈)。
## 6. 合格项(正面确认,防止误伤)
1. **`render_threads_test.rs` +30/−0 纯新增**(`git diff --stat` 核对):
`assert_same_frame` 仍是严格逐字节相等、无容差;计数器期望
(`(6,6,0)`、lru_hits=1/decodes=4)、双侧地面真值图案、时间戳逐帧
断言全部保留。旧 flake 靠**消除解码路径分歧**修复(hwdecode 设备负
缓存进程级粘滞 → 同进程两侧走不同解码路径),不是放宽容差。
2. **`OAK_HWACCEL=0` 软解守卫合规**:该二进制全部 13 个测试第一条语句
都是 `let _lock = lock()`,守卫在锁内设置、drop 逆序先恢复 env 再
放锁;`hwdecode.rs` 每次开流实时读 env,守卫真实生效。代价(记录):
硬解下的管线字节一致性从此无测试,hw/sw 像素等价仅剩
`realmedia_tests.rs:504` 一处(0.08 容差,无硬解机器同样跳过)。
3. **逐字节比对不是"自己比自己"**:inline 与 pipeline 是两条真实执行
机器,两侧用不同文件名隔离 eval/decode 缓存键;footage_import 的
on/off 对比同样用 `fs::copy` 换文件名隔离缓存。
4. **`worker.rs` "needs 16000 bytes" 断言**:只是提取变量重排,未弱化;
`node_factory.rs` 曲线 JSON 断言等价重构 + 补 helper 双分支覆盖。
5. **ForceParams 测试断言的是文档契约**(`-1`,注释明示 "not 0 = U8"),
与手写 `Default` 及 doc 完全一致——契约验证,非投降。
6. **codecbridge 真实 conform 测试是真断言**:两通道 `.pcm` 存在
(metadata 失败即 panic)、非空(len>0)、`.working` 已重命名消失;
提交为源码确认的同步路径,无竞态。不足(低):未校验 PCM 字节数
是否等于预期样本量。
7. **loadotio 的 CALLBACK_LOCK 真消除了竞态**:锁覆盖全部回调消费点
(XML 路径测试不持锁是正确的——源码确认不触碰回调);`take()`
一次性消费 + 毒化锁 `into_inner()` 恢复,残留回调会导致后续测试
**响亮失败**(`.expect("loaded project")`)而非静默通过。
8. **`eval.rs` OCIO 内联测试抽查质量高**:真 LUT(红通道加倍)、真
resolve 管线、逐像素数值断言(0.25→0.5、green 不变、alpha 保持);
跳过仅在 OCIO 库缺失时触发,CI 有真实静态 OCIO(`ocio-env.sh` +
`OCIO_RS_ENABLE_REAL=1`);GPU 跳过经 `shared_gpu_or_skip` 在
`OAK_REQUIRE_GPU=1` 下硬失败,设计正确。
9. **`ffmpeg.rs` 内联测试抽查合格**:像素格式映射矩阵、声道布局回退、
RefFrame 几何/缓冲共享、打开状态机、跨流检索错误——均有具体期望值。
新测试文件无 `#[ignore]`、无 sleep。
## 7. 建议行动(按优先级)
1. ✅ **裁决 `block.rs:93-107` setter 互换**(产品缺陷,§3.1):2026-09-24
按 §9 的三原语方案修复,约 12 个期望值按 graphops NOTE 的意图
"deliberately" 改写;`RippleInfo` 公开构造器与 media_in 断言维度已先行
落地(M5)。
2. **消灭"双向接受"**(§3.2):`render_test.rs:932` 的 Err 分支按错误
内容分流,产品性错误必须失败。
3. **修回放验收测试的跳过判别**(§3.3):source-window 补槽位检查;
给严格模式真实机制(CI 设 env 禁止跳过);`WorkerBinGuard` 改从
`current_exe()` 推导。
4. **修 CI 恒跳过**(§3.4):apt 装 ICC 包;`gpu_context_for_import`
尊重 `OAK_REQUIRE_GPU`;实现计划承诺的"跳过单列"(CI annotation
或汇总)。
5. **对齐 `manager.rs::init()` 文档与实现**(M1)。
6. 小修批次:M2/M3 补格式与效果链断言、M4 补读回、M7 改容差注释、
M9 改 RAII、M8 在 CI 断言确定结果、§5 各项。
7. **流程**:M5 功能与覆盖率测试分开提交(§2 末)。
## 8. 审查局限
- 内联测试约 3 万行,采取"删除行全查 + 模式扫描全查 + 高风险区抽样
精读"策略,未逐行读完;[子代理] 标注项中未注明"已复核"的细节以
子代理报告为准。
- 未重新运行测试套件与覆盖率;文中覆盖率数字引自计划文档 §7.5 自述。
- `block.rs` 互换缺陷的 C++ Olive 原始语义对照基于代码注释与仓库内
其他模块(undosplit/undoripple/undogeneral)的补偿性注释推断,未
直接核对 C++ 源码。
## 9. 处理记录(2026-09-22)
本报告的高/中危与 §5 条目已按下列状态处理;§3.1 的语义裁决首先按报告
建议延后(准备项先行落地),随后于 2026-09-24 完成修复。
### §3.1 ✅(2026-09-24 裁决并修复)
**已用仓库内 C++ 上游源码核准语义**(此前报告 §8 的局限已解除):
- `.cache/olive-upstream/app/node/block/block.cpp`:`Block::set_length_and_media_out/in`
只调用 `set_length_internal(length)`,**从不移动时间线 in/out**;
in/out(`in_point_`/`out_point_`)由 Track 的布局(`track.cpp:469-470,514-515,575-579`)
按前后块与长度推导。
- `.cache/olive-upstream/app/node/block/clip/clip.cpp`(非 reverse 剪辑):
- `set_length_and_media_out`:`media_in` **不变**(media out 随长度移动);
- `set_length_and_media_in`:`media_in += old_length - length`(media out 固定)。
- `.cache/olive-upstream/app/timeline/timelineundopointer.cpp` / `timelineundogeneral.cpp`:
`BlockTrimCommand` 的 TrimIn/TrimOut 与 `BlockResize*` 的调用与本仓库一一对应,
因此缺陷只在 Rust 的两个 setter(绝对 range 模型把 Track 布局效果错误地编码进
setter)。
**结论:不是两个函数简单对调即可**。同一 C++ 函数在不同命令里需要不同的净时间线
锚定:
| 命令 | 时间线锚定 | media 调整 |
|---|---|---|
| `BlockResizeCommand` | in 固定、out 移动 | 无 |
| `BlockResizeWithMediaInCommand` | in 固定、out 移动 | `media_in += old−new` |
| `BlockTrimCommand`(TrimIn) | out 固定、in 移动 | `media_in += old−new` |
| `BlockTrimCommand`(TrimOut) | in 固定、out 移动 | 无 |
另有 `TrackSlide`、`TrackListInsertGaps`、`TrackListRippleToolCommand`、multicam 等
调用点与 undosplit/undoripple/undogeneral 的补偿性选边需要一并裁决(2026-09-24
已随修复落地,见下;`TrackSlide`/`TrackListInsertGaps` 的“调用方摆放/ripple”
契约同时记入模块文档)。
**修复落地(2026-09-24)**。存储 range 模型定为三个原语
(`crates/oak-node/src/block.rs`),各调用点按上表逐点选择:
- `set_length_and_media_out`:**in 固定、out 移动,media 不动**
(Resize / TrimOut / 缺口向右生长);
- `set_length_and_media_in`:**in 固定、out 移动,`media_in += old−new`**
(ResizeWithMediaIn、splice 的右半、ripple TrimIn);
- 新增 `set_length_keeping_out`:**out 固定、in 移动,`media_in += old−new`**
(TrimIn 本体与 out 邻块、滑块右侧邻块、ripple trim_in)。
关键点:
- `TrackReplaceBlockWithGapCommand` 的“仅后随缺口”分支改为 out 锚定:
原实现把缺口向右生长,会吞掉缺口之后的块——这正是“拖动一个素材影响到
其他无关素材”的实证缺陷。回归断言已补(`domain_test`)。
- `undoripple` 的 trim_out 改为 in 锚定(不再误写 media_in),splice 与
trim_in 现在同步推进 `media_in`(内容损坏修复)。
- `undosplit` 显式写两半的 range 与 media:第二半从切点继续,不再依赖
`range.in_()` 的坐标空间巧合。
- `TrackSlideCommand` 保持“调用方摆放滑动块,命令只处理邻块”的存储模型
契约(文档已注明);`TrackListInsertGaps`/`timeline_ripple_delete_gaps`
的后续块 ripple 仍由调用方负责(C++ 布局的显式替代,未在本次范围)。
- 测试:`domain_test`、`undocommands_test` 的全部 KNOWN-SWAP 期望按上表
“故意”改写(roll 真正移动接缝、slide 无负入点、insert-gaps 向右生长、
ResizeWithMediaIn `media_in=20`),`graphops` 内联 roll 期望同步改写;
`phase2_units_test` 按新语义修正并补 `set_length_keeping_out` 断言。
**本批已落地(准备项)**:
- `RippleInfo::new(block, append_gap)` + `block()`/`append_gap()` 访问器;
`undocommands_test.rs` 新增 2 个真实 info 测试(resize 往返、append_gap
插入/撤销),使 `TrackListRippleToolCommand::ripple()` 主体可达(§M5)。
- 补齐 `media_in` 断言维度:roll-edit、`BlockResizeWithMediaInCommand` 往返;
相关期望值加 **KNOWN-SWAP** 标注(roll、slide、insert-gaps、
ResizeWithMediaIn),语义修复时按标注"故意"改写。
- 修正 `graphops.rs` 内联测试 NOTE 的措辞(follower 锚定的是 IN,不是 OUT)。
### 高危(其余三项)
- **§3.2 ✅**:`render_test.rs` 私有调度器测试的 Err 分支按错误内容分流——
仅 `Error::Failed` 且消息以 `"render worker pool"` 开头(池创建/启动失败)
或缺少 worker 二进制(`locate_oak_worker` 提前打印跳过)才跳过;产品性错误
(`"Frame render ticket failed"`、shm 转换、时间戳等)一律 panic。管理器/
环境用 RAII `DispatcherEnvGuard` 恢复,断言前显式 `restore()`;两个交付腿
均断言 `formats == [F32]`。
- **§3.3 ✅**:三个回放验收测试的跳过条件收紧为**零交付**(`filled`/`delivered`
为历史最大值,一旦有过交付就禁用跳过);"交付过但服务/显示从未取用" 走有界
失败上限并打印 `serve_misses` 等诊断。新增 `OAK_STRICT_PLAYBACK=1` 严格模式
(跳过改为 panic,含 `#[should_panic]` 自测)。`WorkerBinGuard` 改用
`renderops::test_worker_bin()` 解析链(已有 env → `current_exe()` 同级 →
`target/{debug,release}` 兜底),仅在文件真实存在时设置变量并恢复旧值;
`process_backend_preview_path_is_zero_copy` 不再硬编码路径。
- **§3.4 ✅**:CI apt 增加 `icc-profiles-free`;同时给 `system_icc()` 补
Ubuntu 实际路径 `/usr/share/color/icc/sRGB.icc`(实测 5 个 display-ICC
测试真跑,BGRA8 中灰精确为 `[128,128,128,255]`)。`gpu_context_for_import`
尊重 `OAK_REQUIRE_GPU=1`(硬失败),所有跳过路径打印 `SKIP:` 标记;文件头注
记录 lavapipe CI 恒跳过与真机验收出处。
### 中危
- **M1 ✅(裁决:文档化同步契约)**:证据为 C++ `taskmanager.cpp` 仅创建
管理器、移植版 codecbridge 的 "submission is synchronous" 契约与
`TaskManager::init` 无生产调用点。已把 `manager.rs` 模块/`init`/`shutdown`
文档与字段说明改为"不注册",测试断言 `init` 后未注册、且手工翻标志不会安装
oakcodec 回调。
- **M2 ✅**:`Recorder` 记录 `formats`/首像素;新增生成帧路径的强制 **U8**
测试(可证伪),另断言 F32 腿的交付格式。
- **M3 ✅**:夹具效果从 Invert 换成 **Opacity = 0**;enabled=true 必须全透明、
enabled=false 必须非透明——效果链丢失或忽略 enable 标志都会失败。
- **M4 ✅**:writethrough 往返测试插入 `"Written Through"` 文件夹后写穿,断言
`library.db` 存在且非空,并用全新 `backend().load_project` 读回 uuid 与标记。
- **M5 ✅**:`RippleInfo::new` + `block()`/`append_gap()`,新增 2 个真实 info
测试(resize 往返、append_gap 插入/撤销),`ripple()` 主体可达。
- **M6 ✅**:两处 FCPXML 往返补齐轨道/块/footage/转场偏移断言
(转场居中偏移 `3/8`)。
- **M7 ✅**:容差对齐先例 0.08;真机实测 sRGB 0.00878 / ACEScg 0.01141,注释
改为正确论证(GPU 双线性色度 vs swscale 滤波)并打印实测值。
- **M8 ✅**:`worker.rs` 渲染器变体测试改为结果不变量断言(成功↔`is_open_gl`、
失败↔阶段错误串)、`has_renderer()` 与工厂结果一致、崩溃钩子 env 用 RAII、
一次性告警补并发存活断言;`instance.rs` 的 5 个 trace 调用全部断言返回值;
`history.rs` 断言 undo/redo 后 `history_index` 与 `done` 变化(行数按面板
契约保持不变,已在注释说明)。
- **M9 ✅**:`StagingDecodeGuard` RAII + 显式 drop;外部预设的 `OAK_GPU_IMPORT`
值会被恢复。
- **M10 ✅**:`external.rs` 新增测试模块:顶部文档列明未单测的 unsafe 平台体与
对应平台 job;4 个测试覆盖纯映射(Vulkan/IOSurface 格式)、参数校验(DMA-BUF
零尺寸/非平面格式)与 D2 别名视图回归。
### 低危 / §5
- oak-task:`import_test` 断言 `Err(Error::Cancelled)`;`codecbridge_test` 同时
断言桥接层消息与直接驱动 `ConformTask`/`ProxyTask` 的路径原因;
`precache_test` 用真实运行兑现"窗口/进度"声明;`task_test` 观测进度钳制;
`render_test` 的配置器边界、透明帧、shutdown 恢复顺序均已修正。
- `gpuinterop.rs`/`footage_import_test.rs` 的 env 泄漏改 RAII(含恢复外部预设)。
### 追加修复
- **新暴露 flake**:`app::tests::preferences_general_tab_writes_cache_ahead_and_storage`
在满载并行下"点击→按键"焦点交接竞态(1/4 次读到 120)。点击后补一次
effect flush + 一帧绘制再派发按键;通过。
### 验证
- 各 crate:oak-task 133、oak-storage 74、oak-core 456+12、oak-render 全部、
oak-worker 全部、oak-plugin 208+、oak-app lib 544(含 `OAK_STRICT_PLAYBACK=1`
一次)、oak-timeline 全部。
- 全 workspace 终验(2026-09-22):**104 个测试目标、3179 passed / 0 failed /
7 ignored**(ignored 为既有 GPU 门控)。
- 覆盖率(插桩终测,干净对象集同口径):区域 93.96%、函数 89.59%、行
**93.49%**(180742/193331)、分支 **71.58%**(11805/16491)。分支较修复前
微降 0.37pp——本批刻意移除了若干"容忍型/同义反复"的执行路径(§3.3 交付即
失败、M3 夹具更换、M8 去重),属测试质量的预期代价。
## 10. 第二轮全量审查(2026-09-22)
> 触发:§9 修复完成后,用户要求全量复审。范围:全部未提交改动
> (66 文件,+38731/−281),含第七批修复自身。方法:五个深查子代理
> 分区逐行通读(oak-app 面板群 19 文件、real.rs/renderops、
> oak-render/oak-worker 269 个测试、oak-plugin/oak-codec 约 250 个测试、
> oak-task/core/timeline/storage),审查会话对全部高危论断与 24 条修复
> 声称的关键链条做了原文实证。标注约定同前([实证]/[子代理])。
### 10.1 修复声称验证总裁定
**24 条声称:20 条完全属实,4 条部分属实,0 条虚假陈述。**
所有核对到的新断言均为可证伪的真断言。上一轮四个高危全部实质化解:
- **§3.1**:语义裁决延后**有据**——`.cache/olive-upstream` 的
`block.cpp:62-79`(C++ setter 只调 `set_length_internal`,时间线位置
由 Track 布局推导)与 `clip.cpp:95-124`(非 reverse 时 media_out 版
不动 media_in、media_in 版 `+= old−new`)经原文核对,支持"不是简单
对调、需逐命令裁决"的结论;§8 原局限(未核对 C++ 源码)解除。准备
项落地:`RippleInfo::new` 被 2 个真实测试使用(resize 往返断言
`[-10,100)`+`media_in==-10`、append_gap 断言块数 1→2+Gap 类型,
ripple 主体确认可达);KNOWN-SWAP 标注 6 处;`clip_media_in` 断言
1→11 处。[实证]
- **§3.2**:`worker_pool_environment_error` 分流精确(`Error::Failed` +
`"render worker pool"` 前缀,全仓库仅池创建/启动两处产生该前缀,
产品错误消息穷举核对均不匹配);`DispatcherEnvGuard` RAII + 断言前
显式 restore;两腿断言 `formats == [F32]`。**"永不失败"测试已消灭。**
固有残留:worker 存在但握手/协议回归导致 `start()` 失败仍归环境跳过
(有打印)。[实证+子代理]
- **§3.3**:三验收测试统一"历史零交付才可跳过"(`filled/delivered`
取历史最大值,一旦有交付跳过分支永久不可达;source-window 旧缺陷已
修);"交付但未服务"走有界 `assert!(pumps < FAIL_PUMPS)` 失败并携
`serve_misses` 诊断;`OAK_STRICT_PLAYBACK=1` 严格模式 + 设计正确的
`#[should_panic]` 自测;`test_worker_bin()` 解析链(env 存在性过滤→
current_exe 同级→target 兜底,`None` 时不动 env)修掉了硬编码复合
隐患;早期 playhead 断言修复与生产 prune 语义精确匹配。**残留:
ci.yml/cd.yml 均未设置 `OAK_STRICT_PLAYBACK`**——门禁 job 上零交付
仍为绿色跳过(可辩护的权衡:全量并行下池饥饿本征 flaky,且兄弟测试
对管理器启动失败一律硬失败、worker 全坏会在别处红;但应在文档显式
登记该取舍)。[实证+子代理]
- **§3.4**:ci.yml 增 `icc-profiles-free`(注释精确指向黑屏守卫)+
`system_icc()` 补 `/usr/share/color/icc/sRGB.icc`(该包实际落点)
[实证];`gpu_context_for_import` 经 `require_gpu_adapter()` 在
`OAK_REQUIRE_GPU=1` 下硬失败,footage_import 三处跳过均带 `SKIP:`,
头注如实登记 lavapipe 恒跳过与真机验收出处 [子代理,头注已实证]。
残留(低):color.rs(15)/eval.rs(4)/procpool.rs(2) 的旧式 `skipping`
打印未统一为 `SKIP:` 标记(CI 上因 ICC/OCIO/二进制修复均不再触发)。
- **M1–M10 与低危批**:M1(文档改为事实 + 真注册表查询断言)、M2
(Recorder formats + 强制 U8 可证伪测试)、M3(Opacity=0 夹具,双分支
断言互斥)、M4(sqlite 落盘 + load_project 读回 uuid/label)、M5、
M7(0.08 对齐先例,实测值打印)、M8(history.rs 真撤销栈三维断言;
instance.rs 5 个 trace 调用全断言且分支敏感;worker.rs 渲染器不变量
+`has_renderer` 一致性+EnvGuard+并发存活)、M9(StagingDecodeGuard
恢复外部预设)全部属实。[实证+子代理]
- **部分属实 4 条**:
1. **M6**:otio_backend_test 全齐(轨道/块/footage/转场 3/8 居中
偏移,算术核对正确);loadotio_test 补了轨道/块/footage 但无转场
断言(夹具本就无转场)——声称"两处"只兑现一处。
2. **M10**:external.rs 顶部文档如实列明未单测平台体;4 测试中 3 个
完全真实(Vulkan/IOSurface 格式映射、DMA-BUF 参数校验精确变体);
**"D2 别名视图回归"守卫不可证伪**——只对三种别名 `.expect()` 视图
创建成功,而删掉生产修复行(external.rs:607 `dimension: Some(D2)`)
后 `create_view` 照样成功(派生 D2Array 合法),真正的回归(planar
pass 的 D2 layout 校验拒绝 bind group)只在**创建 bind group** 时
显现,测试未建 bind group。[实证]
3. **M8-worker 残留**:渲染器两测试仍是 Ok|Err 双向接受(错误串前缀
对即过),未按 `OAK_REQUIRE_GPU` 分流成确定断言——CI(lavapipe)上
"渲染器创建失败"回归不可检出。比 §3.4 已实现的硬失败策略弱一档。
4. **§3.3-CI 接线**:见上。
- 追加修复核实:`source_monitor` 早期 playhead(属实,与生产 prune
语义逐值核对);`preferences_general_tab` 点击→按键竞态(属实,补
`run_until_parked`+整帧 draw+再 park 的同步节拍,断言保持严格
`==128` 无容差,非弱化;配置键 RAII Restore)。[实证+子代理]
- dialogs 184 期望值再确认:gpui_widgets `SliderModel` 吸附实现为
`((raw−min)/step).round()`(半值远离零)→ (180−120)/8=7.5→8→184,
与控件既有测试固化的契约自洽。[子代理,公式已核对]
### 10.2 全量深查新发现(第一轮未覆盖区域)
**高(1 项)**
| 位置 | 问题 |
|---|---|
| `panels/inspector.rs:564-568` | **恒真断言**:`assert!(debug_bounds(..).is_none() \|\| ..is_some())` 逻辑上永不失败;该测试设置 `pending_add=Some(0)` 并 draw 后本应断言 add 菜单 `.is_some()`。全工作区唯一一处恒真断言。[实证] |
**中(12 项)**
| 位置 | 问题 |
|---|---|
| `oak-render/cache.rs:999-1023` | mtime 守卫测试同义反复:`validate` 先污染内存使文件与内存恒同构,`load_state` no-op/守卫反转/真跳过三种实现均通过;名义两个行为均不可证伪。修法:两次 load 间 invalidate 内存范围或用干净实例。[实证] |
| `pipeline.rs:959` ↔ `eval.rs:5636` | 进程级 working-space 竞态:pipeline 10 个测试 `pin_legacy_working_space` 不取 eval 的模块私有 `WORKING_SPACE_TEST_LOCK`,同一 lib 测试二进制并行——`footage_working_lut` 的 `is_some()` 有真实 flake 窗口。修法:锁提为 crate 级。[实证] |
| `eval.rs:1371-1390`(生产) | **M5 planar-resolve 失败→staging 回退分支零覆盖**,且现有测试缝(`decoded_frames` 全局缓存 + `planar_texture()` helper)本可单元级注入;留档"单机走不到"对该分支不成立。M5 最重要容错路径之一。[子代理] |
| `oak-app/mock.rs` ↔ `ofx_params.rs:4886/4825` | MockEngine 未实现 `set_effect_param`/`effect_push_button` 的记录与失败注入(计划 M3.4 缺口)→ 两个"路由/点击触发"名义测试不可证伪;生产侧 `let _ =` 丢弃 Err 加剧不可观测。[子代理] |
| `controls.rs:1842-1856`(及 1424-1434) | checkbox 键盘测试不订阅 `CheckBoxEvent::Toggled`,只断"状态不变"——space/enter 处理整体失效不可检出(同仓库 ofx_params.rs:2489 有正确示范)。[子代理] |
| `displaycolor.rs:558-578` | 缓存/generation 测试用恒真 `>=` 断言,"同 key 命中不重建/换 key 重建"语义均未验证;:594-599 五个指纹调用零断言。[子代理] |
| `oakui/gpu.rs` | **全文件零测试**(M5 功能文件):`upload_rgba16f` 参数校验分支(触碰 GPU 前返回)与 `build_display_lut` 纯 CPU 色彩数学均可确定性测试而未测。[子代理] |
| `project_explorer.rs:677-733` | RealEngine 菜单/打开/导入段:注释声称四种效果,整段零断言(同文件 mock 版对相同行为逐一断言,证明可断)。[子代理] |
| `real.rs:14789` + `:16234` | 代理 drain `matches!(Ready\|Failed)` 双向接受**原样保留**(§9 未声称处理),叠加弱断言后两文件内**无任何测试断言真实转码产出 Ready**——代理生成 happy path 无守卫。[子代理] |
| `real.rs:16147-16155` | "注释声称-结果丢弃"假断言:声称"删除后 name/path 查找 miss",两个查询结果 `let _ =` 丢弃。[子代理] |
| `renderops.rs:3749` | `ensure_render_manager()` 失败→SKIP+return;同情形 real.rs 一律 panic(10 处)——同仓库双标,管理器 init 回归可被静默跳过。[子代理] |
| `undocommands_test.rs:647-648` | KNOWN-SWAP 漏网:注释仍把互换行为写成规范("Trim-out is out-anchored: the clip's in shifts to 25"),与 common.rs:39 及 §9 C++ 裁决表直接矛盾。另 :874/:907、:659-687 三处固化无标注;:820 slide 标注措辞("grow into each other")与断言(next 缩短)不符。[实证] |
**中低/低(择要)**
- `hwdecode.rs:331` 全局 `CREATE_ATTEMPTS` 计数器断言未取 `lock_tests`
——并发的 ffmpeg 真实媒体测试会递增它,唯一可能产生 CI 间歇红的
竞态(VDPAU 选型已封死污染面,仅剩自身受竞态)。[实证+子代理]
- `decoder.rs:899`/`encoder.rs:362` 注册表注入还原非 panic 安全
(`registry_guard()` 只是锁、Drop 不还原;断言 panic 则 stub 注册表
残留进程,后续测试经 poison 恢复静默用假解码器)。[实证]
- `node_factory.rs:2206` 只测自建 mock 入口的边界分支(零生产代码);
`:1672` 读两次全局计数断言相等(近同义反复 + 无锁 flake);`:2350`
无断言尾段;`gl_render.rs:1200` 零断言(注释诚实)。[实证+子代理]
- `external.rs:715` DMA-BUF 校验测试自建软跳过不受 `OAK_REQUIRE_GPU`
约束(Linux CI 是 Vulkan,不触发)。
- `backend.rs:2886` `user_config_env_override` 非 RAII(M9 同类未修到
此处);`:3579` `OAK_REQUIRE_GPU` 翻转窗口与 16 个 GPU 测试竞态(仅
无 GPU 主机);`:2951` shared-slot 测试锁纪律不一致(潜在)。
- `color.rs:1164/1332` if-let 包裹全部断言的静默逃逸(CI 有真 OCIO,
应硬断言);OCIO 缺失跳过仍静默(无 eprintln);`:1420` 不持
config_lock 且恢复非 RAII。
- 裸 `is_err()` 无消息断言(系统性偏弱,非个别假测试):graphops 23
个错误矩阵(分支隔离夹具 + 精确成功腿维持可失败性)、real.rs 无工程
守卫约 35 处(同文件 :11490 有正确示范)、encodingparams 11 个非法
XML(生产明确区分两种失败原因而未断)。
- "结果丢弃/弱断言"群:source_viewer.rs:375-454(config 动作前后读取
全丢弃、transport 9 个只断 handled)、program_viewer.rs:843(workarea
三事件未断)、timeline.rs:2410(约 20 个命令只断 handled 布尔)、
app.rs:8786(`exit_action_quits` 零断言)、eval.rs:5467/5557(无断言)
/6087(OAK_PERF 名义不符)/5585("and_clears" 半截)、procpool.rs
:4752/:4764(smoke/半验注入)、worker.rs:2179(frame_failed 不断错误
文本,同族 :2339 证明可断)、nodeops.rs:1332(零断言,名称诚实)、
writethrough_test.rs:96/277(§5 指出未修,未声称)、precache "窗口"
半边仅 liveness 间接兑现。
- env 非 RAII 残留(与已修 M9 同款):ofx.rs:926 `MARKER_ENV`、
program_viewer.rs:964 `HOME`、eval.rs:6095 `OAK_PERF`、
renderops.rs:2881 配置开关、worker.rs:1992 颜色设置。
- 卫生:`crates/oak-task/tarpaulin-report.html` 覆盖率工件混入源码树
(内嵌他机绝对路径,不应提交);计划文档"nodeops 32 个"实为 24 个、
node_factory/render_driver 的批次计数为组合计(文档口径应注明)。
- `ofx_host.rs:68-77` 生产 `emit` 的 `cfg!(test)` 早退:为测试改形的
轻微实例(shipping 行为不变,集成测试真管道补偿),记录在案。
### 10.3 正面确认(防误伤)
- **无成建制造假**:约 500+ 个新测试中,纯假(恒真/零断言/零生产代码)
共 6 个,均有诚实注释或属笔误级;无 `#[ignore]`、无理由 sleep(全部
有界轮询+deadline+超时 panic);故障注入类全部真注入且断言注入生效
(真 SIGSEGV+marker、/bin/false OFX host→紫帧、假 nvidia-smi 六形态)。
- **修复未引入弱化**:preferences 竞态修复是补同步节拍而非放宽容差;
render_threads 逐字节断言原样;分支覆盖 −0.37pp 是移除容忍路径的
如实代价且已留档解释。
- 教科书级真测试代表(各区各选):node_editor.rs:844(绕过面板证明
守卫在产品代码)、procpool.rs:4780(PATH 注入六形态+精确换算)、
worker.rs:1757(跨进程 shm 游标环游+0xAB 传播)、eval.rs:4415(GPU
旋转单像素精确+全帧 lit==1)、clip.rs:600(f16 −0 位级保留)、
encodingparams.rs:1096(C ABI offset_of 18 项冻结锁)、app.rs:6610
("全分支"名副其实)、dialogs.rs:6483(按键改派+磁盘内容往返)、
ofx.rs:920(真插件 marker 参数串+生命周期顺序)、history.rs:325
(真引擎撤销栈三维断言)。
### 10.4 最终判定与建议
**判定:修复批次诚信且实质有效;工作区达到可提交状态,但下列 8 项
建议先修(均为小改动):**
1. `inspector.rs:564` 恒真断言改 `.is_some()`(一行)。
2. `undocommands_test.rs:647` 补 KNOWN-SWAP 标注(并顺手修 :820 措辞、
补 :874/:907、:659-687 三处)。
3. `cache.rs:999` mtime 测试改为可证伪构造。
4. pipeline/eval 的 working-space 锁提为 crate 级共享。
5. `external.rs:744` D2 守卫补 bind group 创建(或改名去掉"回归守卫"
声称)。
6. `real.rs:14789` 代理 drain:至少在转码可用的环境断言 Ready(可按
ffmpeg 可用性分流,不可用才容忍 Failed)。
7. `renderops.rs:3749` SKIP 改 panic(与 real.rs 对齐)。
8. 删除 `crates/oak-task/tarpaulin-report.html`。
**登记事项(不阻塞提交)**:`OAK_STRICT_PLAYBACK` 的 CI 接线取舍;
`hwdecode.rs:331` 补 `lock_tests`(CI 间歇红风险);decoder/encoder
注册表还原改 RAII;M5 planar 回退分支注入测试;gpu.rs 纯 CPU 分支
补测;MockEngine `set_effect_param` 族记录缺口;旧式 `skipping` 打印
统一 `SKIP:` 标记;block.rs setter 语义裁决独立 PR(§9 清单)。
**提交拆分(重申 §2 末建议)**:M5 功能(gpuinterop/external/Planar/
hwdecode 顺序/RefFrame)与覆盖率批次(测试+两处 bug 修复+文档)分开
提交;tarpaulin 工件与本报告/计划文档更新可并入文档提交。
### 10.5 §10.2/§10.4 处理记录(2026-09-22)
**"建议先修 8 项":全部完成。**
1. ✅ `inspector.rs` 恒真断言 → 以具有 debug selector 的分组头断言菜单
已渲染,并断言 `pending_add == Some(0)` 生效。
2. ✅ `undocommands_test.rs` KNOWN-SWAP 标注补齐::647 措辞改为与
`common.rs:39`/§9 裁决表一致,:659-687、:874、:907 补标,slide 处
措辞修正(next 缩短)。
3. ✅ `cache.rs` mtime 守卫测试改为可证伪构造(干净实例装载 + 内存/文件
不再恒同构),守卫反转或真跳过都会失败。
4. ✅ working-space 锁提升为 crate 级 `eval::working_space_test_lock`,
pipeline 与 eval 两侧共同持锁。
5. ✅ `external.rs` D2 守卫补 bind group 创建(临时删修复行可复现失败,
已还原)。
6. ✅ `real.rs` 代理 drain 按 ffmpeg 可达性分流:可达硬断言 `Ready` +
`ProxyBadge::Ready`;不可达打印 `SKIP:` 并容忍 `Failed`(两种环境均
实测)。
7. ✅ `renderops` 的 `ensure_render_manager` 失败测试改为硬断言(仅
"管理器已初始化" 保留自保护跳过)。
8. ✅ 删除 `crates/oak-task/tarpaulin-report.html`(及其绝对路径泄漏)。
**中危 12 项:**
- ✅ MockEngine 记录 `set_effect_param`/`effect_push_button` 调用(含
失败注入开关),`ofx_params` 生产侧改错误日志;两个名义测试改为完整
路由矩阵 + 类型转换值断言(曲线 JSON 先 `set_points` 再发事件)。
- ✅ `controls.rs` checkbox 键盘测试订阅 `CheckBoxEvent::Toggled` 并断言
事件序列;space/enter 处理整体失效会失败。
- ✅ `displaycolor.rs` generation/链缓存改为精确断言(同 key 不重建、
换 key 恰好 +1、指针同一/不同),5 个指纹逐一断言。
- ✅ `oakui/gpu.rs` 补 4 个测试:`upload_rgba16f` 参数校验、f16 打包
(钳制/字节序/256 对齐行距)、display LUT 网格完整性与确定性、key
跟随色彩设置。
- ✅ `project_explorer.rs` RealEngine 段补断言(序列切换、导入计数、
菜单选择与开关状态、引擎分支前置条件)。
- ✅ `real.rs` 两处丢弃的 name/path 查询改为断言;删除后 rename no-op
一并断言。
- ✅ `hwdecode.rs:331` 取 `lock_tests`;decoder/encoder 注册表注入改
RAII `RegistryGuard`(panic 不再泄漏假解码器)。
- ✅ `color.rs` if-let 逃逸改硬断言(OCIO 缺失才打印跳过);配置锁
RAII。`backend.rs` env 覆盖 RAII、共享上下文测试锁纪律统一、
`OAK_REQUIRE_GPU` 竞态窗口消除。
- ✅ env 残留 RAII:`ofx.rs` MARKER_ENV、`program_viewer.rs` HOME、
`eval.rs` OAK_PERF、`worker.rs` 颜色设置、`renderops.rs` 配置开关。
- ✅ 计划文档计数修正(nodeops 32 → 24,组合批次注明口径)。
**登记(不阻塞提交,遗留项)**:`eval.rs` M5 planar 回退分支注入测试
(需要专用测试缝);`node_factory.rs` 三处弱断言与 `gl_render.rs` 零断言;
旧式 `skipping` 打印统一 `SKIP:`;`OAK_STRICT_PLAYBACK` 的 CI 接线取舍;
`block.rs` setter 语义裁决独立 PR(§9 清单)。
**验收(2026-09-22)**:全 workspace **104 个测试目标、3185 passed /
0 failed / 7 ignored**(ignored 为既有 GPU 门控)。本批生产改动仅
`MockEngine` 记录字段与 `ofx_params` 错误日志两处可观测性增强。