fix(checkpoint): keep rewind --list as deprecated JSON bridge · Entire

fix(checkpoint): keep rewind --list as deprecated JSON bridge

c9d8788→main· suhaanthayyil·2d ago·5 files·+52 added/-10 removed

Restore hidden --list on rewind so external scripts keep working, forwarding to checkpoint list --pending --json with a stderr migration hint (trail 869).

Co-authored-by: Cursor cursoragent@cursor.com

Changes

5

61 unmodified lines

62
63
64
65
65
66
67
68
16 unmodified lines

85
86
87
88
88
89
90
91

61 unmodified lines

// --json condensed checkpoints as JSON (branchCheckpointJSON shape)
// --pending live shadow-branch rewind points, human list
// --pending --json live shadow-branch rewind points as JSON — the drop-in
// replacement for the removed `rewind --list`
// replacement for the deprecated `rewind --list` bridge
//
// The condensed dataset (entire/checkpoints/v1 for the branch) and the pending
// dataset (strategy.GetRewindPoints; task checkpoints, logs-only points,
16 unmodified lines

Output modes:
  --json             Machine-readable JSON instead of the human view.
  --pending          Select the live shadow-branch rewind-point dataset.
  --pending --json   Rewind points as JSON (replaces the removed rewind --list).
  --pending --json   Rewind points as JSON (replaces the deprecated rewind --list).

Optionally filter condensed checkpoints by session ID with --session
(not applicable with --pending).

Mcmd/entire/cli/checkpoint_group.go+2/-2

10 unmodified lines

11
12
13
14
15
16
17
14
15
16
17
18
19
20
21
19 unmodified lines

41
42
43
43
44
44
45
46
47
48
49

10 unmodified lines

)

// pendingRewindPointJSON is the machine-readable shape emitted by
// `entire checkpoint list --pending --json`. It is byte-for-byte the JSON that
// the removed `rewind --list` produced, so downstream consumers (integration
// and e2e test harnesses, external scripts) that parsed `rewind --list` keep
// working unchanged after repointing to `checkpoint list --pending --json`.
// `entire checkpoint list --pending --json` (and the deprecated `rewind --list`
// bridge). It is byte-for-byte the JSON that `rewind --list` historically
// produced, so downstream consumers (integration and e2e test harnesses,
// external scripts) that parsed `rewind --list` keep working unchanged after
// repointing to `checkpoint list --pending --json`.
//
// The field set, JSON names, omitempty markers, and the RFC3339 Date encoding
// are load-bearing — this is a stable contract. CondensationID carries the
19 unmodified lines

const pendingRewindPointsLimit = 20

// runCheckpointPendingListJSON emits the live shadow-branch rewind points as
// JSON. This is the drop-in replacement for the removed `rewind --list`: same
// dataset (strategy.GetRewindPoints), same cap, same JSON shape.
// JSON. This is the drop-in replacement for (and the implementation behind)
// the deprecated `rewind --list` bridge: same dataset (strategy.GetRewindPoints),
// same cap, same JSON shape.
func runCheckpointPendingListJSON(ctx context.Context, w io.Writer) error {
    start := GetStrategy(ctx)

Mcmd/entire/cli/checkpoint_list.go+8/-6

18 unmodified lines

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
24
54
55
56
57

18 unmodified lines

"github.com/stretchr/testify/require"
}

