Skip to content

fix: preserve AI attribution when human edits file after AI checkpoint (fixes #1444)#1667

Open
IanMcNelly wants to merge 1 commit into
git-ai-project:mainfrom
IanMcNelly:main
Open

fix: preserve AI attribution when human edits file after AI checkpoint (fixes #1444)#1667
IanMcNelly wants to merge 1 commit into
git-ai-project:mainfrom
IanMcNelly:main

Conversation

@IanMcNelly

Copy link
Copy Markdown

Problem

When a human modifies a file after an AI checkpoint fires but before committing — without a known_human checkpoint being triggered — AI attribution for the AI's own lines was lost (shown as 100% untracked).
Reported in #1444.

Root cause

The carryover snapshot stays stale (holds the AI checkpoint version). An overlap filter in the attribution loop was then stripping the human-modified position from unstaged_hunks because it also appeared in
committed_hunks — incorrectly crediting that committed line to AI. For the modify case (human replaces an AI-written line), this meant the human's content was attributed to AI.

Fix

virtual_attribution.rs: Skip the committed-vs-unstaged overlap filter when a carryover snapshot is present. With a snapshot, Replace-type unstaged lines represent content divergence between the AI
checkpoint and the commit — they should flow to INITIAL, not be silently re-attributed.

attribution_recovery.rs / post_commit.rs: Replace the content-based guard in recover_adjacent_edges with a displaced_to_initial_lines set (intersection of initial_attributions and
recovery_hunks). This blocks edge recovery from re-claiming lines explicitly sent to INITIAL, while preserving edge recovery for genuinely adjacent uncheckpointed inserts/appends.

Tests

Added tests/integration/human_edit_after_ai_checkpoint.rs with four regression tests covering:

  • Human appends lines after AI block (edge recovery attributes adjacent lines to AI — existing product behavior)
  • Human modifies a line within the AI range (the core bug — now correctly unattributed)
  • Human inserts lines before AI block (edge recovery attributes adjacent lines to AI)
  • Partial staging guard: real uncommitted lines still defer to INITIAL

All existing tests pass including the delayed_checkout/switch_merge_trace_replay tests.

Fixes #1444

When a human modifies a file after an AI checkpoint fires but before
committing — without triggering a known_human checkpoint — the
carryover snapshot could be stale (holding the AI version). This
caused the overlap filter to incorrectly strip the human-modified
line from unstaged_hunks, leaving it attributed to AI.

Fix: skip the committed-vs-unstaged overlap filter entirely when a
carryover snapshot is present. With a snapshot, Replace-type unstaged
lines represent lines where committed content differs from the AI
checkpoint — they should flow to INITIAL, not be re-attributed.

Also replace the content-based guard in recover_adjacent_edges with
a displaced_to_initial_lines set derived from initial_attributions ∩
recovery_hunks. This prevents edge recovery from re-claiming
human-modified lines that were explicitly sent to INITIAL, while
still allowing edge recovery for adjacent uncheckpointed lines
(inserts/appends) that were never in the attribution loop at all.

Fixes git-ai-project#1444

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@CLAassistant

CLAassistant commented Jun 27, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: All attribution lost (100% untracked) when human edits after AI checkpoint in Claude Code

2 participants