#[cfg(test)]
#[must_use]
pub fn prompt_fix(prompt_content: &str, plan_content: &str, issues_content: &str) -> String {
use crate::workspace::WorkspaceFs;
use std::env;
let workspace = WorkspaceFs::new(env::current_dir().unwrap());
let partials = get_shared_partials();
let template_content = include_str!("../templates/fix_mode_xml.txt");
let files_to_modify = extract_file_paths_from_issues(issues_content);
let files_section = format_files_section(&files_to_modify);
let variables = HashMap::from([
("PROMPT", prompt_content.to_string()),
("PLAN", plan_content.to_string()),
("ISSUES", issues_content.to_string()),
("FILES_TO_MODIFY", files_section),
(
"FIX_RESULT_XML_PATH",
workspace.absolute_str(".agent/tmp/fix_result.xml"),
),
(
"FIX_RESULT_XSD_PATH",
workspace.absolute_str(".agent/tmp/fix_result.xsd"),
),
]);
Template::new(template_content)
.render_with_partials(&variables, &partials)
.unwrap_or_else(|_| {
format!(
"FIX MODE\n\nRead .agent/ISSUES.md and fix the issues found.\n\nContext:\nPROMPT:\n{prompt_content}\n\nPLAN:\n{plan_content}\n\nOutput format: <ralph-fix-result><ralph-status>completed|partial|failed</ralph-status><ralph-summary>Summary</ralph-summary></ralph-fix-result>\n"
)
})
}
pub fn prompt_fix_with_context(
context: &TemplateContext,
prompt_content: &str,
plan_content: &str,
issues_content: &str,
workspace: &dyn Workspace,
) -> String {
let partials = get_shared_partials();
let template_content = context
.registry()
.get_template("fix_mode_xml")
.unwrap_or_else(|_| include_str!("../templates/fix_mode_xml.txt").to_string());
let files_to_modify = extract_file_paths_from_issues(issues_content);
let files_section = format_files_section(&files_to_modify);
let variables = HashMap::from([
("PROMPT", prompt_content.to_string()),
("PLAN", plan_content.to_string()),
("ISSUES", issues_content.to_string()),
("FILES_TO_MODIFY", files_section),
(
"FIX_RESULT_XML_PATH",
workspace.absolute_str(".agent/tmp/fix_result.xml"),
),
(
"FIX_RESULT_XSD_PATH",
workspace.absolute_str(".agent/tmp/fix_result.xsd"),
),
]);
Template::new(&template_content)
.render_with_partials(&variables, &partials)
.unwrap_or_else(|_| {
format!(
"FIX MODE\n\nRead .agent/ISSUES.md and fix the issues found.\n\nContext:\nPROMPT:\n{prompt_content}\n\nPLAN:\n{plan_content}\n\nOutput format: <ralph-fix-result><ralph-status>completed|partial|failed</ralph-status><ralph-summary>Summary</ralph-summary></ralph-fix-result>\n"
)
})
}
fn format_files_section(files: &[String]) -> String {
if files.is_empty() {
"================================================================================
FILES YOU MAY MODIFY
================================================================================
(No specific files were extracted from ISSUES content)
PERMISSIONS: FAIL CLOSED (NO FILE LIST PROVIDED)
IMPORTANT: In fix mode, you MUST ONLY work on files mentioned in the ISSUES content.
If no file paths were extracted, do NOT modify any files. Report `issues_remain`
and include that the orchestrator must provide an explicit file list (or update
the issue format to include file paths) to proceed safely.
The ISSUES content is already embedded in this prompt - review it carefully.
================================================================================
END OF FILES SECTION
================================================================================
"
.to_string()
} else {
let files_list: String = files.iter().map(|file| format!("- {file}\n")).collect();
format!(
"================================================================================
FILES YOU MAY MODIFY
================================================================================
{files_list}
IMPORTANT: Work ONLY with the files listed above. The issues
content is already embedded in this prompt - you do NOT need to
read or discover any files to know what to fix.
================================================================================
END OF FILES SECTION
================================================================================
"
)
}
}