schedule
Schedule
Read .noodle/mise.json, write .noodle/orders-next.json.
The loop atomically promotes orders-next.json into orders.json — never write orders.json directly.
Use noodle schema mise and noodle schema orders as the schema source of truth.
Operate fully autonomously. Never ask the user to choose or pause for confirmation.
Orders Model
Output is {orders: [...]} where each order is a pipeline of stages executed sequentially. Group related work into stages within one order rather than separate orders.
Stages
Each stage has a task_key (must match a registered task type) and runs one at a time within the order. The loop advances to the next stage when the current one completes.
A typical order pipeline: execute, then quality, then reflect — all as stages of one order.
Task Types
Read task_types from mise to discover every schedulable task type and its schedule hint. Any registered task type can be a stage within an order. Use task_key on each stage to bind it to a task type.
Execute Tasks
Schedule execute tasks from the backlog array in mise. Use the backlog item ID (as a string) as the order id.
Backlog items always have id and title. Other fields are adapter-defined and may vary. The default adapter (todos.md) provides: status, section, tags, estimate, and plan. Custom adapters may include any fields — treat unknown fields as useful context.
One plan at a time: Schedule all remaining phases of one plan at once. Pick the highest-priority plan with remaining phases and schedule an order for each unfinished phase. Don't spread work across plans — completing one plan end-to-end produces usable results faster than advancing many plans one phase each. If the current plan is blocked, idle (empty orders) rather than context-switching to a different plan.
Shared infrastructure: When multiple plans depend on common infrastructure (shared types, utilities, base packages), propose a standalone infra order that isn't tied to any single plan. Use a descriptive slug ID (e.g., "infra-shared-types", "infra-event-system") — orders don't need to match a backlog item ID. If the infra work is substantial, create a backlog item for it via the adapter (noodle adapter run backlog add), then use that item's ID as the order ID. The infra order should run before any plan that depends on it.
Items with plans: When a backlog item has a plan field (a relative path like brain/plans/29-foo/overview.md), read the plan overview and phase files to understand the work. Schedule an order for each remaining unfinished phase (each unchecked - [ ] item), in order. Populate order.plan with the plan path(s). Use extra_prompt to inject plan context: the plan overview summary, the specific phase brief, and any cross-phase dependencies. The loop executes orders sequentially, so later phases naturally wait for earlier ones to complete.
Items without plans: Assess complexity before scheduling. If the item is straightforward (single concern, clear scope, small change), schedule as a simple execute task using the backlog item's title and description as the prompt. If the item is complex (multi-file, cross-cutting, ambiguous scope, or you'd want to see an architecture sketch before coding), schedule a plan-first order: a prompt-only stage (no task_key) that invokes /plan, followed by an adversarial-review stage to challenge the plan. No quality or reflect stages — planning output is a design document, not code. Do NOT use task_key: "execute" for plan-first stages — the execute skill tells the agent to implement, which conflicts with the plan skill's "stop after planning" instruction. The plan skill will write phased plans to brain/plans/; on the next scheduling cycle, the item will have a plan field and can be scheduled normally with the standard execute → quality → reflect pipeline.
Standalone orders: Orders can have arbitrary IDs — they don't need to correspond to a backlog item. When a standalone order completes, the backlog done adapter call is a no-op (no matching item to mark done). Use standalone orders for shared infrastructure, maintenance tasks, or cross-cutting work that serves multiple backlog items.
Nothing to schedule: When no backlog items are actionable (all blocked, all in-progress, all done, etc.), still write orders-next.json with an empty orders array ({"orders":[]}). This signals to the loop that scheduling ran but found nothing — preventing hot-loop re-spawns.
Follow-Up and Standalone Stages
Each task type's schedule field describes when and how to schedule it — as a follow-up stage within an order, as a standalone order, or both. Read these hints from task_types in mise and compose orders accordingly.
Recent Events
The mise brief includes a recent_events array — lifecycle events emitted by the loop since the last schedule run. These are context for your scheduling decisions, not commands.
Internal Events
These are emitted automatically by the loop. The V2 backend uses canonical event types:
| Event type | Meaning |
|---|---|
stage_completed |
A stage finished successfully (includes order ID, stage index) |
stage_failed |
A stage failed (includes reason) |
order_completed |
All stages in an order finished — the order is done |
order_failed |
An order failed terminally |
merge_failed |
A merge failed (includes error reason) |
order.dropped |
An order was removed because its task type is no longer registered |
order.requeued |
A failed order was reset and re-queued for another attempt |
registry.rebuilt |
The skill registry was rebuilt (skills added or removed) |
External Events
Users can inject custom events via noodle event emit <type> [payload]. These have arbitrary types like ci.failed, deploy.completed, test.flaky, etc. You won't know every possible type — interpret them from context and the summary string.
Using Events for Scheduling
Events are context, not commands. Consider them alongside backlog state and session history when deciding what to schedule:
- After
stage.failedororder.failed— consider whether the failure needs a debugging order, or if the item should be retried with a different approach. - After
order.completed— consider follow-up work (reflect, related items that were blocked). - After
merge.conflict— the affected order may need manual attention; avoid re-scheduling it immediately. - After external events like
ci.failed— consider scheduling an investigation or fix order if it seems actionable. - After
registry.rebuilt— new task types may be available; checktask_typesfor scheduling opportunities.
Don't react mechanically to every event. Use judgment: a single stage failure in a long pipeline is normal; three consecutive failures of the same order suggests a deeper problem.
Situational Awareness
| Trigger | Action |
|---|---|
| Empty orders | Full survey of mise — schedule from scratch |
| Quality rejection | Rescope the rejected item for retry with feedback |
| New backlog items | Create orders respecting workflow stage order |
| Items without plans | Assess complexity — simple items execute directly, complex items get a plan-first order |
| All items blocked/done | Write empty orders array, let loop cooldown |
Scheduling Heuristics
- One plan at a time: Schedule all remaining phases of one plan upfront. Don't spread work across plans — depth-first produces complete, shippable results. The loop executes orders sequentially, so all phases run in order. Exception: shared infra orders can run alongside or before a plan's phases.
- Foundation before feature: Infrastructure and shared types first.
- Cheapest mode: Prefer the lowest-cost provider/model that can handle the task.
- Explicit rationale: Every order must cite which principle or rule drove its placement.
- Timebox failures: If an item has failed 2+ times in
recent_history, deschedule or split it.
Stage Lifecycle
Write stages with "status": "pending". The loop manages all subsequent transitions (dispatching, running, merging, review, completed/failed).
Model Routing
| Task type | Provider | Model |
|---|---|---|
| Tiny/small tasks (no deep thinking needed) | codex | gpt-5.3-codex-spark |
| Tiny/small tasks (no deep thinking needed) | claude | claude-sonnet-4-6 |
| Implementation, execution, coding | codex | gpt-5.3-codex |
| Judgment, strategy, planning, review | claude | claude-opus-4-6 |
Use spark or sonnet for small, mechanical tasks (simple renames, one-liner fixes, straightforward additions). Use full codex for anything requiring multi-step reasoning or cross-file coordination. When uncertain, codex for implementation, opus for judgment.
Runtime Routing
Always set "runtime": "process" on all stages. The sprites runtime is still WIP and should not be used yet. Always include "runtime" on scheduled stages so dispatch routing is explicit.
Output
Write valid JSON to .noodle/orders-next.json matching noodle schema orders.
extra_prompt
Each stage supports an optional extra_prompt string — supplemental instructions about how to approach the task. Distinct from prompt (what to do) and rationale (why it's scheduled).
Use cases:
- Relay failure context from
recent_history(e.g., "previous attempt failed because tests weren't run — run tests this time") - Flag dependencies or preconditions the cook should be aware of
- Suggest approach constraints based on scheduling context
Keep it concise (~1000 chars max; silently truncated if exceeded). Leave empty when there's nothing extra to say — don't fill it for the sake of filling it. The field lives on each stage, not at the order level.
Examples
See references/examples.md for order JSON examples: multi-stage, plan-first, debate, shared infrastructure, single-stage.
Principles
- [[cost-aware-delegation]]
- [[foundational-thinking]]
- [[subtract-before-you-add]]
- [[never-block-on-the-human]]
- [[guard-the-context-window]]