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