Skip to main content

ralph/commands/run/run_one/
mod.rs

1//! Run-one orchestration entrypoints.
2//!
3//! Responsibilities:
4//! - Provide public entrypoints (`run_one*`) used by the CLI and interactive flows.
5//! - Own lock-acquisition policy for run-one execution.
6//!
7//! Not handled here:
8//! - Run loop orchestration (see `run_loop`).
9//! - Queue selection helper primitives (see `selection`).
10//! - Phase execution details (see `phases`).
11//!
12//! Invariants/assumptions:
13//! - `run_one_with_id_locked` is called only when the queue lock is already held by the caller.
14//! - Parallel-worker mode resolves queue/done from worker workspace paths.
15
16use crate::agent::AgentOverrides;
17use crate::config;
18use crate::runner;
19use crate::runutil;
20use anyhow::Result;
21
22mod completion;
23mod context;
24mod execution_setup;
25mod orchestration;
26mod phase_execution;
27mod selection;
28mod webhooks;
29
30#[derive(Clone, Copy, Debug, Eq, PartialEq)]
31pub enum QueueLockMode {
32    Acquire,
33    Held,
34    /// Acquire the queue lock but allow creating upstream branches (used by parallel workers).
35    /// This combines the safety of lock acquisition with the push policy of Skip mode.
36    AcquireAllowUpstream,
37}
38
39/// Outcome of a single task run.
40#[derive(Debug)]
41pub enum RunOutcome {
42    /// No Todo (and no Draft if include_draft is false).
43    NoCandidates,
44    /// Candidates exist, but none are currently runnable (deps/schedule/status flags).
45    Blocked {
46        summary: crate::queue::operations::QueueRunnabilitySummary,
47    },
48    Ran {
49        task_id: String,
50    },
51}
52
53/// Run a specific task by ID.
54pub fn run_one_with_id(
55    resolved: &config::Resolved,
56    agent_overrides: &AgentOverrides,
57    force: bool,
58    task_id: &str,
59    output_handler: Option<runner::OutputHandler>,
60    revert_prompt: Option<runutil::RevertPromptHandler>,
61) -> Result<()> {
62    orchestration::run_one_impl(
63        resolved,
64        agent_overrides,
65        force,
66        QueueLockMode::Acquire,
67        Some(task_id),
68        None,
69        output_handler,
70        revert_prompt,
71        None,
72    )
73    .map(|_| ())
74}
75
76/// Run a specific task as a parallel worker (acquires queue lock, allows upstream creation).
77pub fn run_one_parallel_worker(
78    resolved: &config::Resolved,
79    agent_overrides: &AgentOverrides,
80    force: bool,
81    task_id: &str,
82    target_branch: &str,
83) -> Result<()> {
84    orchestration::run_one_impl(
85        resolved,
86        agent_overrides,
87        force,
88        QueueLockMode::AcquireAllowUpstream,
89        Some(task_id),
90        None,
91        None,
92        None,
93        Some(target_branch),
94    )
95    .map(|_| ())
96}
97
98/// Run a specific task when the queue lock is already held by the caller.
99pub fn run_one_with_id_locked(
100    resolved: &config::Resolved,
101    agent_overrides: &AgentOverrides,
102    force: bool,
103    task_id: &str,
104    output_handler: Option<runner::OutputHandler>,
105    revert_prompt: Option<runutil::RevertPromptHandler>,
106) -> Result<()> {
107    orchestration::run_one_impl(
108        resolved,
109        agent_overrides,
110        force,
111        QueueLockMode::Held,
112        Some(task_id),
113        None,
114        output_handler,
115        revert_prompt,
116        None,
117    )
118    .map(|_| ())
119}
120
121/// Run the first available todo task.
122pub fn run_one(
123    resolved: &config::Resolved,
124    agent_overrides: &AgentOverrides,
125    force: bool,
126    resume_task_id: Option<&str>,
127) -> Result<RunOutcome> {
128    orchestration::run_one_impl(
129        resolved,
130        agent_overrides,
131        force,
132        QueueLockMode::Acquire,
133        None,
134        resume_task_id,
135        None,
136        None,
137        None,
138    )
139}