use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct WorktreeState {
pub session_id: String,
pub worktree_name: String,
pub branch: String,
#[serde(default)]
pub original_branch: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub status: WorktreeStatus,
pub iterations: IterationInfo,
pub stats: WorktreeStats,
pub merged: bool,
pub merged_at: Option<DateTime<Utc>>,
pub error: Option<String>,
pub merge_prompt_shown: bool,
pub merge_prompt_response: Option<String>,
pub interrupted_at: Option<DateTime<Utc>>,
pub interruption_type: Option<InterruptionType>,
pub last_checkpoint: Option<Checkpoint>,
pub resumable: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum WorktreeStatus {
InProgress,
Completed,
Merged,
CleanedUp,
Failed,
Abandoned,
Interrupted,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct IterationInfo {
pub completed: u32,
pub max: u32,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct WorktreeStats {
pub files_changed: u32,
pub commits: u32,
pub last_commit_sha: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum InterruptionType {
UserInterrupt, Termination, ProcessKill, Unknown,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Checkpoint {
pub iteration: u32,
pub timestamp: DateTime<Utc>,
pub last_command: String,
pub last_command_type: CommandType,
pub last_spec_id: Option<String>,
pub files_modified: Vec<String>,
pub command_output: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum CommandType {
CodeReview,
ImplementSpec,
Lint,
Custom(String),
}
impl WorktreeState {
pub fn validate_initial_state(&self, session_name: &str, branch: &str) -> bool {
self.session_id == session_name
&& self.worktree_name == session_name
&& self.branch == branch
&& matches!(self.status, WorktreeStatus::InProgress)
&& self.iterations.completed == 0
&& self.iterations.max == 10
&& !self.merged
&& self.merged_at.is_none()
&& self.error.is_none()
}
}