Skip to content

Shadow/ephemeral checkpoint reachability isn't merge-aware (needs session-origin metadata) #1730

Description

@suhaanthayyil

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.

  1. 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.

  2. 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:

  1. 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions