Skip to content

feat: adopt active sessions across repos and worktrees#1472

Open
peyton-alt wants to merge 3 commits into
mainfrom
feat/session-adopt
Open

feat: adopt active sessions across repos and worktrees#1472
peyton-alt wants to merge 3 commits into
mainfrom
feat/session-adopt

Conversation

@peyton-alt

@peyton-alt peyton-alt commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Trail: https://entire.io/gh/entireio/cli/trails/613/adopt-active-sessions-across-repos-and-worktrees

Summary

Adds entire session adopt [session-id] --from <source-worktree> so a user can explicitly anchor an active agent session into the repo/worktree where the commit is about to happen.

This addresses the case we hit where an agent session was tracked under one repo/worktree, but the agent made and committed changes in another repo. The target repo hooks can fire correctly, but without target-local session state the commit has no session to link and can miss the Entire-Checkpoint trailer.

What changed

  • Adds the session adopt subcommand under entire session.
  • Reads the source worktree session store from .git/entire-sessions.
  • Supports explicit session ID, or a single recent active source session when no ID is provided.
  • Rejects ended or fully condensed source sessions.
  • Writes target-local session state using the target repo HEAD, branch, worktree path, and worktree ID.
  • Keeps the original live transcript path.
  • Seeds FilesTouched from current target repo changes.
  • Warns that those current target changes will be attributed to the adopted session.
  • Clears source-local checkpoint bookkeeping before saving target state.
  • Leaves AttachedManually false because adoption is not entire session attach.

This lets the target repo commit hooks find the adopted session by target worktree, pass the staged-file overlap check, add an Entire-Checkpoint trailer, and condense normally on post-commit.

Review fixes

Addressed the four trail findings in follow-up commit aae06c4e100bf091dd305b222df469ee9cab4228:

  • Added a warning for target-worktree file attribution.
  • Documented why adopted sessions reset target-local checkpoint bookkeeping.
  • Cleared AttachedManually for adopted active sessions.
  • Added test coverage for the warning and attach-flag behavior.

Follow-up trailer: Entire-Checkpoint: b7f863b91041

After that, a new transcript-path finding was opened. The suggested behavior was not correct for cross-repo adoption, because the live transcript belongs to the continuing source agent session, not the target repo. Commit 9ffec38cf2fad2c962d48267aa9a1738358f0070 documents that intent in code.

Clarification trailer: Entire-Checkpoint: 0d316d428771

Commit and checkpoint verification

The original feature commit was created through the real hooks and has:

  • Commit: 6add2bae652a5983fe0ffe9171e92710051714c5
  • Trailer: Entire-Checkpoint: 7fb3d4d78c7f

The review-fix commit was also created through the real hooks and has:

  • Commit: aae06c4e100bf091dd305b222df469ee9cab4228
  • Trailer: Entire-Checkpoint: b7f863b91041

The transcript-path clarification commit was also created through the real hooks and has:

  • Commit: 9ffec38cf2fad2c962d48267aa9a1738358f0070
  • Trailer: Entire-Checkpoint: 0d316d428771

Push output confirmed entire/checkpoints/v1 synced to the checkpoint remote.

Real smoke test

Ran a disposable cross-repository smoke test with two separate temp git repos.

Flow:

  1. Built the local CLI from this branch.
  2. Created a source repo with a fake active Claude Code session and transcript.
  3. Created a separate target repo with src/feature.go staged.
  4. Ran entire session adopt smoke-adopt-session-001 --from <source> --force in the target repo.
  5. Verified adopt output tracked src/feature.go.
  6. Ran the real hooks git prepare-commit-msg handler.
  7. Verified it added Entire-Checkpoint: 08f656dbcb95.
  8. Committed and ran hooks git post-commit.
  9. Verified the committed message retained the trailer and post-commit state referenced that checkpoint.

Smoke result:

SMOKE_OK root=/private/tmp/entire-adopt-smoke-qkoNM8
adopt_output=Adopted session smoke-ad from /private/tmp/entire-adopt-smoke-qkoNM8/source
Tracking 1 file(s): src/feature.go
checkpoint=08f656dbcb95
commit=85a17c3
commit_message=smoke adopt||Entire-Checkpoint: 08f656dbcb95

