fix(app-iced): M100 r4 P2-1 —— 终态判据加「取证模式」前提,交互预览关窗不再 exit 1
复审在 `d298691` 的导出上实测:交互预览模式(不给 `--screenshot`)关窗会被新判据判成失败, exit 1 + 一句「取证结束但没有任何图落盘(窗口提前消失 / 落盘失败)」的**假消息**。 那是把「从未要求出图」判成「取证失败」,退出码因此失去区分力 (真崩溃 / 真取证失败 / 正常关个预览窗全是 1)。 - `no_evidence(capture_mode, written) = capture_mode && written == 0`;调用点传 `request.screenshot.is_some()`。判据里写明:交互预览模式下 `subscription` 是 `None`、 永远不会有 `Captured`,所以「没写盘」在那里不是失败。 - 注释补一条「为什么用计数器而不是 `path.exists()`」:旧 PNG 会让 exists 骗过判据。 - 断言改名 `finishing_without_a_single_write_is_a_failure_only_while_capturing`, 三条:`(false,0)=false`(这次的红线)/ `(true,0)=true` / `(true,1)=false`。 顺手 p3: - p3-1 `CAPTURE_GIVE_UP_FRAMES` 注释删掉「约 3~4 秒(~120ms/帧)」这个没测准的数字, 改成写明帧间隔量级差异(复审实测 2~3ms/帧 vs 本机 `[perf]` 的 ≈200~300ms/帧), 「要调按第 3 帧派发→第 4~5 帧落盘的结构关系调,别按秒」。 - p3-2 旧字段名 `writes` 的注释改成「这个计数器(旧字段名叫 `writes`)」;顺带把 `capture_stalled` 的形参 `writes` 改名 `written`,与字段对齐。 - p3-3 `examples/pages_demo.rs` 的 usage 漏 `--appearance`/`--passthrough`:该文件**不在本 mission scope**(scope 只有 `pages/harness*`),不扩 scope,欠账仍记在已开的 finding 里。 实测: - 交互预览(WM_CLOSE 关窗,取真实退出码):最终二进制 5/5 有效跑 exit=0、`没有任何图落盘` 行 0; 另 2 次 exit=0xC000013A(STATUS_CONTROL_C_EXIT,控制台 Ctrl 事件打断,日志停在半途)不计。 修前同场景 4/4 exit=1。 - M3 变异(第 3 帧 `window::screenshot` → `window::close`)3/3 exit=1 + 具名行(没被误伤)。 - M4 变异(`CAPTURE_GIVE_UP_FRAMES` 30→0)2/2 exit=1 走「采样超时」(没被误伤)。 - 正常取证 `--appearance=real` ×6:exit=0 / png=yes / `落盘次数=1` / `passthrough_ext=on` / 错误行 0 / sha256 `414a71fcb77e9b38…`(与 r1~r4 基线逐字节相同,像素没动)。
This commit is contained in:
1 parent
d298691c17
commit
f67b24cc7b
3 files changed
+45
-20
No files matched your search
@@ -97,15 +97,18 @@ fn should_request_capture(frames: u32, dispatched: bool, capture_mode: bool) ->
|
||||
/// ⇒ 这里的判据根本求值不到**。那一路由 `run()` 里的**终态不变量**兜住(跑完没图 ⇒ 红着退出);
|
||||
/// 而后端报错是另一回事:`run()` 直接返回 `Err`,本来就是非 0。
|
||||
///
|
||||
/// 30 帧在取证窗口里约 3~4 秒(实测 ~120ms/帧),远大于正常路径「第 3 帧派发 → 第 4~5 帧落盘」。
|
||||
/// 30 帧**不换算成秒**(M100 r4 P3-1):帧间隔在不同机器/负载下量级差异极大——复审实测 2~3ms/帧,
|
||||
/// 而本机 `[perf]` 日志里是 `frames=4 elapsed=1133ms` / `frames=5 elapsed=1605ms`(≈200~300ms/帧)。
|
||||
/// 所以这里只承诺「若干帧的宽限」,不写时间预算;要调就按「正常路径是第 3 帧派发、第 4~5 帧落盘」
|
||||
/// 这个结构关系调,别按秒。
|
||||
const CAPTURE_GIVE_UP_FRAMES: u32 = 30;
|
||||
|
||||
/// 采样是不是**卡住了**:过了宽限帧数,一次都没落盘。
|
||||
///
|
||||
/// 不区分「一直没派发」(窗口始终没就绪)与「派发了没回来」——两者对使用者的表现都是
|
||||
/// 「没有图」,都该红着退出而不是挂死。
|
||||
fn capture_stalled(frames: u32, writes: u32) -> bool {
|
||||
writes == 0 && frames > CAPTURE_AT_FRAME + CAPTURE_GIVE_UP_FRAMES
|
||||
fn capture_stalled(frames: u32, written: u32) -> bool {
|
||||
written == 0 && frames > CAPTURE_AT_FRAME + CAPTURE_GIVE_UP_FRAMES
|
||||
}
|
||||
|
||||
struct Harness {
|
||||
@@ -246,8 +249,8 @@ impl Harness {
|
||||
let Some(path) = self.request.screenshot.clone() else {
|
||||
return Task::none();
|
||||
};
|
||||
// 只在真的写成功时计数(U1):`writes` 若在 save 之前自增,一次落盘失败也会被
|
||||
// 记成「有图了」,而 `run()` 的终态不变量正是拿它判「有没有证据」。
|
||||
// 只在真的写成功时计数(U1):这个计数器(旧字段名叫 `writes`)若在 save **之前**
|
||||
// 自增,一次落盘失败也会被记成「有图了」,而 `run()` 的终态不变量正是拿它判「有没有证据」。
|
||||
match shot::save(&screenshot, &path) {
|
||||
Ok(summary) => {
|
||||
eprintln!("{}", summary.describe());
|
||||
|
||||
Reference in new issue
Block a user