v0.2.13

Chainlit/chainlitv0.2.13Aug 4, 2026by het0814

AI Summary

Addresses a major multi-type recall bug, hardens session storage against corruption, and fixes temporal recall correctness. It also introduces an open `source` label system and improves various integrations including MCP, LangGraph, and Claude Code.

Key Highlights

  • Fixed multi-type recall returning nothing by using OR logic instead of AND
  • Hardened session storage with atomic writes, improved Windows lock handling, and crash-safe persistence
  • Introduced open `source` label for per-writer attribution
  • Fixed temporal recall to correctly handle expired memories and date-only bounds

New Features

  • Open `source` label for per-writer attribution (enables any writer to stamp its own identifying label)

Full Release Notes

# Release Notes for v0.2.13

This release fixes a major **multi-type recall bug** (querying multiple memory types returned nothing because filters were AND'd instead of OR'd), hardens **session storage against corruption and races** (file permissions, atomic writes, Windows lock handling), closes a long batch of **temporal recall correctness bugs** (as-of/expired memories, date-only bounds, version-aware dedup, multi-line title corruption), and makes memory `source` an open per-writer attribution label instead of a fixed enum.

## New Features

- **Open `source` label for per-writer attribution** (`memanto/app/constants.py`,
  `memanto/app/core.py`, `memanto/app/models/__init__.py`)
  - `source` is no longer restricted to a fixed enum — any writer (CLI, MCP,
    LangGraph, Hermes, CrewAI, conversation-extraction, migration) can now
    stamp its own identifying label, enabling proper per-writer attribution in
    recall output instead of everything collapsing into a few generic values.

## Bug Fixes

- **Multi-type recall returned nothing** (`memanto/app/services/memory_read_service.py`)
  - Requesting more than one memory type built a query like
    `"#memory_type:fact #memory_type:preference"`, which Moorcheh's keyword
    syntax treats as an AND filter that no single document can satisfy — so
    multi-type recall silently returned zero results. Fixed to issue one query
    per type and union the results (now parallelized for latency).

- **Session storage hardening** (`memanto/app/services/session_service.py`,
  `memanto/app/utils/atomic_write.py`)
  - Session/secret files (which hold live bearer tokens) are now created with
    `0o700`/`0o600` permissions, symlinks are skipped rather than followed, and
    writes go through an atomic `O_EXCL` temp-file + `os.replace` pattern
    instead of writing in place.
  - Session lifecycle locks are now scoped per-agent (was a single global
    lock), renewal is serialized against termination, concurrent auto-renewal
    races are fixed, and external session-marker races are tolerated instead
    of raising.
  - Windows-specific: non-blocking lock retry via `msvcrt`, plus handling for
    additional `OSError` cases during session loading with improved error
    logging.
  - Sessions are now preserved across interrupted writes instead of being
    left corrupted mid-write.

- **Temporal recall correctness** (`memanto/app/services/memory_read_service.py`,
  `memanto/app/utils/temporal_helpers.py`)
  - `search_as_of` (point-in-time recall) now correctly recalls memories that
    were valid at the queried time but have since expired — it previously
    delegated to a helper that always filtered by *current* wall-clock time.
  - As-of deduplication is now version-aware: a delete-and-recreate update
    that briefly exposes both the old and new document with the same id no
    longer causes the wrong version to win against `created_before`.
  - Date-only `as_of` cutoffs (e.g. `"2026-06-01"`) are now detected by
    parsing instead of string shape, fixing rejection of valid ISO-8601 basic
    format dates; date-only end-of-day bounds now correctly keep the final
    sub-second of the day instead of dropping it.
  - "Yesterday" temporal recall is now bounded to that calendar day instead of
    a rolling 24h window.
  - `expires_at` values stored as `datetime` (not just ISO strings) are now
    handled correctly in the as-of expiry path.

- **Multi-line memory title corruption** (`memanto/app/core.py`,
  `memanto/app/services/memory_read_service.py`)
  - A title containing a newline broke the `"[TYPE] title\n\ncontent"`
    document round-trip — the reader's prefix regex couldn't cross the
    embedded newline, corrupting the parsed title/content split. Fixed with a
    partition-based parser that handles embedded newlines correctly.

- **`source_ref` dropped from recall responses** (`memanto/app/routes/memory.py`)
  - `source_ref` is now preserved end-to-end in recall API responses instead
    of being silently dropped.

- **MCP integration repairs** (`integrations/mcp/memanto_mcp/{lifecycle,tools}.py`)
  - Fixed `remember`, `list_agents`, `answer`, and `recall` MCP tools that had
    regressed; automatic agent creation is now restricted to avoid unexpected
    agent proliferation; each agent now gets an isolated session client
    initialized independently (was a shared/serial init path).

- **LangGraph store fixes** (`integrations/langgraph/langgraph_memanto/store.py`)
  - Repeated `put()` calls to the same key now correctly upsert (including
    under concurrent writers) instead of duplicating; removed a local lock-striping
    scheme and rate-limit fallback that masked real errors.

- **Config / metadata persistence made crash-safe** (`memanto/cli/config/manager.py`,
  `memanto/cli/connect/agent_registry.py`)
  - Config writes and local agent-metadata writes are now atomic; a corrupt
    local agent metadata file is treated as absent instead of breaking agent
    listing, and surfaces as a warning in the list payload; `connect` no
    longer duplicates global instruction paths; export caches are now isolated
    per backend (cloud vs on-prem) instead of bleeding into each other.
  - Memory sync now refreshes the export before syncing to a project (and
    reports the refreshed count) instead of syncing a stale cache.

- **Claude Code integration: turn anchoring and negation** (`integrations/claudecode/hooks/`,
  `memanto/app/services/memory_parsing_service.py`)
  - The `Stop` hook now distills only the current conversation turn instead of
    re-processing prior turns; turn anchoring and embedding-query bounds
    hardened, including bounding daily-summary embedding queries.
  - Negated preferences (e.g. "I don't like Python") are now classified as
    preferences instead of misfiled as instructions.

- **Answer generation called directly from the UI** (`memanto/app/clients/moorcheh.py`)
  - The Web UI's answer panel now calls the `answer` function directly through
    the client rather than an intermediate path that had drifted out of sync.

- **VoltAgent `defaultLimit` validation** (`sdks/typescript/src/integrations/voltagent.ts`)
  - `defaultLimit` is now validated at tool-construction time instead of
    failing later at call time.

- **on-prem: `moorcheh-client` 0.1.5 layout support** (`memanto/app/clients/backend.py`)
  - Adapted to the reorganized package layout shipped in `moorcheh-client`
    0.1.5.

## Tests

- New `tests/test_as_of_date_only_parsing.py`, `tests/test_as_of_expired_recall.py`,
  `tests/test_memory_read_multi_type.py`, `tests/test_session_summary_concurrency.py`,
  `tests/test_postcommit_summary_resilience.py`, `tests/test_title_newline_roundtrip.py`,
  `tests/test_moorcheh_user_config_compat.py`, `tests/test_daily_summary_query_length.py`,
  `tests/test_review_followups.py`.
- Large expansion of `tests/test_unit.py`, `tests/test_api.py`, and MCP/LangGraph
  integration test suites covering every fix above.

## Full Changelog

Full Changelog: https://github.com/moorcheh-ai/memanto/compare/v0.2.12...v0.2.13