use crate::flow::{Actor, Builtin, Check};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WorkerRole {
Stage,
PanelReviewer,
}
pub fn definition_of_done(role: WorkerRole, check: &Check) -> Vec<String> {
let obligation = match (role, check) {
(WorkerRole::PanelReviewer, _) => {
"This stage passes only on your reported verdict; the work under review is not yours to change"
}
(WorkerRole::Stage, Check::Reported) => {
"This stage passes only on your reported verdict; nothing else you do can pass it"
}
(WorkerRole::Stage, Check::Actor(Actor::Builtin(Builtin::Commits))) => {
"Commit your work to the run branch"
}
(WorkerRole::Stage, Check::None) => {
"This stage passes on your own exit status: exit 0 only if the work succeeded"
}
(WorkerRole::Stage, Check::Actor(_) | Check::Panel(_)) => {
"An independent check judges this stage's work after you exit"
}
};
vec![obligation.to_owned()]
}
pub fn check_label(check: &Check) -> &'static str {
match check {
Check::None => "none",
Check::Reported => "reported",
Check::Panel(_) => "panel",
Check::Actor(Actor::Agent) => "agent",
Check::Actor(Actor::Exec { .. }) => "exec",
Check::Actor(Actor::Builtin(Builtin::Commits)) => "commits",
Check::Actor(Actor::Builtin(Builtin::Merge)) => "merge",
Check::Actor(Actor::Builtin(Builtin::Sync)) => "sync",
}
}
#[cfg(test)]
mod tests {
use crate::flow::{Actor, Builtin, Check, Panel, Reviewer};
use super::{WorkerRole, check_label, definition_of_done};
fn panel() -> Panel {
Panel {
prompt: "prompts/panel.md".into(),
reviewers: vec![Reviewer {
target: "alpha".into(),
model: None,
effort: None,
}],
quorum: 1,
}
}
fn every_check() -> Vec<Check> {
vec![
Check::None,
Check::Reported,
Check::Actor(Actor::Agent),
Check::Actor(Actor::Exec {
cmd: vec!["cargo".into(), "test".into()],
}),
Check::Actor(Actor::Builtin(Builtin::Commits)),
Check::Actor(Actor::Builtin(Builtin::Merge)),
Check::Actor(Actor::Builtin(Builtin::Sync)),
Check::Panel(panel()),
]
}
#[test]
fn only_a_commits_checked_stage_worker_is_told_to_commit() {
for role in [WorkerRole::Stage, WorkerRole::PanelReviewer] {
for check in every_check() {
let text = definition_of_done(role, &check).join("\n").to_lowercase();
let expected = role == WorkerRole::Stage
&& check == Check::Actor(Actor::Builtin(Builtin::Commits));
assert_eq!(
text.contains("commit"),
expected,
"role {role:?} with check {check:?} said: {text}"
);
}
}
}
#[test]
fn every_role_and_check_states_exactly_one_obligation() {
for role in [WorkerRole::Stage, WorkerRole::PanelReviewer] {
for check in every_check() {
let obligation = definition_of_done(role, &check);
assert_eq!(obligation.len(), 1, "{role:?} / {check:?}");
assert!(!obligation[0].trim().is_empty(), "{role:?} / {check:?}");
}
}
}
#[test]
fn the_builders_definition_of_done_is_unchanged() {
assert_eq!(
definition_of_done(
WorkerRole::Stage,
&Check::Actor(Actor::Builtin(Builtin::Commits))
),
vec!["Commit your work to the run branch".to_owned()]
);
}
#[test]
fn a_reported_stage_turns_only_on_the_verdict() {
for role in [WorkerRole::Stage, WorkerRole::PanelReviewer] {
let text = definition_of_done(role, &Check::Reported).join("\n");
assert!(text.contains("reported verdict"), "{role:?}: {text}");
}
}
#[test]
fn the_check_label_names_the_kind_and_not_the_command() {
assert_eq!(check_label(&Check::None), "none");
assert_eq!(check_label(&Check::Reported), "reported");
assert_eq!(check_label(&Check::Panel(panel())), "panel");
assert_eq!(
check_label(&Check::Actor(Actor::Builtin(Builtin::Commits))),
"commits"
);
let exec = Check::Actor(Actor::Exec {
cmd: vec!["cargo".into(), "test".into()],
});
assert_eq!(check_label(&exec), "exec");
}
}