flywheel-mneme 0.4.2__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.
- flywheel_mneme-0.4.2/LICENSE +110 -0
- flywheel_mneme-0.4.2/PKG-INFO +373 -0
- flywheel_mneme-0.4.2/README.md +353 -0
- flywheel_mneme-0.4.2/pyproject.toml +34 -0
- flywheel_mneme-0.4.2/setup.cfg +4 -0
- flywheel_mneme-0.4.2/src/flywheel_mneme.egg-info/PKG-INFO +373 -0
- flywheel_mneme-0.4.2/src/flywheel_mneme.egg-info/SOURCES.txt +60 -0
- flywheel_mneme-0.4.2/src/flywheel_mneme.egg-info/dependency_links.txt +1 -0
- flywheel_mneme-0.4.2/src/flywheel_mneme.egg-info/entry_points.txt +2 -0
- flywheel_mneme-0.4.2/src/flywheel_mneme.egg-info/requires.txt +3 -0
- flywheel_mneme-0.4.2/src/flywheel_mneme.egg-info/top_level.txt +1 -0
- flywheel_mneme-0.4.2/src/mneme/__init__.py +14 -0
- flywheel_mneme-0.4.2/src/mneme/__main__.py +4 -0
- flywheel_mneme-0.4.2/src/mneme/bench.py +113 -0
- flywheel_mneme-0.4.2/src/mneme/cli.py +524 -0
- flywheel_mneme-0.4.2/src/mneme/compose.py +115 -0
- flywheel_mneme-0.4.2/src/mneme/consolidate.py +125 -0
- flywheel_mneme-0.4.2/src/mneme/drift.py +137 -0
- flywheel_mneme-0.4.2/src/mneme/embed.py +66 -0
- flywheel_mneme-0.4.2/src/mneme/entity.py +129 -0
- flywheel_mneme-0.4.2/src/mneme/extract.py +90 -0
- flywheel_mneme-0.4.2/src/mneme/ingest.py +147 -0
- flywheel_mneme-0.4.2/src/mneme/inspect.py +118 -0
- flywheel_mneme-0.4.2/src/mneme/llm_extract.py +112 -0
- flywheel_mneme-0.4.2/src/mneme/mcp.py +333 -0
- flywheel_mneme-0.4.2/src/mneme/memory.py +257 -0
- flywheel_mneme-0.4.2/src/mneme/origin.py +509 -0
- flywheel_mneme-0.4.2/src/mneme/recall.py +201 -0
- flywheel_mneme-0.4.2/src/mneme/receipt.py +187 -0
- flywheel_mneme-0.4.2/src/mneme/replay.py +319 -0
- flywheel_mneme-0.4.2/src/mneme/scenario.py +74 -0
- flywheel_mneme-0.4.2/src/mneme/schema.py +44 -0
- flywheel_mneme-0.4.2/src/mneme/source.py +308 -0
- flywheel_mneme-0.4.2/src/mneme/store.py +519 -0
- flywheel_mneme-0.4.2/src/mneme/temporal.py +74 -0
- flywheel_mneme-0.4.2/tests/test_audit_integrity.py +65 -0
- flywheel_mneme-0.4.2/tests/test_bench.py +82 -0
- flywheel_mneme-0.4.2/tests/test_compose.py +233 -0
- flywheel_mneme-0.4.2/tests/test_consolidate.py +85 -0
- flywheel_mneme-0.4.2/tests/test_crucible_replay.py +1271 -0
- flywheel_mneme-0.4.2/tests/test_drift_content.py +217 -0
- flywheel_mneme-0.4.2/tests/test_embed.py +70 -0
- flywheel_mneme-0.4.2/tests/test_entity.py +63 -0
- flywheel_mneme-0.4.2/tests/test_forget.py +89 -0
- flywheel_mneme-0.4.2/tests/test_ingest.py +291 -0
- flywheel_mneme-0.4.2/tests/test_inspect.py +86 -0
- flywheel_mneme-0.4.2/tests/test_llm_extract.py +88 -0
- flywheel_mneme-0.4.2/tests/test_mneme.py +138 -0
- flywheel_mneme-0.4.2/tests/test_multiuser.py +60 -0
- flywheel_mneme-0.4.2/tests/test_origin_recheck.py +425 -0
- flywheel_mneme-0.4.2/tests/test_provenance_grounding.py +44 -0
- flywheel_mneme-0.4.2/tests/test_recall_receipt.py +67 -0
- flywheel_mneme-0.4.2/tests/test_recency.py +65 -0
- flywheel_mneme-0.4.2/tests/test_repo_art.py +212 -0
- flywheel_mneme-0.4.2/tests/test_scenario_mcp.py +451 -0
- flywheel_mneme-0.4.2/tests/test_scope_isolation.py +343 -0
- flywheel_mneme-0.4.2/tests/test_temporal.py +76 -0
- flywheel_mneme-0.4.2/tests/test_tour.py +11 -0
- flywheel_mneme-0.4.2/tests/test_union_and_migration.py +76 -0
- flywheel_mneme-0.4.2/tests/test_verify_audit_cli.py +59 -0
- flywheel_mneme-0.4.2/tests/test_verify_recall.py +53 -0
- flywheel_mneme-0.4.2/tests/test_version_metadata.py +95 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Functional Source License, Version 1.1, MIT Future License
|
|
2
|
+
|
|
3
|
+
## Abbreviation
|
|
4
|
+
|
|
5
|
+
FSL-1.1-MIT
|
|
6
|
+
|
|
7
|
+
## Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 Zain Dana Harper
|
|
10
|
+
|
|
11
|
+
## Terms and Conditions
|
|
12
|
+
|
|
13
|
+
### Licensor ("We")
|
|
14
|
+
|
|
15
|
+
The party offering the Software under these Terms and Conditions.
|
|
16
|
+
|
|
17
|
+
### The Software
|
|
18
|
+
|
|
19
|
+
The "Software" is each version of the software that we make available under
|
|
20
|
+
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
21
|
+
Conditions with the Software.
|
|
22
|
+
|
|
23
|
+
### License Grant
|
|
24
|
+
|
|
25
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
26
|
+
Redistribution and Trademark clauses below, we hereby grant you the right to
|
|
27
|
+
use, copy, modify, create derivative works, publicly perform, publicly display
|
|
28
|
+
and redistribute the Software for any Permitted Purpose identified below.
|
|
29
|
+
|
|
30
|
+
### Permitted Purpose
|
|
31
|
+
|
|
32
|
+
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
33
|
+
means making the Software available to others in a commercial product or
|
|
34
|
+
service that:
|
|
35
|
+
|
|
36
|
+
1. substitutes for the Software;
|
|
37
|
+
|
|
38
|
+
2. substitutes for any other product or service we offer using the Software
|
|
39
|
+
that exists as of the date we make the Software available; or
|
|
40
|
+
|
|
41
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
42
|
+
|
|
43
|
+
Permitted Purposes specifically include using the Software:
|
|
44
|
+
|
|
45
|
+
1. for your internal use and access;
|
|
46
|
+
|
|
47
|
+
2. for non-commercial education;
|
|
48
|
+
|
|
49
|
+
3. for non-commercial research; and
|
|
50
|
+
|
|
51
|
+
4. in connection with professional services that you provide to a licensee
|
|
52
|
+
using the Software in accordance with these Terms and Conditions.
|
|
53
|
+
|
|
54
|
+
### Patents
|
|
55
|
+
|
|
56
|
+
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
57
|
+
patents, the license grant above includes a license under our patents. If you
|
|
58
|
+
make a claim against any party that the Software infringes or contributes to
|
|
59
|
+
the infringement of any patent, then your patent license to the Software ends
|
|
60
|
+
immediately.
|
|
61
|
+
|
|
62
|
+
### Redistribution
|
|
63
|
+
|
|
64
|
+
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
65
|
+
the Software.
|
|
66
|
+
|
|
67
|
+
If you redistribute any copies, modifications or derivatives of the Software,
|
|
68
|
+
you must include a copy of or a link to these Terms and Conditions and not
|
|
69
|
+
remove any copyright notices provided in or with the Software.
|
|
70
|
+
|
|
71
|
+
### Disclaimer
|
|
72
|
+
|
|
73
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
|
|
74
|
+
IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
|
|
75
|
+
PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
|
|
76
|
+
|
|
77
|
+
IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
|
|
78
|
+
SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
|
|
79
|
+
EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
80
|
+
|
|
81
|
+
### Trademarks
|
|
82
|
+
|
|
83
|
+
Except for displaying the License Details and identifying us as the origin of
|
|
84
|
+
the Software, you have no right under these Terms and Conditions to use our
|
|
85
|
+
trademarks, trade names, service marks or product names.
|
|
86
|
+
|
|
87
|
+
## Grant of Future License
|
|
88
|
+
|
|
89
|
+
We hereby irrevocably grant you an additional license to use the Software under
|
|
90
|
+
the MIT license that is effective on the second anniversary of the date we make
|
|
91
|
+
the Software available. On or after that date, you may use the Software under
|
|
92
|
+
the MIT license, in which case the following will apply:
|
|
93
|
+
|
|
94
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
95
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
96
|
+
the Software without restriction, including without limitation the rights to
|
|
97
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
98
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
99
|
+
so, subject to the following conditions:
|
|
100
|
+
|
|
101
|
+
The above copyright notice and this permission notice shall be included in all
|
|
102
|
+
copies or substantial portions of the Software.
|
|
103
|
+
|
|
104
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
105
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
106
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
107
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
108
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
109
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
110
|
+
SOFTWARE.
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flywheel-mneme
|
|
3
|
+
Version: 0.4.2
|
|
4
|
+
Summary: Accountable agent memory with layered retrieval, source provenance, re-derivable recall receipts, and drift checks. Zero runtime dependencies.
|
|
5
|
+
Author: Zain Dana Harper
|
|
6
|
+
License-Expression: LicenseRef-FSL-1.1-MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/HarperZ9/mneme
|
|
8
|
+
Keywords: agent-memory,llm-memory,long-term-memory,provenance,retrieval,bm25,rag
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
14
|
+
Requires-Python: >=3.11
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Provides-Extra: test
|
|
18
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
<p align="center"><img src="docs/art/mneme-header.svg" alt="mneme: Source provenance, reproducible ranking, and drift checks." width="100%"></p>
|
|
22
|
+
|
|
23
|
+
# mneme
|
|
24
|
+
|
|
25
|
+
> Accountable agent memory. Mneme records source provenance for stored
|
|
26
|
+
> memories, returns recall receipts that reproduce ranking, and detects source
|
|
27
|
+
> drift when checks run.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
### Released v0.4.2 wheel
|
|
32
|
+
|
|
33
|
+
The public `v0.4.2` wheel is the current released package. It covers the released memory, recall, drift, provenance, accountable forgetting, local-origin freshness, and MCP Crucible export/replay workflows documented below.
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python -m pip install flywheel-mneme
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`flywheel-mneme` is the HarperZ9 distribution, published with PEP 740 attestations. The bare name `mneme-memory` on PyPI belongs to an unrelated project.
|
|
40
|
+
|
|
41
|
+
To check the bytes yourself rather than trust the index, install the release wheel directly:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python -m pip install "https://github.com/HarperZ9/mneme/releases/download/v0.4.2/flywheel_mneme-0.4.2-py3-none-any.whl"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Source install
|
|
48
|
+
|
|
49
|
+
For development from a source checkout:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
python -m pip install -e .
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
For a non-editable install from the public source repository:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
python -m pip install "flywheel-mneme @ git+https://github.com/HarperZ9/mneme.git"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Zero runtime dependencies · fully local · deterministic · fair-source.
|
|
62
|
+
|
|
63
|
+
## Why it matters
|
|
64
|
+
|
|
65
|
+
Agent memory systems need evidence for two operational questions:
|
|
66
|
+
|
|
67
|
+
- **Why did you recall *this* memory?** Mneme returns the ranked hits, component
|
|
68
|
+
scores, and fusion rule so the ranking can be reproduced.
|
|
69
|
+
- **Is this memory still grounded in its cited source?** Mneme records source
|
|
70
|
+
hashes and re-checks them to detect drift, missing sources, or unverifiable
|
|
71
|
+
grounding.
|
|
72
|
+
|
|
73
|
+
Mneme stores that evidence with the memory workflow instead of leaving it as a
|
|
74
|
+
separate operator note.
|
|
75
|
+
|
|
76
|
+
## The 4-tier memory model
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
L0 turn raw dialogue -> stored verbatim
|
|
80
|
+
L1 atom atomic user facts -> extracted, each bound to its turn
|
|
81
|
+
L2 scenario scene blocks of related atoms
|
|
82
|
+
L3 persona the user profile -> synthesized, citing its atoms
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Retrieval is hybrid: BM25 (pure Python, always on) fused with an optional
|
|
86
|
+
embedding channel by Reciprocal Rank Fusion, with no required embedding API.
|
|
87
|
+
|
|
88
|
+
<p align="center"><img src="docs/art/recall-lane.svg" alt="Eight stages from a raw turn to a receipt, ending in reproduced or did not reproduce." width="100%"></p>
|
|
89
|
+
|
|
90
|
+
## Accountability features
|
|
91
|
+
|
|
92
|
+
**A recall you can re-derive.** Every `recall` returns a receipt with the ranked
|
|
93
|
+
hits, their BM25 and vector scores, and the exact fusion rule. And `verify_recall`
|
|
94
|
+
ships the check: it re-runs the scorer over the same rows and confirms the ranking,
|
|
95
|
+
so a fabricated or tampered recall is caught even if its definition hash still
|
|
96
|
+
matches, and a store that changed no longer reproduces. The recall is auditable by a
|
|
97
|
+
function you can put in CI, not a claim you take on faith.
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from mneme import recall, verify_recall
|
|
101
|
+
|
|
102
|
+
r = recall("deploy steps", rows, strategy="hybrid", embedder=embed)
|
|
103
|
+
assert verify_recall(r, rows, embedder=embed) # re-derived from the store, not trusted
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
mneme remember chat session.json --user alice
|
|
108
|
+
mneme recall "where does the user live" --user alice --json
|
|
109
|
+
# -> {"schema":"mneme.recall/1","hits":[{"memory_id":"…","bm25":2.14,"fused":…}],
|
|
110
|
+
# "recheck":"mneme recall --query Q --state DB (re-run the scorer, reproduce the ranking)"}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**A drift check for source changes.** `drift` re-derives every memory's
|
|
114
|
+
grounding against the current store: `MATCH` (source present and unchanged),
|
|
115
|
+
`DRIFT` (a source changed under the memory), `UNVERIFIABLE` (a source is gone).
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
mneme drift # -> {"overall":"DRIFT","drifted":["…"], …} exit 1 on drift
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
<p align="center"><img src="docs/art/drift-lane.svg" alt="Eight stages from a stored memory to a verdict of match, drift, or unverifiable." width="100%"></p>
|
|
122
|
+
|
|
123
|
+
Two details make that verdict hard to fake. A memory row has to reproduce its own
|
|
124
|
+
content hash before any of its sources are looked at, which catches a direct edit
|
|
125
|
+
of the text, the source list, or the criterion. Each cited source is then re-hashed
|
|
126
|
+
from its actual fields rather than read back from the hash stored beside it,
|
|
127
|
+
because trusting that stored value would let someone edit the database directly,
|
|
128
|
+
leave a stale hash in place, and collect a `MATCH`. The check re-derives on both
|
|
129
|
+
sides before it will agree with itself.
|
|
130
|
+
|
|
131
|
+
The three verdicts are also ordered when they roll up across a store: any `DRIFT`
|
|
132
|
+
makes the whole report `DRIFT`, otherwise any `UNVERIFIABLE` makes it
|
|
133
|
+
`UNVERIFIABLE`, and only a clean sweep reports `MATCH`. That order fails closed. A
|
|
134
|
+
memory whose source has been deleted is never rounded up to a match on the grounds
|
|
135
|
+
that nothing contradicted it, so absence of evidence is reported as absence rather
|
|
136
|
+
than as agreement.
|
|
137
|
+
|
|
138
|
+
<p align="center"><img src="docs/art/grounding-verdicts.svg" alt="Nine conditions a memory's grounding check can land on, one to a row, each with the verdict it produces. Four produce DRIFT: unreadable provenance, a memory row edited in place, a source whose bytes disagree with the address it carries, and a source that hashes differently than it did at extraction. Four produce UNVERIFIABLE: a missing memory, a memory citing no sources at all, a cited source that has left the store, and a source present but never snapshotted. One produces MATCH: all cited sources are present and re-hash to what was recorded. The row for a source whose bytes disagree with the address stored beside it is accented, because that is the one case a check reading only the stored address would call a match." width="100%"></p>
|
|
139
|
+
|
|
140
|
+
Nine conditions reach one of those three verdicts, and the drawing above
|
|
141
|
+
lists every one of them. Four resolve to `DRIFT` and four to
|
|
142
|
+
`UNVERIFIABLE`. Exactly one reaches `MATCH`, which is the shape of a check
|
|
143
|
+
that has to earn agreement rather than assume it.
|
|
144
|
+
|
|
145
|
+
**Provenance on every memory.** Every atom names the turn it came from, the
|
|
146
|
+
extractor, the criterion, and a content hash. The persona is not free text: it
|
|
147
|
+
cites its atoms, so it is drift-checkable too.
|
|
148
|
+
|
|
149
|
+
## Library
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from mneme import AgentMemory
|
|
153
|
+
|
|
154
|
+
mem = AgentMemory("mem.db") # or ":memory:"
|
|
155
|
+
mem.remember("chat", [{"role": "user", "text": "I live in Denver and love dark roast."}],
|
|
156
|
+
user="alice")
|
|
157
|
+
|
|
158
|
+
receipt = mem.recall("coffee preference", user="alice") # RecallReceipt, re-derivable
|
|
159
|
+
print(mem.drift()["overall"]) # MATCH until a source changes
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
An embedder (`AgentMemory(..., embedder=fn)`) turns on the vector channel; an
|
|
163
|
+
LLM `Extractor` plugs in for richer atoms. Neither is required: the
|
|
164
|
+
deterministic floor works with no model and no API.
|
|
165
|
+
|
|
166
|
+
## The ecosystem: memory that traces to its source
|
|
167
|
+
|
|
168
|
+
Point mneme at an accountable intake tool ([gather](https://github.com/HarperZ9/gather),
|
|
169
|
+
the sibling flagship) and the provenance chain can run end to end:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
origin ref --(intake sha256)--> mneme turn --> mneme atom --> recall
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
mneme ingest research items.json --user alice # gather-shaped {id,text,source,ref,method,sha256}
|
|
177
|
+
mneme recall "where is the user based" --user alice
|
|
178
|
+
mneme chain <memory_id> # -> the supplied origin ref + intake hash
|
|
179
|
+
mneme origin-recheck <memory_id> --allowed-root docs/
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
An agent that remembers what it researched, and can prove a recalled memory
|
|
183
|
+
traces to the receipt supplied by its intake tool. For supported local Gather
|
|
184
|
+
docs receipts, `origin-recheck` can re-read the operator-approved file under
|
|
185
|
+
`--allowed-root` and compare Gather's normalized decoded text hash. Legacy
|
|
186
|
+
receipts do not prove raw byte integrity, and unsupported refs remain
|
|
187
|
+
`UNVERIFIABLE` rather than silently promoted. `origin-recheck` opens Mneme state
|
|
188
|
+
read-only, refuses local path aliases and unsupported refs, and reports `MATCH`,
|
|
189
|
+
`DRIFT`, or `UNVERIFIABLE` without including source content in the report.
|
|
190
|
+
Any intake tool that emits the receipt shape composes; mneme never imports gather. Named-user `remember` and
|
|
191
|
+
Gather ingest derive source turn IDs from the user, session, supplied item/turn
|
|
192
|
+
ID, and for Gather the origin hash. The shared default user keeps the legacy
|
|
193
|
+
raw-ID namespace, except new default-user writes cannot use Mneme's reserved
|
|
194
|
+
internal source ID prefix.
|
|
195
|
+
|
|
196
|
+
And the loop closes at the other end. `mneme to-crucible` emits a schema-v2
|
|
197
|
+
[crucible](https://github.com/HarperZ9/crucible) export: each memory is a claim
|
|
198
|
+
paired with Mneme's source-bound drift measurement. Crucible independently
|
|
199
|
+
recomputes and seals `MATCH`, `DRIFT`, or `UNVERIFIABLE` from that measurement.
|
|
200
|
+
Each exported measurement now carries a declarative `mneme.recheck/1`
|
|
201
|
+
descriptor. After Crucible writes an assessment-bound replay template, Mneme
|
|
202
|
+
can re-read the supplied state and fill its replay pack without importing
|
|
203
|
+
Crucible or embedding a database path or executable command in the descriptor:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
crucible recheck REGISTRY --template replay-template.json
|
|
207
|
+
python -c "import sqlite3; s=sqlite3.connect('file:mneme.db?mode=ro', uri=True); d=sqlite3.connect('mneme-replay-snapshot.db'); s.backup(d); d.execute('PRAGMA journal_mode=DELETE'); d.close(); s.close()"
|
|
208
|
+
mneme --state mneme-replay-snapshot.db replay-crucible replay-template.json --out replay-pack.json
|
|
209
|
+
crucible recheck REGISTRY --pack replay-pack.json --json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The replay command fails closed when the assessment triple, claim binding,
|
|
213
|
+
descriptor, original measurement contract, or target memory grounding differs.
|
|
214
|
+
Ordinary source drift remains a replay result (`1.0`); a missing source remains
|
|
215
|
+
unverifiable (`null`). Crucible still does not independently re-read Mneme's
|
|
216
|
+
source. The source recheck is Mneme-owned, and Crucible verifies that the
|
|
217
|
+
replayed measurement exactly reproduces its sealed contract.
|
|
218
|
+
|
|
219
|
+
The command consumes `crucible.replay-template/1` from a caller-owned,
|
|
220
|
+
quiescent, single-link rollback-journal snapshot. The example uses SQLite's
|
|
221
|
+
backup API to materialize one; keep that file unchanged until replay returns.
|
|
222
|
+
|
|
223
|
+
Open the source read-only when you take that snapshot, exactly as the example
|
|
224
|
+
does. A read-write handle on a WAL database whose writer exited without a clean
|
|
225
|
+
close will recover and checkpoint it: measured on Windows, that rewrote the main
|
|
226
|
+
file and deleted both sidecars. The read-only handle leaves the main file and
|
|
227
|
+
the WAL byte-identical. It can still update the `-shm` index, because SQLite
|
|
228
|
+
readers coordinate through shared memory. Stop source writers first when even
|
|
229
|
+
that is unacceptable.
|
|
230
|
+
|
|
231
|
+
Replay refuses WAL, SHM, or journal sidecars and hardlink aliases, fingerprints
|
|
232
|
+
the source around a consistent private SQLite backup, and reads only that
|
|
233
|
+
process-owned copy in immutable mode. It then verifies and preserves the compact
|
|
234
|
+
descriptor-only
|
|
235
|
+
`crucible.replay-set/1` binding, and emits `crucible.replay-pack/1`. The binding
|
|
236
|
+
records descriptor and skipped-row counts without disclosing descriptorless
|
|
237
|
+
assessment rows. Historical schema-less templates remain compatible only when
|
|
238
|
+
they have no replay binding and their complete measurement seal reproduces;
|
|
239
|
+
bound templates require the canonical schema. Read-only schema compatibility is
|
|
240
|
+
checked without migration, and a completed, synced pack is published atomically
|
|
241
|
+
without overwriting an existing path. Output paths that alias the state database
|
|
242
|
+
or a standard SQLite sidecar are rejected. Malformed provenance is rejected
|
|
243
|
+
before descriptor or pack creation. Replay does not modify the supplied
|
|
244
|
+
snapshot or its sidecar namespace. Changes detected while the private copy is
|
|
245
|
+
created fail the handoff; later source changes cannot affect that copy.
|
|
246
|
+
|
|
247
|
+
Library callers use the same contract explicitly and always close the private
|
|
248
|
+
snapshot owner:
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
memory = AgentMemory(
|
|
252
|
+
"mneme-replay-snapshot.db",
|
|
253
|
+
read_only=True,
|
|
254
|
+
immutable_snapshot=True,
|
|
255
|
+
)
|
|
256
|
+
try:
|
|
257
|
+
pack = memory.replay_crucible(template)
|
|
258
|
+
finally:
|
|
259
|
+
memory.close()
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
gather (intake) --> mneme (drift + replay) --> crucible (sealed recomputation)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
The export keeps measurement and assessment separate without claiming independent
|
|
267
|
+
source certification.
|
|
268
|
+
|
|
269
|
+
## Accountable forgetting
|
|
270
|
+
|
|
271
|
+
Mneme deletes facts with an audit trail: `forget` and `update` leave a
|
|
272
|
+
hash-chained tombstone, what was forgotten, its hash, and why, so the deletion
|
|
273
|
+
record remains reviewable for GDPR-style "right to be forgotten" workflows.
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
mneme forget <memory_id> --reason "user requested deletion"
|
|
277
|
+
mneme audit # -> {"entries":1,"chain_intact":true,"log":[{"op":"forget", …}]}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
`update` edits a memory's text while keeping its provenance and recording the
|
|
281
|
+
before/after hash. Tamper a tombstone and the chain breaks.
|
|
282
|
+
|
|
283
|
+
## Agents plug in over MCP
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
mneme mcp # JSON-RPC 2.0 over stdio; MNEME_STATE points at the DB
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
The released `v0.4.2` wheel exposes the MCP memory, recall, drift, provenance, origin recheck, forget, audit, status, doctor, Crucible export, and Crucible replay tools.
|
|
290
|
+
|
|
291
|
+
MCP tools `mneme.to_crucible` and `mneme.replay_crucible` reuse the same replay library boundaries as the CLI. A recall
|
|
292
|
+
through MCP returns the same re-derivable receipt, so the agent (or its operator)
|
|
293
|
+
can see and re-check why a memory was surfaced; the accountability travels with
|
|
294
|
+
the tool result. `mneme.to_crucible` returns the existing
|
|
295
|
+
`mneme.crucible-export/2` object from the server-bound `MNEME_STATE`; MCP
|
|
296
|
+
callers must pass either `user` to select one tenant inside that configured
|
|
297
|
+
state, or `all_users: true` to deliberately export every tenant visible to the
|
|
298
|
+
server. Optional `session` filters must be non-empty strings; `layer` is limited
|
|
299
|
+
to `L1`, `L2`, or `L3`. The `user` value is a selector, not an authentication
|
|
300
|
+
boundary; the host still owns which state DB the server may open. Crucible
|
|
301
|
+
export and replay fail when `MNEME_STATE` is unset or empty. `mneme.replay_crucible`
|
|
302
|
+
consumes a decoded `crucible.replay-template/1` object and returns
|
|
303
|
+
`crucible.replay-pack/1` from the same explicitly configured state. State paths
|
|
304
|
+
and executable commands stay out of the untrusted recheck descriptors. All-row
|
|
305
|
+
templates (`skipped_count: 0`) are checked against the assessment measurement
|
|
306
|
+
seal. Mixed templates with skipped rows are refused until the template carries a
|
|
307
|
+
verifier-enforced full denominator that binds the disclosed descriptors, skipped
|
|
308
|
+
count, and undisclosed rows to the assessment; Mneme cannot authenticate
|
|
309
|
+
undisclosed rows from an external assessment from a caller-recomputed binding
|
|
310
|
+
alone.
|
|
311
|
+
|
|
312
|
+
## Benchmark you can re-run
|
|
313
|
+
|
|
314
|
+
Token-reduction benchmarks are more useful when paired with answer-retention
|
|
315
|
+
checks. Mneme reports both for the included benchmark.
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
mneme bench
|
|
319
|
+
# token_reduction: 76.6% (full history 125 tok -> avg recalled 29 tok)
|
|
320
|
+
# answer_recall: 100% (5 probes, every needed fact survived the reduction)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
The included reduction is reported **alongside** answer recall, so a run that
|
|
324
|
+
forgets required answers is visible in the result. The receipt carries the
|
|
325
|
+
per-probe detail and the exact token estimator, so a third party can re-run the
|
|
326
|
+
measurement over the same conversation and compare the number. Point it at your
|
|
327
|
+
own conversation with `--turns convo.json --probes probes.json`.
|
|
328
|
+
|
|
329
|
+
## Scenarios (L2)
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
mneme scenarios alice # cluster the session's atoms into scene blocks
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Atoms sharing a theme cluster deterministically into L2 scenarios; each scenario
|
|
336
|
+
cites its atoms, so it is drift-checkable too (a scenario whose atom is gone is
|
|
337
|
+
`UNVERIFIABLE`, never silently kept).
|
|
338
|
+
|
|
339
|
+
## Guarantees
|
|
340
|
+
|
|
341
|
+
- **Zero runtime dependencies** (stdlib `sqlite3`). `pytest` is the only dev dep.
|
|
342
|
+
- **Deterministic core.** Stored hashes and default rankings are derived from
|
|
343
|
+
the supplied turns, so the same input rebuilds the same memory state.
|
|
344
|
+
- **Tests are the contract.** The core workflows above have regression coverage
|
|
345
|
+
with false-success controls for recall, drift, audit, and ingestion.
|
|
346
|
+
|
|
347
|
+
## Development
|
|
348
|
+
|
|
349
|
+
For a local development checkout:
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
python -m pip install -e ".[test]"
|
|
353
|
+
python -m pytest
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Use synthetic SQLite state for tests and examples. `mneme mcp` reads `MNEME_STATE`; do not point examples, demos, or interop checks at a live user database. Release publication remains gated by `DELIVERY.md`, CI, version/tag alignment, and explicit operator action.
|
|
357
|
+
|
|
358
|
+
## License
|
|
359
|
+
|
|
360
|
+
Mneme is fair-source: open to read, run, and build on, with commercial use reserved so the project can fund its own development. See [LICENSE](LICENSE).
|
|
361
|
+
|
|
362
|
+
## What this believes
|
|
363
|
+
|
|
364
|
+
This tool is one lane of a family that holds a single belief steady across
|
|
365
|
+
every surface: knowledge open to anyone who can attain the means; acceptance
|
|
366
|
+
decided by external checks, never reputation; every result re-runnable;
|
|
367
|
+
honest nulls first-class; ownership earned by comprehension; learning woven
|
|
368
|
+
into the work. The full text lives in [CREDO.md](CREDO.md).
|
|
369
|
+
The long form of this belief: [The Unbundling](https://github.com/HarperZ9/flywheel/blob/fix/release-model-identity/docs/essays/2026-07-13-the-unbundling.md).
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
**[Zentropy Labs](https://github.com/ZentropyLabs-ai)** · order out of entropy. An independent lab building evidence-first tools that leave a re-checkable artifact behind. Built by Zain Dana Harper in Seattle. The full workbench is at [Project Telos](https://harperz9.github.io).
|