feat(checkpoint): flag compact transcript via has_compact_transcript · Entire
feat(checkpoint): flag compact transcript via has_compact_transcript
278addd→main·
computermode·3w ago·5 files·+33 added/-11 removed
Add a has_compact_transcript boolean to the root metadata.json sessions[]
entries instead of repointing sessions[].transcript at transcript.jsonl.
The transcript pointer keeps targeting full.jsonl; the flag (omitted when
false) signals to external readers that a compact transcript.jsonl was
written alongside it. Derived from the actual tree entry so it can't drift
from what was written.
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Sessions
9c9ee0f533ffView transcript
?\
Add Compact Transcript Metadata FieldClaude Code·Opus 4.8·4 steps
Changes
5
MCLAUDE.md+1/-1
api/checkpoint
Mmetadata.go+10/-3
cmd/entire/cli/checkpoint
Mpersistent.go+7/-1
Mpersistent_compact_transcript_test.go+7/-1
docs/architecture
Msessions-and-checkpoints.md+8/-5
494 unmodified lines
495
496
497
498
498
499
500
501
494 unmodified lines
- **Worktree-specific branches** - each git worktree gets its own shadow branch namespace, preventing conflicts
- **Supports multiple concurrent sessions** - checkpoints from different sessions in the same directory interleave on the same shadow branch
- Condenses session logs to permanent `entire/checkpoints/v1` branch on user commits
- Each committed session stores the raw transcript (`full.jsonl`, read by CLI rewind/resume/explain) plus a best-effort compact transcript (`transcript.jsonl`, generated via `transcript/compact` and pre-sliced to the checkpoint's `checkpoint_transcript_start`). Both are pushed with the v1 branch. The root `metadata.json` `sessions[].transcript` pointer still targets `full.jsonl`; pointing it at `transcript.jsonl` is deferred to a later change.
- Uses the `post-rewrite` Git hook to keep local session linkage aligned after amend/rebase rewrites
- Builds git trees in-memory using go-git plumbing APIs
- Rewind restores files from shadow branch commit tree (does not use `git reset`)
MCLAUDE.md+1/-1
379 unmodified lines
380
381
382
383
384
385
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
379 unmodified lines
// Used in CheckpointSummary.Sessions to map session IDs to their file locations.
type SessionFilePaths struct {
Metadata string `json:"metadata"`
// Transcript points at the compact transcript.jsonl when one was
// generated, otherwise at the raw full.jsonl. Checkpoints written by
// older CLI versions always point at full.jsonl.
// Transcript points at the raw full.jsonl, which CLI read paths
// (rewind/resume/explain) resolve by filename. When a compact
// transcript.jsonl is also generated it is written into the same session
// directory alongside full.jsonl and signalled by HasCompactTranscript.
Transcript string `json:"transcript,omitempty"`
ContentHash string `json:"content_hash,omitempty"`
Prompt string `json:"prompt"`
// HasCompactTranscript is true when a compact transcript.jsonl was
// generated and written into this session's directory alongside full.jsonl.
// Omitted (false) for non-compactable, empty, or oversized transcripts and
// for checkpoints written by older CLI versions. When set, the compact file
// lives next to Transcript, named transcript.jsonl.
HasCompactTranscript bool `json:"has_compact_transcript,omitempty"`
}
// CheckpointSummary is the root-level metadata.json for a checkpoint.
Mapi/checkpoint/metadata.go+10/-3
405 unmodified lines
406
407
408
409
409
410
411
412
413
1 unmodified line
415
416
417
418
419
420
421
422
423
424
425
405 unmodified lines
// Write transcript. The pointer targets full.jsonl, which CLI
// rewind/resume/explain read by filename. The compact transcript.jsonl is
// also written into the tree (so it is pushed) but is not yet pointed at.
// also written into the tree (so it is pushed) and signalled to external
// readers via the HasCompactTranscript flag below.
wroteTranscript, err := s.writeTranscript(ctx, opts, sessionPath, entries)
if err != nil {
return filePaths, err
}
1 unmodified line
if wroteTranscript {
filePaths.Transcript = "/" + sessionPath + paths.TranscriptFileName
filePaths.ContentHash = "/" + sessionPath + paths.ContentHashFileName
// Signal the compact transcript.jsonl when writeTranscript wrote one
// into the tree (best-effort; skipped for non-compactable, empty, or
// oversized transcripts). Derived from the actual tree entry so the
// flag can never drift from what was written.
_, filePaths.HasCompactTranscript = entries[sessionPath+paths.CompactTranscriptFileName]
}
// Write prompts via the 7-layer pipeline. OPF runs only in the
Mcmd/entire/cli/checkpoint/persistent.go+7/-1
80 unmodified lines
81
82
83
84
84
85
86
87
6 unmodified lines
94
95
96
97
98
99
100
101
102
57 unmodified lines
160
161
162
163
164
165
166
167
168
80 unmodified lines
}
// Root metadata.json still points at full.jsonl; the compact transcript is
// written into the tree (and pushed) but not yet referenced by metadata.
// written into the tree (and pushed) and flagged via has_compact_transcript.
summary := readSummaryFromBranch(t, repo, cpID)
if len(summary.Sessions) != 1 {
t.Fatalf("session count = %d, want 1", len(summary.Sessions))
6 unmodified lines
if summary.Sessions[0].ContentHash != wantHash {
t.Errorf("sessions[0].content_hash = %q, want %q", summary.Sessions[0].ContentHash, wantHash)
}
if !summary.Sessions[0].HasCompactTranscript {
t.Error("sessions[0].has_compact_transcript = false, want true")
}
}
func TestWriteCommitted_CompactTranscriptScopedToCheckpointStart(t *testing.T) {
57 unmodified lines
if summary.Sessions[0].Transcript != wantTranscript {
t.Errorf("sessions[0].transcript = %q, want %q", summary.Sessions[0].Transcript, wantTranscript)
}
if summary.Sessions[0].HasCompactTranscript {
t.Error("sessions[0].has_compact_transcript = true for non-compactable transcript, want false")
}
}
// codexTranscriptWithCompactionBeforeStart returns a Codex-format JSONL
Mcmd/entire/cli/checkpoint/persistent_compact_transcript_test.go+7/-1
212 unmodified lines
213
214
215
216
217
218
216
217
218
219
220
221
222
223
12 unmodified lines
236
237
238
237
239
240
239
241
242
243
244
245
212 unmodified lines
`checkpoint_transcript_start`), `transcript.jsonl` is pre-sliced to the
checkpoint's own portion (`compact.Compact` is called with
`StartLine = checkpoint_transcript_start`), so it needs no offset to consume.
It is written into the checkpoint tree and pushed alongside `full.jsonl`, but
the root `metadata.json` `sessions[].transcript` pointer still targets
`full.jsonl`; pointing it at `transcript.jsonl` is deferred to a later change.
It is written into the checkpoint tree and pushed alongside `full.jsonl`. The
root `metadata.json` `sessions[].transcript` pointer keeps targeting
`full.jsonl`; when a compact transcript was generated the session entry also
carries `has_compact_transcript: true` (omitted otherwise) so external readers
can find `transcript.jsonl` next to it.
CLI read paths (rewind/resume/explain) read `full.jsonl` by filename. Compact
generation is best-effort: failures are logged but never fail the checkpoint
write, and during finalization a failed regeneration keeps the previous
12 unmodified lines
"sessions": [\
{\
"metadata": "/ab/c123def456/0/metadata.json",\
"transcript": "/ab/c123def456/0/transcript.jsonl",\
"transcript": "/ab/c123def456/0/full.jsonl",\
"content_hash": "/ab/c123def456/0/content_hash.txt",\
"prompt": "/ab/c123def456/0/prompt.txt"\
"prompt": "/ab/c123def456/0/prompt.txt",\
"has_compact_transcript": true\
}\
],\
"token_usage": {