checkpoint: tier the read surface into CheckpointReader / SessionReader · Entire
checkpoint: tier the read surface into CheckpointReader / SessionReader
5a4925d→main·
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
}
``