Skip to content

Matrix Memory plugin: document import path, codify Tier 1 read-only boundary, link to #141 #145

Description

@Interstellar-code

Context

Validated matrix-memory v0.1.0 end-to-end against the active provider
(see #141 for the broader MEMORY.md/USER.md scaling discussion — this
issue is complementary, not a duplicate).

Validation: 14/14 tools callable (5 base + 9 chat-mode), end-to-end
write→index→recall (FTS5 BM25) works, safety flow verified (dry_run
default in chat mode + confirm_token for destructive ops). Plugin
shippable as-is for v0.1.0. Reporting two improvements found during
validation, not blockers.

Improvement 1: plugin is undocumented how to import from outside the loader

The plugin directory is plugins/memory/matrix-memory/ (hyphenated
Python-illegal name). It only works because MemoryManager loads it
via importlib.util.spec_from_file_location(..., submodule_search_locations=[...]).
Anyone trying to use the plugin outside MemoryManager (validation
scripts, REPL tests, ad-hoc inspection) hits three cascading errors:

  1. from plugins.memory.matrix_memory import ...ImportError
    (hyphen in module name, illegal dot syntax)
  2. from provider import ... with plugin dir on sys.path
    ModuleNotFoundError: No module named \'tools.registry\' because
    the plugin's own directory shadows Hermes's top-level tools/
  3. spec_from_file_location(\'matrix_memory\', ...) (no
    submodule_search_locations) — ImportError: attempted relative import with no known parent package

Request: add a _smoke_test.py or tests/load_test.py that
exercises the register(ctx) flow with a mock ctx, plus a one-paragraph
note in the README explaining the import story. Bonus: a 3-line
load_matrix_memory(ctx) helper in __init__.py that handles the
spec dance, so external scripts don't reinvent it.

This is the same shape as plugins/memory/holographic/__init__.py:404
and plugins/memory/mem0/__init__.py:372 — they don't need a helper
because their directory names have no hyphens.

Improvement 2: codify the Tier 1 boundary

Currently memory_forget(kind="memory"|"user", target=...) and
memory_recall operate directly on $HERMES_HOME/memories/MEMORY.md
and USER.md. This is read + delete only (verified by reading
provider.py:124-135, 199-222, and tools.py:108-109) — no
write path into MEMORY.md/USER.md exists in matrix-memory today.

But the contract is implicit. A future contributor could easily
add a Tier 1 write to matrix-memory thinking "of course, facts go
in MEMORY.md" and break the design.

Request: add a docstring or class-level constant in provider.py
making the boundary explicit, e.g.:

# Tier 1 contract: matrix-memory is READ + DELETE ONLY on MEMORY.md / USER.md.
# All Tier 1 WRITES go through the built-in `memory` tool (agent/memory_tool.py).
# Rationale: MEMORY.md is the always-loaded hot path (frozen snapshot at
# session start, 2,200 char ceiling). Long-term memory belongs in Tier 2 (wiki)
# or Tier 3 (FTS5). See issues #141 + the design doc at
# docs/design/matrix-memory.md for the full rationale.

Plus a 1-line test in tests/test_provider.py asserting that
matrix-memory never writes to MEMORY.md/USER.md under any tool call.

Why this is related to #141

#141 is the scaling problem: MEMORY.md/USER.md as flat §-delimited
files hit context-window limits as the agent's working memory grows.
The proposed fix is to push long-term memory out of Tier 1 and into
the wiki (Tier 2) + FTS5 (Tier 3) — which is exactly the design
matrix-memory v0.1.0 implements.

This issue is the boundary enforcement piece: making sure the
contract is documented and tested so the split stays clean as the
codebase grows. The two issues are complementary; both should land
before v1.0.

What I am NOT asking for

  • Not asking for a code change to the import machinery itself.
    The hyphenated name is the right call (it's the user-facing
    plugin name, matches config.yaml's memory.provider value).
  • Not asking to remove the read/delete paths. Tier 1 is part of
    the system prompt snapshot — recall and forget on it are
    correct, just not write.
  • Not asking to break the existing memory_forget(kind="memory",...)
    API. Just asking to document why it exists and what it does/doesn't
    do.

Test evidence

  • venv/bin/python ... (validation script, available on request)
  • 17/12 MEMORY.md/USER.md entries verified via memory_status (Tier 1)
  • 0/0/0 wiki/fts counts before test, 1/1/3 after memory_ingest,
    0/0/0 after memory_forget (clean rollback)
  • All 14 tool calls return valid JSON; safety flow enforced in chat
    mode (dry_run default → confirm_token → apply)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpluginPlugin-related

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions