fix(sessions): return archived pins from the sidebar back-fill

The include_pinned query reused the listing WHERE, including archived = 0.
The sidebar lists with include_archived=False, so a pinned row stamped
archived never back-filled. Rebuild that query without the archived
constraint and keep the other filters. The stale sweep already skips pins.
This commit is contained in:
brooklyn!
2026-09-24 05:57:33 -05:00
parent 4573438877
commit d85ab85fc6
2 changed files with 117 additions and 5 deletions

View File

@@ -1267,7 +1267,9 @@ class SessionSessionsMixin:
) -> List[Dict[str, Any]]:
"""List sessions with preview and ``last_active`` in one query. ``order_by_last_active`` sorts
by the chain TIP via a recursive CTE (the only path honouring ``id_query`` / ``search_query``);
``include_pinned`` back-fills pins the page missed, still obeying the other filters."""
``include_pinned`` back-fills pins the page missed, still obeying the other
filters except archived: a pin is an explicit keep, so a pinned row stamped
archived must still return."""
self.flush_token_counts() # rows carry token/cost totals
where_clauses, params = _session_filter_where(
exclude_children=not include_children, source=source, sources=sources, session_key=session_key,
@@ -1281,7 +1283,6 @@ class SessionSessionsMixin:
if not include_hidden and not archived_only:
where_clauses.append("s.hidden = 0")
where_sql = _where_sql(where_clauses)
base_where_params = list(params) # pinned back-fill reuses the WHERE before LIMIT/OFFSET
# Shared projection head of the three list queries (whitespace is part of the SQL text).
select_head = (
f"SELECT {self._compact_session_cols() if compact_rows else 's.*'}"
@@ -1342,17 +1343,27 @@ class SessionSessionsMixin:
params.extend([limit, offset])
sessions = [self._list_row(row) for row in self._read_all(query, params)]
# Pinned back-fill runs BEFORE compression projection so a back-filled root
# projects to its tip like any other row.
# projects to its tip like any other row. Do not inherit the archived
# constraint: the sidebar lists with include_archived=False, and a pin
# must stay reachable even when that row is also archived.
if include_pinned:
seen_ids = {s["id"] for s in sessions}
pinned_where = f"{where_sql} AND s.pinned = 1" if where_sql else "WHERE s.pinned = 1"
pinned_clauses, pinned_params = _session_filter_where(
exclude_children=not include_children, source=source, sources=sources,
session_key=session_key, exclude_sources=exclude_sources, cwd_prefix=cwd_prefix,
min_message_count=min_message_count, archived_only=False, include_archived=True,
)
if not include_hidden and not archived_only:
pinned_clauses.append("s.hidden = 0")
pinned_clauses.append("s.pinned = 1")
pinned_where = _where_sql(pinned_clauses)
pinned_query = f"""
{select_head}{_sql_session_last_active("s")} AS last_active
{from_sessions}
{pinned_where}
ORDER BY s.started_at DESC
"""
for row in self._read_all(pinned_query, base_where_params):
for row in self._read_all(pinned_query, pinned_params):
s = self._list_row(row)
if s["id"] not in seen_ids:
seen_ids.add(s["id"])