replace_all in fuzzy mode (passes 2 and 3 of fuzzyReplace) only
replaced the first match. seekLines returned the first match,
spliceLines replaced one range, and there was no loop.
Extract fuzzy pass logic into fuzzyReplaceLines which:
- Returns a 3-tuple (result, matched, error) for clean caller flow
- When replaceAll is true, collects all non-overlapping matches
then applies replacements from last to first to preserve indices
- When replaceAll is false with multiple matches, returns an error
Add test cases for replace_all with fuzzy trailing whitespace and
fuzzy indent matching.