fix(sessions): reserve the recent window before the fair assigned draw

The fair draw spent the whole assigned budget round-robin before the
recent cap was applied, and the keep loop then dropped every assigned
row it had not drawn. When the newest conversations cluster in one
project, that project loses its undrawn newest rows: with 11 projects x
20 sessions and all 20 newest in project-00, p0-19 appeared in neither
the default payload nor behind its project chip — a session the base
displays (2026-09-24 re-gate reproduction).

The rows the recent window itself would show (the first cli_cap CLI
rows in sort order, assigned or not) are now RESERVED before the draw,
and the remaining assigned budget spreads round-robin over the undrawn
rows only, so the reservation cannot double-spend a slot. Assigned rows
stay bounded by CLI_PROJECT_ASSIGNED_CAP in total.

The regression pins the literal reproduction; removing the reservation
makes it fail with the row dropped, as reported. The draw-first pins
were re-anchored to the reserve-then-draw contract.
This commit is contained in:
Rodrigo Gomes da Silva committed 2026-09-24 11:24:18 -03:00
1 parent 3d0a14e8e0
commit f62cdfe77a
2 files changed
+147 -16

No files matched your search

+33 -4
View File
@@ -10594,10 +10594,39 @@ def _cap_recent_cli_sessions(
project_id = str(session.get("project_id") or "").strip()
if project_id:
rows_by_project.setdefault(project_id, []).append(index)
drawn = (
None if project_cap <= 0
else _draw_assigned_cli_rows_fairly(rows_by_project, project_cap)
)
if project_cap > 0 and rows_by_project:
# Reserve the CLI rows the recent window already shows — the first
# ``cli_cap`` CLI rows in sort order, assigned or not — before the fair
# draw spreads the REST of the assigned budget across projects. Without
# this, a project holding all the newest sessions can lose its newest
# rows in the draw and the payload drops sessions the base displays
# (2026-09-24 re-gate reproduction: 11 projects x 20 sessions, all 20
# newest in one project, ``p0-19`` vanished from the payload).
reserved: set[int] = set()
seen_cli = 0
for index, session in enumerate(sessions):
if not _is_cli_session_for_settings(session):
continue
if seen_cli >= cli_cap:
break
seen_cli += 1
reserved.add(index)
# The reserved rows have already been paid for by the recent window;
# draw the remaining budget over the queues MINUS those rows, so the
# reservation cannot double-spend slots the draw would have granted.
remaining_rows_by_project: dict[str, list[int]] = {
project: [index for index in indices if index not in reserved]
for project, indices in rows_by_project.items()
}
assigned_reserved = sum(
1 for index in reserved
if str(sessions[index].get("project_id") or "").strip()
)
drawn = reserved | _draw_assigned_cli_rows_fairly(
remaining_rows_by_project, max(project_cap - assigned_reserved, 0)
)
else:
drawn = None if project_cap <= 0 else set()
kept = []
recent_seen = 0
unassigned_seen = 0