let content = tokio::fs::read_to_string(path).await?;
// Normalize line endings for cross-platform compatibility
// Windows files use \r\n, but AI input uses \n
let content_normalized = content.replace("\r\n", "\n");
let old_string_normalized = old_string.replace("\r\n", "\n");
let new_string_normalized = new_string.replace("\r\n", "\n");
let count = content_normalized.matches(&old_string_normalized).count();
if count == 0 {
anyhow::bail!("old_string not found in {}", path);
}
if count > 1 {
anyhow::bail!(
"old_string found {} times in {} — must be unique",
count,
path
);
}
let new_content_normalized = content_normalized.replacen(&old_string_normalized, &new_string_normalized, 1);
// Preserve original line endings
let new_content = if content.contains("\r\n") {
new_content_normalized.replace("\n", "\r\n")
} else {
new_content_normalized
};
tokio::fs::write(path, &new_content).await?;