memtrust-cli 0.3.2__tar.gz → 0.3.3__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.
Files changed (112) hide show
  1. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/CHANGELOG.md +69 -0
  2. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/CONTRIBUTING.md +43 -0
  3. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/PKG-INFO +171 -85
  4. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/README.md +170 -84
  5. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/docs/methodology.md +152 -24
  6. memtrust_cli-0.3.3/leaderboard/data.json +75 -0
  7. memtrust_cli-0.3.3/leaderboard/mem0_direct-2026-07-20.json +300 -0
  8. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/memtrust-cli/package.json +7 -7
  9. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/pyproject.toml +1 -1
  10. memtrust_cli-0.3.3/src/memtrust/__init__.py +26 -0
  11. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/cli.py +26 -11
  12. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_cli.py +49 -1
  13. memtrust_cli-0.3.3/tests/test_init.py +67 -0
  14. memtrust_cli-0.3.2/leaderboard/data.json +0 -60
  15. memtrust_cli-0.3.2/src/memtrust/__init__.py +0 -11
  16. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/.github/CODEOWNERS +0 -0
  17. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/.github/workflows/ci.yml +0 -0
  18. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/.github/workflows/publish-pypi.yml +0 -0
  19. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/.gitignore +0 -0
  20. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/.pre-commit-config.yaml +0 -0
  21. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/LICENSE +0 -0
  22. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/SECURITY.md +0 -0
  23. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/docs/assets/dev-to-demos/demo-1-zero-credentials.gif +0 -0
  24. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/docs/assets/dev-to-demos/demo-2-fictional-api-discovery.gif +0 -0
  25. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/docs/assets/dev-to-demos/demo-3-cli-surface.gif +0 -0
  26. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/docs/assets/dev-to-demos/demo-4-temporal-kg-tests.gif +0 -0
  27. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/docs/demo.gif +0 -0
  28. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/docs/usage.gif +0 -0
  29. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/leaderboard/index.html +0 -0
  30. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/memtrust-cli/LICENSE +0 -0
  31. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/memtrust-cli/README.md +0 -0
  32. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/memtrust-cli/bin/memtrust.js +0 -0
  33. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-darwin-arm64/LICENSE +0 -0
  34. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-darwin-arm64/README.md +0 -0
  35. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-darwin-arm64/package.json +0 -0
  36. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-darwin-x64/LICENSE +0 -0
  37. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-darwin-x64/README.md +0 -0
  38. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-darwin-x64/package.json +0 -0
  39. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-linux-arm64/LICENSE +0 -0
  40. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-linux-arm64/README.md +0 -0
  41. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-linux-arm64/package.json +0 -0
  42. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-linux-x64/LICENSE +0 -0
  43. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-linux-x64/README.md +0 -0
  44. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-linux-x64/package.json +0 -0
  45. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-win32-arm64/LICENSE +0 -0
  46. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-win32-arm64/README.md +0 -0
  47. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-win32-arm64/package.json +0 -0
  48. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-win32-x64/LICENSE +0 -0
  49. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-win32-x64/README.md +0 -0
  50. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/platforms/@memtrust-cli-win32-x64/package.json +0 -0
  51. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/npm/scripts/fetch-binary.js +0 -0
  52. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/adapters/__init__.py +0 -0
  53. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/adapters/base.py +0 -0
  54. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/adapters/mem0_adapter.py +0 -0
  55. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/adapters/mem0_direct_adapter.py +0 -0
  56. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/adapters/mempalace_adapter.py +0 -0
  57. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/adapters/openviking_adapter.py +0 -0
  58. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/adapters/zep_graphiti_adapter.py +0 -0
  59. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/adapters/zep_graphiti_selfhosted_adapter.py +0 -0
  60. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/__init__.py +0 -0
  61. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/compression.py +0 -0
  62. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/contradiction.py +0 -0
  63. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/crash_recovery.py +0 -0
  64. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/embedder_cost.py +0 -0
  65. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/embedding_drift.py +0 -0
  66. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/episode_temporal_leak.py +0 -0
  67. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/extraction_quality.py +0 -0
  68. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/filter_injection.py +0 -0
  69. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/language_degradation.py +0 -0
  70. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/lock_contention.py +0 -0
  71. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/locomo.py +0 -0
  72. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/longmemeval.py +0 -0
  73. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/mempalace_metadata_scale.py +0 -0
  74. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/migration_rollback.py +0 -0
  75. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/orphan_cleanup.py +0 -0
  76. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/ranking_quality.py +0 -0
  77. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/resource_sync_safety.py +0 -0
  78. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/result_consistency.py +0 -0
  79. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/scale_fixtures.py +0 -0
  80. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/scale_stress.py +0 -0
  81. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/stats_accuracy.py +0 -0
  82. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/evals/temporal_kg_boundary.py +0 -0
  83. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/receipt.py +0 -0
  84. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/scoring/__init__.py +0 -0
  85. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/scoring/cost_tracker.py +0 -0
  86. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/src/memtrust/scoring/llm_judge.py +0 -0
  87. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/compression_cases.json +0 -0
  88. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/contradiction_cases.json +0 -0
  89. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/crash_recovery_cases.json +0 -0
  90. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/embedding_drift_cases.json +0 -0
  91. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/extraction_quality_cases.json +0 -0
  92. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/filter_injection_cases.json +0 -0
  93. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/language_degradation_cases.json +0 -0
  94. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/locomo_sample.json +0 -0
  95. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/longmemeval_sample.json +0 -0
  96. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/migration_rollback_cases.json +0 -0
  97. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/orphan_cleanup_cases.json +0 -0
  98. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/ranking_quality_cases.json +0 -0
  99. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/resource_sync_cases.json +0 -0
  100. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/fixtures/result_consistency_cases.json +0 -0
  101. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_adapters.py +0 -0
  102. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_compression.py +0 -0
  103. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_episode_temporal_leak.py +0 -0
  104. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_evals.py +0 -0
  105. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_lock_contention.py +0 -0
  106. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_mem0_direct_adapter.py +0 -0
  107. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_mempalace_metadata_scale.py +0 -0
  108. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_receipt.py +0 -0
  109. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_scale_stress.py +0 -0
  110. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_scoring.py +0 -0
  111. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/tests/test_stats_accuracy.py +0 -0
  112. {memtrust_cli-0.3.2 → memtrust_cli-0.3.3}/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.2
