use crate::agents::AgentRole;
use crate::reducer::effect::Effect;
use crate::reducer::event::PipelineEvent;
use crate::reducer::event::PipelinePhase;
use crate::reducer::orchestration::determine_next_effect;
use crate::reducer::state::PipelineState;
fn initial_with_locked_permissions(dev_iters: u32, review_passes: u32) -> PipelineState {
PipelineState {
prompt_permissions: crate::reducer::state::PromptPermissionsState {
locked: true,
restore_needed: true,
..Default::default()
},
..PipelineState::initial(dev_iters, review_passes)
}
}
#[test]
fn test_review_with_issues_emits_prepare_fix_prompt() {
let state = PipelineState {
phase: PipelinePhase::Review,
reviewer_pass: 0,
total_reviewer_passes: 1,
review_issues_found: true,
agent_chain: PipelineState::initial(1, 1)
.agent_chain
.with_agents(vec!["mock".to_string()], vec![vec![]], AgentRole::Reviewer)
.with_drain(crate::agents::AgentDrain::Fix),
..initial_with_locked_permissions(1, 1)
};
let effect = determine_next_effect(&state);
assert!(matches!(effect, Effect::PrepareFixPrompt { pass: 0, .. }));
}
#[test]
fn test_fix_chain_emits_cleanup_fix_result_xml_after_fix_prompt_prepared() {
let state = PipelineState {
phase: PipelinePhase::Review,
reviewer_pass: 0,
total_reviewer_passes: 1,
review_issues_found: true,
fix_prompt_prepared_pass: Some(0),
agent_chain: PipelineState::initial(1, 1)
.agent_chain
.with_agents(vec!["mock".to_string()], vec![vec![]], AgentRole::Reviewer)
.with_drain(crate::agents::AgentDrain::Fix),
..initial_with_locked_permissions(1, 1)
};
let effect = determine_next_effect(&state);
assert!(
matches!(effect, Effect::CleanupRequiredFiles { ref files } if files.iter().any(|f| f.contains("fix_result.xml")))
);
}
#[test]
fn test_fix_chain_emits_extract_fix_result_xml_after_fix_agent_invoked() {
let state = PipelineState {
phase: PipelinePhase::Review,
reviewer_pass: 0,
total_reviewer_passes: 1,
review_issues_found: true,
fix_prompt_prepared_pass: Some(0),
fix_required_files_cleaned_pass: Some(0),
fix_agent_invoked_pass: Some(0),
fix_analysis_agent_invoked_pass: Some(0),
agent_chain: PipelineState::initial(1, 1)
.agent_chain
.with_agents(vec!["mock".to_string()], vec![vec![]], AgentRole::Reviewer)
.with_drain(crate::agents::AgentDrain::Analysis),
..initial_with_locked_permissions(1, 1)
};
let effect = determine_next_effect(&state);
assert!(matches!(effect, Effect::ExtractFixResultXml { pass: 0 }));
}
#[test]
fn test_fix_chain_emits_validate_fix_result_xml_after_extracted() {
let state = PipelineState {
phase: PipelinePhase::Review,
reviewer_pass: 0,
total_reviewer_passes: 1,
review_issues_found: true,
fix_prompt_prepared_pass: Some(0),
fix_required_files_cleaned_pass: Some(0),
fix_agent_invoked_pass: Some(0),
fix_analysis_agent_invoked_pass: Some(0),
fix_result_xml_extracted_pass: Some(0),
agent_chain: PipelineState::initial(1, 1)
.agent_chain
.with_agents(vec!["mock".to_string()], vec![vec![]], AgentRole::Reviewer)
.with_drain(crate::agents::AgentDrain::Analysis),
..initial_with_locked_permissions(1, 1)
};
let effect = determine_next_effect(&state);
assert!(matches!(effect, Effect::ValidateFixResultXml { pass: 0 }));
}
#[test]
fn test_fix_chain_applies_all_issues_addressed_to_fix_attempt_completed() {
let state = PipelineState {
phase: PipelinePhase::Review,
reviewer_pass: 0,
total_reviewer_passes: 1,
review_issues_found: true,
fix_prompt_prepared_pass: Some(0),
fix_required_files_cleaned_pass: Some(0),
fix_agent_invoked_pass: Some(0),
fix_analysis_agent_invoked_pass: Some(0),
fix_result_xml_extracted_pass: Some(0),
fix_validated_outcome: Some(crate::reducer::state::FixValidatedOutcome {
pass: 0,
status: crate::reducer::state::FixStatus::AllIssuesAddressed,
summary: Some("ok".to_string()),
}),
fix_result_xml_archived_pass: Some(0),
agent_chain: PipelineState::initial(1, 1)
.agent_chain
.with_agents(vec!["mock".to_string()], vec![vec![]], AgentRole::Reviewer)
.with_drain(crate::agents::AgentDrain::Analysis),
..initial_with_locked_permissions(1, 1)
};
assert!(matches!(
determine_next_effect(&state),
Effect::ApplyFixOutcome { pass: 0 }
));
let handler_event = crate::reducer::mock_effect_handler::MockEffectHandler::new(state)
.execute_mock(&Effect::ApplyFixOutcome { pass: 0 })
.event;
assert!(matches!(
handler_event,
PipelineEvent::Review(crate::reducer::event::ReviewEvent::FixOutcomeApplied { pass: 0 })
));
}
#[test]
fn test_fix_chain_emits_archive_fix_result_xml_after_validated() {
let state = PipelineState {
phase: PipelinePhase::Review,
reviewer_pass: 0,
total_reviewer_passes: 1,
review_issues_found: true,
fix_prompt_prepared_pass: Some(0),
fix_required_files_cleaned_pass: Some(0),
fix_agent_invoked_pass: Some(0),
fix_analysis_agent_invoked_pass: Some(0),
fix_result_xml_extracted_pass: Some(0),
fix_validated_outcome: Some(crate::reducer::state::FixValidatedOutcome {
pass: 0,
status: crate::reducer::state::FixStatus::AllIssuesAddressed,
summary: None,
}),
agent_chain: PipelineState::initial(1, 1)
.agent_chain
.with_agents(vec!["mock".to_string()], vec![vec![]], AgentRole::Reviewer)
.with_drain(crate::agents::AgentDrain::Analysis),
..initial_with_locked_permissions(1, 1)
};
let effect = determine_next_effect(&state);
assert!(matches!(effect, Effect::ArchiveFixResultXml { pass: 0 }));
}
#[test]
fn test_fix_chain_emits_apply_fix_outcome_after_fix_result_xml_archived() {
let state = PipelineState {
phase: PipelinePhase::Review,
reviewer_pass: 0,
total_reviewer_passes: 1,
review_issues_found: true,
fix_prompt_prepared_pass: Some(0),
fix_required_files_cleaned_pass: Some(0),
fix_agent_invoked_pass: Some(0),
fix_analysis_agent_invoked_pass: Some(0),
fix_result_xml_extracted_pass: Some(0),
fix_validated_outcome: Some(crate::reducer::state::FixValidatedOutcome {
pass: 0,
status: crate::reducer::state::FixStatus::AllIssuesAddressed,
summary: None,
}),
fix_result_xml_archived_pass: Some(0),
agent_chain: PipelineState::initial(1, 1)
.agent_chain
.with_agents(vec!["mock".to_string()], vec![vec![]], AgentRole::Reviewer)
.with_drain(crate::agents::AgentDrain::Analysis),
..initial_with_locked_permissions(1, 1)
};
let effect = determine_next_effect(&state);
assert!(matches!(effect, Effect::ApplyFixOutcome { pass: 0 }));
}