Channel history fold drops messages introduced by the compaction-triggering checkpoint

Problem

The display fold (ChannelValuesReconstructor#channel_history, and #channel_changes) keeps conversation deltas and drops mid-stream compaction snapshots. When a compaction is triggered by a turn, the gateway re-seeds every channel as full compaction snapshots in that same group boundary (gitlab_workflow.py — is_compaction → _serialize_all_channels_full). The turn's own ui_chat_log messages can then exist only inside the dropped compaction snapshot, never as a surviving conversation delta.

The fold's comment names the collision risk ("a colliding compaction would lose the version's messages") but the compaction-triggering step is the unconsidered case.

Symptom (reported while testing Manual Retry + Compaction)

  • "Say 4" triggered a compaction; agent replied "4".
  • On page reload, "Say 4" and "4" disappear from the chat.
  • After sending "Say 5", they reappear — but after "Say 5", because the blob that carries them again sits later in chain order.

Repro

  1. Set CompactionConfig(max_recent_messages=4, trim_threshold=0.1) in duo_workflow_service/workflows/chat/workflow.py.
  2. Enable duo_workflow_incremental_checkpoints, duo_workflow_read_incremental_checkpoints, dw_read_blobs_graphql.
  3. Chat until a message triggers compaction ("Ran compaction" badge), reload the page.

Where

  • ee/lib/gitlab/duo_workflow/channel_values_reconstructor.rb — channel_history drops step_action == COMPACTION blobs unless they seed the base; channel_changes skips them unless index == 0.
  • Consumer: GraphQL messages/checkpoints under dw_read_blobs_graphql (IC-D25's display fold).

Acceptance criteria

  • Messages that first appear in the compaction-triggering checkpoint render after a reload, in their original position.
  • Ordering stays chronological across the compaction boundary (no reappearance after later messages).
  • A spec covering "delta content introduced only by a compaction snapshot".

Notes

  • Not a production incident: dw_read_blobs_graphql has never been enabled on gprd. It blocks enabling it (and everything downstream, #607029).
  • Related: the fold-vs-deletion family (IC-D13/IC-D54, #613975 (closed)).