feat(trace): attribute lines to their last writer by content
Merged
JI
4h ago+2286+2286+0123456789012345678901234567890123456789-147-147-012345678901234567890123456789
Implements milestone 1 of spec docs/specs/issue-3639-trace-line-attribution.md (#3639): R-001, R-002, R-005, R-006 and R-011.
What changes
- Each agent edit records a fingerprint for every line it adds and removes. The fingerprint ignores whitespace, so a re-indent or a moved line keeps its owner (D-008). The ledger also keeps the added and removed counts of every edit, including edits that never reach a commit (R-011).
- Before the next agent edit of a file, and at commit time, the session's uncommitted AI lines that are gone from the file close. A human change then counts as human, also when a later agent edit keeps it (R-001, R-002).
- A commit closes only the AI lines that it holds. The other AI lines of the file stay pending, and the next commit with them is credited to the session (R-006).
- At push, an added line is AI when it matches a line that the session wrote. A removed line is AI only when an agent edit of the session removed it (R-005). Matching by content keeps the split after a cherry-pick or a rebase.
- Each file entry of the evidence gets
ai_lines_added,ai_lines_removed,human_lines_addedandhuman_lines_removed(D-010). The session totals are their sums. The file-levelattributionmarker stays for older platforms (R-009). The JSON schema has the new fields. - Ledgers written by older CLIs keep the range-based rule, file by file.
- The Trace README feature table has the new behavior.
Implementation choices not in the spec
- A commit that names two sessions: a line that matches the other session counts for neither side in this session's evidence.
- A shell command has no content snapshot from before the command. The file at
HEADstands in for it, so uncommitted human lines of a file that the command changes count as AI. - The commit-msg hook still credits sessions file by file. A file now stays pending only while it has open AI lines.
- Each agent file edit now reads the session's ledger to find the replaced lines.
Not in this PR
- Net contribution per session, sending a session again after a later replacement, and human commits that join a session (R-003, R-004, R-010): milestone 2. Until then, commits of a session are still added up.
- Renames (R-007): milestone 3.
- Platform use of the per-file split (R-008): follow-up platform ticket.
AI disclosure: this change was written with the assistance of Claude Code.
š¤ Generated with Claude Code