-
Notifications
You must be signed in to change notification settings - Fork 76
bug: pinned messages lost after session resync #259
Description
Pinned messages are silently deleted whenever a session goes through a full message replacement sync. The pin is gone after the next server restart or when the SSE watcher triggers a resync on an active session.
Root Cause Research
ReplaceSessionMessages in internal/db/messages.go deletes all messages for a session and re-inserts them from the parsed source file. The pinned_messages table has a foreign key message_id ... REFERENCES messages(id) ON DELETE CASCADE, so the delete cascades and silently wipes all pins. The ordinal column in pinned_messages already exists as a stable re-attachment key but seems to not be used for this purpose.
ReplaceSessionMessages is called in two situations:
- All OpenCode sessions — on every SyncAll (every 15 minutes, or on manual sync)
- Any agent via SyncSingleSession — triggered by the SSE watcher fallback when a session file changes while the detail view is open and the watcher hasn't caught up within 5 seconds
Reproduction Steps
(note: I'm using copilot cli sessions, but feel free to try this with any other agent)
- Open a Copilot session in agentsview and pin a message
- Navigate to that session's detail view and leave it open
- In a terminal, touch the session file to simulate a file change:
touch <path-to-copilot-session-file> - Wait ~5 seconds for the SSE fallback sync to fire
- Refresh — the pin is gone
Proposed Fix
Before deletion, save (ordinal, note, created_at) for all existing pins. After the new messages are inserted, re-attach each saved pin by matching ordinal to the new message row. Pins for ordinals that no longer exist are dropped. Will put up a PR to showcase this and update this description