Skip to content

Add opt-in EvalOps memory sync#49

Merged
haasonsaas merged 1 commit intomainfrom
codex/evalops-memory-sync
Apr 21, 2026
Merged

Add opt-in EvalOps memory sync#49
haasonsaas merged 1 commit intomainfrom
codex/evalops-memory-sync

Conversation

@haasonsaas
Copy link
Copy Markdown
Collaborator

Summary

  • add off-by-default EvalOps Memory sync settings with chat, meeting, and journal category toggles
  • sync chat threads, meeting summaries, and journal entries to memory.v1.Store with deterministic Kestrel memory IDs
  • pass caller-supplied memory IDs through the existing StoreMemory path so local updates stay idempotent

Refs #15

Validation

  • npm ci --ignore-scripts
  • npm run build
  • git diff --check

Follow-up kept on #15

  • durable offline queue
  • export/wipe controls for cloud memory copies

@cursor
Copy link
Copy Markdown

cursor Bot commented Apr 21, 2026

PR Summary

Medium Risk
When enabled, this changes data egress behavior by uploading local chat/meeting/journal content to an external service; although gated by settings, the new background sync paths could surface privacy/perf issues if misconfigured or invoked unexpectedly.

Overview
Adds an opt-in EvalOps Memory sync feature, with new settings to enable syncing and independently toggle chat, meetings, and journal categories.

Introduces evalops/memory-sync to serialize local chat threads, meeting summaries (plus transcript excerpt), and journal entries into bounded payloads and store them in EvalOps Memory using deterministic kestrel-* IDs; these background sync calls are triggered after message creation / chat finalize, meeting summary generation, and journal upsert/generation.

Updates the EvalOps memory store path to accept and forward a caller-supplied id (EvalOpsStoreMemoryRequest.id) so repeated syncs update the same remote memory record instead of creating duplicates.

Reviewed by Cursor Bugbot for commit 5c6552f. Bugbot is set up for automated code reviews on this repo. Configure here.

@haasonsaas haasonsaas merged commit f170dc4 into main Apr 21, 2026
5 checks passed
@haasonsaas haasonsaas deleted the codex/evalops-memory-sync branch April 21, 2026 10:35
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before autofix could start.

Reviewed by Cursor Bugbot for commit 5c6552f. Configure here.

Comment thread src/main/ipc/handlers.ts
.set({ updatedAt: new Date(now) })
.where(eq(schema.threads.id, data.threadId))
.run()
syncChatThreadMemoryInBackground(data.threadId)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chat memory sync race can overwrite complete data

Medium Severity

Every chat turn triggers syncChatThreadMemoryInBackground twice on the same memory ID: first from the messages:create IPC handler (capturing only the user message), and then from finalize in presenter-agent.ts (capturing both user and assistant messages). If the first sync's network call is delayed beyond the LLM response time, it can complete after the second sync, overwriting the complete conversation snapshot with a stale, user-message-only version. The renderer calls these sequentially (messages:create then ai:chatStream), confirmed in chatStore.ts and hummingbird/App.tsx.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5c6552f. Configure here.

'',
meeting.summary,
meeting.transcript ? `\nTranscript excerpt:\n${meeting.transcript.slice(0, 4_000)}` : ''
].filter(Boolean).join('\n'))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter(Boolean) removes intentional blank line separators

Low Severity

The filter(Boolean) in syncMeetingSummaryMemory and syncJournalEntryMemory is meant to strip conditional empty-string entries (e.g. when audioPath or tldr is absent), but it also silently removes the intentional '' blank-line separators between the metadata header and the content body. This is inconsistent with syncChatThreadMemory, which uses .join('\n') without filter(Boolean) and correctly preserves its blank line. The result is that meeting and journal memory content has no visual separation between metadata and body text.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5c6552f. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant