git:20260923.4575b13 to git:20260928.0bc633c

4 added, 6 removed. Audit A to A.

# Scheduler Module Rules
## 范围与职责
适用于 `src/host/scheduler/`。
按用户配置的**执行窗口**与**触发策略**,驱动既有编排运行时运行所选工作流模板的实例:
- 任务配置的校验、规范化与持久化;
- 时间语义:时区换算、触发点推算、窗口判定;
- 决策与推进:何时触发、何时挂起、何时续跑、何时跳过;
- 触发时的实例化语义(模板 → 实例)与会话策略分派。
- 判断归属:该修改是否改变**定时任务的配置契约、时间语义或触发/挂起/续跑决策**?若主要属于时间基元之外的其他领域(编排推进、Agent 语义、持久化原语、UI 展示、HTTP 端点),应放到对应模块。
+ 判断归属:该修改是否改变**定时任务的配置契约、时间语义或触发/挂起/续跑决策**?若主要属于时间基元之外的其他领域,应放到对应模块。
## 时间语义契约
时间语义必须确定、可测、与时区显式绑定:
- 时间的解析/格式化/换算/推算一律为**纯函数**:相同输入 → 相同输出,不读系统时钟、不读环境时区、不依赖全局状态;需要"当前时刻"时经参数传入;
- 绝对时间在存储与比较层面统一用 UTC 毫秒;用户可见的时刻("HH:mm"、日期)一律按任务自身声明的时区解释——**禁止**使用进程本地时区或隐式时区;
- 跨天区间(结束不晚于开始)必须与跨天触发点、跨日期窗口扫描的语义一致,不得各处自行解释;
- 调度语义分两层且语义固定:「执行窗口」决定何时允许运行,「触发策略」决定何时应当触发;**触发成立的条件是两层同时满足**。
## 子域边界
模块内部存在变化原因不同的子域:
- 子域之间只通过明确的输入输出协作,不得互相承担对方职责;
- 时间基元不理解"任务";窗口判定与触发计算不理解持久化;配置契约不读盘、不决策;决策引擎不重复实现时间算法;
- 新增能力先判断属于哪个子域,再放到该子域的职责中,不得为就近而堆进已有位置。
## 依赖边界
- 只允许依赖共享契约层(任务实体与窗口/触发配置的形状)与本模块内部;
- - 对外部能力的依赖必须是抽象缝(接口 + 注入),方向单向:调用方依赖本模块的决策,本模块不反向依赖任何调用方。
+ - 对外部能力的依赖必须是抽象缝(接口 + 注入)。
## 验证补充
- 时间相关断言全部使用**固定日期与时区**,不依赖运行机器的本地时区与当前时间;
- 窗口边界、跨天区间、跨日期扫描、无解配置(永不触发)等边界行为均有测试锁定;
- - 决策路径的关键分支(触发 / 触发失败 / 并发跳过 / 窗口挂起 / 窗口续跑 / 用户接管 / 停用 / 重启游标)均有测试锁定;
+ - 决策路径的关键分支均有测试锁定;
- 重叠扫描、重复启动、终止后再启动等并发与生命周期行为有测试锁定;
## 核心原则
1. 时间语义确定且时区显式,纯计算不读时钟。
2. 窗口与触发两层语义固定,缺一不触发。
3. 收敛、校验、规范化各有唯一实现且顺序固定。
- 4. 任务文件单一写者;持久化复用 storage 原子原语,不自建协议。
- 5. 扫描可重入安全,终止后不复活。
- 6. 外部能力经显式依赖缝注入。
+ 4. 扫描可重入安全,终止后不复活。