| 92 | // ── Ablation edits ──────────────────────────────────────────────────────────── |
| 93 | |
| 94 | function applyEdits(content, edits) { |
| 95 | const lines = content.split(/\r?\n/); |
| 96 | // Apply bottom-up so line indices stay stable across deletes. |
| 97 | const sorted = [...edits].sort((a, b) => b.lineNo - a.lineNo); |
| 98 | for (const e of sorted) { |
| 99 | const idx = e.lineNo - 1; |
| 100 | if (idx < 0 || idx >= lines.length) continue; |
| 101 | if (e.action === 'delete') { |
| 102 | lines.splice(idx, 1); |
| 103 | } else if (e.action === 'trim' && e.trimmed_line) { |
| 104 | const lead = (lines[idx].match(/^(\s*)/) || ['', ''])[1]; |
| 105 | lines[idx] = lead + e.trimmed_line.replace(/^\s+/, ''); |
| 106 | } |
| 107 | } |
| 108 | return lines.join('\n'); |
| 109 | } |
| 110 | |
| 111 | // ── Scenario runs ───────────────────────────────────────────────────────────── |
| 112 | |