checkpoint: tier the read surface into CheckpointReader / SessionReader · Entire

checkpoint: tier the read surface into CheckpointReader / SessionReader

3210376·

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

Changes

10

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
    }