Summary
isShadowBranchReachable (the read path for temporary / in-progress shadow-branch checkpoints, surfaced by entire checkpoint list / explain) uses a first-parent-only walk of HEAD's history. It is the ephemeral counterpart of the committed-checkpoint bug fixed in #931, but it is not merge-aware, and making it so is a genuine design decision (needs data we don't persist today), so it was deliberately left out of the #931 fix.
The two harms (a tension, not a single bug)
A shadow branch is named entire/<base-commit-short>-<worktreeHash> and records only its base commit (where the session started) plus the worktree hash — not the branch it was created on.
-
False negative (merge not followed). A shadow branch whose base entered history via a merge's second parent — e.g. an in-progress session on a feature branch that is then merged into a non-default release — is judged unreachable (first-parent walk never visits second parents), so its in-progress checkpoints are dropped from release.
-
False positive (cross-branch leak). If the walk is made a full-DAG reachability walk to fix (1), then once a branch merges the default branch in, a shadow branch based on the default branch's own history becomes reachable and leaks its in-progress session checkpoints onto that unrelated branch.
Fixing (2) by pruning sharedWithMain (mirroring the committed path) then reintroduces a third harm:
- Fresh-branch hiding. On a brand-new branch (
git checkout -b feature && start coding), HEAD == the default branch's tip and the session's only possible base is that shared commit, so pruning shared history hides the active in-progress session until the first commit. This is the common branch-then-code workflow.
Why it's irreducible without new metadata
Harms (2) and (3) are the same topological case: a default-branch session (base = a default-branch commit) and a feature-session-at-the-branch-point (base = that same shared commit) have identical base + worktree hash. An in-place git checkout -b even shares the worktree hash, so worktree filtering can't disambiguate them either. At read time there is no signal to tell "master's session" from "feature's session that started at the branch point."
The clean fix is to persist the session's origin branch (or a branch-scoped session id) at session start, then filter shadow branches by origin at read time. That's a feature-sized change to the write path (manual-commit strategy shadow-branch creation), out of scope for #931 (which is a committed-checkpoint read-path bug).
Current state
The shadow path is intentionally left at its pre-existing first-parent-only behavior (see isShadowBranchReachable in cmd/entire/cli/explain.go). It matches the behavior that shipped before #931. This issue tracks making it merge-aware once session-origin metadata exists.
Related: #931 (committed-checkpoint counterpart).
Summary
isShadowBranchReachable(the read path for temporary / in-progress shadow-branch checkpoints, surfaced byentire checkpoint list/explain) uses a first-parent-only walk of HEAD's history. It is the ephemeral counterpart of the committed-checkpoint bug fixed in #931, but it is not merge-aware, and making it so is a genuine design decision (needs data we don't persist today), so it was deliberately left out of the #931 fix.The two harms (a tension, not a single bug)
A shadow branch is named
entire/<base-commit-short>-<worktreeHash>and records only its base commit (where the session started) plus the worktree hash — not the branch it was created on.False negative (merge not followed). A shadow branch whose base entered history via a merge's second parent — e.g. an in-progress session on a feature branch that is then merged into a non-default
release— is judged unreachable (first-parent walk never visits second parents), so its in-progress checkpoints are dropped fromrelease.False positive (cross-branch leak). If the walk is made a full-DAG reachability walk to fix (1), then once a branch merges the default branch in, a shadow branch based on the default branch's own history becomes reachable and leaks its in-progress session checkpoints onto that unrelated branch.
Fixing (2) by pruning
sharedWithMain(mirroring the committed path) then reintroduces a third harm:git checkout -b feature && start coding), HEAD == the default branch's tip and the session's only possible base is that shared commit, so pruning shared history hides the active in-progress session until the first commit. This is the common branch-then-code workflow.Why it's irreducible without new metadata
Harms (2) and (3) are the same topological case: a default-branch session (base = a default-branch commit) and a feature-session-at-the-branch-point (base = that same shared commit) have identical base + worktree hash. An in-place
git checkout -beven shares the worktree hash, so worktree filtering can't disambiguate them either. At read time there is no signal to tell "master's session" from "feature's session that started at the branch point."The clean fix is to persist the session's origin branch (or a branch-scoped session id) at session start, then filter shadow branches by origin at read time. That's a feature-sized change to the write path (manual-commit strategy shadow-branch creation), out of scope for #931 (which is a committed-checkpoint read-path bug).
Current state
The shadow path is intentionally left at its pre-existing first-parent-only behavior (see
isShadowBranchReachableincmd/entire/cli/explain.go). It matches the behavior that shipped before #931. This issue tracks making it merge-aware once session-origin metadata exists.Related: #931 (committed-checkpoint counterpart).