Merge pull request #3028

This commit is contained in:
nesquena-hermes 2026-05-28 01:02:58 +00:00
commit d75bbfc90d
2 changed files with 130 additions and 2 deletions

View file

@ -2195,6 +2195,70 @@ def _has_live_sidebar_state(session: dict) -> bool:
)
def _is_intentionally_background_sidebar_session(session: dict) -> bool:
sid = str(session.get('session_id') or '')
source = session.get('source_tag') or session.get('source')
return source == 'cron' or sid.startswith('cron_')
def _preserve_messageful_sidebar_discoverability(
candidates: list[dict],
visible: list[dict],
) -> list[dict]:
"""Keep at least one messageful row per non-background conversation visible.
The normal sidebar filters intentionally hide empty drafts, cron/background
rows, and duplicate pre-compression snapshots. They must not make the only
messageful representative of a conversation disappear. If every visible row
for a lineage was filtered out, rescue the best hidden messageful row and
mark it so callers can surface or audit the degraded state.
"""
sessions_by_id = {
str(session.get('session_id')): session
for session in candidates
if session.get('session_id')
}
covered_roots = {
_sidebar_lineage_root_id(session, sessions_by_id)
for session in visible
if _sidebar_message_count(session) > 0
}
visible_ids = {
str(session.get('session_id'))
for session in visible
if session.get('session_id')
}
rescue_by_root: dict[str, dict] = {}
for session in candidates:
sid = str(session.get('session_id') or '')
if not sid or sid in visible_ids:
continue
if _sidebar_message_count(session) <= 0:
continue
if _is_intentionally_background_sidebar_session(session):
continue
root = _sidebar_lineage_root_id(session, sessions_by_id)
if root in covered_roots:
continue
current = rescue_by_root.get(root)
if current is None or (
_sidebar_message_count(session), _session_sort_timestamp(session)
) > (
_sidebar_message_count(current), _session_sort_timestamp(current)
):
rescued = dict(session)
rescued['discoverability_warning'] = 'rescued_messageful_hidden_session'
rescue_by_root[root] = rescued
if not rescue_by_root:
return visible
rescued_rows = sorted(
rescue_by_root.values(),
key=lambda session: (session.get('pinned', False), _session_sort_timestamp(session)),
reverse=True,
)
return visible + rescued_rows
def _prefer_fuller_snapshots_for_sidebar(sessions: list[dict]) -> list[dict]:
"""Expose a hidden snapshot when it is the fuller transcript for a lineage.
@ -2412,7 +2476,8 @@ def all_sessions(diag=None):
and not s.get('worktree_path')
)]
result = _prefer_fuller_snapshots_for_sidebar(result)
result = [s for s in result if not _hide_from_default_sidebar(s)]
visible_result = [s for s in result if not _hide_from_default_sidebar(s)]
result = _preserve_messageful_sidebar_discoverability(result, visible_result)
_strip_sidebar_internal_flags(result)
# Backfill: sessions created before Sprint 22 have no profile tag.
# Attribute them to 'default' so the client profile filter works correctly.
@ -2450,7 +2515,8 @@ def all_sessions(diag=None):
and not getattr(s, 'worktree_path', None)
)]
result = _prefer_fuller_snapshots_for_sidebar(result)
result = [s for s in result if not _hide_from_default_sidebar(s)]
visible_result = [s for s in result if not _hide_from_default_sidebar(s)]
result = _preserve_messageful_sidebar_discoverability(result, visible_result)
_strip_sidebar_internal_flags(result)
for s in result:
if not s.get('profile'):

View file

@ -0,0 +1,62 @@
"""Regression coverage for session sidebar discoverability invariants."""
def test_messageful_hidden_snapshot_is_preserved_when_no_visible_representative():
from api.models import _preserve_messageful_sidebar_discoverability
hidden_snapshot = {
"session_id": "root_snapshot",
"title": "Long conversation snapshot",
"message_count": 42,
"pre_compression_snapshot": True,
}
result = _preserve_messageful_sidebar_discoverability(
candidates=[hidden_snapshot],
visible=[],
)
assert [row["session_id"] for row in result] == ["root_snapshot"]
assert result[0]["discoverability_warning"] == "rescued_messageful_hidden_session"
def test_messageful_hidden_snapshot_stays_hidden_when_continuation_is_visible():
from api.models import _preserve_messageful_sidebar_discoverability
hidden_snapshot = {
"session_id": "root_snapshot",
"title": "Archived snapshot",
"message_count": 42,
"pre_compression_snapshot": True,
}
visible_tip = {
"session_id": "tip_session",
"parent_session_id": "root_snapshot",
"title": "Visible continuation",
"message_count": 50,
}
result = _preserve_messageful_sidebar_discoverability(
candidates=[hidden_snapshot, visible_tip],
visible=[visible_tip],
)
assert [row["session_id"] for row in result] == ["tip_session"]
def test_intentional_background_sessions_are_not_rescued_into_sidebar():
from api.models import _preserve_messageful_sidebar_discoverability
cron_row = {
"session_id": "cron_digest_001",
"title": "Digest",
"source_tag": "cron",
"message_count": 12,
}
result = _preserve_messageful_sidebar_discoverability(
candidates=[cron_row],
visible=[],
)
assert result == []