A chat's messages are deleted with the jobs behind them, and the user row now
carries its run, so retention can empty a conversation completely. When it does,
the `flow_conversation` row and the agent memory keyed on it are all that is
left, and nothing else collects them — `ai_agent_memory` has no job id for
retention to match on. Both delete paths (the retention sweep in
`windmill_common::jobs` and the `/jobs/delete` endpoint) now drop a conversation
that has no messages left, and its memory with it. The trigger is the emptiness,
so a partly-purged chat keeps what it still has.
Two statements rather than one CTE: a data-modifying CTE reads the snapshot from
before the message delete, so every conversation would still look non-empty.
Both halves are pinned by a test on each path.
Also from review: the rename endpoint bounds the title three short of the
column, since the helper appends an ellipsis; and `OpenAIResponsesSSEParser`
loses the reasoning field it never wrote — that stream has no reasoning-summary
event, so the value could only ever be empty.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QN7VboDEm9HAB1t4sMxMdE