Merge trail: feat(checkpoint): add checkpoint list --json; migrate off rewind --list · Entire

Merge trail: feat(checkpoint): add checkpoint list --json; migrate off rewind --list

1ec80f6→main·suhaanthayyil·2d ago·12 files·+499 added/-103 removed

feat(checkpoint): add checkpoint list --json (machine-readable listing; migrate off rewind --list)

Changes

12

176 unmodified lines
176 unmodified lines
  /tmp/entire-bin hooks claude-code post-task

# Verify task checkpoint created
/tmp/entire-bin rewind --list | jq '.[] | select(.is_task_checkpoint == true)'
/tmp/entire-bin checkpoint list --pending --json | jq '.[] | select(.is_task_checkpoint == true)'

Test User Commits (Condensation)


M.claude/skills/test-repo/SKILL.md+1/-1

```
150 unmodified lines

```

M.claude/skills/test-repo/test-harness.sh+1/-1

```
79 unmodified lines

2. `entire.exe enable` — in a git repo with an agent installed
3. Start an agent session, make file changes
4. `git add . && git commit -m "test"` — hooks should fire (prepare-commit-msg, post-commit)
5. `entire.exe rewind --list` — should show checkpoint(s)
5. `entire.exe checkpoint list --pending --json` — should show checkpoint(s)
6. `entire.exe explain` — pager should use `more` by default

## Architecture Notes

```

MWINDOWS.md+1/-1

```
52 unmodified lines

```

...

// newCheckpointListCmd wraps the existing branch-default list view.
   // newCheckpointListCmd wraps the existing branch-default list view and adds
   // machine-readable (--json) and pending-rewind-point (--pending) modes.
   //
   // Dataset/format matrix:
   //
   // 	(default)            condensed checkpoints on the branch, human view (pager)
   // 	--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 deprecated `rewind --list` bridge
   //
   // The condensed dataset (entire/checkpoints/v1 for the branch) and the pending
   // dataset (strategy.GetRewindPoints; task checkpoints, logs-only points,
   // condensation IDs) are deliberately distinct — see issue #1767.

func newCheckpointListCmd() *cobra.Command {
       ...  
}

```

Mcmd/entire/cli/checkpoint_group.go+49/-3

```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

package cli

import (  
    ...
)

// pendingRewindPointJSON is the machine-readable shape emitted by
// `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
// checkpoint ID (RewindPoint.CheckpointID) for logs-only points; it is empty
// for shadow-branch (uncommitted) points. Do not change these without
// migrating every consumer.

type pendingRewindPointJSON struct {
    ID               string `json:"id"`
    Message          string `json:"message"`
    MetadataDir      string `json:"metadata_dir"`
    Date             string `json:"date"`
    IsTaskCheckpoint bool   `json:"is_task_checkpoint"`
    ToolUseID        string `json:"tool_use_id,omitempty"`
    IsLogsOnly       bool   `json:"is_logs_only"`
    CondensationID   string `json:"condensation_id,omitempty"`
    SessionID        string `json:"session_id,omitempty"`
    SessionPrompt    string `json:"session_prompt,omitempty"`
}

// pendingRewindPointsLimit caps how many live shadow-branch rewind points the
// pending views request. Matches the historical `rewind --list` cap of 20 so
// the migrated output is identical.
const pendingRewindPointsLimit = 20

// runCheckpointPendingListJSON emits the live shadow-branch rewind points as
// 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 {
    ...
}

// runCheckpointPendingListHuman prints the live shadow-branch rewind points in
// a human-readable list. `rewind --list` was JSON-only, so there is no legacy
// human output to mirror; this renders each point with the same label format
// the former interactive rewind picker used (see rewindPointLabel).
func runCheckpointPendingListHuman(ctx context.Context, w io.Writer) error {
    ...
}

// hasMultipleSessions reports whether the points span more than one session,
// which controls whether per-line session identifiers are shown.
func hasMultipleSessions(points []strategy.RewindPoint) bool {
    ...
}

// rewindPointLabel renders a single rewind point as a display label. Shared by
// the interactive rewind picker (runRewindInteractive) and the
// `checkpoint list --pending` human view so both stay in sync. When
// hasMultipleSessions is true, a sanitized session prompt is appended to help
// disambiguate concurrent sessions.
func rewindPointLabel(p strategy.RewindPoint, hasMultipleSessions bool) string {
    ...
}
}

```

Mcmd/entire/cli/checkpoint_list.go+144

package cli

import (
    ...
)

// 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.
func TestRewindListBridge_ForwardsToPendingJSON(t *testing.T) {
    ...
}

// TestPendingRewindPointJSON_MatchesRewindListContract pins the machine-readable
// shape emitted by `checkpoint list --pending --json`. It must stay byte-for-byte
// 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) {
    ...
}

// TestRunCheckpointPendingList_EmptyReturnsEmptyArray verifies the pending JSON
// view emits `[]` (not `null`) when there are no rewind points — the drop-in
// contract downstream JSON parsers rely on.
func TestRunCheckpointPendingList_EmptyReturnsEmptyArray(t *testing.T) {
    ...
}

// TestCheckpointListCmd_Routing drives the real `checkpoint list` command
// end-to-end and asserts each flag combination routes to the right
// dataset/renderer. The repo is seeded with a shadow checkpoint so the
// condensed dataset is non-empty; the pending dataset stays empty because
// GetRewindPoints requires active-session state (created by lifecycle hooks,
// exercised by the integration canary), which a raw ephemeral-store seed does
// not register — this also demonstrates the two datasets are distinct.
func TestCheckpointListCmd_Routing(t *testing.T) {
    ...
}

// TestCheckpointListCmd_SessionWithPendingErrors verifies --session is rejected
// with --pending (the pending dataset is session-agnostic, mirroring rewind --list).
func TestCheckpointListCmd_SessionWithPendingErrors(t *testing.T) {
    ...
}

// runListCmd executes `checkpoint list <args>` via the real cobra command and
// returns stdout. Entire must already be enabled in CWD (setup helpers do this).
func runListCmd(t *testing.T, args ...string) string {
    ...
}

// setupCheckpointListRepo initializes an enabled Entire repo with one commit in a
// temp CWD. No checkpoints are seeded.
func setupCheckpointListRepo(t *testing.T) (*git.Repository, string) {
    ...
}

// setupCheckpointListRepoWithShadowCheckpoint extends setupCheckpointListRepo by
// seeding a checkpoint on the v1 metadata branch with real code changes, so the
// condensed branch view is non-empty for routing tests.
func setupCheckpointListRepoWithShadowCheckpoint(t *testing.T) {
    ...
}

```

Acmd/entire/cli/checkpoint_list_test.go+280

```  
103 unmodified lines

```

Mcmd/entire/cli/integration_test/setup_cmd_test.go+3/-3

```  
719 unmodified lines

```

```

```

```

```

```