调度器

本页定义 Holon 调度器的当前契约:它消费哪些输入、如何推导调度姿态与可运行性、 以及发出哪些决策。页面同时记录附加的协议转换层:它把调度器决策包进带重放保护的 原子事务,并承担显式 activation 归属、终态结算和公开诊断事件流。

Last verified: 2026-09-13 against src/runtime/scheduler.rs, src/runtime/scheduler_executor.rs, src/runtime/waiting.rs, src/runtime/closure.rs, src/runtime/turn/execution.rs, src/runtime_db/transitions.rs, src/runtime_event.rs, and src/types.rs.

源 RFC

核心模型

调度器回答的问题是:给定 Agent 的当前状态,下一步该做什么?

它消费一个 SchedulerProjection,即由下列来源汇总而成的快照:

输入来源
Agent 状态AgentState.status
队列深度AgentState.pending
活跃任务状态非终态的 TaskRecord
当前 WorkItemcurrent_work_item_id → WorkItemRecord
可运行 WorkItemis_runnable()=true 的开放 WorkItem
等待条件活跃的 WaitConditionRecord
等待意图活跃的 WaitConditionRecord,按 Agent 和 WorkItem 范围划分
唤醒提示PendingWakeHint
轮次状态turn_in_progress、last_turn_terminal
运行时错误runtime_error_active()

投影是只读快照;调度器从不直接修改持久状态。决策发出后交给执行器。

调度器输入(SchedulerInput)

输入变体触发条件
MessageAgent 队列中到达了一条新消息
IdleSignal::WakeHint收到一个待处理的唤醒提示
IdleSignal::ContinueActive上一次轮次结束时有可运行的 WorkItem
IdleSignal::QueuedAvailable队列中的消息已可处理
Idle周期性的空闲边界检查

调度器决策(SchedulerDecisionKind)

决策含义
StartModelTurn组装上下文并开始一次新的模型轮次
ReduceMessageOnly只归约一条消息,不启动完整模型轮次
EmitSystemTick发出运行时自有的后续消息(system tick)
WaitForTask阻塞,直到某个非终态任务完成
WaitForExternalChange阻塞,直到外部事件到达
WaitForTimer阻塞,直到定时器触发
WaitForOperator阻塞,直到操作者输入到达
Sleep运行时让 Agent 进入休眠;没有立即动作
StayIdleAgent 已处于休眠;没有动作
StopAgent 已停止;无法调度
Noop没有动作(重复被抑制,或轮次进行中)

每个决策都携带元数据:reason、model_reentry、liveness_only、 work_item_id、task_id 和 evidence。

决策流程

                    SchedulerInput
                         │
                         ▼
              ┌─────────────────────┐
              │ Status == Stopped?  │──Yes──► Stop
              └─────────┬───────────┘
                        │ No
                        ▼
              ┌─────────────────────┐
              │ Turn in progress?   │──Yes──► Noop
              └─────────┬───────────┘
                        │ No
                        ▼
         ┌──────────────────────────┐
         │ Queue has pending input? │──Yes──► StartModelTurn
         └──────────────┬───────────┘        (or ReduceMessageOnly)
                        │ No
                        ▼
         ┌──────────────────────────┐
         │ Runnable WorkItem?       │──Yes──► EmitSystemTick
         └──────────────┬───────────┘        (ContinueActive)
                        │ No
                        ▼
         ┌──────────────────────────┐
         │ Active wait condition?   │──Yes──► WaitFor{Task,
         └──────────────┬───────────┘         External,Timer,Operator}
                        │ No
                        ▼
                      Sleep

WorkItem 调度状态

WorkItem 会经过调度器消费的这些调度状态:

状态含义调度器动作
Runnable可以处理可能被自动选为当前 WorkItem
WaitingOperatorplan_status=NeedsInput 或操作者等待Agent 等待操作者
Blocked设置了 blocked_by 但没有更具体的等待不可运行;存在遗留 recheck_at 时检查它
WaitingTask对任务结果的等待条件任务进入终态时唤醒
WaitingExternal对外部事件的等待条件外部触发时唤醒
WaitingTimer运行时定时器等待定时器触发时唤醒
WaitingSystem运行时 system-tick 等待发出 system tick
Completedstate=Completed从可运行集合中排除

唤醒/休眠边界

协议转换层

调度器把每个边界都包进原子的 QueueTransitionCommand 事务,该事务可以同时:

  1. 提交队列操作(admit、claim 或 enqueue);
  2. 更新 Agent 状态投影;
  3. 持久化消息证据、transcript 条目和审计事件;
  4. 绑定规范的 activation 归属方和执行处置;
  5. 持久化结算、恢复和投递证据。

所有效果在同一个 SQLite 事务中提交。事务失败或 CAS 不匹配时,不会留下任何部分的 队列、activation、结算或投递状态。

规范调度器是唯一的运行时引擎。队列、WorkItem、等待、任务、Turn、transcript、 brief、投递、activation、结算和执行事实共享同一权威和事务路径。

已接受的转换契约退役了运行时 manifest/preflight 门、逐场景权威、自动硬阻塞回滚、 生产影子比较、遗留引擎和运行时引擎选择器。历史选择器配置不再是运行时输入。

集成点

QueueTransitionCommand 在每个调度器边界提交。每个边界都记录下一个边界所需的 规范事实:

边界操作必需的规范证据
消息准入(scheduler_executor::prepare_message)Claim输入身份、activation 归属方、处置、权威围栏
等待恢复Claim精确的 wait id 和 generation、消费 activation
结算(runtime::commit_queue_settlement)Settle匹配的 activation、终态 Turn、WorkItem 处置
投递处置Settle绑定结算的 brief 或投递证据
操作者插话Interject运行中的 activation 和安全点身份
工作队列空闲 tick(scheduler_continuation::emit_system_tick_from_work_queue)Admit可运行 WorkItem 的身份、generation 和源修订

语义决策平面不属于生产准入。它的生产模块和 fixture 已被移除。确定性的结构绑定和 规范协议保留了全部状态转换控制。

公开诊断事件流

调度器为每个经过 append_scheduler_decision 的决策发出一个类型化的 SchedulerDiagnosticAuditEvent。该事件携带:

字段内容
decisionSchedulerDecisionKind 变体
reason人类可读的决策原因
boundary做出决策的位置(例如 run_loop、after_provider_round)
work_item_id与该决策关联的可选 WorkItem
message_id触发该决策的可选消息
task_id与该决策关联的可选任务
evidence决策使用的证据字符串
scenario_class可选的场景分类(例如 operator_interjection)

事件通过 RuntimeEventKind::SchedulerDiagnostic 发出,与遗留的 scheduler_decision 审计事件并列。两者与调度器决策在同一事务中持久化。 类型化事件是公开的可观测面;遗留审计事件保留用于向后兼容。

调度建议

SchedulingAdvisory 是内部的、非权威的告警系统,用于发现潜在的调度器状态不一致: 空闲姿态下存在可运行工作、外部等待恢复能力薄弱、不可恢复的阻塞 WorkItem 等。 建议以 scheduling_advisory 审计事件追加,并与近期事件去重。

建议不是诊断事件流意义上的诊断。它们是供调试和运维感知使用的内部提示; 确定性的调度器投影和姿态推导仍是调度决策的唯一权威。

已知缺口