Skip to content

Sweep state CSV writers emit multi-line records that merge=union corrupts #2680

@brendancol

Description

@brendancol

Describe the bug

The sweep state files (.claude/sweep-*-state.csv) carry merge=union in .gitattributes so parallel sweep agents can append rows without clobbering each other. Union merge is line-based: it unions and dedupes physical lines. The sweep writers use csv.DictWriter with QUOTE_MINIMAL, which is valid CSV but writes a newline-containing note as a quoted field spanning several physical lines.

When two agents append concurrently, union merge splits those multi-line records on their internal newlines. The file ends up with phantom rows, duplicate header lines, and notes torn apart mid-sentence. PR #2679 repaired the latest instance in sweep-test-coverage-state.csv (31 corrupted physical lines collapsed back to 7 clean records).

The "notes": "<single-line notes or empty>" placeholder in the writer is a hint, not enforcement. Nothing stops an agent from writing a note that contains a newline.

Expected behavior

Each record occupies exactly one physical line on disk regardless of note content, so union merges stay record-aligned and cannot corrupt the file.

Fix

In every sweep writer (.claude/commands/sweep-*.md and deep-sweep.md), sanitize each field to collapse embedded CR/LF to a " | " separator right before writerow, so a record is always one physical line. This enforces the invariant in code rather than relying on the unenforced placeholder hint.

Additional context

Affects all seven sweep commands plus the deep-sweep reset path. The OS/browser/device fields from the bug template do not apply; this is repository tooling, not a runtime code path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginfrastructureCI, benchmarks, and tooling

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions