fix(dispatch): window reachable checkpoints by in-range commit time · Entire

fix(dispatch): window reachable checkpoints by in-range commit time

cf509f7→main·

alishakawaguchi·yesterday·2 files·+61 added/-7 removed

Bugbot review: reachableCheckpointIDsInRange recorded each checkpoint's latest referencing commit time with no upper bound, then the caller dropped entries outside [since, until). A checkpoint referenced by both an in-window commit and a later out-of-window commit stored the later time and was wrongly omitted despite qualifying in-window activity (reachable with an explicit past --until).

Bound the scan with --until and, authoritatively, skip any commit outside [since, until) in the parse loop, recording the max in-window time. A checkpoint is now present iff it has at least one in-window referencing commit, with an in-window timestamp.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com Claude-Session: https://claude.ai/code/session_01Wi6WfsYgVrWDrZXpu62u8u

Changes

2

167 unmodified lines

168
169
170
171
171
172
173
174
120 unmodified lines

295
296
297
298
299
300
301
302
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
2 unmodified lines

315
316
317
318
319
320
321
14 unmodified lines

336
337
338
339
340
341
342
343
344

167 unmodified lines

if len(branches) > 0 {
        currentBranch = branches[0]
    }
    reachableCheckpointIDs, err = reachableCheckpointIDsInRange(ctx, repoRoot, branchLocalRevRange(ctx, repoRoot, currentBranch), since)
    reachableCheckpointIDs, err = reachableCheckpointIDsInRange(ctx, repoRoot, branchLocalRevRange(ctx, repoRoot, currentBranch), since, until)
    if err != nil {
        return nil, err
    }
120 unmodified lines

}
// reachableCheckpointIDsInRange maps each checkpoint ID referenced by a commit
// trailer in revRange (since <cutoff>) to the most recent commit time that
// references it. The commit time is the "landed on this branch" timestamp,
// used both for membership checks and to window checkpoints that are fetched
// on demand by ID (whose CheckpointSummary carries no CreatedAt of its own).
func reachableCheckpointIDsInRange(ctx context.Context, repoRoot, revRange string, since time.Time) (map[string]time.Time, error) {
// trailer in revRange, within the window [since, until), to the most recent
// referencing commit time *that falls inside the window*. The commit time is
// the "landed on this branch" timestamp, used both for membership checks and to
// window checkpoints that are fetched on demand by ID (whose CheckpointSummary
// carries no CreatedAt of its own).
//
// Commits outside the window are ignored entirely, so a checkpoint referenced
// by both an in-window commit and a later out-of-window commit still records
// its in-window time (and is therefore not dropped by the caller's window
// check). git's --since/--until only bound the scan; the explicit in-loop check
// is authoritative for the half-open [since, until) boundary.
func reachableCheckpointIDsInRange(ctx context.Context, repoRoot, revRange string, since, until time.Time) (map[string]time.Time, error) {
    cmd := exec.CommandContext(
        ctx,
        "git",

2 unmodified lines

"log",
        revRange,
        "--since="+since.UTC().Format(time.RFC3339),
        "--until="+until.UTC().Format(time.RFC3339),
        "--grep",
        "Entire-Checkpoint:",
        "--format=%cI%x00%B%x00%x00",
        )
14 unmodified lines

if parseErr != nil {
        continue
    }
    if commitTime.Before(since) || !commitTime.Before(until) {
        continue
    }
    for _, checkpointID := range trailers.ParseAllCheckpoints(parts[1]) {
        idStr := checkpointID.String()
        if existing, ok := reachable[idStr]; !ok || commitTime.After(existing) {

Mcmd/entire/cli/dispatch/mode_local.go+17/-6

812 unmodified lines

813
814
815
816
816
817
818
819
820
12 unmodified lines

833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885

812 unmodified lines

t.Setenv("TEST_GIT_ARGS_FILE", argsFile)

since := time.Date(2026, 4, 1, 12, 30, 0, 0, time.UTC)
    reachable, err := reachableCheckpointIDsInRange(context.Background(), "/tmp/repo", "origin/main..HEAD", since)
    until := time.Date(2026, 5, 1, 12, 30, 0, 0, time.UTC)
    reachable, err := reachableCheckpointIDsInRange(context.Background(), "/tmp/repo", "origin/main..HEAD", since, until)
    if err != nil {
        t.Fatal(err)
    }
12 unmodified lines

if !strings.Contains(args, "--since=2026-04-01T12:30:00Z") {
        t.Fatalf("expected git log to bound history by since window, got args %q", args)
    }
    if !strings.Contains(args, "--until=2026-05-01T12:30:00Z") {
        t.Fatalf("expected git log to bound history by until window, got args %q", args)
    }
    if !strings.Contains(args, "origin/main..HEAD") {
        t.Fatalf("expected git log to use the supplied rev range, got args %q", args)
    }
}
// TestReachableCheckpointIDsInRange_KeepsInWindowTimeDespiteLaterCommit is the
// regression test for the bugbot finding: a checkpoint referenced by both an
// in-window commit and a later out-of-window commit must record its in-window
// time so the caller's [since, until) check does not drop it.
func TestReachableCheckpointIDsInRange_KeepsInWindowTimeDespiteLaterCommit(t *testing.T) {
    tmpDir := t.TempDir()
    gitPath := filepath.Join(tmpDir, "git")

// git log emits newest-first: the out-of-window commit (after until) comes
    // before the in-window commit, both referencing the same checkpoint. Only
    // the in-window one should be recorded.
    script := "#!/bin/sh\n" +
        "if [ \"$3\" = \"log\" ]; then\n" +
        "  printf '2026-06-15T10:00:00Z\000later subject\n\nEntire-Checkpoint: " + testCheckpointID + "\000\000'\n" +
        "  printf '2026-04-10T10:00:00Z\000in-window subject\n\nEntire-Checkpoint: " + testCheckpointID + "\000\000'\n" +
        "  exit 0\n" +
        "fi\n" +
        "exit 1\n"
    if err := os.WriteFile(gitPath, []byte(script), 0o755); err != nil {
        t.Fatal(err)
    }
    t.Setenv("PATH", tmpDir+string(os.PathListSeparator)+os.Getenv("PATH"))

since := time.Date(2026, 4, 1, 0, 0, 0, 0, time.UTC)
    ilop := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC)
    reachable, err := reachableCheckpointIDsInRange(context.Background(), "/tmp/repo", "HEAD", since, until)
    if err != nil {
        t.Fatal(err)
    }
    got, ok := reachable[testCheckpointID]
    if !ok {
        t.Fatalf("expected checkpoint %s to be reachable via its in-window commit, got %v", testCheckpointID, reachable)
    }
    want := time.Date(2026, 4, 10, 10, 0, 0, 0, time.UTC)
    if !got.Equal(want) {
        t.Fatalf("expected in-window commit time %s, got %s (later out-of-window commit leaked)", want, got)
    }
}

func TestLoadCommitSubjectsByCheckpoint_UsesSingleWindowedLogScan(t *testing.T) {
    tmpDir := t.TempDir()
    argsFile := filepath.Join(tmpDir, "git-args.txt")