Help us shape the future of Go! Take the 2026 Go Developer Survey

attribution

package
v1.127.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ChangedPaths

func ChangedPaths(before, after map[string]string) (changed, deleted []string)

ChangedPaths diffs two working-tree signatures (repo-relative path → content hash) captured before and after a shell command, returning the paths the command created or modified (changed) and the paths it removed (deleted). Both slices are sorted for deterministic recording. Used to attribute files touched by agent-run shell commands, which never fire the file-writing tool hooks.

func ComputeLineRanges

func ComputeLineRanges(before, after []byte) ([]aicodingsession.LineRange, bool)

ComputeLineRanges computes which line ranges in "after" are new or modified compared to "before". Returns 1-indexed, inclusive line ranges plus a `changed` flag that is true whenever before and after differ — including deletion-only changes where no "after" ranges exist. If before is nil, the entire file is considered new.

func Enrich

func Enrich(sessionID string, ledgers map[string]*state.AILineAttribution, commits []CommitLines, tip map[string][]tracegit.BlameLine, changes *aicodingsession.CodeChanges)

Enrich adds AI/human attribution to the code changes of a session.

ledgers holds the AI line ledger of each session by ID. commits holds the session's commits, oldest first. Each line that a commit added is AI when its content matches a line that an edit of the session wrote (R-001), and each removed line is AI when an edit of the session removed it (R-005). Each ledger line matches one commit line at most.

The session's own ledger is matched first. When it and another session of the commit both hold a line, the evidence of each session counts the line as its own: each evidence is the view of one session. A line that matches only another session of the commit counts for neither side: it is that session's work. All other lines are human.

tip holds, for each file, its lines at the pushed commit with the commit that last wrote each one. The added lines of a file in tip are the net contribution of the session (R-003): the lines that its commits added and that no later commit replaced, each one counted once. A file that tip holds with no lines is gone, and adds nothing. A file that tip does not hold falls back to the sum of the added lines of each commit. Removed lines are the sum over the session's own commits; each commit holds only the removed lines that no earlier commit of the session wrote. The line counts of a file with a split are the sum of the split, so the AI and human numbers add up to them (issue 3674).

The line ranges of a file in tip are the positions of the session's net added lines in the pushed commit, each range AI or human (spec issue-3639, line ranges R-001, R-002). They hold as many lines as the net counts (R-003). A file that tip does not hold keeps the AI ranges at edit time, with no attribution, as older CLIs write them (R-005).

A file that was renamed after a commit of the session has the lines of its new path in tip (R-007). A line there counts for the path that its commit changed, so a session that changed the file under both paths counts each line once. A commit that renamed a file matches the ledger of the new path, then of the old one.

A file with an edit recorded before line fingerprints existed keeps the earlier rule: AI lines are the recorded ranges, capped at the file's diff.

func FilterGenerated

func FilterGenerated(changes *aicodingsession.CodeChanges, isGenerated func(path string) bool)

FilterGenerated removes files matched by isGenerated from changes.Files and subtracts their contributions from the aggregate line and file-count totals, so generated code does not skew downstream AI/human attribution. A nil isGenerated leaves changes untouched.

func Fingerprint added in v1.126.0

func Fingerprint(line string) string

Fingerprint returns the content key of one line. Whitespace is dropped before hashing, so a line that a change only re-indented keeps its key, and with it its owner (D-008).

func FingerprintLines added in v1.126.0

func FingerprintLines(content []byte) []string

FingerprintLines returns the fingerprint of each line of content, in order.

func ReplacedLines added in v1.126.0

func ReplacedLines(open *state.OpenLines, current []byte) state.LineSet

ReplacedLines returns the open added lines of a file that its current content no longer holds. Before an agent edit, these are the lines that a human or another session changed since the session's last edit (R-002).

func ReverseApplyEdits

func ReverseApplyEdits(after []byte, edits []trace.HookEdit) []byte

ReverseApplyEdits reconstructs the "before" content of a file given its "after" content and the sequence of old_string → new_string replacements that were applied to produce it. Edits are reversed in reverse order.

Best-effort and inherently ambiguous when new_string is not unique in the current content: bytes.Index always picks the first occurrence, which can be the wrong one if the same literal appears more than once. Cursor's afterFileEdit edits are typically context-rich enough that this rarely misfires in practice, and the worst-case outcome is a downstream line-range comparison reporting noisy ranges rather than a crash — but callers should treat the reconstructed bytes as a hint, not ground truth.

If an edit's new_string cannot be located in the current content (because a later edit overlapped it, or the file was touched externally), that edit is skipped. When the resulting "before" equals "after" we return nil so callers can fall back to other reconstruction strategies.

func SettleCommit added in v1.126.0

func SettleCommit(open *state.OpenLines, committed tracegit.FileLines, worktree []byte, clean bool) state.LineSet

SettleCommit returns the open lines of one file that a commit closes: the open lines that the commit added or removed, and the open added lines that the worktree no longer holds, because something other than the session changed them (R-002). The other open lines stay open for a later commit (R-006). When clean is true, the worktree holds the file as the commit does, so nothing of the file is left to commit and all of it closes.

Types

type CommitLines added in v1.126.0

type CommitLines struct {
	SHA        string
	SessionIDs []string
	Files      []tracegit.FileLines
	// Joined is set on a commit in no session that replaced lines of the
	// session and so joined it (R-010). It holds, for each file, the
	// fingerprints of the lines that its replacing hunks added. Only these
	// lines count for the session, and they are human.
	Joined map[string][]string
}

CommitLines is one commit of a session: the lines it changed and the sessions that its record names.

type Edit added in v1.126.0

type Edit struct {
	// Changed is true whenever the content differs, including a change that
	// only removes lines.
	Changed bool
	// Ranges are the 1-indexed, inclusive line ranges of the new content that
	// the change wrote.
	Ranges []aicodingsession.LineRange
	// AddedCount and RemovedCount are the lines the change added and removed,
	// counted as the line diff shows them.
	AddedCount, RemovedCount int
	// Added and Removed are the fingerprints of the lines the change added and
	// removed. A line that the change only re-indented or moved shows as one
	// removal and one addition with the same fingerprint; such pairs are left
	// out, because the change wrote no new code on that line (D-008).
	Added, Removed []string
}

Edit is what one change did to a file: the line ranges it wrote in the new content, and the lines it added and removed.

func ComputeEdit added in v1.126.0

func ComputeEdit(before, after []byte) Edit

ComputeEdit diffs the content of a file before and after a change. A nil before means the file is new, and a nil or empty after means the change removed all of its lines.

func DropOpen added in v1.126.0

func DropOpen(edit Edit, open *state.OpenLines) Edit

DropOpen removes from an edit the lines that are already open for the session, and lowers its counts by the same amount. A shell command is diffed against HEAD, not against the session's last edit, so its diff holds again the uncommitted lines that earlier edits recorded. A command that writes one more copy of an open line loses that copy too; the ledger cannot tell the two apart.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL