## Summary

All four specs implemented, formatted, linted clean, and tested.

### Spec 1 — Full summary in `--json` (`explain_export.go`)

- Extended `checkpointSessionSummary` with `Learnings`, `Friction`, `OpenItems` (matching upstream tags `learnings`/`friction`/`open_items`, all `omitempty`). Added nested `checkpointSessionLearnings` (repo/code/workflow, omitempty) and reused `checkpoint.CodeLearning` for code entries.
- New `summaryToExportJSON` helper populates them from `meta.Summary`, reusing the existing `hasAnyLearning` helper so an empty learnings block stays `nil` (no `{}` noise). Redaction is already applied upstream, so no new privacy surface.

### Spec 2 — Prose-list truncation visibility (`explain.go`)

- `runExplainBranchWithFilter` now probes `branchCheckpointsLimit+1`, slices to the cap, and prints a stderr note when checkpoints are hidden. Logic extracted into testable `capBranchCheckpoints`. Note wording is honest — "showing first 100 checkpoints (more exist); rerun with --json --limit <N> for more", never an exact remaining count. Threaded `errW` through the call chain.

### Spec 3 — Fast-fail `--generate` on imported (`explain.go`)

- Added a metadata-only `checkpoint.ReadCheckpoint` guard before `loadCheckpointForExplain`, so imported checkpoints are rejected before any transcript-blob fetch. Removed the now-redundant post-load guard.

### Spec 4 — Clearer no-trailer message (`explain.go`)

- Hint now reads "the commit exists but was not created during an Entire session (or its trailer was removed)", distinguishing a found-but-untracked commit from "commit not found".

### Tests

- `TestSessionMetadataToJSON_FullSummary` + `TestSessionMetadataToJSON_EmptySummaryStaysClean` (Spec 1)
- `TestCapBranchCheckpoints` with under/at/over-cap subtests (Spec 2)
- Added a `--generate`-on-imported rejection assertion to the existing `TestImportClaudeCode_EndToEnd` integration test (Spec 3)
- Spec 4 needed none (existing tests only assert the title, which is unchanged).
