feat(trace): report the net contribution of each session
Merged
JI
8d ago+1192+1192+0123456789012345678901234567890123456789-139-139-012345678901234567890123456789
Implements milestone 2 of spec docs/specs/issue-3639-trace-line-attribution.md (#3639): R-003, R-004 and R-010. With milestone 1, cases 1 to 5 of the spec appendix now give the expected results.
What changes
- Net contribution (R-003). The AI/human split of the added lines of a session comes from
git blameof each session file at the pushed commit. A line counts only when a commit of the session added it and it is still there, and each line counts one time. The match of a line to the ledger is the same as in milestone 1. The removed lines stay the sum of the removals of the session's own commits. - Session updates (R-004). For each commit that a push did not read yet, the CLI blames the parent of each file with ledger entries and finds the commit that last wrote each removed line. The session of that commit is sent again with its new numbers. A push with nothing new still sends nothing. A commit that replaced no line of a session is marked tracked after one read.
- Human commits join a session (R-010). A commit in no session that replaced lines of a session joins it. Its record keeps the lines that its replacing hunks added, per session. The session's commit list holds the commit, and only those lines count, as human, while they are still at the pushed commit.
- Retention. The trace state of a pushed session is kept for 30 days, instead of 7. A commit that joined a session keeps the session alive.
- The Trace README has two new rows: net contribution and session updates.
Spec entries
- D-012 (new): keep the trace state of a pushed session for 30 days. It answers the open question of the spec, which is now ticked.
- D-013 (new): the push sends a session again only when its own commits are on the branch that the push sends.
Implementation choices not in the spec
- A new factory picks the git client for all of Trace: the client that runs the
gitbinary when one is on the PATH, and the go-git client otherwise. Blame is the reason: on this repository the go-git blame took 0.2 to 1.4 seconds per file, andgit blame --porcelain25 to 57 ms. D-007 leaves this choice to the build. - A later commit that only re-indents a line takes the line, because blame sees a change. D-008 still applies to the match with the ledger.
- Removed lines are not netted: a line that the session added and later removed counts as a removal of the commit that removed it.
Not in this PR
- Renames and history rewrites (R-007): milestone 3.
- Attributed line ranges in the pushed commit: spec
docs/specs/issue-3639-line-ranges.md. - 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