authorgravatar for maria@kuuro.netmaria <maria@kuuro.net> 2026-09-04 04:12:46-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-04 04:12:46-04:00
log5f878d2a85807618a4c8571cdef5daa3124672d6
tree1071e5e0d8dca7c48ed185d075a85f1977b10fc8
parentec3ec6f0b4e005c47aff07d4d9e31506241bce3a
signature Signed by PGP key B5690EEEBB952194

fix(web,mobile): fold context compaction under settled turn folds (#9623)

Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>

2 files changed, 24 insertions(+), 9 deletions(-)

apps/mobile/src/lib/threadActivity.ts+10-3
......@@ -1375,9 +1375,6 @@ function deriveThreadFeedTurnFolds(
13751375 pendingUserBoundary = entry.message.createdAt;
13761376 continue;
13771377 }
1378 if (entry.type === "activity-group" && isContextCompactionActivityGroup(entry)) {
1379 continue;
1380 }
13811378 const turnId =
13821379 entry.type === "message" && entry.message.role === "assistant"
13831380 ? entry.message.turnId
......@@ -1423,6 +1420,16 @@ function deriveThreadFeedTurnFolds(
14231420 if (hiddenEntryIds.size === 0) {
14241421 continue;
14251422 }
1423 // A lone compaction row stays visible on its own; it only folds away as
1424 // part of a turn that already folds other work.
1425 const hidesNonCompactionWork = entries.some(
1426 (entry) =>
1427 hiddenEntryIds.has(entry.id) &&
1428 !(entry.type === "activity-group" && isContextCompactionActivityGroup(entry)),
1429 );
1430 if (!hidesNonCompactionWork) {
1431 continue;
1432 }
14261433
14271434 const firstEntry = entries[0];
14281435 const firstHiddenEntry = entries.find((entry) => hiddenEntryIds.has(entry.id));
apps/web/src/components/chat/MessagesTimeline.logic.ts+14-6
......@@ -619,17 +619,15 @@ function deriveTurnFolds(input: {
619619 if (entry.id === group.terminalEntry?.id) {
620620 continue;
621621 }
622 if (index > terminalEntryIndex) {
622 const isCompaction =
623 entry.kind === "work" && entry.entry.sourceActivityKind === "context-compaction";
624 if (!isCompaction && index > terminalEntryIndex) {
623625 continue;
624626 }
625627 // Agent-spawn CTA rows never fold: workflows outlive their launching
626628 // turn (dynamic spawns, background execution), and folding the CTA
627629 // when the turn settles makes a still-running fleet invisible.
628 if (
629 entry.kind === "work" &&
630 (entry.entry.agentSpawn !== undefined ||
631 entry.entry.sourceActivityKind === "context-compaction")
632 ) {
630 if (entry.kind === "work" && entry.entry.agentSpawn !== undefined) {
633631 continue;
634632 }
635633 hiddenEntryIds.add(entry.id);
......@@ -637,6 +635,16 @@ function deriveTurnFolds(input: {
637635 if (hiddenEntryIds.size === 0) {
638636 continue;
639637 }
638 // A lone compaction row stays visible on its own; it only folds away as
639 // part of a turn that already folds other work.
640 const hidesNonCompactionWork = group.entries.some(
641 (entry) =>
642 hiddenEntryIds.has(entry.id) &&
643 !(entry.kind === "work" && entry.entry.sourceActivityKind === "context-compaction"),
644 );
645 if (!hidesNonCompactionWork) {
646 continue;
647 }
640648
641649 const firstEntry = group.entries[0];
642650 const firstHiddenEntry = group.entries.find((entry) => hiddenEntryIds.has(entry.id));