# Runtime Scheduler Contract Implementation Notes
Related handle:
- `rfc-runtime-scheduler-contract`
## Current implementation posture
The scheduler contract is now implemented as an explicit projection and decision
boundary for normal runtime scheduling. `SchedulerProjection` derives scheduler
facts from durable storage and agent state, `decide_next_action` produces the
shared decision vocabulary, and `SchedulerDecisionExecutor` owns the normal
run-loop message decision before queue mutation.
The implementation is still intentionally incremental: control, bootstrap, and
shutdown remain explicit posture authorities, and the provider turn loop still
owns safe-point operator interjection. These are preserved boundaries, not open
scheduler blockers.
## Landed contract anchors
- Normal queued-message processing records a `scheduler_decision` before the
message is dequeued and moved into a run.
- Active tasks are ledger-derived from latest task records; the separate
`active_task_ids` cache has been retired.
- Task lifecycle writes use `TaskTransition` on the main command, child-agent,
worktree, task-status, and task-result paths.
- Work queue ticks use revision-based idempotency keys such as
`work_queue:queued_available:<work_item_id>:<revision>`.
- Explicit idempotency keys are checked before fallback recent-ledger duplicate
heuristics.
- Queue recovery replays `Queued` and `Dequeued` messages, but excludes
`Processed`, `Aborted`, `Interjected`, and `Dropped` messages.
- Prior tool executions remain ledger evidence and are not automatically replayed
as scheduler-owned tool calls.
- Compaction records, briefs, and checkpoint artifacts do not become scheduler
truth.
## Verification anchors
Focused verification currently lives in:
- `src/runtime/tests/scheduler.rs`
- `src/runtime/tests/task_recovery.rs`
- `src/runtime/tests/runtime_state.rs`
- `src/runtime/tests/wake_hints.rs`
- `src/runtime/continuation.rs`
- `src/runtime/memory_refresh.rs`
- `src/runtime/task_state_reducer.rs`
- `tests/fixtures/scheduler/`
Useful local checks:
```bash
cargo test scheduler --quiet
cargo test mismatched_timer_trigger_stays_liveness_only --quiet
cargo test queued_system_tick_explicit_idempotency_key_wins_over_newer_signals --quiet
cargo test operator_interjection_prompt_is_interjected_before_next_provider_round --quiet
```
## Remaining follow-up
1. Keep `ContinuationResolution` as trigger classification and
`decide_next_action` as the final model-reentry decision boundary.
2. Keep operator-interjection classification in scheduler code, while preserving
turn-loop safe-point injection until provider/tool loop ownership changes.
3. Track bootstrap, control, and shutdown posture ownership through
[Agent Lifecycle Control Posture](../rfcs/agent-lifecycle-control-posture.md).
The scheduler RFC owns runnable-agent next-action decisions; lifecycle
control owns whether the agent is runnable at all.
4. Treat recent-ledger duplicate scans as fallback evidence. Explicit
idempotency keys should remain the primary duplicate contract.