memtrust-cli 0.3.2__tar.gz → 0.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/CHANGELOG.md +69 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/CONTRIBUTING.md +43 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/PKG-INFO +174 -85
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/README.md +172 -84
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/docs/methodology.md +152 -24
- memtrust_cli-0.3.4/leaderboard/data.json +75 -0
- memtrust_cli-0.3.4/leaderboard/mem0_direct-2026-07-20.json +300 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/memtrust-cli/package.json +11 -7
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/pyproject.toml +2 -1
- memtrust_cli-0.3.4/src/memtrust/__init__.py +26 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/cli.py +62 -15
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_cli.py +101 -1
- memtrust_cli-0.3.4/tests/test_init.py +87 -0
- memtrust_cli-0.3.2/leaderboard/data.json +0 -60
- memtrust_cli-0.3.2/src/memtrust/__init__.py +0 -11
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/.github/CODEOWNERS +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/.github/workflows/ci.yml +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/.github/workflows/publish-pypi.yml +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/.gitignore +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/.pre-commit-config.yaml +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/LICENSE +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/SECURITY.md +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/docs/assets/dev-to-demos/demo-1-zero-credentials.gif +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/docs/assets/dev-to-demos/demo-2-fictional-api-discovery.gif +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/docs/assets/dev-to-demos/demo-3-cli-surface.gif +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/docs/assets/dev-to-demos/demo-4-temporal-kg-tests.gif +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/docs/demo.gif +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/docs/usage.gif +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/leaderboard/index.html +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/memtrust-cli/LICENSE +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/memtrust-cli/README.md +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/memtrust-cli/bin/memtrust.js +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-darwin-arm64/LICENSE +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-darwin-arm64/README.md +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-darwin-arm64/package.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-darwin-x64/LICENSE +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-darwin-x64/README.md +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-darwin-x64/package.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-linux-arm64/LICENSE +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-linux-arm64/README.md +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-linux-arm64/package.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-linux-x64/LICENSE +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-linux-x64/README.md +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-linux-x64/package.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-win32-arm64/LICENSE +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-win32-arm64/README.md +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-win32-arm64/package.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-win32-x64/LICENSE +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-win32-x64/README.md +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/platforms/@memtrust-cli-win32-x64/package.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/npm/scripts/fetch-binary.js +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/adapters/__init__.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/adapters/base.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/adapters/mem0_adapter.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/adapters/mem0_direct_adapter.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/adapters/mempalace_adapter.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/adapters/openviking_adapter.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/adapters/zep_graphiti_adapter.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/adapters/zep_graphiti_selfhosted_adapter.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/__init__.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/compression.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/contradiction.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/crash_recovery.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/embedder_cost.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/embedding_drift.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/episode_temporal_leak.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/extraction_quality.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/filter_injection.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/language_degradation.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/lock_contention.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/locomo.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/longmemeval.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/mempalace_metadata_scale.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/migration_rollback.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/orphan_cleanup.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/ranking_quality.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/resource_sync_safety.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/result_consistency.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/scale_fixtures.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/scale_stress.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/stats_accuracy.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/evals/temporal_kg_boundary.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/receipt.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/scoring/__init__.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/scoring/cost_tracker.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/src/memtrust/scoring/llm_judge.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/compression_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/contradiction_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/crash_recovery_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/embedding_drift_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/extraction_quality_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/filter_injection_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/language_degradation_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/locomo_sample.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/longmemeval_sample.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/migration_rollback_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/orphan_cleanup_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/ranking_quality_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/resource_sync_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/fixtures/result_consistency_cases.json +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_adapters.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_compression.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_episode_temporal_leak.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_evals.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_lock_contention.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_mem0_direct_adapter.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_mempalace_metadata_scale.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_receipt.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_scale_stress.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_scoring.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_stats_accuracy.py +0 -0
- {memtrust_cli-0.3.2 → memtrust_cli-0.3.4}/tests/test_temporal_kg_boundary.py +0 -0
|
@@ -3,6 +3,75 @@
|
|
|
3
3
|
All notable changes to this project are documented here. Format loosely follows
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
5
|
|
|
6
|
+
## [0.3.3] - 2026-07-21
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- **`memtrust --version` was still broken on the `memtrust` mirror package.** 0.3.2's fix
|
|
11
|
+
hardcoded the distribution-name lookup to `"memtrust-cli"`, which fixed that package but broke
|
|
12
|
+
`pip install memtrust` the same way in reverse: that environment has no `memtrust-cli` entry in
|
|
13
|
+
its own installed-package metadata, so the lookup always missed and fell through to
|
|
14
|
+
`0.0.0+unknown` again. `src/memtrust/__init__.py` now tries `memtrust-cli` first, falls back to
|
|
15
|
+
`memtrust`, and only reports `0.0.0+unknown` if neither distribution name is installed.
|
|
16
|
+
Independently reproduced against a clean `pip install memtrust==0.3.2` before this fix.
|
|
17
|
+
- `memtrust run --help`'s `--eval` flag description was a hand-maintained string literal that had
|
|
18
|
+
drifted out of sync with the real `ALL_EVALS` list -- it was still missing `temporal_kg_boundary`
|
|
19
|
+
even though the eval itself worked correctly. Now generated directly from `ALL_EVALS`, so it
|
|
20
|
+
can't drift again.
|
|
21
|
+
- `npm/memtrust-cli/package.json`'s `optionalDependencies` pinned the 6 platform packages
|
|
22
|
+
(`@memtrust-cli/darwin-x64` etc.) to an exact `0.1.0`, which had already drifted from the
|
|
23
|
+
actually-published `0.1.1`. Changed to `^0.1.1` so patch releases of the platform packages
|
|
24
|
+
resolve automatically instead of drifting stale again.
|
|
25
|
+
- CI had been failing on every push since the 0.3.2 commit (`ruff format --check` alone, every
|
|
26
|
+
other job green) -- only `ruff check` had been run locally, not the separate formatting check.
|
|
27
|
+
- README.md's "Success stories" section cited MemPalace/mempalace#524 (@gaby) as the source of a
|
|
28
|
+
ChromaDB-network-dependency finding. That citation was fabricated: the real issue #524 is
|
|
29
|
+
titled "Remove Baldfaced Lies Please," filed by a different user, about unrelated content, and
|
|
30
|
+
no user named "gaby" has filed anything in that repository. The underlying technical claim
|
|
31
|
+
(documented separately in `mempalace_adapter.py`'s own module docstring) is real; the citation
|
|
32
|
+
attributing it to a specific reported issue was not. Removed the bullet. Every other citation in
|
|
33
|
+
the section (~32 across MemPalace, mem0, Zep/Graphiti, OpenViking, and one cross-project
|
|
34
|
+
citation) was independently re-verified against the live GitHub API and confirmed accurate.
|
|
35
|
+
- README.md's pasted `pytest --cov` output and coverage table were stale relative to the actual
|
|
36
|
+
test suite (585 passed / 93% vs. the real 589 passed / 93%); refreshed, and the table now notes
|
|
37
|
+
explicitly that it's an 11-of-33-module excerpt rather than implying completeness.
|
|
38
|
+
- README.md's mem0#4884 success-story bullet credited `LanguageDegradationSignal` without
|
|
39
|
+
disclosing that eval isn't wired into `memtrust run --eval` (it's `Mem0DirectAdapter`-specific,
|
|
40
|
+
requiring `query(explain=True)`) -- added the same honest not-yet-wired-in caveat this project
|
|
41
|
+
uses for every other eval in the same situation.
|
|
42
|
+
|
|
43
|
+
## [0.3.2] - 2026-07-20
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- `memtrust --version` always printed `0.0.0+unknown`, even when properly installed,
|
|
48
|
+
because `src/memtrust/__init__.py` read `importlib.metadata.version("memtrust")`
|
|
49
|
+
instead of `version("memtrust-cli")`, the actual installed distribution name. Now
|
|
50
|
+
reads the correct key and matches `pip show memtrust-cli`.
|
|
51
|
+
- The Python sdist ballooned to 142MB because `npm/platforms/*/bin/` (locally-staged
|
|
52
|
+
`uv` binaries used to build the npm platform packages, ~350MB across 6 platforms)
|
|
53
|
+
was untracked and ungitignored, so hatchling's default sdist inclusion swept it in.
|
|
54
|
+
Excluded via `.gitignore` and an explicit `[tool.hatch.build.targets.sdist]` exclude.
|
|
55
|
+
- `Mem0DirectAdapter` now passes `is_reasoning_model=True` to work around a real
|
|
56
|
+
`mem0ai==2.0.12` bug: its default LLM model (`gpt-5-mini`) is not recognized by its
|
|
57
|
+
own reasoning-model detection (which checks for the different string
|
|
58
|
+
`gpt-5o-mini`), so every LLM-based extraction call sent `temperature=0.1` to a model
|
|
59
|
+
that only accepts the API default, 400ing on every call out of the box for anyone
|
|
60
|
+
with just `OPENAI_API_KEY` set.
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- `temporal_kg_boundary` is now wired into `memtrust run --eval`, gated to the
|
|
65
|
+
`mempalace` backend (reports `not_applicable` against any other backend).
|
|
66
|
+
- First live benchmark result: `mem0_direct` (self-hosted `mem0ai`, local Qdrant,
|
|
67
|
+
OpenAI embeddings/extraction) run against `contradiction`, `compression`, and
|
|
68
|
+
`extraction_quality`. See README.md's "Benchmarks" section for the numbers.
|
|
69
|
+
|
|
70
|
+
### Changed
|
|
71
|
+
|
|
72
|
+
- `pyproject.toml`: `Development Status :: 4 - Beta` (was Alpha), expanded PyPI
|
|
73
|
+
keywords, refreshed description.
|
|
74
|
+
|
|
6
75
|
## [0.3.0] - 2026-07-17
|
|
7
76
|
|
|
8
77
|
### Changed
|
|
@@ -109,6 +109,49 @@ conversion (or a second loader function) is needed.
|
|
|
109
109
|
4. Every claim in a PR description about a score or benchmark number must be reproducible from a
|
|
110
110
|
command someone else can run. "I ran X and got Y" needs the X.
|
|
111
111
|
|
|
112
|
+
## Release process
|
|
113
|
+
|
|
114
|
+
There are three packages, not one, and CI only automates one of them. Missing any of the other two
|
|
115
|
+
silently breaks something for someone -- this is written down because it has already happened.
|
|
116
|
+
|
|
117
|
+
1. Bump the version in `pyproject.toml` (and `npm/memtrust-cli/package.json` in the same PR if a
|
|
118
|
+
matching npm publish is planned -- see step 4).
|
|
119
|
+
2. Before pushing, run the full local check list: `ruff check .`, `ruff format --check .` (a
|
|
120
|
+
separate step from `ruff check` -- CI fails on formatting alone even when linting passes),
|
|
121
|
+
`mypy --strict src/memtrust`, `pytest --cov=memtrust --cov-report=term-missing
|
|
122
|
+
--cov-fail-under=80`, `pip-audit`.
|
|
123
|
+
3. **PyPI has two packages kept in lockstep, and CI only publishes one of them.**
|
|
124
|
+
`.github/workflows/publish-pypi.yml` (triggered by a GitHub Release) publishes whatever
|
|
125
|
+
`pyproject.toml`'s `[project].name` currently says -- `memtrust-cli`, the canonical name. The
|
|
126
|
+
separate mirror package literally named `memtrust` (which `npm/memtrust-cli/bin/memtrust.js`
|
|
127
|
+
pins its `uv tool run --from` call to) has no CI automation at all and must be published
|
|
128
|
+
manually every release: temporarily set `name = "memtrust"` in `pyproject.toml`, `uv build && uv
|
|
129
|
+
publish`, then revert the name back to `memtrust-cli`. Skipping this step doesn't break
|
|
130
|
+
`memtrust-cli`'s own release, but it does mean the npm wrapper starts fetching a stale PyPI
|
|
131
|
+
version the next time someone bumps `npm/memtrust-cli/package.json` without also doing this.
|
|
132
|
+
4. **npm publish is also manual, and its own version must exactly match the PyPI release it
|
|
133
|
+
pins to.** `npm/memtrust-cli/package.json`'s version is not independent -- `bin/memtrust.js`
|
|
134
|
+
reads it directly to build `uv tool run --from memtrust==<that version>`, so bumping the npm
|
|
135
|
+
package's version without a matching live PyPI `memtrust` release (step 3) breaks the wrapper
|
|
136
|
+
for every subsequent install. Publish PyPI first, confirm both `memtrust-cli` and `memtrust`
|
|
137
|
+
are live (`pip index versions memtrust-cli`, or the PyPI JSON API if the simple index is
|
|
138
|
+
lagging), then `npm publish npm/memtrust-cli --access public`.
|
|
139
|
+
5. **Building the sdist from a working tree that has locally-downloaded platform binaries staged
|
|
140
|
+
for npm publish will silently balloon it.** If `npm/platforms/*/bin/` has real `uv` binaries in
|
|
141
|
+
it (staged for an npm publish, ~50-70MB each across 6 platforms), `pyproject.toml`'s
|
|
142
|
+
`[tool.hatch.build.targets.sdist]` exclude should already keep them out -- but if that exclude
|
|
143
|
+
is ever removed, `uv build`'s sdist output size is the tripwire: it should be a few MB, not
|
|
144
|
+
100MB+.
|
|
145
|
+
6. The 6 `@memtrust-cli/<platform>` packages have their own independent version numbers, not tied
|
|
146
|
+
to `memtrust-cli`'s. `npm/memtrust-cli/package.json`'s `optionalDependencies` should use a caret
|
|
147
|
+
range (`^0.1.1`, not an exact `0.1.0`) so a platform-package patch release resolves
|
|
148
|
+
automatically instead of drifting stale again.
|
|
149
|
+
7. Create the GitHub Release last, after both registries are confirmed live -- this is what
|
|
150
|
+
triggers `publish-pypi.yml`. If `memtrust-cli` was already published manually before the
|
|
151
|
+
Release exists (e.g. to unblock testing), that workflow run will fail with a harmless
|
|
152
|
+
"File already exists" 400 from PyPI -- expected, not a regression, since the file it's trying
|
|
153
|
+
to upload is already there.
|
|
154
|
+
|
|
112
155
|
## Code of conduct
|
|
113
156
|
|
|
114
157
|
Be direct, be specific, assume good faith. Disagreement about a methodology choice is welcome and
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memtrust-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: Independent, reproducible benchmark harness for agent-memory backends (MemPalace, Mem0, Zep/Graphiti, OpenViking): runs LongMemEval, LoCoMo, contradiction-detection, and a dozen other evals against all four and publishes the raw logs, not vendor-curated numbers.
|
|
5
5
|
Project-URL: Homepage, https://github.com/RudrenduPaul/memtrust
|
|
6
6
|
Project-URL: Issues, https://github.com/RudrenduPaul/memtrust/issues
|
|
@@ -11,6 +11,7 @@ License: Apache-2.0
|
|
|
11
11
|
License-File: LICENSE
|
|
12
12
|
Keywords: agent-memory,ai-agents,benchmark,contradiction-detection,graphiti,llm-eval,llm-memory,locomo,longmemeval,mem0,memory-backend,mempalace,reproducible-benchmark,zep
|
|
13
13
|
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
14
15
|
Classifier: Intended Audience :: Developers
|
|
15
16
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
17
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -45,12 +46,13 @@ Description-Content-Type: text/markdown
|
|
|
45
46
|
|
|
46
47
|
# memtrust
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
Agent memory backends each publish their own benchmark numbers, on different tests, measured
|
|
50
|
+
different ways. memtrust runs the same evals against all four and publishes the raw logs. Run
|
|
51
|
+
against the vendors, not by them.
|
|
50
52
|
|
|
51
53
|
[](https://github.com/RudrenduPaul/memtrust/actions/workflows/ci.yml)
|
|
52
54
|
[](https://github.com/RudrenduPaul/memtrust/blob/main/LICENSE)
|
|
53
|
-
[](https://pypi.org/project/memtrust-cli/)
|
|
54
56
|
[](https://pypi.org/project/memtrust-cli/)
|
|
55
57
|
|
|
56
58
|
```bash
|
|
@@ -77,22 +79,23 @@ memtrust run --backends mempalace,mem0,zep,openviking --eval all
|
|
|
77
79
|
|
|
78
80
|
If you've compared agent-memory backends recently, you've probably noticed each one leads with a
|
|
79
81
|
different accuracy number, on a different benchmark, measured a different way. MemPalace's own
|
|
80
|
-
community already flagged the problem in public. Issue [#27](https://github.com/
|
|
81
|
-
on the MemPalace repository, opened April 7, 2026 and still open, documents a
|
|
82
|
-
LongMemEval
|
|
83
|
-
|
|
84
|
-
ChromaDB's default embeddings doing the work
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
community already flagged the problem in public. Issue [#27](https://github.com/MemPalace/mempalace/issues/27)
|
|
83
|
+
on the MemPalace repository, opened April 7, 2026 and still open, documents that a headline 100%
|
|
84
|
+
LongMemEval figure, measured with Haiku reranking, wasn't reproducible from the repository's own
|
|
85
|
+
benchmark scripts and was pulled from the README as unverifiable. A separate 96.6% figure people
|
|
86
|
+
cite everywhere turns out to be mostly ChromaDB's default embeddings doing the work in raw mode,
|
|
87
|
+
not MemPalace's own architecture. A "lossless" compression claim (the "AAAK" mode) drops the same
|
|
88
|
+
LongMemEval score from 96.6% to 84.2% in practice, a 12.4 percentage point gap. Two internal pull
|
|
89
|
+
requests attempting to fix the reporting problem, #433 and #729, were both closed without merging
|
|
90
|
+
on April 12, 2026 -- #729 within seven minutes of being opened. As of this writing, the issue has
|
|
91
|
+
233 thumbs-up reactions and 39 comments.
|
|
88
92
|
|
|
89
93
|
None of that means MemPalace, or any other backend, doesn't work. It means nobody outside the
|
|
90
94
|
vendor had run the same test, the same way, against every option, and published the raw logs.
|
|
91
95
|
|
|
92
96
|
memtrust does that. It runs LongMemEval, LoCoMo, and a growing set of evals built specifically for
|
|
93
|
-
this project --
|
|
94
|
-
|
|
95
|
-
CLI yet. The two that matter most for understanding what this project is actually for:
|
|
97
|
+
this project -- 17 of them as of this writing, all registered in the CLI's `--eval` flag. The two
|
|
98
|
+
that matter most for understanding what this project is actually for:
|
|
96
99
|
contradiction detection, because neither LongMemEval nor LoCoMo tests the question that actually
|
|
97
100
|
matters once a memory system sits underneath a production agent -- what happens when a new fact
|
|
98
101
|
contradicts an old one? Does the backend flag the conflict? Silently overwrite the old fact with no
|
|
@@ -102,13 +105,21 @@ test claims like the "lossless" one above: it stores content, retrieves it, and
|
|
|
102
105
|
reconstruction fidelity rather than semantic accuracy, per operating mode a backend exposes (see
|
|
103
106
|
`MemoryBackendAdapter.supported_modes`) -- the mechanism that would let a contributor with live
|
|
104
107
|
MemPalace credentials actually reproduce the 12.4-point compressed-mode accuracy drop
|
|
105
|
-
mempalace/mempalace#27 documents, instead of just citing it. **Neither has been run against
|
|
106
|
-
|
|
108
|
+
mempalace/mempalace#27 documents, instead of just citing it. **Neither has been run against a live
|
|
109
|
+
MemPalace instance as of this writing** -- both have, however, been run against a live
|
|
110
|
+
self-hosted `mem0ai` install; see "Benchmarks" below. The other evals -- ranking quality,
|
|
107
111
|
crash recovery, extraction quality, embedding drift, scale/volume stress, lock contention, stats
|
|
108
112
|
accuracy, orphan cleanup, result consistency, migration rollback, filter injection, resource-sync
|
|
109
113
|
safety, and temporal-KG boundary detection -- each grew out of a specific real bug report against
|
|
110
114
|
one of the four tracked backends; see "Success stories" below for the full list.
|
|
111
115
|
|
|
116
|
+
**Where this stands right now, in one place:** [live benchmark results](#benchmarks) for one
|
|
117
|
+
backend (`mem0_direct`, self-hosted `mem0ai`), including a real bug this project's own attempt to
|
|
118
|
+
get those numbers surfaced in mem0's default configuration; and [197 real GitHub issues and PRs](#success-stories)
|
|
119
|
+
filed against MemPalace, Mem0, Zep/Graphiti, and OpenViking independently root-caused against this
|
|
120
|
+
codebase -- 55 (28%) PASS, 16 (8%) PARTIAL, 42 (21%) a genuine capability gap, 84 (43%) not
|
|
121
|
+
applicable, every verdict re-verified by a reviewer independent of whoever built the fix.
|
|
122
|
+
|
|
112
123
|
## What it does
|
|
113
124
|
|
|
114
125
|
Every command below was actually run against this repo, with zero vendor API keys configured, to
|
|
@@ -116,11 +127,11 @@ produce the output shown. Nothing here is simulated.
|
|
|
116
127
|
|
|
117
128
|
```
|
|
118
129
|
$ memtrust run --backends mempalace,mem0,zep,openviking --eval all
|
|
119
|
-
memtrust 0.
|
|
130
|
+
memtrust 0.3.3 -- run_id=mt_2026-07-21T004232Z
|
|
120
131
|
Backends: mempalace, mem0, zep, openviking Evals: longmemeval, locomo, contradiction,
|
|
121
132
|
resource_sync_safety, compression, ranking_quality, scale_stress, embedding_drift, crash_recovery,
|
|
122
133
|
extraction_quality, migration_rollback, filter_injection, lock_contention, stats_accuracy,
|
|
123
|
-
orphan_cleanup, result_consistency
|
|
134
|
+
orphan_cleanup, result_consistency, temporal_kg_boundary
|
|
124
135
|
|
|
125
136
|
mempalace: SKIPPED (not configured) -- mempalace is not configured: environment variable
|
|
126
137
|
MEMPALACE_STORAGE_PATH is not set. Skipping this backend. See docs/methodology.md for setup
|
|
@@ -135,17 +146,19 @@ instructions.
|
|
|
135
146
|
|
|
136
147
|
Cost: $0.00 (no LLM-judged evals ran -- structural evals only, or judge not configured)
|
|
137
148
|
|
|
138
|
-
Full report: memtrust-report-2026-07-
|
|
149
|
+
Full report: memtrust-report-2026-07-20.json
|
|
139
150
|
```
|
|
140
151
|
|
|
141
152
|
That's the real, reproducible behavior of a fresh clone with no credentials: every backend reports
|
|
142
153
|
SKIPPED, the command exits cleanly, and a valid JSON report is still written. `memtrust --version`
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
154
|
+
now correctly prints `0.3.3`, matching `pip show memtrust-cli`. Earlier releases printed
|
|
155
|
+
`0.0.0+unknown` even when properly installed, because `src/memtrust/__init__.py` read
|
|
156
|
+
`importlib.metadata.version("memtrust")` while the installed distribution is actually named
|
|
157
|
+
`memtrust-cli` -- kept in the FAQ below for the record rather than deleted, since silently erasing
|
|
158
|
+
a bug the moment it's fixed is exactly the kind of curation this project exists to push back on in
|
|
159
|
+
other people's benchmarks. Set the relevant environment variable for any backend you want to
|
|
160
|
+
actually test (`MEM0_API_KEY`, `ZEP_API_KEY`, `OPENVIKING_API_KEY`, `MEMPALACE_STORAGE_PATH`) and
|
|
161
|
+
that backend runs for real against its live API instead of being skipped.
|
|
149
162
|
|
|
150
163
|
The eval logic itself is proven offline, against the bundled synthetic fixtures and, for several
|
|
151
164
|
adapters, the real installed vendor packages with only the network boundary mocked, by the test
|
|
@@ -153,29 +166,33 @@ suite:
|
|
|
153
166
|
|
|
154
167
|
```
|
|
155
168
|
$ pytest --cov=memtrust --cov-report=term-missing
|
|
156
|
-
...
|
|
169
|
+
... (33 module rows total; the 11 most relevant to this README are shown below)
|
|
157
170
|
Name Stmts Miss Cover
|
|
158
171
|
-------------------------------------------------------------------------------------
|
|
159
|
-
src/memtrust/adapters/base.py
|
|
160
|
-
src/memtrust/adapters/mempalace_adapter.py
|
|
172
|
+
src/memtrust/adapters/base.py 305 16 95%
|
|
173
|
+
src/memtrust/adapters/mempalace_adapter.py 254 15 94%
|
|
161
174
|
src/memtrust/adapters/mem0_adapter.py 140 12 91%
|
|
162
|
-
src/memtrust/adapters/mem0_direct_adapter.py
|
|
175
|
+
src/memtrust/adapters/mem0_direct_adapter.py 277 34 88%
|
|
163
176
|
src/memtrust/adapters/openviking_adapter.py 178 18 90%
|
|
164
177
|
src/memtrust/adapters/zep_graphiti_adapter.py 63 3 95%
|
|
165
|
-
src/memtrust/adapters/zep_graphiti_selfhosted_adapter.py
|
|
178
|
+
src/memtrust/adapters/zep_graphiti_selfhosted_adapter.py 161 24 85%
|
|
166
179
|
src/memtrust/evals/contradiction.py 127 2 98%
|
|
167
180
|
src/memtrust/evals/compression.py 86 1 99%
|
|
168
|
-
src/memtrust/evals/temporal_kg_boundary.py 90
|
|
181
|
+
src/memtrust/evals/temporal_kg_boundary.py 90 3 97%
|
|
169
182
|
src/memtrust/receipt.py 118 10 92%
|
|
170
183
|
-------------------------------------------------------------------------------------
|
|
171
|
-
TOTAL
|
|
184
|
+
TOTAL 4147 276 93%
|
|
172
185
|
|
|
173
|
-
|
|
186
|
+
589 passed, 8 skipped in 3.57s
|
|
174
187
|
```
|
|
175
188
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
189
|
+
This is an excerpt, not the full table -- the weakest-covered module in the repo,
|
|
190
|
+
`evals/mempalace_metadata_scale.py` (70%), isn't one of the 11 shown above; run the command
|
|
191
|
+
yourself for the complete per-module breakdown.
|
|
192
|
+
|
|
193
|
+
589 passing tests across 33 source modules, 93% overall statement coverage, 98% on the
|
|
194
|
+
contradiction-detection eval, 99% on compression/round-trip fidelity, 97% on the temporal-KG
|
|
195
|
+
boundary eval, 85-95% across the adapter layer. The 8 skips are live-`mempalace`-package tests that
|
|
179
196
|
only run with the optional `mempalace-direct` extra installed (`pip install -e
|
|
180
197
|
'.[dev,mempalace-direct]'`). Every test mocks its HTTP or wire
|
|
181
198
|
layer, or uses an in-memory fake backend -- none of them touch a real network, though a meaningful
|
|
@@ -210,16 +227,11 @@ Commands:
|
|
|
210
227
|
|
|
211
228
|
| Command | Flags | What it does |
|
|
212
229
|
|---|---|---|
|
|
213
|
-
| `memtrust run` | `--backends TEXT` comma-separated list or `all` (default `all`) · `--eval TEXT` comma-separated from `longmemeval,locomo,contradiction,resource_sync_safety,compression,ranking_quality,scale_stress,embedding_drift,crash_recovery,extraction_quality,migration_rollback,filter_injection,lock_contention,stats_accuracy,orphan_cleanup,result_consistency`, or `all` (default `all`) · `--output FILE` (defaults to `./memtrust-report-<date>.json`) · `--locomo-dataset-path FILE` points the LoCoMo eval at a real, downloaded `locomo10.json` instead of the bundled synthetic fixture (memtrust does not bundle or auto-fetch the real dataset) · `--locomo-exclude-question-ids-file FILE` excludes known-bad-ground-truth LoCoMo question IDs from scoring · `--scale-stress-n-records INTEGER` (default `500`) sets how many synthetic records the scale-stress eval stores and re-queries · `--sign FILE` writes a signed `<output>.receipt.json` alongside the report, proving it was produced by the holder of the given Ed25519 private key | Runs the eval suite against the requested backends. A backend without its credential env var set prints `SKIPPED` and the run continues -- this command never crashes on missing credentials. |
|
|
230
|
+
| `memtrust run` | `--backends TEXT` comma-separated list or `all` (default `all`) · `--eval TEXT` comma-separated from `longmemeval,locomo,contradiction,resource_sync_safety,compression,ranking_quality,scale_stress,embedding_drift,crash_recovery,extraction_quality,migration_rollback,filter_injection,lock_contention,stats_accuracy,orphan_cleanup,result_consistency,temporal_kg_boundary`, or `all` (default `all`) · `--output FILE` (defaults to `./memtrust-report-<date>.json`) · `--locomo-dataset-path FILE` points the LoCoMo eval at a real, downloaded `locomo10.json` instead of the bundled synthetic fixture (memtrust does not bundle or auto-fetch the real dataset) · `--locomo-exclude-question-ids-file FILE` excludes known-bad-ground-truth LoCoMo question IDs from scoring · `--scale-stress-n-records INTEGER` (default `500`) sets how many synthetic records the scale-stress eval stores and re-queries · `--sign FILE` writes a signed `<output>.receipt.json` alongside the report, proving it was produced by the holder of the given Ed25519 private key | Runs the eval suite against the requested backends. A backend without its credential env var set prints `SKIPPED` and the run continues -- this command never crashes on missing credentials. `temporal_kg_boundary` only applies to the `mempalace` backend (the only adapter that wires `kg_add`/`kg_invalidate`/`kg_query`); requesting it against any other backend reports `not_applicable`, not an error. |
|
|
214
231
|
| `memtrust report REPORT_PATH` | positional path to a prior JSON report | Reads a report written by `memtrust run` and prints a formatted summary. |
|
|
215
232
|
| `memtrust keygen` | -- | Generates a new Ed25519 keypair for signing reports with `run --sign`. |
|
|
216
233
|
| `memtrust verify RECEIPT_PATH` | -- | Verifies a signed receipt produced by `memtrust run --sign`; a tampered or mismatched receipt fails verification. |
|
|
217
|
-
| `memtrust --version` | -- | Prints the installed version
|
|
218
|
-
|
|
219
|
-
The temporal-KG boundary eval (`src/memtrust/evals/temporal_kg_boundary.py`,
|
|
220
|
-
`run_temporal_kg_boundary_eval()`) is not yet wired into `--eval`'s known-eval list -- it exists as
|
|
221
|
-
a tested module and a MemPalace-specific capability, callable directly, not yet a `memtrust run
|
|
222
|
-
--eval temporal_kg_boundary` option. See its own section below.
|
|
234
|
+
| `memtrust --version` | -- | Prints the installed version (currently `0.3.3`). |
|
|
223
235
|
|
|
224
236
|
Every line above came straight from running `memtrust --help`, `memtrust run --help`, and
|
|
225
237
|
`memtrust report --help` against this repo. Nothing here is invented.
|
|
@@ -249,10 +261,10 @@ section below until a live run actually produces them:
|
|
|
249
261
|
|
|
250
262
|
| Backend | GitHub stars | Self-reported description |
|
|
251
263
|
|---|---|---|
|
|
252
|
-
| [MemPalace](https://github.com/MemPalace/mempalace) | 57,
|
|
253
|
-
| [Mem0](https://github.com/mem0ai/mem0) |
|
|
254
|
-
| [Zep / Graphiti](https://github.com/getzep/graphiti) | 28,
|
|
255
|
-
| [OpenViking](https://github.com/volcengine/OpenViking) |
|
|
264
|
+
| [MemPalace](https://github.com/MemPalace/mempalace) | 57,512 | "The best-benchmarked open-source AI memory system. And it's free." |
|
|
265
|
+
| [Mem0](https://github.com/mem0ai/mem0) | 61,318 | "Universal memory layer for AI Agents" |
|
|
266
|
+
| [Zep / Graphiti](https://github.com/getzep/graphiti) | 28,978 | "Build Real-Time Knowledge Graphs for AI Agents" |
|
|
267
|
+
| [OpenViking](https://github.com/volcengine/OpenViking) | 27,016 | "Self-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills." |
|
|
256
268
|
|
|
257
269
|
None of these numbers say anything about which backend handles a contradicted fact correctly --
|
|
258
270
|
that's the whole reason the harness exists. Star count measures adoption, not correctness.
|
|
@@ -287,8 +299,9 @@ similarity ratio (`fidelity_ratio()`, via `difflib.SequenceMatcher` -- not an LL
|
|
|
287
299
|
"lossless" claim is a literal-reconstruction claim, not a semantic one). This is what would let a
|
|
288
300
|
contributor with live MemPalace credentials point `memtrust run --eval compression` at it and
|
|
289
301
|
reproduce a "raw vs AAAK" fidelity gap directly. **As of this writing this eval has not been run
|
|
290
|
-
against
|
|
291
|
-
|
|
302
|
+
against a live MemPalace instance** -- it has been run against a live self-hosted `mem0ai` install
|
|
303
|
+
(mean fidelity 31.6%, see "Benchmarks" below); see `docs/methodology.md` for the same
|
|
304
|
+
live-credentials caveat that applies to every other eval and backend not yet measured live.
|
|
292
305
|
|
|
293
306
|
## The eval built from MemPalace's own bug: temporal-KG boundary detection
|
|
294
307
|
|
|
@@ -311,18 +324,76 @@ shipped in a released `mempalace` version as of this adapter's live-verified 3.5
|
|
|
311
324
|
lands under the package's `[Unreleased]` changelog section. `tests/test_temporal_kg_boundary.py`
|
|
312
325
|
proves the *classification logic* is correct against two hand-written fake implementations that
|
|
313
326
|
reproduce the confirmed pre-#1914 (closed-interval) and post-#1914 (half-open-interval) SQL
|
|
314
|
-
comparison exactly. **This has not been run against a live MemPalace instance.** It
|
|
315
|
-
|
|
316
|
-
|
|
327
|
+
comparison exactly. **This has not been run against a live MemPalace instance.** It is wired into
|
|
328
|
+
`memtrust run --eval temporal_kg_boundary` (see "Commands" above); against any backend other than
|
|
329
|
+
`mempalace`, it reports `not_applicable` rather than an error.
|
|
317
330
|
|
|
318
331
|
## Benchmarks
|
|
319
332
|
|
|
320
|
-
**
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
333
|
+
**Live results: mem0_direct (self-hosted), July 2026.** MemPalace, Zep, and OpenViking are still
|
|
334
|
+
not yet measured against a live backend -- see "Backend coverage" below for the confidence level
|
|
335
|
+
on each adapter. Mem0 has one real result, produced against the actual `mem0ai` OSS library
|
|
336
|
+
running self-hosted -- in-process, via `Mem0DirectAdapter`, backed by a local Qdrant instance and
|
|
337
|
+
the OpenAI API for embeddings and extraction -- not against Mem0's hosted Platform API. Keep that
|
|
338
|
+
distinction in mind before reading this as a claim about the hosted product.
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
$ export MEM0_DIRECT_EMBEDDER_PROVIDER=openai
|
|
342
|
+
$ export MEM0_DIRECT_VECTOR_STORE_PROVIDER=qdrant
|
|
343
|
+
$ export MEM0_DIRECT_VECTOR_STORE_URL=http://localhost:6333
|
|
344
|
+
$ memtrust run --backends mem0_direct --eval contradiction,compression,extraction_quality
|
|
345
|
+
memtrust 0.3.2 -- run_id=mt_2026-07-20T210918Z
|
|
346
|
+
Backends: mem0_direct Evals: contradiction, compression, extraction_quality
|
|
347
|
+
|
|
348
|
+
mem0_direct: configured, running evals...
|
|
349
|
+
Running Contradiction-Detection against mem0_direct...
|
|
350
|
+
flagged: 0.0% silent-overwrite: 100.0% served-stale: 0.0% empty-or-lost: 0.0%
|
|
351
|
+
Running Compression/Round-Trip-Fidelity against mem0_direct...
|
|
352
|
+
fidelity by mode -- default: 31.6%
|
|
353
|
+
Running Extraction-Quality against mem0_direct...
|
|
354
|
+
junk-retained: 0.0% valid-lost: 100.0%
|
|
355
|
+
feedback-loop-duplicate: 0.0%
|
|
356
|
+
|
|
357
|
+
Cost: $0.00 (no LLM-judged evals ran -- structural evals only, or judge not configured)
|
|
358
|
+
```
|
|
324
359
|
|
|
325
|
-
|
|
360
|
+
The full raw report is committed at `leaderboard/mem0_direct-2026-07-20.json`, and `leaderboard/data.json`
|
|
361
|
+
carries the contradiction numbers into the static leaderboard site (`mempalace`/`mem0`/`zep`/`openviking`
|
|
362
|
+
still show `not_measured` there; `mem0_direct` is the one real row).
|
|
363
|
+
|
|
364
|
+
What that means case by case, not just the percentage:
|
|
365
|
+
|
|
366
|
+
- **Contradiction detection, 7/7 cases: every contradicting fact silently overwrote the old one.**
|
|
367
|
+
0% were flagged as a conflict, 0% served stale, 0% empty-or-lost. Tell it your meeting moved from
|
|
368
|
+
2pm to 3pm and it stores the new fact with no signal that anything changed -- this is exactly the
|
|
369
|
+
question LongMemEval and LoCoMo don't test, and exactly what "Why this exists" above is about.
|
|
370
|
+
- **Compression/round-trip fidelity, 5 cases: 31.6% mean literal character-level reconstruction.**
|
|
371
|
+
This is expected, not a defect -- mem0's design goal is semantic fact extraction, not verbatim
|
|
372
|
+
storage, so a literal-reconstruction score was never going to be high. It quantifies what "not
|
|
373
|
+
built for lossless storage" concretely means for this backend: ask it what you said and you get
|
|
374
|
+
the gist back, not your words.
|
|
375
|
+
- **Extraction quality, 15 cases (12 deliberately junk, 3 deliberately valid): 0% junk retained,
|
|
376
|
+
100% of the valid cases lost.** All 12 junk inputs (boot-file restating, cron heartbeat noise,
|
|
377
|
+
system dumps, hallucinated-profile bait) were correctly rejected. All 3 valid-content cases were
|
|
378
|
+
also dropped -- stored but never came back on retrieval. The valid-side sample is small (n=3);
|
|
379
|
+
treat this as a signal worth digging into further, not a settled number.
|
|
380
|
+
|
|
381
|
+
**A real bug this run surfaced in mem0ai itself, not in memtrust.** Getting any of the numbers
|
|
382
|
+
above required a fix first: a fresh `mem0ai==2.0.12` install with nothing but `OPENAI_API_KEY` set
|
|
383
|
+
fails every single LLM-based extraction call, out of the box, for anyone. mem0's own default model
|
|
384
|
+
(`mem0/llms/openai.py`: `self.config.model = "gpt-5-mini"`) is a reasoning-tier model that only
|
|
385
|
+
accepts the API's default temperature, but mem0's own reasoning-model detection
|
|
386
|
+
(`mem0/llms/base.py`'s `reasoning_models` set) checks for the string `"gpt-5o-mini"`, not
|
|
387
|
+
`"gpt-5-mini"` -- two different strings, so the check never fires, and mem0 sends `temperature=0.1`
|
|
388
|
+
on every call regardless. The result is a `400 Unsupported value: 'temperature' does not support
|
|
389
|
+
0.1 with this model` error on every extraction call, silently caught by mem0 and reported by
|
|
390
|
+
memtrust as `N/A (no scoreable cases)` rather than a real result. `Mem0DirectAdapter` now works
|
|
391
|
+
around it by passing `is_reasoning_model=True` explicitly -- mem0's own documented override for
|
|
392
|
+
exactly this situation -- see `src/memtrust/adapters/mem0_direct_adapter.py`'s "Default LLM
|
|
393
|
+
extraction is broken out of the box" section for the full citation. No upstream mem0ai issue filed
|
|
394
|
+
for this as of this writing.
|
|
395
|
+
|
|
396
|
+
To reproduce this or measure the remaining three backends:
|
|
326
397
|
|
|
327
398
|
```bash
|
|
328
399
|
export MEM0_API_KEY=... # and/or
|
|
@@ -403,13 +474,8 @@ LongMemEval/LoCoMo datasets). Nothing leaves your machine unless you choose to p
|
|
|
403
474
|
|
|
404
475
|
### npx (agent-native)
|
|
405
476
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
> this repo is built, tested, and passes both `npm pack --dry-run` and `npm publish --dry-run`
|
|
409
|
-
> cleanly (re-verified this session), but has not actually been pushed to the npm registry yet --
|
|
410
|
-
> `npm install memtrust-cli` still 404s as of this writing. The command below is the real,
|
|
411
|
-
> working distribution path once that publish happens; nothing about it is speculative except the
|
|
412
|
-
> "it's live on npm" part.
|
|
477
|
+
Both PyPI and npm are live. `pip install memtrust-cli` works today, and so does the `npx` command
|
|
478
|
+
below -- `npm install memtrust-cli` no longer 404s.
|
|
413
479
|
|
|
414
480
|
For CI and agent runners that have Node.js available but not necessarily a Python toolchain:
|
|
415
481
|
|
|
@@ -429,9 +495,11 @@ first use. What it removes is no Python toolchain to provision by hand -- `npx m
|
|
|
429
495
|
handles the interpreter and package fetch for you via a bundled, verified copy of Astral's
|
|
430
496
|
[`uv`](https://github.com/astral-sh/uv). Each platform package bundles a genuine, SHA-256-verified
|
|
431
497
|
copy of `uv`'s own GitHub release binary (fetched at npm package-publish time, never at end-user
|
|
432
|
-
install time), and its `bin` shim runs `uv tool run --from memtrust memtrust
|
|
433
|
-
transparently bootstraps a Python interpreter and installs
|
|
434
|
-
the first run.
|
|
498
|
+
install time), and its `bin` shim runs `uv tool run --from memtrust==<pinned version> memtrust
|
|
499
|
+
<args>`, which transparently bootstraps a Python interpreter and installs that exact pinned
|
|
500
|
+
`memtrust` release from PyPI, caching it after the first run. The npm package is pinned to its own
|
|
501
|
+
version -- bump `npm/memtrust-cli/package.json`'s version when a new PyPI release ships, and every
|
|
502
|
+
subsequent install resolves to that exact release, not whatever happens to be newest at run time.
|
|
435
503
|
|
|
436
504
|
## What a hosted trust layer would add
|
|
437
505
|
|
|
@@ -488,7 +556,7 @@ commit than remember to run them by hand.
|
|
|
488
556
|
## FAQ
|
|
489
557
|
|
|
490
558
|
**What is memtrust, and what actually makes it different from reading a vendor's own benchmark
|
|
491
|
-
page?** It's a CLI harness that runs the same evals (LongMemEval, LoCoMo, and
|
|
559
|
+
page?** It's a CLI harness that runs the same evals (LongMemEval, LoCoMo, and 15 others registered
|
|
492
560
|
in `--eval`, including a contradiction-detection eval none of the four tracked backends publish a
|
|
493
561
|
number for) against MemPalace, Mem0, Zep/Graphiti, and OpenViking, and prints the raw output rather
|
|
494
562
|
than a curated summary. The differentiator isn't a proprietary scoring model; it's that nobody
|
|
@@ -524,20 +592,39 @@ those four backends make about themselves. If you need broad RAG or prompt-evalu
|
|
|
524
592
|
RAGAS or a similar framework is the right tool; if you need to check whether a memory backend
|
|
525
593
|
silently drops or overwrites a contradicted fact, memtrust is the one built for that question.
|
|
526
594
|
|
|
527
|
-
**Why
|
|
528
|
-
This
|
|
529
|
-
PyPI into a clean virtualenv and running `pip show memtrust-cli`
|
|
530
|
-
`memtrust --version`
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
595
|
+
**Why did `memtrust --version` used to print a version that didn't match what pip said I
|
|
596
|
+
installed?** This was a real, shipped bug through 0.3.1, not a hypothetical one: installing
|
|
597
|
+
`memtrust-cli` from PyPI into a clean virtualenv and running `pip show memtrust-cli` reported the
|
|
598
|
+
correct version, but `memtrust --version` printed `0.0.0+unknown` regardless, because
|
|
599
|
+
`src/memtrust/__init__.py` read `importlib.metadata.version("memtrust")` -- the wrong distribution
|
|
600
|
+
name -- instead of `version("memtrust-cli")`, the name the package is actually installed under.
|
|
601
|
+
0.3.2's fix was itself incomplete: it hardcoded the lookup to `"memtrust-cli"`, which broke the
|
|
602
|
+
separate `memtrust` mirror package (see "Can I `pip install memtrust` instead of
|
|
603
|
+
`memtrust-cli`?" below) the same way in reverse -- a `pip install memtrust` environment has no
|
|
604
|
+
`memtrust-cli` entry in its own installed-package metadata at all, so the lookup always missed and
|
|
605
|
+
fell through to the same `0.0.0+unknown` fallback. Fixed for real in 0.3.3: the lookup now tries
|
|
606
|
+
`memtrust-cli` first, falls back to `memtrust`, and only reports `0.0.0+unknown` if neither
|
|
607
|
+
distribution name is installed. `memtrust --version` now matches `pip show` under either package
|
|
608
|
+
name.
|
|
609
|
+
|
|
610
|
+
**Can I `pip install memtrust` instead of `memtrust-cli`?** Yes -- `memtrust` is a real, separate
|
|
611
|
+
PyPI package, publishing the identical source and currently in sync with `memtrust-cli`'s version.
|
|
612
|
+
That sync is a manual release step, not an automated guarantee (see CONTRIBUTING.md's Release
|
|
613
|
+
process for exactly how, and why it has drifted stale before) -- so "currently in sync" is the
|
|
614
|
+
honest framing, not "always in sync." It exists because the npm wrapper's `bin/memtrust.js` pins
|
|
615
|
+
`uv tool run --from memtrust==<version>` (not `memtrust-cli`), so a working `npx memtrust-cli`
|
|
616
|
+
depends on the `memtrust` name staying live and in sync. `memtrust-cli` is the name to lead with in new
|
|
617
|
+
documentation, since the `-cli` suffix makes it unambiguous as a CLI tool at a glance; `memtrust`
|
|
618
|
+
is a legitimate, supported install path, not a typo or a squatted name.
|
|
534
619
|
|
|
535
620
|
**Has memtrust actually been run against a live memory backend, or is this all synthetic?** Both,
|
|
536
621
|
and the README doesn't blur the line. The eval logic itself is proven against bundled synthetic
|
|
537
622
|
fixtures and, for several adapters, real installed vendor packages with only the network boundary
|
|
538
|
-
mocked (see the pytest coverage table above).
|
|
539
|
-
|
|
540
|
-
"Benchmarks"
|
|
623
|
+
mocked (see the pytest coverage table above). One backend has a real live result: `mem0_direct`,
|
|
624
|
+
the self-hosted `mem0ai` OSS library (not Mem0's hosted Platform API), run against contradiction,
|
|
625
|
+
compression, and extraction-quality -- see "Benchmarks" above for the exact numbers and a real bug
|
|
626
|
+
that run surfaced in `mem0ai` itself. MemPalace, the hosted Mem0 Platform API, Zep, and OpenViking
|
|
627
|
+
have not yet been run against a live backend with real credentials as of this writing. The
|
|
541
628
|
"Backend coverage" table gives a per-adapter confidence level (high/medium/low) for exactly this
|
|
542
629
|
reason; run it yourself against your own credentials to get a live-verified number.
|
|
543
630
|
|
|
@@ -547,7 +634,7 @@ and requires you to preserve the license and copyright notice and to note any ch
|
|
|
547
634
|
the code. It does not require you to open-source your own product just because you depend on
|
|
548
635
|
memtrust.
|
|
549
636
|
|
|
550
|
-
**How do I get real accuracy numbers
|
|
637
|
+
**How do I get real accuracy numbers for the backends still marked "not yet measured"?** Set the
|
|
551
638
|
credential environment variable for whichever backend you want to test
|
|
552
639
|
(`MEMPALACE_STORAGE_PATH`, `MEM0_API_KEY`, `ZEP_API_KEY`, `OPENVIKING_API_KEY`, plus
|
|
553
640
|
`MEMTRUST_JUDGE_API_KEY` for LLM-judged evals like LongMemEval and LoCoMo), then run
|
|
@@ -607,10 +694,6 @@ shipped in the open rather than quietly. See "Backend coverage" above for the fu
|
|
|
607
694
|
(@JosefAschauer): an `authored_at` chronology tie-break fix for `_hybrid_rank`. memtrust's ranking
|
|
608
695
|
classifier now credits a top-level `authored_at` field, not just one nested under `metadata`, as
|
|
609
696
|
a genuine ranking-driving signal.
|
|
610
|
-
- [#524](https://github.com/MemPalace/mempalace/issues/524) (@gaby): a buried-comment report that
|
|
611
|
-
"no API key required" doesn't mean "no network required" -- ChromaDB's default embedder still
|
|
612
|
-
needs to download a model on first use, which silently breaks airgapped setups. The adapter's
|
|
613
|
-
module docstring now says so explicitly.
|
|
614
697
|
|
|
615
698
|
**mem0**
|
|
616
699
|
- [#5973](https://github.com/mem0ai/mem0/pull/5973) (@abhay-codes07, superseded by
|
|
@@ -635,7 +718,13 @@ shipped in the open rather than quietly. See "Backend coverage" above for the fu
|
|
|
635
718
|
update) against this taxonomy.
|
|
636
719
|
- [#4884](https://github.com/mem0ai/mem0/issues/4884) (@wangjiawei-vegetable): a hardcoded
|
|
637
720
|
English-only tokenizer silently degrading non-Latin-script retrieval. A new
|
|
638
|
-
`LanguageDegradationSignal` and non-Latin-script fixtures now catch this shape
|
|
721
|
+
`LanguageDegradationSignal` and non-Latin-script fixtures now catch this shape --
|
|
722
|
+
`Mem0DirectAdapter`-specific (it reads `query(explain=True)`'s real per-result diagnostic
|
|
723
|
+
fields, a capability only that adapter exposes) and, like `embedder_cost.py`'s cost-attribution
|
|
724
|
+
eval and `episode_temporal_leak.py`'s Graphiti-specific eval, not yet wired into `memtrust run
|
|
725
|
+
--eval`'s general list; call `run_language_degradation_eval()` directly, or see the
|
|
726
|
+
`test_query_language_degradation_*` tests in `tests/test_mem0_direct_adapter.py`, until that CLI
|
|
727
|
+
surface exists.
|
|
639
728
|
|
|
640
729
|
**Zep / Graphiti**
|
|
641
730
|
- [#1489](https://github.com/getzep/graphiti/issues/1489) (@brentkearney): a bi-temporal
|