Tests

  • go test ./cmd/entire/cli -run TestSessionAdopt_CopiesExternalSessionIntoCurrentWorktree -count=1
  • go test ./cmd/entire/cli -run TestSessionAdopt -count=1
  • go test ./cmd/entire/cli -count=1
  • mise run lint
  • mise run check

Caveats

This is explicit adoption, not automatic discovery. Users should run it from the target repo/worktree before committing, and the source transcript path must still be readable on the same machine.

Entire-Checkpoint: 7fb3d4d78c7f
@peyton-alt peyton-alt requested a review from a team as a code owner June 18, 2026 22:38
Copilot AI review requested due to automatic review settings June 18, 2026 22:38

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 6add2ba. Configure here.

adopted.PromptWindowResetPending = false
adopted.AttachedManually = true

return &adopted, filesTouched, nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale transcript offsets block trailers

High Severity

buildAdoptedSessionState clears target-local checkpoint IDs but keeps source CheckpointTranscriptStart and CheckpointTranscriptSize. After adoption, prepare-commit-msg often uses the live-transcript path (no shadow branch on the target repo). That path calls hasNewTranscriptWork before considering seeded FilesTouched, so when the transcript position has not moved past the copied offset, the hook treats the session as having no new content and skips the Entire-Checkpoint trailer despite staged overlap.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6add2ba. Configure here.

}

cmd := exec.CommandContext(ctx, "git", "-C", absWorktree, "rev-parse", "--show-toplevel", "--git-common-dir")
output, err := cmd.CombinedOutput()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Git rev-parse uses CombinedOutput

Low Severity

stateStoreForWorktree resolves --show-toplevel and --git-common-dir with cmd.CombinedOutput() and then splits stdout into paths. Git may write advice or warnings to stderr on success; merging streams can prepend that text to the parsed lines and break common-dir resolution for the source session store.

Fix in Cursor Fix in Web

Triggered by learned rule: Use cmd.Output() with separate stderr buffer for git CLI commands that parse stdout

Reviewed by Cursor Bugbot for commit 6add2ba. Configure here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an explicit entire session adopt subcommand to copy (“adopt”) an in-progress agent session that’s currently tracked under a different repo/worktree into the current repo/worktree so the commit hooks can find local session state and reliably add an Entire-Checkpoint trailer.

Changes:

  • Add entire session adopt [session-id] --from <source-worktree> command wiring under the session group.
  • Implement adoption logic that locates the source worktree’s .git/entire-sessions, selects an adoptable session, and writes a target-local session state seeded with current file changes.
  • Add unit tests covering cross-repo adoption, source resolution from a nested path, and PrepareCommitMsg trailer insertion after adoption.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
cmd/entire/cli/sessions.go Adds the adopt subcommand to session help text and registers the command.
cmd/entire/cli/session_adopt.go Implements the adopt command, source store resolution, session selection, and target-local state writing.
cmd/entire/cli/session_adopt_test.go Adds tests for adoption behavior and hook trailer behavior after adoption.

Comment on lines +142 to +144
if sourceState.Phase == session.PhaseEnded || sourceState.FullyCondensed {
return nil, fmt.Errorf("session %s is ended or fully condensed and cannot be adopted", sessionID)
}
Comment on lines +177 to +180
func isRecentAdoptCandidate(state *session.State) bool {
if state == nil || state.Phase == session.PhaseEnded || state.FullyCondensed {
return false
}
Comment on lines +225 to +246
now := time.Now()
adopted := *source
adopted.CLIVersion = versioninfo.Version
adopted.BaseCommit = head.Hash().String()
adopted.AttributionBaseCommit = head.Hash().String()
adopted.WorktreePath = worktreeRoot
adopted.WorktreeID = worktreeID
adopted.Branch = branch
adopted.LastInteractionTime = &now
adopted.FilesTouched = filesTouched
adopted.TurnCheckpointIDs = nil
adopted.LastCheckpointID = id.EmptyCheckpointID
adopted.LastCheckpointCommitHash = ""
adopted.FullyCondensed = false
adopted.DivergenceNoticeShown = false
adopted.UntrackedFilesAtStart = nil
adopted.PromptAttributions = nil
adopted.PendingPromptAttribution = nil
adopted.PromptWindowBase = 0
adopted.PromptWindowResetPending = false
adopted.AttachedManually = true

Entire-Checkpoint: b7f863b91041
Entire-Checkpoint: 0d316d428771
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants