fix(strategy): defer checkpoint push only on a truly empty remote · Entire

fix(strategy): defer checkpoint push only on a truly empty remote

a05a6a8→main· ?
Karthik Rameshkumar·3d ago·1 file·+27 added/-21 removed

The first cut deferred whenever the push target had no *non-metadata* branch, which broke checkpoint sync to a remote that already carries entire/checkpoints/v1 but no user branch (the alternates canary seeds exactly this to force a non-fast-forward rebase).

The default-branch hazard #1743 guards against only exists when our push would create the remote's first branch — i.e. a truly empty remote. Once any head exists there, including a checkpoint branch from an earlier push, deferring cannot prevent the default being set and only blocks legitimate syncs. Narrow the guard to fire solely for a target with no refs/heads/*.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Sessions

01KXFWG7JGFND3AS833FDTQSJFView transcript

[?
Fix Checkpoint Push on Empty RemoteClaude Code·Opus 4.8[1m]·4 steps](/content/gh/entireio/cli/session/b46b1cd5-a38d-49b5-9758-c373a036b37f#timeline-01KXFWG7JGFND3AS833FDTQSJF/index.html)

Changes

1

59 unmodified lines

60
61
62
63
63
64
65
66
92 unmodified lines

159
160
161
162
163
164
165
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
169
178
179
180
181
11 unmodified lines

193
194
195
187
196
197
198
199
6 unmodified lines

206
207
208
200
209
210
211
212
2 unmodified lines

215
216
217
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
221
222
223
224
230
231
232
233

59 unmodified lines

if ps.pushDisabled {
        return nil
    }
    deferAutomaticCheckpointPush := protectFirstUserBranch && deferCheckpointPushUntilNormalBranch(ctx, ps)
    deferAutomaticCheckpointPush := protectFirstUserBranch && deferCheckpointPushOnEmptyRemote(ctx, ps)

// git-refs primary: push the per-checkpoint refs recorded in the push queue
    // instead of the single v1 branch. (A configured git-branch mirror's v1 ref
92 unmodified lines

return nil
}

// deferCheckpointPushUntilNormalBranch keeps Entire's metadata from becoming
// the first branch on a repository. Hosting providers such as GitHub can make
// the first branch their default, so a pre-push hook must not independently
// publish checkpoint metadata before the user's first normal branch lands.
// deferCheckpointPushOnEmptyRemote keeps Entire's metadata from becoming the
// first branch on a repository. Hosting providers such as GitHub make the first
// branch a repository's default, so a pre-push hook must not independently
// publish checkpoint metadata to a remote that has no branches yet: the user's
// own branch, pushed by the same git invocation right after this hook, must be
// the one to land first.
//
// The guard triggers only for a genuinely empty push target (no refs/heads/*).
// Once any branch exists there — including a checkpoint branch already present
// from an earlier push or a separate setup — our push can no longer be the one
// that establishes the default branch, so deferring would only block legitimate
// checkpoint syncs (e.g. a non-fast-forward v1 update) without preventing any
// harm.
//
// A separate checkpoint remote is intentionally exempt: it is a dedicated
// metadata store, rather than the repository the user is pushing to.
func deferCheckpointPushUntilNormalBranch(ctx context.Context, ps pushSettings) bool {
func deferCheckpointPushOnEmptyRemote(ctx context.Context, ps pushSettings) bool {
    if ps.hasCheckpointURL() {
        return false
    }
11 unmodified lines

if err != nil {
        // Fail closed for checkpoint publication: the user's git push continues
        // normally, while a later push can publish the pending metadata once the
        // remote is reachable and has a normal branch.
        // remote is reachable and has a branch.
        logging.Warn(ctx, "checkpoint push deferred: could not inspect remote branches",
            slog.String("remote", ps.remote),
            slog.String("error", err.Error()),
6 unmodified lines

if lsErr != nil {
            // Fail closed for checkpoint publication: the user's git push continues
            // normally, while a later push can publish the pending metadata once the
            // remote is reachable and has a normal branch.
            // remote is reachable and has a branch.
            logging.Warn(ctx, "checkpoint push deferred: could not inspect remote branches",
                slog.String("remote", ps.remote),
                slog.String("target", target),
2 unmodified lines

return true
        }

for _, line := range strings.Split(string(out), "\n") {
            fields := strings.Fields(line)
            if len(fields) != 2 {
                continue
            }
            branch := strings.TrimPrefix(fields[1], "refs/heads/")
            if branch != fields[1] && branch != paths.MetadataBranchName {
                return false
            }
            // A truly empty target (no heads) is the only case our metadata push
            // could make the repository's default branch. Any existing head means
            // it is safe to publish now.
            if strings.TrimSpace(string(out)) == "" {
                logging.Info(ctx, "checkpoint push deferred until the remote has a branch",
                    slog.String("remote", ps.remote),
                    slog.String("target", target),
            )
                return true
            }
        }

logging.Info(ctx, "checkpoint push deferred until a normal remote branch exists",
                slog.String("remote", ps.remote),
            )
        return true
    return false
}

// prePushCheckpointRefs drains the per-checkpoint push queue and batch-pushes the