You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Repo relocation silently loses commit trailers on 0.9.0: findSessionsForWorktree has no fallback when the recorded worktree path no longer exists (#1440 covers siblings only) #1890
Moving a repository to a different absolute path silently stops commits getting an Entire-Checkpoint trailer, for the rest of the session's life. Same root cause as #1852
(SessionState.WorktreePath recorded once, matched by exact string equality in findSessionsForWorktree), but the fix that closed #1852 does not cover it.
#1440 added a fallback across sibling worktrees sharing a git common dir. A whole-repo
relocation is not that case: the recorded path is not a sibling worktree, and after the move it
does not exist at all, so there is nothing for the fallback to match.
I verified #1440 is present in this binary before concluding anything — a session started in a main
checkout does now link commits made in a linked worktree (control below). So this is a gap in that
fix, not an old build.
Four things make it hard to notice or recover from:
The decline is DEBUG-only.prepare-commit-msg: no active sessions. The WARN added in fix(strategy): warn when ambiguous worktree sessions block commit linking #1856 does not fire, because it covers the ambiguous multiple candidates case. The
zero-match case is the one that silently loses data, and it is still silent.
entire status and entire session current disagree with the commit-time matcher. Run from
the new path, both report the session as active, and session current — documented as "Show the
active session for the current worktree" — returns it while printing Worktree: old-location,
a directory that no longer exists. One code path considers the session to belong to this
worktree; the other does not.
entire doctor reports everything OK and does not flag the stale worktree path.
Impact in my case: a repo moved mid-session, and roughly 12 commits across a 6.5 hour session were
left unlinked. The session itself never appeared in entire session list afterwards, so entire why reports the main design document as 100% human-authored when an agent wrote it. That is
provenance that is not merely missing but confidently wrong, which for a tool whose output people
rely on is the part that worried me.
A relocation is a fairly ordinary thing to do (renaming a project directory, moving it under a
parent folder), and unlike the sibling-worktree topology it gives no hint that session state is
path-keyed.
Steps to reproduce
Verified on 0.9.0. Full scripts drive entire hooks git prepare-commit-msg directly, the same
way #1852's reproduction did.
# 1. A repo with Entire enabled and a live session started in it
mkdir -p /tmp/repro/old-location &&cd /tmp/repro/old-location
git init -q -b main
printf'one\n'> file.txt && git add -A && git commit -q -m "initial commit"
entire enable --agent claude-code --no-github --checkpoint-backend refs -f
SID=11111111-2222-3333-4444-555555555555
T=/tmp/repro/transcript.jsonl
cat >$T<<EOF{"type":"user","uuid":"u1","sessionId":"$SID","cwd":"/tmp/repro/old-location","gitBranch":"main","timestamp":"2026-08-03T09:00:00.000Z","message":{"role":"user","content":"add a line"}}EOFprintf'{"session_id":"%s","transcript_path":"%s","cwd":"%s","hook_event_name":"SessionStart","source":"startup"}' \
"$SID""$T" /tmp/repro/old-location | entire hooks claude-code session-start
printf'{"session_id":"%s","transcript_path":"%s","cwd":"%s","hook_event_name":"UserPromptSubmit","prompt":"add a line"}' \
"$SID""$T" /tmp/repro/old-location | entire hooks claude-code user-prompt-submit
# 2. CONTROL: commit from the original path -> trailer is addedprintf'two\n'>> file.txt && git add -A
printf'control commit\n'> /tmp/repro/msg1
entire hooks git prepare-commit-msg /tmp/repro/msg1 message
cat /tmp/repro/msg1
# control commit## Entire-Checkpoint: 01KZ3ATEMW1PQTN7XY6A6HF6Q8 <-- present
git commit -q -F /tmp/repro/msg1
# 3. Move the whole repo. Nothing else changes.cd /tmp/repro && mv old-location new-location &&cd new-location
# 4. THE BUG: commit from the new path -> no trailer, no warningprintf'three\n'>> file.txt && git add -A
printf'commit after the repo moved\n'> /tmp/repro/msg2
ENTIRE_LOG_LEVEL=DEBUG entire hooks git prepare-commit-msg /tmp/repro/msg2 message
cat /tmp/repro/msg2
# commit after the repo moved <-- no trailer, exit 0, nothing on stderr
Meanwhile, from the new path:
$ entire session currentSession 11111111-2222-3333-4444-555555555555Agent: Claude CodeStatus: activeWorktree: old-location # <-- no longer existsCheckpoints: 0
$ entire session adopt $SID --from /tmp/repro/old-location --yesresolve source git directory: fatal: cannot change to '/tmp/repro/old-location': No such file or directory: exit status 128
$ entire session adopt $SID --yessource worktree is required; pass --from <path>
$ entire doctor✓ Metadata branches: OK✓ Claude Code hook config: OKNo stuck sessions found.
Control proving #1440 is present in this same binary (session started in the main checkout,
commit made in a linked worktree). Note that the Entire config has to be committed before git worktree add, or the new worktree has no .entire/settings.json and the hook declines for an
unrelated reason — that caught me out first time:
mkdir -p /tmp/sib/main-checkout &&cd /tmp/sib/main-checkout
git init -q -b main
printf'one\n'> file.txt && git add -A && git commit -q -m "initial commit"
entire enable --agent claude-code --no-github --checkpoint-backend refs -f
git add -A && git commit -q -m "chore: enable entire"# important# ... start a session with cwd = /tmp/sib/main-checkout ...
git worktree add -q -b feature /tmp/sib/probe
cd /tmp/sib/probe
printf'two\n'>> file.txt && git add -A
printf'commit from a sibling worktree\n'> /tmp/sib/msg
entire hooks git prepare-commit-msg /tmp/sib/msg message
cat /tmp/sib/msg
# commit from a sibling worktree## Entire-Checkpoint: 01KZ3AXWBDDDRAYMC68Z9SFJTM <-- #1440 working
Suggestions
Only as starting points, since you know the constraints:
Match on something that survives relocation. The session store already lives in $GIT_COMMON_DIR/entire-sessions/, so any state found there is by construction the same repo;
a "recorded worktree path does not resolve, and this is the only candidate" case looks safely
adoptable without guessing.
Let adopt work without a live source: --from cannot be satisfied once the path is gone.
Have doctor flag session state whose WorktreePath does not exist.
Entire CLI version
Entire CLI 0.9.0 (Go go1.26.4, darwin/arm64)
OS and architecture
macOS 27.0 arm64 (Darwin 27.0.0), git 2.54.0
Agent
Claude Code
Terminal
Ghostty 1.3.1 (build 15212)
Logs / debug output
# prepare-commit-msg from the new path, ENTIRE_LOG_LEVEL=DEBUG
{"level":"DEBUG","msg":"prepare-commit-msg hook invoked","session_id":"11111111-...","component":"hooks","hook":"prepare-commit-msg","hook_type":"git","strategy":"manual-commit","source":"message"}
{"level":"DEBUG","msg":"prepare-commit-msg: no active sessions","session_id":"11111111-...","component":"checkpoint","strategy":"manual-commit","source":"message"}
{"level":"DEBUG","msg":"perf","component":"perf","op":"prepare-commit-msg","duration_ms":17,"steps.open_repository_ms":0,"steps.find_sessions_for_worktree_ms":11,"hook_type":"git"}
For contrast, the warning the real (non-synthetic) session emitted on every subsequent command was session attribution diverged after recent history movement; figures may be off until next checkpoint. It names history movement rather than a path change, which is why I spent a day
looking at git history and hook installation before finding #1852.
What happened?
Moving a repository to a different absolute path silently stops commits getting an
Entire-Checkpointtrailer, for the rest of the session's life. Same root cause as #1852(
SessionState.WorktreePathrecorded once, matched by exact string equality infindSessionsForWorktree), but the fix that closed #1852 does not cover it.#1440 added a fallback across sibling worktrees sharing a git common dir. A whole-repo
relocation is not that case: the recorded path is not a sibling worktree, and after the move it
does not exist at all, so there is nothing for the fallback to match.
I verified #1440 is present in this binary before concluding anything — a session started in a main
checkout does now link commits made in a linked worktree (control below). So this is a gap in that
fix, not an old build.
Four things make it hard to notice or recover from:
prepare-commit-msg: no active sessions. The WARN added infix(strategy): warn when ambiguous worktree sessions block commit linking #1856 does not fire, because it covers the ambiguous multiple candidates case. The
zero-match case is the one that silently loses data, and it is still silent.
entire statusandentire session currentdisagree with the commit-time matcher. Run fromthe new path, both report the session as active, and
session current— documented as "Show theactive session for the current worktree" — returns it while printing
Worktree: old-location,a directory that no longer exists. One code path considers the session to belong to this
worktree; the other does not.
entire session adopt --from <old-path>is theremedy given on Worktree commits get no Entire-Checkpoint trailer when the session started in another worktree of the same repo (findSessionsForWorktree exact-path match) #1852, but it requires the source worktree to exist:
resolve source git directory: fatal: cannot change to '<old-path>': No such file or directory.--fromis mandatory (source worktree is required; pass --from <path>), so after a relocationthere is no value that works.
entire doctorreports everything OK and does not flag the stale worktree path.Impact in my case: a repo moved mid-session, and roughly 12 commits across a 6.5 hour session were
left unlinked. The session itself never appeared in
entire session listafterwards, soentire whyreports the main design document as 100% human-authored when an agent wrote it. That isprovenance that is not merely missing but confidently wrong, which for a tool whose output people
rely on is the part that worried me.
A relocation is a fairly ordinary thing to do (renaming a project directory, moving it under a
parent folder), and unlike the sibling-worktree topology it gives no hint that session state is
path-keyed.
Steps to reproduce
Verified on 0.9.0. Full scripts drive
entire hooks git prepare-commit-msgdirectly, the sameway #1852's reproduction did.
Meanwhile, from the new path:
Control proving #1440 is present in this same binary (session started in the main checkout,
commit made in a linked worktree). Note that the Entire config has to be committed before
git worktree add, or the new worktree has no.entire/settings.jsonand the hook declines for anunrelated reason — that caught me out first time:
Suggestions
Only as starting points, since you know the constraints:
$GIT_COMMON_DIR/entire-sessions/, so any state found there is by construction the same repo;a "recorded worktree path does not resolve, and this is the only candidate" case looks safely
adoptable without guessing.
alone would have saved me a day, because the failure would have named itself.
adoptwork without a live source:--fromcannot be satisfied once the path is gone.doctorflag session state whoseWorktreePathdoes not exist.Entire CLI version
Entire CLI 0.9.0 (Go go1.26.4, darwin/arm64)
OS and architecture
macOS 27.0 arm64 (Darwin 27.0.0), git 2.54.0
Agent
Claude Code
Terminal
Ghostty 1.3.1 (build 15212)
Logs / debug output
For contrast, the warning the real (non-synthetic) session emitted on every subsequent command was
session attribution diverged after recent history movement; figures may be off until next checkpoint. It names history movement rather than a path change, which is why I spent a daylooking at git history and hook installation before finding #1852.