Skip to content

Show pre-compaction conversation history in session view#63

Merged
delexw merged 3 commits intomainfrom
worktree-pre-compact-history
Apr 27, 2026
Merged

Show pre-compaction conversation history in session view#63
delexw merged 3 commits intomainfrom
worktree-pre-compact-history

Conversation

@delexw
Copy link
Copy Markdown
Owner

@delexw delexw commented Apr 27, 2026

What

When a Claude Code session is compacted, the pre-compaction conversation history was invisible in the UI. This PR makes it visible, fixes the compact summary display, and gives each kind of compaction marker its own distinct label.

Changes

image

Show pre-compaction messages (entry.rs, session.rs)

  • Added logical_parent_uuid and is_compact_summary fields to the Entry struct
  • compact_boundary entries (written by Claude Code when compaction occurs) have parentUuid: null but carry logicalParentUuid pointing to the last pre-compact message — resolve_live_chain_uuids now follows this link instead of stopping, so all pre-compact messages are included in the session view
  • Handles single compaction, multiple sequential compactions, and dead-end branches correctly

Classify compaction markers (classify.rs, chunk.rs, convert.rs)

  • isCompactSummary: true user entries (AI-generated summary injected after compaction) now produce CompactMsg { is_recap: false }ChunkType::Compactrole: "compact"
  • away_summary system entries (idle-return recap, previously also labelled "Context compacted") now produce CompactMsg { is_recap: true }ChunkType::Recaprole: "recap"
  • Legacy summary entries also produce is_recap: false
  • Added ChunkType::Recap variant to propagate the distinction through the pipeline

Render as message bubbles (MessageItem.tsx, MessageList.tsx, MessageDetail.tsx, global.css)

  • Removed CompactSeparator horizontal-line component; both roles now render through MessageItem using the same CSS structure as user/claude messages
  • role: "compact" → label "Compacted Message", CSS class message--compact
  • role: "recap" → label "Session Recap", CSS class message--compact
  • Added message__role--compact colour token and extended DisplayMessage role union to include "recap"

Tests

  • classify.rs: added 3 tests for logical_parent_uuid parsing; 3 tests for is_compact_summary parsing; 3 session-chain tests (single, double, dead-branch compaction); updated away_summary tests to assert is_recap: true; updated isCompactSummary test to assert is_recap: false
  • MessageList.test.tsx: replaced separator DOM assertions with message-bubble assertions for both compact and recap roles

delexw added 3 commits April 27, 2026 16:05
When Claude Code compacts a session it writes a compact_boundary entry
(type:"system", subtype:"compact_boundary") with parentUuid:null and
logicalParentUuid pointing to the last pre-compact message. This broke the
live-chain walk — the backward traversal from the live tip stopped at the
boundary because parentUuid was empty, leaving all pre-compact messages
invisible in the UI.

Changes:

entry.rs
- Add logical_parent_uuid field (from logicalParentUuid) so compact_boundary
  entries can carry the pre-compact chain link.
- Add is_compact_summary field (from isCompactSummary) to identify the
  AI-generated summary user entry Claude Code injects after compaction.

session.rs / resolve_live_chain_uuids
- When the backward walk reaches an entry whose parentUuid is empty but
  logicalParentUuid is set, follow logicalParentUuid instead of stopping.
  This makes all pre-compaction messages part of the live chain, so they
  appear in the session view just before the compaction separator.
- Handles multiple compactions correctly — each compact_boundary bridges
  to the previous chunk of pre-compact history.

classify.rs
- User entries with isCompactSummary:true are now classified as CompactMsg
  (rendered as a styled separator with the summary text) instead of appearing
  as a regular user turn alongside the real pre-compact messages they summarise.

Tests added: 3 in entry.rs, 3 in session.rs, 2 in classify.rs
The compact summary content is a multi-paragraph AI-generated text.
Rendering it inline as the separator label produced an unreadable wall
of text. Fix:

- Show 'Context compacted ▼' as the always-visible label (button)
- Full summary text only appears in a scrollable box when the user
  clicks to expand
- Export CompactSeparator from MessageList and import it in
  MessageDetail to avoid duplication
- Add CSS for .compact-separator__label and .compact-separator__summary
- Update test: assert label text and add expand/collapse test
- Add is_recap field to CompactMsg: true for away_summary entries (session
  recap on idle return), false for isCompactSummary/summary entries (actual
  compaction events)
- Add ChunkType::Recap variant; convert.rs maps it to role:recap in
  DisplayMessage, keeping role:compact for actual compaction
- Extend DisplayMessage role union to include recap
- Replace CompactSeparator horizontal-line UI with message-style bubble
  rendering: compact shows Compacted Message label, recap shows Session
  Recap label — same CSS structure as user/claude messages
- Remove CompactSeparator component; both compact and recap now go through
  MessageItem with message--compact CSS class
- Update tests: assert is_recap flag in classify tests; replace separator
  DOM assertions with message bubble assertions
@delexw delexw merged commit 0415a6c into main Apr 27, 2026
1 check passed
@delexw delexw deleted the worktree-pre-compact-history branch April 27, 2026 09:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant