Skip to content

fix: memory dedup race and episode end time going backwards - #44

Merged
alexeybe1kin merged 3 commits into
mainfrom
fix/relay-memorygate-2026-11-03
Nov 3, 2026
Merged

alexeybe1kin merged 3 commits into
mainfrom
fix/relay-memorygate-2026-11-03

Conversation

@alexeybe1kin

Copy link
Copy Markdown
Collaborator

Found by the GLM bug relay, confirmed by votes, reviewed by Claude.

  • Exact-match dedup checked, then inserted, so two concurrent writes of the same memory both got in. A Postgres transaction-scoped advisory lock on (agent, text) now serialises the check and the insert; SQLite (tests) skips it.
  • episode.occurred_end could be overwritten with an earlier time or None; it now only moves forward.

Local (services/api): 406 passed; file-size and package-boundary checks ok.

🤖 Generated with Claude Code

alexeybe1kin and others added 3 commits November 3, 2026 03:09
Two concurrent process_evidence calls with identical content for the same agent both run the ilike lookup before either commits, both pass the `if not memory` check, and both insert a Memory row and enqueue separate Qdrant upserts; if the owner then forgets one copy, the duplicate stays stored and vector-indexed, so 'forgotten' content is still recallable.

Found by the GLM relay (memorygate__services__api_p1__sec__0), confirmed by 3 votes and Corti.
Regression test to add: Run two concurrent process_evidence calls with identical content for the same agent and assert exactly one Memory row and one enqueued Qdrant upsert are produced, so a later forget of that memory leaves nothing recallable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reuse query only requires occurred_start >= evidence.occurred_at - 30min, so evidence dated up to 30 minutes before the episode's start sets occurred_end < occurred_start; and if evidence.occurred_at is None (the fallback at line 59), occurred_end is wiped to None, destroying a previously stored end time.

Found by the GLM relay (memorygate__services__api_p1__bugs__2), confirmed by 3 votes and Corti.
Regression test to add: Add a regression test that processes evidence with occurred_at earlier than an open episode's occurred_end (and separately with occurred_at None) and asserts the episode's occurred_end is unchanged rather than overwritten with an earlier or None timestamp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Lite

In Postgres `^` is exponentiation, so `hashtext(a) ^ hashtext(b)` is a float and
pg_advisory_xact_lock has no overload for it. Use the two-int form instead, key it
on the lowercased text (the lookup is case-insensitive), and only run it on
PostgreSQL: the SQLite test database has no advisory locks and the commit broke
tests/test_like_literal.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alexeybe1kin
alexeybe1kin merged commit 36c17ef into main Nov 3, 2026
3 checks passed
@alexeybe1kin
alexeybe1kin deleted the fix/relay-memorygate-2026-11-03 branch November 3, 2026 02:20
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