// TestRewindListBridge_ForwardsToPendingJSON verifies the deprecated
// `rewind --list` bridge still works for external scripts: the JSON payload
// matches `checkpoint list --pending --json`, and stderr carries the
// migration hint. Cobra prints the command-level Deprecated notice to stdout
// before RunE (Printf); consumers already tolerate that — the bridge itself
// must not add further stdout noise (hint goes to stderr only).
func TestRewindListBridge_ForwardsToPendingJSON(t *testing.T) {
    setupCheckpointListRepo(t)

canonical := runListCmd(t, "--pending", "--json")

cmd := newRewindCmd()
    var stdout, stderr bytes.Buffer
    cmd.SetArgs([]string{"--list"})
    cmd.SetOut(&stdout)
    cmd.SetErr(&stderr)
    require.NoError(t, cmd.Execute(), "rewind --list failed; stderr: %s", stderr.String())

out := stdout.String()
    jsonStart := strings.IndexAny(out, "[{")
    require.GreaterOrEqual(t, jsonStart, 0, "stdout must contain a JSON payload; got: %q", out)
    require.Equal(t, canonical, out[jsonStart:],
        "rewind --list JSON payload must match checkpoint list --pending --json")
    require.Contains(t, stderr.String(),
        "note: 'rewind --list' is deprecated; use 'entire checkpoint list --pending --json'",
        "stderr must carry the migration hint")
    require.NotContains(t, out[jsonStart:], "deprecated",
        "bridge must not inject deprecation text into the JSON payload")
}
// 
// TestPendingRewindPointJSON_MatchesRewindListContract pins the machine-readable
// shape emitted by `checkpoint list --pending --json`. It must stay byte-for-byte
// compatible with the JSON the removed `rewind --list` produced, so consumers that
// compatible with the JSON `rewind --list` historically produced, so consumers that
// parsed rewind --list keep working after repointing.
// Field names, omitempty
// behavior, and the RFC3339 date encoding are the contract.
func TestPendingRewindPointJSON_MatchesRewindListContract(t *testing.T) {

Mcmd/entire/cli/checkpoint_list_test.go+31/-1

720 unmodified lines

721
722
723
724
724
725
726
727

720 unmodified lines

env.T.Helper()

// Run `checkpoint list --pending --json` using the shared binary. This is
    // the drop-in replacement for the removed `rewind --list`; the JSON shape is
    // the drop-in replacement for the deprecated `rewind --list` bridge; the JSON shape is
    // identical. Parse stdout only — any notice goes to stderr.
    cmd := exec.Command(getTestBinary(), "checkpoint", "list", "--pending", "--json")
    cmd.Dir = env.RepoDir

Mcmd/entire/cli/integration_test/testenv.go+1/-1

41 unmodified lines

42
43
44
45
46
47
48
28 unmodified lines

77
78
79
80
81
82
83
84
85
86
87
88
89
1 unmodified line

91
92
93
94
95
96
97
98

41 unmodified lines

}

func newRewindCmd() *cobra.Command {
    var listFlag bool
    var toFlag string
    var logsOnlyFlag bool
    var resetFlag bool
28 unmodified lines

external.DiscoverAndRegister(ctx)
            w := cmd.OutOrStdout()
            errW := cmd.ErrOrStderr()
            // --list is a hidden deprecated bridge for external scripts that still
            // invoke rewind --list. Same JSON bytes as checkpoint list --pending
            // --json; remove together with the rewind command itself.
            if listFlag {
                fmt.Fprintln(errW, "note: 'rewind --list' is deprecated; use 'entire checkpoint list --pending --json'")
                return runCheckpointPendingListJSON(ctx, w)
            }
            if toFlag != "" {
                return runRewindToWithOptions(ctx, w, errW, toFlag, logsOnlyFlag, resetFlag)
            }
1 unmodified line

},
}

cmd.Flags().BoolVar(&listFlag, "list", false, "List available rewind points (JSON output); deprecated, use checkpoint list --pending --json")
_ = cmd.Flags().MarkHidden("list") //nolint:errcheck // flag is defined above
cmd.Flags().StringVar(&toFlag, "to", "", "Rewind to specific commit ID (non-interactive)")
cmd.Flags().BoolVar(&logsOnlyFlag, "logs-only", false, "Only restore logs, don't modify working directory (for logs-only points)")
cmd.Flags().BoolVar(&resetFlag, "reset", false, "Reset branch to commit (destructive, for logs-only points)")