use std::path::Path;
use super::compliance::ComplianceResult;
#[allow(clippy::too_many_arguments)]
pub fn build_agent_integration_prompt(
task_id: &str,
task_title: &str,
target_branch: &str,
queue_path: &Path,
done_path: &Path,
attempt: u32,
max_attempts: u32,
phase_summary: &str,
status_snapshot: &str,
ci_enabled: bool,
ci_label: &str,
previous_failure: Option<&str>,
) -> String {
let queue_path_display = queue_path.display();
let done_path_display = done_path.display();
let failure_block = previous_failure.map_or_else(String::new, |failure| {
format!("\n## Previous Attempt Failed\n{}\n", failure)
});
let ci_block = if ci_enabled {
format!(
"- Run CI gate and fix failures before pushing: `{}`",
ci_label
)
} else {
"- CI gate is disabled for this task".to_string()
};
sanitize_prompt_for_runner(&format!(
r#"# Parallel Integration (Mandatory) - Attempt {attempt}/{max_attempts}
You are finalizing task `{task_id}` (`{task_title}`) for direct push to `origin/{target_branch}`.
## Hard Requirement
You MUST execute integration git operations yourself in this turn. Do not stop early.
You are NOT done until all required checks are satisfied.
## Context
- Phase summary: {phase_summary}
- Current git status snapshot:
```text
{status_snapshot}
```
{failure_block}
## Required Sequence
1. `git fetch origin {target_branch}`
2. Rebase on latest remote state: `git rebase origin/{target_branch}`
3. If conflicts exist:
- Resolve every conflict marker while preserving both upstream and task intent.
- For queue/done files, preserve other workers' entries exactly.
- Ensure `{task_id}` is removed from queue and present as done in done.
- Continue rebase until complete (`git add ...`, `git rebase --continue`).
4. Ensure bookkeeping is correct:
- `{queue_path_display}` does NOT contain `{task_id}`
- `{done_path_display}` DOES contain `{task_id}` with done status
5. Stage and commit any remaining changes needed for integration.
6. {ci_block}
7. Push directly to base branch: `git push origin HEAD:{target_branch}`
8. If push is rejected (non-fast-forward), repeat from step 1 in this same turn.
## Completion Contract (Mandatory)
Before ending your response:
- No unresolved merge conflicts remain.
- Push to `origin/{target_branch}` has succeeded.
- Bookkeeping files are semantically correct for `{task_id}`.
- CI has passed when enabled.
If any check fails, keep working in this same turn until fixed.
"#
))
}
pub fn compose_block_reason(
compliance: &ComplianceResult,
pushed: bool,
extra: Option<&str>,
) -> String {
let mut reasons = Vec::new();
if compliance.has_unresolved_conflicts {
reasons.push(format!(
"unresolved conflicts: {}",
compliance.conflict_files.join(", ")
));
}
if !compliance.queue_done_valid {
reasons.push("queue/done semantic validation failed".to_string());
}
if !compliance.task_archived {
reasons.push("task archival validation failed".to_string());
}
if !compliance.ci_passed {
reasons.push("CI validation failed".to_string());
}
if !pushed {
reasons.push("HEAD is not yet integrated into target branch".to_string());
}
if let Some(extra) = extra {
reasons.push(extra.to_string());
}
if let Some(validation_error) = &compliance.validation_error {
reasons.push(validation_error.clone());
}
if reasons.is_empty() {
"integration did not satisfy completion contract".to_string()
} else {
reasons.join("; ")
}
}
fn sanitize_prompt_for_runner(prompt: &str) -> String {
prompt
.chars()
.map(|c| {
if c.is_control() && c != '\n' && c != '\r' && c != '\t' {
' '
} else {
c
}
})
.collect()
}