# checkpoint: tier the read surface into CheckpointReader / SessionReader

`5a4925d`→[main](/content/gh/entireio/cli/commits/main/index.html)·

Soph·3w ago·10 files·+91 added/-48 removed

Mirror the write-side session/checkpoint split on reads: replace the mixed
PersistentReader/PersistentListReader with
CheckpointReader { Read, List } (checkpoint-level)
SessionReader { ReadSession{Content,Metadata,Prompts,MetadataAndPrompts} } (session-level)
and compose PersistentStore = CheckpointReader + SessionReader + Writer.

Helpers now take the minimal tier they need (ReadCheckpoint: CheckpointReader,
ReadLatestSessionContent: SessionReader); callers and stubs updated. Also drops
a now-dead type assertion in readSessionMetadataForExport (SessionReader
guarantees ReadSessionMetadata). No behavior change.

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

## Sessions

8e1b3d190167View transcript

[?\
Review Checkpoint Commit f16b7101Codex·GPT-5.5·1 step](/content/gh/entireio/cli/session/019eefbd-bb6a-7f51-a909-feb4cd95588d#timeline-8e1b3d190167/index.html)

## Changes

10

- cmd/entire/cli

- checkpoint

- Mpersistent_reader.go+31/-23

- Mpersistent_reader_test.go+17/-1

- Mexplain.go+1/-1

- Mexplain_export.go+5/-18

- Mexplain_export_test.go+20

- Mresume.go+1/-1

- Mresume_test.go+4

- Mreview_context.go+3/-3

- Mreview_context_test.go+8

```  
6 unmodified lines

7  
8  
9  
10  
11  
10  
11  
12  
13  
14  
13  
14  
15  
16  
17  
18  
15  
16  
17  
18  
19  
20  
21  
22  
22  
23  
24  
25  
26  
27  
28  
29  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
2 unmodified lines

39  
40  
41  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
48  
51  
52  
53  
54  
2 unmodified lines

57  
58  
59  
57  
58  
60  
61  
62  
63  
64  
5 unmodified lines

70  
71  
72  
70  
73  
74  
75  
76  
77  
78  
79  
80  
81

6 unmodified lines

"github.com/entireio/cli/cmd/entire/cli/checkpoint/id";
// PersistentReader provides read access to committed checkpoint data.
type PersistentReader interface {
// CheckpointReader provides read access to checkpoint-level persistent data.

nolint:revive // CheckpointReader stutter is accepted — the name marks the checkpoint (vs session) read tier.
type CheckpointReader interface {
	Read(ctx context.Context, checkpointID id.CheckpointID) (*CheckpointSummary, error)
	ReadSessionContent(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (*SessionContent, error)
}

// PersistentListReader provides read and list access to committed checkpoint data.
type PersistentListReader interface {
	PersistentReader
	List(ctx context.Context) ([]CheckpointInfo, error)
}

// SessionReader provides read access to session-level data within a checkpoint.
type SessionReader interface {
	ReadSessionContent(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (*SessionContent, error)
	ReadSessionMetadata(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (*Metadata, error)
	ReadSessionPrompts(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (string, error)
}

// PersistentStore provides the production committed checkpoint storage surface.
// Writes go through the unified Writer.Write(ctx, WriteRequest); the concrete
// per-operation methods (WriteCommitted/UpdateCommitted/...) remain on GitStore
// as the implementation Write dispatches to.
type PersistentStore interface {
	PersistentListReader
	ReadSessionMetadataAndPrompts(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (*SessionContent, error)
}

// PersistentStore provides the production persistent checkpoint storage surface:
// checkpoint-level reads, session-level reads, and the unified Write. Writes go
// through Writer.Write(ctx, WriteRequest); the concrete per-operation methods
// (writeSession/backfillTranscript/...) live on the git implementation as the
// methods Write dispatches to.
type PersistentStore interface {
	CheckpointReader
	SessionReader
	Writer
}

2 unmodified lines

GetCheckpointAuthor(ctx context.Context, checkpointID id.CheckpointID) (Author, error)
}

// ReadCheckpoint reads a committed checkpoint summary and normalizes
// a nil store response into ErrCheckpointNotFound.
func ReadCheckpoint(ctx context.Context, reader PersistentReader, checkpointID id.CheckpointID) (*CheckpointSummary, error) {
// ReadCheckpoint reads a checkpoint summary and normalizes a nil store response
// into ErrCheckpointNotFound.
func ReadCheckpoint(ctx context.Context, reader CheckpointReader, checkpointID id.CheckpointID) (*CheckpointSummary, error) {
	if err := ctx.Err(); err != nil {
		return nil, err //nolint:wrapcheck // Propagating context cancellation
	}

summary, err := reader.Read(ctx, checkpointID)
	if err != nil {
		return nil, fmt.Errorf("read committed checkpoint: %w", err)
		return nil, fmt.Errorf("read persistent checkpoint: %w", err)
	}
	if summary == nil {
		return nil, ErrCheckpointNotFound
2 unmodified lines

}

// ReadLatestSessionContent reads the latest session from an already-resolved
// committed reader and summary.
func ReadLatestSessionContent(ctx context.Context, reader PersistentReader, checkpointID id.CheckpointID, summary *CheckpointSummary) (*SessionContent, error) {
// session reader and summary.
func ReadLatestSessionContent(ctx context.Context, reader SessionReader, checkpointID id.CheckpointID, summary *CheckpointSummary) (*SessionContent, error) {
	if summary == nil || len(summary.Sessions) == 0 {
		return nil, ErrCheckpointNotFound
	}
5 unmodified lines

return content, nil
}

func ReadRawSessionLogForCheckpoint(ctx context.Context, reader PersistentReader, checkpointID id.CheckpointID) ([]byte, string, error) {
// ReadRawSessionLogForCheckpoint reads a checkpoint's latest-session transcript;
// it needs both reader tiers (resolve the checkpoint, then its latest session).
func ReadRawSessionLogForCheckpoint(ctx context.Context, reader interface {
	CheckpointReader
	SessionReader
}, checkpointID id.CheckpointID) ([]byte, string, error) {
	if err := ctx.Err(); err != nil {
		return nil, "", err //nolint:wrapcheck // Propagating context cancellation
	}
``
