This is a patch release, and the headline is a bug that had been quietly inverting user instructions. If you use MEMORIA instruction extraction, upgrade, and then read the second half of this section.
The one that matters
MEMORIA extracts standing instructions from conversation. Its pattern for
negative instructions was not word-boundary anchored, so
never
matched inside
whenever.
The result was not a missed instruction. It was a stored inversion. On a production bank, the sentence "Good, whenever needed we can use it." was recorded as the standing instruction "never needed we can use it". The extractor stored the opposite of what the user said, and nothing about that is visible at write time.
All five locale patterns (en, de, ru, it, es) are now anchored with a leading word boundary. Genuine instructions are unaffected, including ones preceded by another word or punctuation.
If you have been running instruction extraction, audit your stored instructions. The fix stops new inversions. It cannot repair ones already written, because from the database's point of view they are ordinary instructions.
This came out of a 61-row production audit by @Axmr1, with the original diagnosis and fix approach from @Sanjays2402 and @Souptik96. Finding it required someone reading their own memory bank row by row. That is worth more than it sounds.
The rest
Recall crashed on its own schema default. The tool schema
declared
query_time
with a default of the empty string, but the parser mapped only
None
to "now", so a blank string fell through to the ISO parser and raised. Any
MCP harness that sends declared defaults could not call recall at all.
Blank values are now treated as unset, and the schema no longer advertises
a default that means "omitted".
Enhanced Recall served invalidated rows until TTL expiry. Invalidation now clears the query cache, including the persisted cache when the instance has no in-memory one of its own.
Catastrophic regex backtracking in version-string extraction. The pattern could be driven into exponential backtracking by Title-Case input, hanging every write and import on user-supplied content. Behavioural equivalence was verified across a 200,000-string fuzz with zero differences.
Also shipping here, carried from work that was versioned 3.15.0 but never published:
- The memory browser resolves default and named-bank databases correctly and opens them read-only, so a wrong path cannot create an empty database.
- A trim-before-embedding race no longer logs spurious storage failures when trimming removes a row before its embedding lands.
- Jina v2 base embedding models silently fell back to 384 dimensions. Those models output 768 but were missing from the dimension table, so they resolved to the unknown-model fallback. That is a silent dimension mismatch that corrupts similarity search for anyone using them, notably the Spanish and English bilingual model.
Why there is no 3.15.0 on PyPI
Because it was never released. The version existed in the source tree and had a dated changelog section, but no tag was ever cut, so nothing was built and nothing was published.
That left four surfaces disagreeing: the package said 3.15.1, PyPI said 3.14.0, the changelog implied 3.15.0 had shipped, and the two websites each reported a different one of those depending on which file they happened to read. The changes attributed to 3.15.0 are real and are in this release. The changelog keeps that section rather than folding it in, so the individual fixes stay attributable, with a note that they first reached users here.
What changed about releasing
A release touches three repositories: the package, the documentation site, and this one. Nothing coordinated them, which is how the above happened.
There is now a release script that does. It validates readiness across all three, bumps every version surface, promotes the changelog, regenerates the derived documentation, and drafts the announcements. It refuses to proceed when a changelog section is dated but untagged, which is exactly the state that produced the confusion. It also builds the package before you tag, because the release workflow builds after, and a failure there leaves a tag with no release and nothing published.
Upgrading
Run
pip install --upgrade 'mnemosyne-memory[embeddings]'.
No migration, no schema change, no configuration change.
Full notes on the v3.15.1 release page.

