1use crate::flow::{Actor, Builtin, Check};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum WorkerRole {
22 Stage,
24 PanelReviewer,
27}
28
29pub fn definition_of_done(role: WorkerRole, check: &Check) -> Vec<String> {
35 let obligation = match (role, check) {
36 (WorkerRole::PanelReviewer, _) => {
37 "This stage passes only on your reported verdict; the work under review is not yours to change"
38 }
39 (WorkerRole::Stage, Check::Reported) => {
40 "This stage passes only on your reported verdict; nothing else you do can pass it"
41 }
42 (WorkerRole::Stage, Check::Actor(Actor::Builtin(Builtin::Commits))) => {
43 "Commit your work to the run branch"
44 }
45 (WorkerRole::Stage, Check::None) => {
46 "This stage passes on your own exit status: exit 0 only if the work succeeded"
47 }
48 (WorkerRole::Stage, Check::Actor(_) | Check::Panel(_)) => {
49 "An independent check judges this stage's work after you exit"
50 }
51 };
52 vec![obligation.to_owned()]
53}
54
55pub fn check_label(check: &Check) -> &'static str {
60 match check {
61 Check::None => "none",
62 Check::Reported => "reported",
63 Check::Panel(_) => "panel",
64 Check::Actor(Actor::Agent) => "agent",
65 Check::Actor(Actor::Exec { .. }) => "exec",
66 Check::Actor(Actor::Builtin(Builtin::Commits)) => "commits",
67 Check::Actor(Actor::Builtin(Builtin::Merge)) => "merge",
68 Check::Actor(Actor::Builtin(Builtin::Sync)) => "sync",
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use crate::flow::{Actor, Builtin, Check, Panel, Reviewer};
75
76 use super::{WorkerRole, check_label, definition_of_done};
77
78 fn panel() -> Panel {
79 Panel {
80 prompt: "prompts/panel.md".into(),
81 reviewers: vec![Reviewer {
82 target: "alpha".into(),
83 model: None,
84 effort: None,
85 }],
86 quorum: 1,
87 }
88 }
89
90 fn every_check() -> Vec<Check> {
93 vec![
94 Check::None,
95 Check::Reported,
96 Check::Actor(Actor::Agent),
97 Check::Actor(Actor::Exec {
98 cmd: vec!["cargo".into(), "test".into()],
99 }),
100 Check::Actor(Actor::Builtin(Builtin::Commits)),
101 Check::Actor(Actor::Builtin(Builtin::Merge)),
102 Check::Actor(Actor::Builtin(Builtin::Sync)),
103 Check::Panel(panel()),
104 ]
105 }
106
107 #[test]
113 fn only_a_commits_checked_stage_worker_is_told_to_commit() {
114 for role in [WorkerRole::Stage, WorkerRole::PanelReviewer] {
115 for check in every_check() {
116 let text = definition_of_done(role, &check).join("\n").to_lowercase();
117 let expected = role == WorkerRole::Stage
118 && check == Check::Actor(Actor::Builtin(Builtin::Commits));
119 assert_eq!(
120 text.contains("commit"),
121 expected,
122 "role {role:?} with check {check:?} said: {text}"
123 );
124 }
125 }
126 }
127
128 #[test]
131 fn every_role_and_check_states_exactly_one_obligation() {
132 for role in [WorkerRole::Stage, WorkerRole::PanelReviewer] {
133 for check in every_check() {
134 let obligation = definition_of_done(role, &check);
135 assert_eq!(obligation.len(), 1, "{role:?} / {check:?}");
136 assert!(!obligation[0].trim().is_empty(), "{role:?} / {check:?}");
137 }
138 }
139 }
140
141 #[test]
144 fn the_builders_definition_of_done_is_unchanged() {
145 assert_eq!(
146 definition_of_done(
147 WorkerRole::Stage,
148 &Check::Actor(Actor::Builtin(Builtin::Commits))
149 ),
150 vec!["Commit your work to the run branch".to_owned()]
151 );
152 }
153
154 #[test]
157 fn a_reported_stage_turns_only_on_the_verdict() {
158 for role in [WorkerRole::Stage, WorkerRole::PanelReviewer] {
159 let text = definition_of_done(role, &Check::Reported).join("\n");
160 assert!(text.contains("reported verdict"), "{role:?}: {text}");
161 }
162 }
163
164 #[test]
167 fn the_check_label_names_the_kind_and_not_the_command() {
168 assert_eq!(check_label(&Check::None), "none");
169 assert_eq!(check_label(&Check::Reported), "reported");
170 assert_eq!(check_label(&Check::Panel(panel())), "panel");
171 assert_eq!(
172 check_label(&Check::Actor(Actor::Builtin(Builtin::Commits))),
173 "commits"
174 );
175 let exec = Check::Actor(Actor::Exec {
176 cmd: vec!["cargo".into(), "test".into()],
177 });
178 assert_eq!(check_label(&exec), "exec");
179 }
180}