use crate::cm_agent::plan_artifact::{
PlanStepAcceptance, PlanStepExecutorKind, PlanStepV1,
plan_step_description_implies_build_execution,
};
pub const DEFAULT_COMMAND_EXIT_CODE: i32 = 0;
pub fn apply_executor_kind_acceptance_defaults(step: &mut PlanStepV1) {
if step.executor_kind != Some(PlanStepExecutorKind::TestRunner) {
return;
}
let acc = step
.acceptance
.get_or_insert_with(PlanStepAcceptance::default);
if acc.expect_exit_code.is_none() {
acc.expect_exit_code = Some(DEFAULT_COMMAND_EXIT_CODE);
}
}
pub fn effective_plan_step_acceptance(step: &PlanStepV1) -> Option<PlanStepAcceptance> {
let mut merged = step.acceptance.clone().unwrap_or_default();
if step.executor_kind == Some(PlanStepExecutorKind::TestRunner)
&& merged.expect_exit_code.is_none()
{
merged.expect_exit_code = Some(DEFAULT_COMMAND_EXIT_CODE);
}
if merged.is_effective() {
Some(merged)
} else {
None
}
}
pub fn default_exit_code_for_build_execution_description(desc: &str) -> Option<i32> {
if plan_step_description_implies_build_execution(desc) {
Some(DEFAULT_COMMAND_EXIT_CODE)
} else {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cm_agent::plan_artifact::PlanStepV1;
#[test]
fn test_runner_gets_default_exit_code_when_acceptance_missing() {
let mut step = PlanStepV1 {
id: "t".into(),
description: "cargo test".into(),
workflow_node_id: None,
executor_kind: Some(PlanStepExecutorKind::TestRunner),
step_kind: None,
acceptance: None,
max_step_retries: None,
transitions: None,
};
apply_executor_kind_acceptance_defaults(&mut step);
let acc = step.acceptance.expect("injected");
assert_eq!(acc.expect_exit_code, Some(0));
}
#[test]
fn effective_plan_step_acceptance_merges_without_mutation() {
let step = PlanStepV1 {
id: "t".into(),
description: "run tests".into(),
workflow_node_id: None,
executor_kind: Some(PlanStepExecutorKind::TestRunner),
step_kind: None,
acceptance: None,
max_step_retries: None,
transitions: None,
};
let eff = effective_plan_step_acceptance(&step).expect("effective");
assert_eq!(eff.expect_exit_code, Some(0));
assert!(step.acceptance.is_none());
}
#[test]
fn review_readonly_without_acceptance_stays_none() {
let step = PlanStepV1 {
id: "r".into(),
description: "read docs".into(),
workflow_node_id: None,
executor_kind: Some(PlanStepExecutorKind::ReviewReadonly),
step_kind: None,
acceptance: None,
max_step_retries: None,
transitions: None,
};
assert!(effective_plan_step_acceptance(&step).is_none());
}
#[test]
fn build_description_default_exit_code() {
assert_eq!(
default_exit_code_for_build_execution_description("在本工作区运行 cargo build"),
Some(0)
);
assert!(default_exit_code_for_build_execution_description("阅读 README").is_none());
}
}