> 来源:2026-11-11 全矩阵深度代码审查(6 路并行扫描约 24 万行 Go)。判定已复核;行号基于 2026-11-11 的 main,动手前请核对现场。 > 归档索引:oekit/pkg#372(本仓重构 backlog) ## 位置 pkg/timex/cron/cron.go:517-519(对照 :142-149、:157-166,已人工复核) ## 证据 ```go func (w WrapSchedule) Next(t time.Time) time.Time { return w.Schedule.Next(t).Add(w.Delay) // 零值也 Add } ``` SpecSchedule.Next 契约明文「返回值保证严格晚于入参(除非返回零值 time.Time 表示放弃)」,并警告「调用方消费 Next 前应判 IsZero」;但包装器对零值直接 Add——`time.Time{}.Add(delay)` 是公元 1 年 + delay 的**非零**具体时刻。`0 0 31 2 *`(2 月永无 31 日,#185 记录的形态)包一层 WrapSchedule 后:消费方 IsZero 判定失效,time.Until 为极大负值 → 立即触发、prev 停在远古 → SpecSchedule.next 再从远古扫 5 年 → 调度器热转。哨兵语义只覆盖了内层,组合子把它漏掉了。 ## 建议 WrapSchedule.Next 对 `next.IsZero()` 短路直返零值(哨兵穿透包装器);同检 DelaySchedule/RandomDelaySchedule 是否需要同样约定并在 Next 的 godoc 写明零值穿透契约,用例钉住「不可满足 spec + Wrap → 仍返回零值」。
Activity
Merge pull request #421 from oekit/sweep/20261112-l1
zy84338719 commentedon Nov 12, 2026
已合入修复 ✅(无 SemVer 发布:本次改动不发版本)
变更内容
WrapSchedule.Next 零值哨兵穿透——不可满足表达式经包装后仍返回零值 time.Time,热循环消除
合入:PR #421(https://github.com/oekit/pkg/pull/421),merge commit
63917515,2026-11-12T17:10:03ZCI:
link✅ /Lint & Test / Test✅ /Lint & Test / Lint✅ /Zero Third-Party Deps✅