use super::Attempt;
use crate::workdiff::Change;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Intent {
Judge,
Synthesize,
Deliver { handle: String },
Retire { handle: String },
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Draft {
pub text: String,
pub new_conversation: bool,
}
pub fn draft(intent: &Intent, rows: &[Attempt]) -> Option<Draft> {
match intent {
Intent::Judge => goal(rows, JUDGE),
Intent::Synthesize => goal(rows, SYNTHESIZE),
Intent::Deliver { handle } => Some(Draft {
text: format!("/deliver {handle} "),
new_conversation: false,
}),
Intent::Retire { handle } => Some(Draft {
text: format!("/retire {handle}"),
new_conversation: false,
}),
}
}
const JUDGE: &str = "Judge the candidate attempts below. Each is one isolated attempt branch in \
the project repository, all forked from the same base toward the same \
target. Read each candidate at its exact commit and reply with a verdict \
per candidate: approve or reject, and why. Do not merge or deliver \
anything.";
const SYNTHESIZE: &str = "Synthesize one result from the candidate attempts below. Each is one \
isolated attempt branch in the project repository, all forked from the \
same base toward the same target. Take the best of each; your own work is \
an ordinary attempt on that same target.";
fn goal(rows: &[Attempt], ask: &str) -> Option<Draft> {
let candidates: Vec<&Attempt> = rows
.iter()
.filter(|row| row.diff.handle.is_some())
.collect();
let cited: Vec<String> = candidates.iter().filter_map(|row| cite(row)).collect();
let (project, ball, target, target_oid) =
candidates.iter().find_map(|row| match &row.diff.change {
Change::Diff {
target, target_oid, ..
} => Some((&row.diff.project, &row.diff.ball_id, target, target_oid)),
_ => None,
})?;
(!cited.is_empty()).then(|| Draft {
text: format!(
"{ask}\n\nProject {project}, ball {ball}, target {target} at {target_oid}.\n{}",
cited.join("\n")
),
new_conversation: true,
})
}
fn cite(row: &Attempt) -> Option<String> {
let handle = row.diff.handle.as_ref()?;
let Change::Diff {
source, source_oid, ..
} = &row.diff.change
else {
return None;
};
let base = row.base.as_deref().unwrap_or("unknown");
Some(format!(
"- candidate {handle}: branch {source} at {source_oid}, forked from base {base}"
))
}