🐞 Bug Report
Describe the bug
Re-adding a peer that is already an active member of a session updates that membership's joined_at to the current database time.
This makes the otherwise idempotent “ensure this peer belongs to this session” operation move the start of an uninterrupted membership window. Workspace message searches using peer_perspective then exclude existing messages whose created_at falls before the newly advanced joined_at, so valid searches can become empty or incomplete.
The conflict path in src/crud/session.py::_get_or_add_peers_to_session() currently assigns joined_at = func.now() for every existing SessionPeer row. It does so both for a genuine rejoin (left_at IS NOT NULL) and for an already-active membership (left_at IS NULL).
Is this a regression?
Unknown. The behavior is present in v3.0.12 and current main at 3ee890fa6f55388abd23b7660fb726e14d83459d.
To reproduce
- Create a workspace, two peers, and a session containing both peers.
- Add a message whose timestamp is after the original
SessionPeer.joined_at.
- Add one of the still-active peers to the same session again through the normal add/ensure-peer path.
- Observe that the existing membership row's
joined_at advances even though left_at was already null.
- Search workspace messages with that peer as
peer_perspective.
- Observe that the existing message is omitted because the temporal filter requires
message.created_at >= session_peers.joined_at.
Directly querying the message without that temporal perspective constraint still finds it.
Expected behavior
- Re-adding an already-active peer is idempotent:
- preserve the original
joined_at;
- preserve the active membership's existing configuration.
- Re-adding a peer that previously left remains a genuine rejoin:
- assign a new
joined_at;
- clear
left_at;
- apply the supplied configuration.
- Existing
peer_perspective temporal boundary behavior remains unchanged.
A focused regression should prove that an existing message remains visible through perspective search after an active-peer re-add, while genuine rejoin behavior still starts a new membership window.
Environment
- Honcho Server: v3.0.12 and current
main at 3ee890fa6f55388abd23b7660fb726e14d83459d
- Database: PostgreSQL
Additional context
Current temporal-search tests seed membership timestamps directly, so they validate the search boundary but do not exercise the active-peer conflict update that changes the boundary later.
🐞 Bug Report
Describe the bug
Re-adding a peer that is already an active member of a session updates that membership's
joined_atto the current database time.This makes the otherwise idempotent “ensure this peer belongs to this session” operation move the start of an uninterrupted membership window. Workspace message searches using
peer_perspectivethen exclude existing messages whosecreated_atfalls before the newly advancedjoined_at, so valid searches can become empty or incomplete.The conflict path in
src/crud/session.py::_get_or_add_peers_to_session()currently assignsjoined_at = func.now()for every existingSessionPeerrow. It does so both for a genuine rejoin (left_at IS NOT NULL) and for an already-active membership (left_at IS NULL).Is this a regression?
Unknown. The behavior is present in v3.0.12 and current
mainat3ee890fa6f55388abd23b7660fb726e14d83459d.To reproduce
SessionPeer.joined_at.joined_atadvances even thoughleft_atwas already null.peer_perspective.message.created_at >= session_peers.joined_at.Directly querying the message without that temporal perspective constraint still finds it.
Expected behavior
joined_at;joined_at;left_at;peer_perspectivetemporal boundary behavior remains unchanged.A focused regression should prove that an existing message remains visible through perspective search after an active-peer re-add, while genuine rejoin behavior still starts a new membership window.
Environment
mainat3ee890fa6f55388abd23b7660fb726e14d83459dAdditional context
Current temporal-search tests seed membership timestamps directly, so they validate the search boundary but do not exercise the active-peer conflict update that changes the boundary later.