Skip to content

Working-log displacement: three gt-plumbing shapes strand uncommitted AI checkpoints (empty-attestation notes survive #1976) #2103

Description

@scouredimage

Summary

Three distinct defects share one signature: uncommitted AI checkpoints (the working log) are stranded when Graphite-style plumbing moves the branch, so the next commit mints an empty-attestation note and the pending AI lines blame human. #1976 fixed the forward reset --keep carry (confirmed working — forward controls pass); these are the surviving variants. Isolated by the graphite-workflows scenario suite (#2021), where they drive ~54 failing scenarios across the SYNC_RESTACK / RESTACK / WORKTREE / CONFLICT_CONTINUE families.

Verified present on current main (cb748e61d): the implicated regions are byte-identical to the suite's verification base (src/daemon.rs:5648-5673, src/daemon.rs:5713-5766, src/daemon/ref_cursor.rs:916-931ref_cursor.rs has no changes at all since then).

In production (enterprise fleet) this is the "empty note" class: PRs whose every commit carries a zero-attestation note despite heavy captured AI activity; in a single day's audit ~30% of AI-flagged-but-unattributed PRs had this shape.

Defect A — sideways reset -q --keep onto a commit-tree-minted sibling

gt restack's core move for the checked-out branch. The Reset handler renames the working log only for ancestor-related moves (src/daemon.rs:5648-5673); the minted replacement is a sibling, so the flow falls through to handle_non_fast_forward_rewrite, which shifts committed notes but never the working log. Pending checkpoints stay keyed to the now-unreachable old tip.

Minimal repro (traced repo, daemon running):

# 1. AI edit checkpointed while branch tip is O (working log keyed to O)
git-ai checkpoint claude file.txt
# 2. mint a SIBLING of O the way gt restack does (same tree, new parent)
NEW=$(git commit-tree O^{tree} -p <new-parent> -m restacked)
# 3. sideways move (traced)
git reset -q --keep "$NEW"
# 4. commit the still-pending AI lines
git commit -am work
git ai show HEAD   # note exists but has ZERO attestations; AI lines blame human

Suite: GT-RESTACK-005 and the SYNC_RESTACK/RESTACK traced mixed/uncommitted clusters.

Defect C — cross-worktree update-ref strands the log even on fast-forwards

The update-ref working-log carry (src/daemon.rs:5713-5766) requires the move to affect the invoking command's HEAD. A branch checked out in a different worktree records no HEAD reflog entry in the invoking worktree, so even plain fast-forward update-ref moves strand its working log.

git worktree add ../wt2 feature       # AI checkpoints happen in wt2 (log keyed to feature's tip)
# from the MAIN worktree (as gt does when restacking the whole stack):
git update-ref refs/heads/feature <descendant-sha>
# wt2's pending checkpoints are now stranded; next commit in wt2 -> empty note

Suite: the WORKTREE family's mixed/uncommitted clusters (all shapes).

Defect D — stash pop -q never restores stashed attribution

enrich_stash (src/daemon/ref_cursor.rs:916-931) passes stash_args.get(1) as the stash target without stripping flags, so -q fails target resolution and the attribution saved at stash push (present on disk under .git/ai/stashes_v2/<sha>/INITIAL) is never restored. All existing upstream stash tests are flag-less, which is why this survives.

git-ai checkpoint claude file.txt
git stash push
git stash pop -q       # target resolution gets "-q", restore silently skipped
git commit -am work    # AI lines blame human

Suite: drives the CONFLICT_CONTINUE clusters (gt uses -q on its stash plumbing).

Fix direction (from the suite triage)

  • Carry the working log old→new in the Reset handler's non-ancestor arm (A) and in the update-ref handler for branches checked out in any worktree (C) — mirroring the unconditional rename apply_checkout_switch_working_log_side_effect already performs for checkouts.
  • Skip flags when resolving stash pop targets, defaulting to stash@{0} (D).

Executable failing tests for all three live in #2021 (tests/integration/graphite_workflows/, taxonomy in EXPECTED_FAILURES.md § Mechanism 2). Related: #1976 (forward fix these variants escape), #2093 / #2099 (sibling gt-plumbing issues on the rewrite/push paths).

Environment: verified on main cb748e61d and enterprise fleet v1.6.15–1.6.20, macOS arm64, git 2.55, Graphite 1.8.x.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions