Skip to main content

codetether_agent/github_pr/
autopilot.rs

1//! PR Auto-Pilot — submit, watch CI, fix failures, respond to reviews.
2
3use serde::{Deserialize, Serialize};
4
5/// Lifecycle states for an auto-pilot PR.
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
7#[serde(rename_all = "snake_case")]
8pub enum PrLifecycle {
9    Draft,
10    CiRunning,
11    CiFailed,
12    Fixing,
13    CiGreen,
14    AwaitingReview,
15    ReviewCommentsReceived,
16    AddressingComments,
17    ReadyToMerge,
18    Merged,
19    Failedterminal,
20}
21
22/// Configuration for a PR auto-pilot run.
23#[derive(Debug, Clone)]
24pub struct AutopilotConfig {
25    pub issue_number: Option<u64>,
26    pub branch_prefix: String,
27    pub max_fix_iterations: usize,
28    pub poll_interval_secs: u64,
29    pub auto_merge: bool,
30}
31
32impl Default for AutopilotConfig {
33    fn default() -> Self {
34        Self {
35            issue_number: None,
36            branch_prefix: "autopilot".to_string(),
37            max_fix_iterations: 5,
38            poll_interval_secs: 30,
39            auto_merge: false,
40        }
41    }
42}
43
44/// One tick of the auto-pilot state machine.
45pub fn advance_lifecycle(
46    current: &PrLifecycle,
47    ci_green: bool,
48    has_review_comments: bool,
49) -> PrLifecycle {
50    match current {
51        PrLifecycle::Draft => PrLifecycle::CiRunning,
52        PrLifecycle::CiRunning if ci_green => PrLifecycle::CiGreen,
53        PrLifecycle::CiRunning => PrLifecycle::CiFailed,
54        PrLifecycle::CiFailed => PrLifecycle::Fixing,
55        PrLifecycle::Fixing => PrLifecycle::CiRunning,
56        PrLifecycle::CiGreen if has_review_comments => PrLifecycle::ReviewCommentsReceived,
57        PrLifecycle::CiGreen => PrLifecycle::AwaitingReview,
58        PrLifecycle::ReviewCommentsReceived => PrLifecycle::AddressingComments,
59        PrLifecycle::AddressingComments => PrLifecycle::CiRunning,
60        PrLifecycle::AwaitingReview if has_review_comments => PrLifecycle::ReviewCommentsReceived,
61        PrLifecycle::AwaitingReview => PrLifecycle::ReadyToMerge,
62        other => other.clone(),
63    }
64}