fix(notify): M298 r1 —— toast 退场腿接上触发点,四条 nit 一并收

复审 P2-1:进场腿自己续帧所以能跑,但进场结束 view_dirty 回 false,
3.6s 后 remaining_ms 掉进 150ms 退场窗口时没有任何代码重新置脏 ⇒ 那一段
收缩从不发生,expire 一抹胶囊整块消失(复审探针:120 拍后 progress 仍 1.0)。

- update/clock.rs:expire 之后用无副作用的 ToastTracks::needs_frame 置脏,
  落到既有的 if view_dirty { refresh_view() } 上采样;refresh_view 仍是门控,
  没有变成每帧无条件调用(静止态判据不变)。
- state/toast.rs:进出两条腿改成**同一个时钟**(寿命 = 首次看见时的
  remaining_ms,已活 = 寿命 - remaining),去掉 Instant 与节拍的二时钟错位;
  新增 needs_frame;新增两条真节拍用例(退场腿必被抽到 / 到期后不再续帧)。
- N1:装配失败与 spawn 失败也用 publish_before_start 的返回值填 session。
- N2:m298 用例注释改准(它抓不住删守卫,那条由 a_report_from_another_session 守)。
- N3:before_start 文档不再把两种来源都说成「进程没起来」。
- N4:refresh_view 末尾的死赋值 view_dirty = false 删掉。

红灯原文(摘掉那 3 行触发点,其余为最终代码):
  退场窗口内必须真的开始收(remaining=Some(40)ms, progress=1)
This commit is contained in:
AskaEth committed 2026-11-13 13:50:41 +08:00
1 parent aa25583806
commit 3b4f8bb997
6 files changed
+190 -58

No files matched your search

+9 -2
View File
@@ -241,8 +241,15 @@ impl CrashReport {
/// 「别人的报告」而**静默不弹**。归因必须由调用方给(只有它知道是哪一场),本函数只负责
/// 把它原样记进报告——两边同源,守卫才可能判对。
///
/// 这种失败最常见的形态就是「找不到 crash-report」——游戏根本没被执行到,所以
/// [`Evidence`] 落到 [`Evidence::Nothing`],界面必须说「游戏还没来得及写日志」。
/// 两个用法的**证据形态不同,判据同一个**([`CrashReport::evidence`] 只看有没有
/// crash-report / 有没有捕获输出,**不**看 `stage`):
///
/// | 用法 | 常见形态 | 界面该说什么 |
/// |---|---|---|
/// | `session: None`(装配 / spawn 失败) | 「找不到 crash-report」,游戏根本没被执行到 ⇒ [`Evidence::Nothing`] | 「游戏还没来得及写日志」 |
/// | `session: Some`(收尾失败) | 进程起来过、事件流有落点,只是拿不到 `SessionHandle` | 按真实证据说(多半有捕获输出) |
///
/// 别把这张表读成「本函数只描述没起来的那种」——M298 r0 的注释正是这么写的,复审 N3 抓到。
#[must_use]
pub fn before_start(
ctx: &ReportContext,