From 8dc12713cad0f6f64c6ae0fd8ae97ec434ff79b7 Mon Sep 17 00:00:00 2001 From: nesquena-hermes Date: Sun, 14 Jun 2026 23:51:22 -0700 Subject: [PATCH] fix(sidebar): keep multiple messageful imported/CLI sessions discoverable (#4218) (#4232) * Fix imported lineage sidebar discoverability * chore(release): stamp v0.51.429 (Release OP) for #4218 --------- Co-authored-by: Dennis Soong Co-authored-by: nesquena-hermes --- CHANGELOG.md | 6 +++ api/models.py | 7 +++ ...test_session_discoverability_invariants.py | 51 +++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6fee957..19652a10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ ## [Unreleased] +## [v0.51.429] — 2026-06-15 — Release OP (preserve multiple messageful imported/CLI sessions in the sidebar) + +### Fixed + +- **Multiple imported / CLI sessions that share a lineage with a fuller pre-compression snapshot are no longer collapsed out of the sidebar.** The sidebar's "prefer the fuller snapshot" grouping would hide continuation rows behind a single snapshot even when several of those rows actually have their own messages — making real sessions undiscoverable. Now, when more than one messageful session shares the lineage, the continuations are kept visible; the single-inactive-continuation replacement and the fuller-snapshot preference (when only one row has messages) are unchanged. (#4218) + ## [v0.51.428] — 2026-06-15 — Release OO (bound non-git project-context file walk, #4164) ### Fixed diff --git a/api/models.py b/api/models.py index de7527d6..439a07ab 100644 --- a/api/models.py +++ b/api/models.py @@ -2716,6 +2716,13 @@ def _prefer_fuller_snapshots_for_sidebar(sessions: list[dict]) -> list[dict]: if newest_visible_ts > snapshot_ts: continue + messageful_visible = [ + session for session in visible + if _sidebar_message_count(session) > 0 + ] + if len(messageful_visible) > 1: + continue + continuation_ids_to_hide.update( str(session.get('session_id')) for session in visible diff --git a/tests/test_session_discoverability_invariants.py b/tests/test_session_discoverability_invariants.py index 4c553bee..74141eee 100644 --- a/tests/test_session_discoverability_invariants.py +++ b/tests/test_session_discoverability_invariants.py @@ -60,3 +60,54 @@ def test_intentional_background_sessions_are_not_rescued_into_sidebar(): ) assert result == [] + + +def _lineage_row(session_id, *, root="lineage", count=1, ts=1.0, snapshot=False, source="cli"): + return { + "session_id": session_id, + "title": session_id, + "source_tag": source, + "session_source": source, + "_lineage_root_id": root, + "message_count": count, + "user_message_count": 1 if count else 0, + "last_message_at": ts, + "updated_at": ts, + "pre_compression_snapshot": snapshot, + } + + +def test_fuller_snapshot_does_not_hide_multirow_imported_cli_lineage(): + """Multiple messageful imported/CLI rows in one lineage are user-facing segments.""" + from api.models import _prefer_fuller_snapshots_for_sidebar + + rows = [ + _lineage_row("imported-a", count=3, ts=100.0), + _lineage_row("imported-b", count=4, ts=200.0), + _lineage_row("snapshot", count=20, ts=300.0, snapshot=True), + ] + + result = _prefer_fuller_snapshots_for_sidebar(rows) + + assert [row["session_id"] for row in result] == [ + "imported-a", + "imported-b", + "snapshot", + ] + snapshot = next(row for row in result if row["session_id"] == "snapshot") + assert snapshot["_show_pre_compression_snapshot"] is True + + +def test_fuller_snapshot_still_replaces_single_inactive_continuation(): + """The existing single-continuation cleanup stays intact.""" + from api.models import _prefer_fuller_snapshots_for_sidebar + + rows = [ + _lineage_row("continuation", count=3, ts=100.0, source="webui"), + _lineage_row("snapshot", count=20, ts=300.0, snapshot=True, source="webui"), + ] + + result = _prefer_fuller_snapshots_for_sidebar(rows) + + assert [row["session_id"] for row in result] == ["snapshot"] + assert result[0]["_show_pre_compression_snapshot"] is True