fix: compare legacy reset children against the parent's started_at, not ended_at

The reopen backfill guard `child.started_at >= parent.ended_at` compared against
the parent's CURRENT end boundary. A genuine markerless legacy reset child whose
parent was later reopened and re-ended has started_at earlier than that second
boundary, so it was no longer frozen with `_reset_from`; once end_reason cleared
it dropped out of /sessions as ephemeral — the multi-cycle gateway-peer shape the
issue describes. Comparing against the parent's started_at still rejects
children that predate the parent while keeping every earlier-boundary reset
child; the marker and source exclusions are unchanged.

Review finding: cycled parent's earlier reset child lost its `_reset_from` stamp and vanished from the session list on reopen.
This commit is contained in:
teknium1
2026-09-14 21:29:03 -07:00
committed by Teknium
parent 61e8f1cd82
commit 5ffdf823ae
2 changed files with 30 additions and 4 deletions

View File

@@ -448,9 +448,10 @@ class SessionSessionsMixin:
return changed
def reopen_session(self, session_id: str) -> None:
"""Clear ended_at/end_reason so a session can be resumed; first freeze only legacy reset children
whose creation order proves they followed the reset. The shared legacy predicate keeps list-time
compatibility broad, while this durable backfill must not overwrite explicit fork provenance."""
"""Clear ended_at/end_reason so a session can be resumed; first freeze markerless legacy reset
children, skipping explicit fork/delegate provenance and children that predate the parent itself.
The guard compares against the parent's started_at, not its current ended_at: a parent that was
reopened and re-ended later still owns reset children from its earlier boundaries."""
def _do(conn):
conn.execute(
"UPDATE sessions AS child SET model_config = json_set("
@@ -459,7 +460,7 @@ class SessionSessionsMixin:
f"AND {_sql_json_extract('child.model_config', '$._branched_from')} IS NULL "
f"AND {_sql_json_extract('child.model_config', '$._delegate_from')} IS NULL "
"AND COALESCE(child.source, '') != 'tool' "
"AND child.started_at >= (SELECT p.ended_at FROM sessions p WHERE p.id = child.parent_session_id) "
"AND child.started_at >= (SELECT p.started_at FROM sessions p WHERE p.id = child.parent_session_id) "
f"AND {_legacy_reset_child_sql('child', _session_ids_placeholders(_RESET_END_REASONS))}",
(session_id, *_RESET_END_REASONS),
)