3
+ Version: 0.3.3
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
@@ -45,12 +45,13 @@ Description-Content-Type: text/markdown
45
45
 
46
46
  # memtrust
47
47
 
48
- Standardized, reproducible benchmarks for agent-memory backends, run against the vendors, not
49
- published by them.
48
+ Agent memory backends each publish their own benchmark numbers, on different tests, measured
49
+ different ways. memtrust runs the same evals against all four and publishes the raw logs. Run
50
+ against the vendors, not by them.
50
51
 
51
52
  [![CI](https://github.com/RudrenduPaul/memtrust/actions/workflows/ci.yml/badge.svg)](https://github.com/RudrenduPaul/memtrust/actions/workflows/ci.yml)
52
53
  [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://github.com/RudrenduPaul/memtrust/blob/main/LICENSE)
53
- [![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](https://github.com/RudrenduPaul/memtrust/blob/main/pyproject.toml)
54
+ [![PyPI Version](https://img.shields.io/pypi/v/memtrust-cli)](https://pypi.org/project/memtrust-cli/)
54
55
  [![PyPI](https://img.shields.io/badge/pypi-memtrust--cli-blue.svg)](https://pypi.org/project/memtrust-cli/)
55
56
 
56
57
  ```bash
@@ -77,22 +78,23 @@ memtrust run --backends mempalace,mem0,zep,openviking --eval all
77
78
 
78
79
  If you've compared agent-memory backends recently, you've probably noticed each one leads with a
79
80
  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/mempalace/mempalace/issues/27)
81
- on the MemPalace repository, opened April 7, 2026 and still open, documents a widely-cited 100%
82
- LongMemEval score that came from hand-tuning on the failed test questions themselves. The held-out
83
- score is 98.4%, not 100%. A separate 96.6% figure people cite everywhere turns out to be mostly
84
- ChromaDB's default embeddings doing the work, not MemPalace's own architecture. A "lossless"
85
- compression claim drops accuracy by 12.4 percentage points in practice. Two internal pull requests
86
- attempting to fix the reporting problem (#433 and #729) were both closed without merging on April
87
- 12, 2026. As of this writing, the issue has 233 thumbs-up reactions and 39 comments.
81
+ community already flagged the problem in public. Issue [#27](https://github.com/MemPalace/mempalace/issues/27)
82
+ on the MemPalace repository, opened April 7, 2026 and still open, documents that a headline 100%
83
+ LongMemEval figure, measured with Haiku reranking, wasn't reproducible from the repository's own
84
+ benchmark scripts and was pulled from the README as unverifiable. A separate 96.6% figure people
85
+ cite everywhere turns out to be mostly ChromaDB's default embeddings doing the work in raw mode,
86
+ not MemPalace's own architecture. A "lossless" compression claim (the "AAAK" mode) drops the same
87
+ LongMemEval score from 96.6% to 84.2% in practice, a 12.4 percentage point gap. Two internal pull
88
+ requests attempting to fix the reporting problem, #433 and #729, were both closed without merging
89
+ on April 12, 2026 -- #729 within seven minutes of being opened. As of this writing, the issue has
90
+ 233 thumbs-up reactions and 39 comments.
88
91
 
89
92
  None of that means MemPalace, or any other backend, doesn't work. It means nobody outside the
90
93
  vendor had run the same test, the same way, against every option, and published the raw logs.
91
94
 
92
95
  memtrust does that. It runs LongMemEval, LoCoMo, and a growing set of evals built specifically for
93
- this project -- 14 of them as of this writing, registered in the CLI's `--eval` flag, plus a
94
- fifteenth (temporal-KG boundary detection) that exists as a tested module but isn't wired into the
95
- CLI yet. The two that matter most for understanding what this project is actually for:
96
+ this project -- 17 of them as of this writing, all registered in the CLI's `--eval` flag. The two
97
+ that matter most for understanding what this project is actually for:
96
98
  contradiction detection, because neither LongMemEval nor LoCoMo tests the question that actually
97
99
  matters once a memory system sits underneath a production agent -- what happens when a new fact
98
100
  contradicts an old one? Does the backend flag the conflict? Silently overwrite the old fact with no
@@ -102,13 +104,21 @@ test claims like the "lossless" one above: it stores content, retrieves it, and
102
104
  reconstruction fidelity rather than semantic accuracy, per operating mode a backend exposes (see
103
105
  `MemoryBackendAdapter.supported_modes`) -- the mechanism that would let a contributor with live
104
106
  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 any
106
- live backend as of this writing** -- see `docs/methodology.md`. The other evals -- ranking quality,
107
+ mempalace/mempalace#27 documents, instead of just citing it. **Neither has been run against a live
108
+ MemPalace instance as of this writing** -- both have, however, been run against a live
109
+ self-hosted `mem0ai` install; see "Benchmarks" below. The other evals -- ranking quality,
107
110
  crash recovery, extraction quality, embedding drift, scale/volume stress, lock contention, stats
108
111
  accuracy, orphan cleanup, result consistency, migration rollback, filter injection, resource-sync
109
112
  safety, and temporal-KG boundary detection -- each grew out of a specific real bug report against
110
113
  one of the four tracked backends; see "Success stories" below for the full list.
111
114
 
115
+ **Where this stands right now, in one place:** [live benchmark results](#benchmarks) for one
116
+ backend (`mem0_direct`, self-hosted `mem0ai`), including a real bug this project's own attempt to
117
+ get those numbers surfaced in mem0's default configuration; and [197 real GitHub issues and PRs](#success-stories)
118
+ filed against MemPalace, Mem0, Zep/Graphiti, and OpenViking independently root-caused against this
119
+ codebase -- 55 (28%) PASS, 16 (8%) PARTIAL, 42 (21%) a genuine capability gap, 84 (43%) not
120
+ applicable, every verdict re-verified by a reviewer independent of whoever built the fix.
121
+
112
122
  ## What it does
113
123
 
114
124
  Every command below was actually run against this repo, with zero vendor API keys configured, to
@@ -116,11 +126,11 @@ produce the output shown. Nothing here is simulated.
116
126
 
117
127
  ```
118
128
  $ memtrust run --backends mempalace,mem0,zep,openviking --eval all
119
- memtrust 0.1.0 -- run_id=mt_2026-07-17T155402Z
129
+ memtrust 0.3.3 -- run_id=mt_2026-07-21T004232Z
120
130
  Backends: mempalace, mem0, zep, openviking Evals: longmemeval, locomo, contradiction,
121
131
  resource_sync_safety, compression, ranking_quality, scale_stress, embedding_drift, crash_recovery,
122
132
  extraction_quality, migration_rollback, filter_injection, lock_contention, stats_accuracy,
123
- orphan_cleanup, result_consistency
133
+ orphan_cleanup, result_consistency, temporal_kg_boundary
124
134
 
125
135
  mempalace: SKIPPED (not configured) -- mempalace is not configured: environment variable
126
136
  MEMPALACE_STORAGE_PATH is not set. Skipping this backend. See docs/methodology.md for setup
@@ -135,17 +145,19 @@ instructions.
135
145
 
136
146
  Cost: $0.00 (no LLM-judged evals ran -- structural evals only, or judge not configured)
137
147
 
138
- Full report: memtrust-report-2026-07-17.json
148
+ Full report: memtrust-report-2026-07-20.json
139
149
  ```
140
150
 
141
151
  That's the real, reproducible behavior of a fresh clone with no credentials: every backend reports
142
152
  SKIPPED, the command exits cleanly, and a valid JSON report is still written. `memtrust --version`
143
- currently prints `0.1.0` even though the package installs as `0.2.0` on PyPI -- a stale hardcoded
144
- string in `src/memtrust/__init__.py` that hasn't caught up with `pyproject.toml`, shown here exactly
145
- as it actually runs rather than smoothed over. Set the relevant environment variable for any backend
146
- you want to actually test (`MEM0_API_KEY`, `ZEP_API_KEY`, `OPENVIKING_API_KEY`,
147
- `MEMPALACE_STORAGE_PATH`) and that backend runs for real against its live API instead of being
148
- skipped.
153
+ now correctly prints `0.3.3`, matching `pip show memtrust-cli`. Earlier releases printed
154
+ `0.0.0+unknown` even when properly installed, because `src/memtrust/__init__.py` read
155
+ `importlib.metadata.version("memtrust")` while the installed distribution is actually named
156
+ `memtrust-cli` -- kept in the FAQ below for the record rather than deleted, since silently erasing
157
+ a bug the moment it's fixed is exactly the kind of curation this project exists to push back on in
158
+ other people's benchmarks. Set the relevant environment variable for any backend you want to
159
+ actually test (`MEM0_API_KEY`, `ZEP_API_KEY`, `OPENVIKING_API_KEY`, `MEMPALACE_STORAGE_PATH`) and
160
+ that backend runs for real against its live API instead of being skipped.
149
161
 
150
162
  The eval logic itself is proven offline, against the bundled synthetic fixtures and, for several
151
163
  adapters, the real installed vendor packages with only the network boundary mocked, by the test
@@ -153,29 +165,33 @@ suite:
153
165
 
154
166
  ```
155
167
  $ pytest --cov=memtrust --cov-report=term-missing
156
- ...
168
+ ... (33 module rows total; the 11 most relevant to this README are shown below)
157
169
  Name Stmts Miss Cover
158
170
  -------------------------------------------------------------------------------------
159
- src/memtrust/adapters/base.py 290 1 99%
160
- src/memtrust/adapters/mempalace_adapter.py 265 15 94%
171
+ src/memtrust/adapters/base.py 305 16 95%
172
+ src/memtrust/adapters/mempalace_adapter.py 254 15 94%
161
173
  src/memtrust/adapters/mem0_adapter.py 140 12 91%
162
- src/memtrust/adapters/mem0_direct_adapter.py 281 34 88%
174
+ src/memtrust/adapters/mem0_direct_adapter.py 277 34 88%
163
175
  src/memtrust/adapters/openviking_adapter.py 178 18 90%
164
176
  src/memtrust/adapters/zep_graphiti_adapter.py 63 3 95%
165
- src/memtrust/adapters/zep_graphiti_selfhosted_adapter.py 165 24 85%
177
+ src/memtrust/adapters/zep_graphiti_selfhosted_adapter.py 161 24 85%
166
178
  src/memtrust/evals/contradiction.py 127 2 98%
167
179
  src/memtrust/evals/compression.py 86 1 99%
168
- src/memtrust/evals/temporal_kg_boundary.py 90 4 96%
180
+ src/memtrust/evals/temporal_kg_boundary.py 90 3 97%
169
181
  src/memtrust/receipt.py 118 10 92%
170
182
  -------------------------------------------------------------------------------------
171
- TOTAL 4130 256 94%
183
+ TOTAL 4147 276 93%
172
184
 
173
- 580 passed, 8 skipped in 3.31s
185
+ 589 passed, 8 skipped in 3.57s
174
186
  ```
175
187
 
176
- 580 passing tests across 33 source modules, 94% overall statement coverage, 98% on the
177
- contradiction-detection eval, 99% on compression/round-trip fidelity, 96% on the new temporal-KG
178
- boundary eval, 94-99% across the adapter layer. The 8 skips are live-`mempalace`-package tests that
188
+ This is an excerpt, not the full table -- the weakest-covered module in the repo,
189
+ `evals/mempalace_metadata_scale.py` (70%), isn't one of the 11 shown above; run the command
190
+ yourself for the complete per-module breakdown.
191
+
192
+ 589 passing tests across 33 source modules, 93% overall statement coverage, 98% on the
193
+ contradiction-detection eval, 99% on compression/round-trip fidelity, 97% on the temporal-KG
194
+ boundary eval, 85-95% across the adapter layer. The 8 skips are live-`mempalace`-package tests that
179
195
  only run with the optional `mempalace-direct` extra installed (`pip install -e
180
196
  '.[dev,mempalace-direct]'`). Every test mocks its HTTP or wire
181
197
  layer, or uses an in-memory fake backend -- none of them touch a real network, though a meaningful
@@ -210,16 +226,11 @@ Commands:
210
226
 
211
227
  | Command | Flags | What it does |
212
228
  |---|---|---|
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. |
229
+ | `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
230
  | `memtrust report REPORT_PATH` | positional path to a prior JSON report | Reads a report written by `memtrust run` and prints a formatted summary. |
215
231
  | `memtrust keygen` | -- | Generates a new Ed25519 keypair for signing reports with `run --sign`. |
216
232
  | `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. Currently prints `0.1.0`, one release behind the `0.2.0` this package actually installs as -- see the note above. |
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.
233
+ | `memtrust --version` | -- | Prints the installed version (currently `0.3.3`). |
223
234
 
224
235
  Every line above came straight from running `memtrust --help`, `memtrust run --help`, and
225
236
  `memtrust report --help` against this repo. Nothing here is invented.
@@ -249,10 +260,10 @@ section below until a live run actually produces them:
249
260
 
250
261
  | Backend | GitHub stars | Self-reported description |
251
262
  |---|---|---|
252
- | [MemPalace](https://github.com/MemPalace/mempalace) | 57,268 | "The best-benchmarked open-source AI memory system. And it's free." |
253
- | [Mem0](https://github.com/mem0ai/mem0) | 60,688 | "Universal memory layer for AI Agents" |
254
- | [Zep / Graphiti](https://github.com/getzep/graphiti) | 28,648 | "Build Real-Time Knowledge Graphs for AI Agents" |
255
- | [OpenViking](https://github.com/volcengine/OpenViking) | 26,639 | "Self-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills." |
263
+ | [MemPalace](https://github.com/MemPalace/mempalace) | 57,512 | "The best-benchmarked open-source AI memory system. And it's free." |
264
+ | [Mem0](https://github.com/mem0ai/mem0) | 61,318 | "Universal memory layer for AI Agents" |
265
+ | [Zep / Graphiti](https://github.com/getzep/graphiti) | 28,978 | "Build Real-Time Knowledge Graphs for AI Agents" |
266
+ | [OpenViking](https://github.com/volcengine/OpenViking) | 27,016 | "Self-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills." |
256
267
 
257
268
  None of these numbers say anything about which backend handles a contradicted fact correctly --
258
269
  that's the whole reason the harness exists. Star count measures adoption, not correctness.
@@ -287,8 +298,9 @@ similarity ratio (`fidelity_ratio()`, via `difflib.SequenceMatcher` -- not an LL
287
298
  "lossless" claim is a literal-reconstruction claim, not a semantic one). This is what would let a
288
299
  contributor with live MemPalace credentials point `memtrust run --eval compression` at it and
289
300
  reproduce a "raw vs AAAK" fidelity gap directly. **As of this writing this eval has not been run
290
- against any live backend** -- see `docs/methodology.md` for the same live-credentials caveat that
291
- applies to every other eval in this table.
301
+ against a live MemPalace instance** -- it has been run against a live self-hosted `mem0ai` install
302
+ (mean fidelity 31.6%, see "Benchmarks" below); see `docs/methodology.md` for the same
303
+ live-credentials caveat that applies to every other eval and backend not yet measured live.
292
304
 
293
305
  ## The eval built from MemPalace's own bug: temporal-KG boundary detection
294
306
 
@@ -311,18 +323,76 @@ shipped in a released `mempalace` version as of this adapter's live-verified 3.5
311
323
  lands under the package's `[Unreleased]` changelog section. `tests/test_temporal_kg_boundary.py`
312
324
  proves the *classification logic* is correct against two hand-written fake implementations that
313
325
  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 also isn't
315
- wired into `memtrust run --eval` yet -- call `run_temporal_kg_boundary_eval()` directly, or see the
316
- test suite, until that CLI surface exists.
326
+ comparison exactly. **This has not been run against a live MemPalace instance.** It is wired into
327
+ `memtrust run --eval temporal_kg_boundary` (see "Commands" above); against any backend other than
328
+ `mempalace`, it reports `not_applicable` rather than an error.
317
329
 
318
330
  ## Benchmarks
319
331
 
320
- **Not yet measured against live backends.** This repo was built without API credentials for
321
- MemPalace, Mem0, Zep, or OpenViking. Publishing a number here without actually running the harness
322
- against a live backend would be exactly the kind of unverifiable claim this project exists to
323
- push back on, so there isn't one.
332
+ **Live results: mem0_direct (self-hosted), July 2026.** MemPalace, Zep, and OpenViking are still
333
+ not yet measured against a live backend -- see "Backend coverage" below for the confidence level
334
+ on each adapter. Mem0 has one real result, produced against the actual `mem0ai` OSS library
335
+ running self-hosted -- in-process, via `Mem0DirectAdapter`, backed by a local Qdrant instance and
336
+ the OpenAI API for embeddings and extraction -- not against Mem0's hosted Platform API. Keep that
337
+ distinction in mind before reading this as a claim about the hosted product.
338
+
339
+ ```
340
+ $ export MEM0_DIRECT_EMBEDDER_PROVIDER=openai
341
+ $ export MEM0_DIRECT_VECTOR_STORE_PROVIDER=qdrant
342
+ $ export MEM0_DIRECT_VECTOR_STORE_URL=http://localhost:6333
343
+ $ memtrust run --backends mem0_direct --eval contradiction,compression,extraction_quality
344
+ memtrust 0.3.2 -- run_id=mt_2026-07-20T210918Z
345
+ Backends: mem0_direct Evals: contradiction, compression, extraction_quality
346
+
347
+ mem0_direct: configured, running evals...
348
+ Running Contradiction-Detection against mem0_direct...
349
+ flagged: 0.0% silent-overwrite: 100.0% served-stale: 0.0% empty-or-lost: 0.0%
350
+ Running Compression/Round-Trip-Fidelity against mem0_direct...
351
+ fidelity by mode -- default: 31.6%
352
+ Running Extraction-Quality against mem0_direct...
353
+ junk-retained: 0.0% valid-lost: 100.0%
354
+ feedback-loop-duplicate: 0.0%
355
+
356
+ Cost: $0.00 (no LLM-judged evals ran -- structural evals only, or judge not configured)
357
+ ```
324
358
 
325
- To produce real numbers:
359
+ The full raw report is committed at `leaderboard/mem0_direct-2026-07-20.json`, and `leaderboard/data.json`
360
+ carries the contradiction numbers into the static leaderboard site (`mempalace`/`mem0`/`zep`/`openviking`
361
+ still show `not_measured` there; `mem0_direct` is the one real row).
362
+
363
+ What that means case by case, not just the percentage:
364
+
365
+ - **Contradiction detection, 7/7 cases: every contradicting fact silently overwrote the old one.**
366
+ 0% were flagged as a conflict, 0% served stale, 0% empty-or-lost. Tell it your meeting moved from
367
+ 2pm to 3pm and it stores the new fact with no signal that anything changed -- this is exactly the
368
+ question LongMemEval and LoCoMo don't test, and exactly what "Why this exists" above is about.
369
+ - **Compression/round-trip fidelity, 5 cases: 31.6% mean literal character-level reconstruction.**
370
+ This is expected, not a defect -- mem0's design goal is semantic fact extraction, not verbatim
371
+ storage, so a literal-reconstruction score was never going to be high. It quantifies what "not
372
+ built for lossless storage" concretely means for this backend: ask it what you said and you get
373
+ the gist back, not your words.
374
+ - **Extraction quality, 15 cases (12 deliberately junk, 3 deliberately valid): 0% junk retained,
375
+ 100% of the valid cases lost.** All 12 junk inputs (boot-file restating, cron heartbeat noise,
376
+ system dumps, hallucinated-profile bait) were correctly rejected. All 3 valid-content cases were
377
+ also dropped -- stored but never came back on retrieval. The valid-side sample is small (n=3);
378
+ treat this as a signal worth digging into further, not a settled number.
379
+
380
+ **A real bug this run surfaced in mem0ai itself, not in memtrust.** Getting any of the numbers
381
+ above required a fix first: a fresh `mem0ai==2.0.12` install with nothing but `OPENAI_API_KEY` set
382
+ fails every single LLM-based extraction call, out of the box, for anyone. mem0's own default model
383
+ (`mem0/llms/openai.py`: `self.config.model = "gpt-5-mini"`) is a reasoning-tier model that only
384
+ accepts the API's default temperature, but mem0's own reasoning-model detection
385
+ (`mem0/llms/base.py`'s `reasoning_models` set) checks for the string `"gpt-5o-mini"`, not
386
+ `"gpt-5-mini"` -- two different strings, so the check never fires, and mem0 sends `temperature=0.1`
387
+ on every call regardless. The result is a `400 Unsupported value: 'temperature' does not support
388
+ 0.1 with this model` error on every extraction call, silently caught by mem0 and reported by
389
+ memtrust as `N/A (no scoreable cases)` rather than a real result. `Mem0DirectAdapter` now works
390
+ around it by passing `is_reasoning_model=True` explicitly -- mem0's own documented override for
391
+ exactly this situation -- see `src/memtrust/adapters/mem0_direct_adapter.py`'s "Default LLM
392
+ extraction is broken out of the box" section for the full citation. No upstream mem0ai issue filed
393
+ for this as of this writing.
394
+
395
+ To reproduce this or measure the remaining three backends:
326
396
 
327
397
  ```bash
328
398
  export MEM0_API_KEY=... # and/or
@@ -403,13 +473,8 @@ LongMemEval/LoCoMo datasets). Nothing leaves your machine unless you choose to p
403
473
 
404
474
  ### npx (agent-native)
405
475
 
406
- > **PyPI is live; the npm wrapper is publish-ready but not yet published.** `pip install memtrust-cli`
407
- > works today -- version 0.2.0 is on PyPI. The `memtrust-cli` npm package in `npm/memtrust-cli/` in
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.
476
+ Both PyPI and npm are live. `pip install memtrust-cli` works today, and so does the `npx` command
477
+ below -- `npm install memtrust-cli` no longer 404s.
413
478
 
414
479
  For CI and agent runners that have Node.js available but not necessarily a Python toolchain:
415
480
 
@@ -429,9 +494,11 @@ first use. What it removes is no Python toolchain to provision by hand -- `npx m
429
494
  handles the interpreter and package fetch for you via a bundled, verified copy of Astral's
430
495
  [`uv`](https://github.com/astral-sh/uv). Each platform package bundles a genuine, SHA-256-verified
431
496
  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 <args>`, which
433
- transparently bootstraps a Python interpreter and installs `memtrust` from PyPI, caching it after
434
- the first run.
497
+ install time), and its `bin` shim runs `uv tool run --from memtrust==<pinned version> memtrust
498
+ <args>`, which transparently bootstraps a Python interpreter and installs that exact pinned
499
+ `memtrust` release from PyPI, caching it after the first run. The npm package is pinned to its own
500
+ version -- bump `npm/memtrust-cli/package.json`'s version when a new PyPI release ships, and every
501
+ subsequent install resolves to that exact release, not whatever happens to be newest at run time.
435
502
 
436
503
  ## What a hosted trust layer would add
437
504
 
@@ -488,7 +555,7 @@ commit than remember to run them by hand.
488
555
  ## FAQ
489
556
 
490
557
  **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 14 others registered
558
+ page?** It's a CLI harness that runs the same evals (LongMemEval, LoCoMo, and 15 others registered
492
559
  in `--eval`, including a contradiction-detection eval none of the four tracked backends publish a
493
560
  number for) against MemPalace, Mem0, Zep/Graphiti, and OpenViking, and prints the raw output rather
494
561
  than a curated summary. The differentiator isn't a proprietary scoring model; it's that nobody
@@ -524,20 +591,37 @@ those four backends make about themselves. If you need broad RAG or prompt-evalu
524
591
  RAGAS or a similar framework is the right tool; if you need to check whether a memory backend
525
592
  silently drops or overwrites a contradicted fact, memtrust is the one built for that question.
526
593
 
527
- **Why does `memtrust --version` print a version that doesn't match what pip says I installed?**
528
- This is a real, currently open limitation, not a hypothetical one -- installing `memtrust-cli` from
529
- PyPI into a clean virtualenv and running `pip show memtrust-cli` reports `0.3.0`, but
530
- `memtrust --version` prints `0.0.0+unknown`. The CLI's version string isn't reading the installed
531
- package metadata correctly. Until it's fixed, use `pip show memtrust-cli` (or
532
- `python3 -c "import importlib.metadata as m; print(m.version('memtrust-cli'))"`) to check what's
533
- actually installed, not the CLI's own `--version` output.
594
+ **Why did `memtrust --version` used to print a version that didn't match what pip said I
595
+ installed?** This was a real, shipped bug through 0.3.1, not a hypothetical one: installing
596
+ `memtrust-cli` from PyPI into a clean virtualenv and running `pip show memtrust-cli` reported the
597
+ correct version, but `memtrust --version` printed `0.0.0+unknown` regardless, because
598
+ `src/memtrust/__init__.py` read `importlib.metadata.version("memtrust")` -- the wrong distribution
599
+ name -- instead of `version("memtrust-cli")`, the name the package is actually installed under.
600
+ 0.3.2's fix was itself incomplete: it hardcoded the lookup to `"memtrust-cli"`, which broke the
601
+ separate `memtrust` mirror package (see "Can I `pip install memtrust` instead of
602
+ `memtrust-cli`?" below) the same way in reverse -- a `pip install memtrust` environment has no
603
+ `memtrust-cli` entry in its own installed-package metadata at all, so the lookup always missed and
604
+ fell through to the same `0.0.0+unknown` fallback. Fixed for real in 0.3.3: the lookup now tries
605
+ `memtrust-cli` first, falls back to `memtrust`, and only reports `0.0.0+unknown` if neither
606
+ distribution name is installed. `memtrust --version` now matches `pip show` under either package
607
+ name.
608
+
609
+ **Can I `pip install memtrust` instead of `memtrust-cli`?** Yes -- `memtrust` is a real, separate
610
+ PyPI package, kept at the same version as `memtrust-cli` on every release, publishing the identical
611
+ source. It exists because the npm wrapper's `bin/memtrust.js` pins `uv tool run --from
612
+ memtrust==<version>` (not `memtrust-cli`), so a working `npx memtrust-cli` depends on the
613
+ `memtrust` name staying live and in sync. `memtrust-cli` is the name to lead with in new
614
+ documentation, since the `-cli` suffix makes it unambiguous as a CLI tool at a glance; `memtrust`
615
+ is a legitimate, supported install path, not a typo or a squatted name.
534
616
 
535
617
  **Has memtrust actually been run against a live memory backend, or is this all synthetic?** Both,
536
618
  and the README doesn't blur the line. The eval logic itself is proven against bundled synthetic
537
619
  fixtures and, for several adapters, real installed vendor packages with only the network boundary
538
- mocked (see the pytest coverage table above). But no eval in this repo has been run against a live
539
- MemPalace, Mem0, Zep, or OpenViking backend with real credentials as of this writing -- the
540
- "Benchmarks" section above states that directly rather than publishing a placeholder number. The
620
+ mocked (see the pytest coverage table above). One backend has a real live result: `mem0_direct`,
621
+ the self-hosted `mem0ai` OSS library (not Mem0's hosted Platform API), run against contradiction,
622
+ compression, and extraction-quality -- see "Benchmarks" above for the exact numbers and a real bug
623
+ that run surfaced in `mem0ai` itself. MemPalace, the hosted Mem0 Platform API, Zep, and OpenViking
624
+ have not yet been run against a live backend with real credentials as of this writing. The
541
625
  "Backend coverage" table gives a per-adapter confidence level (high/medium/low) for exactly this
542
626
  reason; run it yourself against your own credentials to get a live-verified number.
543
627
 
@@ -547,7 +631,7 @@ and requires you to preserve the license and copyright notice and to note any ch
547
631
  the code. It does not require you to open-source your own product just because you depend on
548
632
  memtrust.
549
633
 
550
- **How do I get real accuracy numbers instead of the "not yet measured" placeholder?** Set the
634
+ **How do I get real accuracy numbers for the backends still marked "not yet measured"?** Set the
551
635
  credential environment variable for whichever backend you want to test
552
636
  (`MEMPALACE_STORAGE_PATH`, `MEM0_API_KEY`, `ZEP_API_KEY`, `OPENVIKING_API_KEY`, plus
553
637
  `MEMTRUST_JUDGE_API_KEY` for LLM-judged evals like LongMemEval and LoCoMo), then run
@@ -607,10 +691,6 @@ shipped in the open rather than quietly. See "Backend coverage" above for the fu
607
691
  (@JosefAschauer): an `authored_at` chronology tie-break fix for `_hybrid_rank`. memtrust's ranking
608
692
  classifier now credits a top-level `authored_at` field, not just one nested under `metadata`, as
609
693
  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
694
 
615
695
  **mem0**
616
696
  - [#5973](https://github.com/mem0ai/mem0/pull/5973) (@abhay-codes07, superseded by
@@ -635,7 +715,13 @@ shipped in the open rather than quietly. See "Backend coverage" above for the fu
635
715
  update) against this taxonomy.
636
716
  - [#4884](https://github.com/mem0ai/mem0/issues/4884) (@wangjiawei-vegetable): a hardcoded
637
717
  English-only tokenizer silently degrading non-Latin-script retrieval. A new
638
- `LanguageDegradationSignal` and non-Latin-script fixtures now catch this shape.
718
+ `LanguageDegradationSignal` and non-Latin-script fixtures now catch this shape --
719
+ `Mem0DirectAdapter`-specific (it reads `query(explain=True)`'s real per-result diagnostic
720
+ fields, a capability only that adapter exposes) and, like `embedder_cost.py`'s cost-attribution
721
+ eval and `episode_temporal_leak.py`'s Graphiti-specific eval, not yet wired into `memtrust run
722
+ --eval`'s general list; call `run_language_degradation_eval()` directly, or see the
723
+ `test_query_language_degradation_*` tests in `tests/test_mem0_direct_adapter.py`, until that CLI
724
+ surface exists.
639
725
 
640
726
  **Zep / Graphiti**
641
727
  - [#1489](https://github.com/getzep/graphiti/issues/1489) (@brentkearney): a bi-temporal