memdsl 0.1.0__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.
- memdsl-0.1.0/.gitignore +7 -0
- memdsl-0.1.0/LICENSE +26 -0
- memdsl-0.1.0/PKG-INFO +229 -0
- memdsl-0.1.0/README.md +211 -0
- memdsl-0.1.0/docs/SPEC.md +318 -0
- memdsl-0.1.0/examples/alex/projects.aurora.mem +91 -0
- memdsl-0.1.0/examples/alex/self.mem +84 -0
- memdsl-0.1.0/examples/lint-demo/broken.mem +70 -0
- memdsl-0.1.0/examples/mira/self.mem +78 -0
- memdsl-0.1.0/pyproject.toml +29 -0
- memdsl-0.1.0/src/memdsl/__init__.py +27 -0
- memdsl-0.1.0/src/memdsl/cli.py +89 -0
- memdsl-0.1.0/src/memdsl/linter.py +202 -0
- memdsl-0.1.0/src/memdsl/model.py +184 -0
- memdsl-0.1.0/src/memdsl/parser.py +235 -0
- memdsl-0.1.0/src/memdsl/query.py +268 -0
- memdsl-0.1.0/tests/test_linter.py +141 -0
- memdsl-0.1.0/tests/test_parser.py +74 -0
- memdsl-0.1.0/tests/test_query.py +133 -0
memdsl-0.1.0/.gitignore
ADDED
memdsl-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 liyuan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
The specification document (docs/SPEC.md) is licensed separately under
|
|
26
|
+
CC-BY-4.0. See docs/SPEC.md for details.
|
memdsl-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: memdsl
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agent memory as normative source code: a lintable, queryable memory DSL for LLM agents
|
|
5
|
+
Author: liyuan
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: agent,context-engineering,dsl,llm,memory
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# memdsl
|
|
20
|
+
|
|
21
|
+
[English](#english) | [中文](#中文)
|
|
22
|
+
|
|
23
|
+
## English
|
|
24
|
+
|
|
25
|
+
**Agent memory as normative source code.**
|
|
26
|
+
|
|
27
|
+
Most agent memory systems store what you said. Almost none of them
|
|
28
|
+
distinguish what an agent *must obey* from what it *may consider*. memdsl
|
|
29
|
+
treats long-term memory as a small, typed, lintable source language —
|
|
30
|
+
`.mem` files you can read, review, diff, version, and test — where a
|
|
31
|
+
`boundary` is a rule to enforce, not a fact to recall.
|
|
32
|
+
|
|
33
|
+
```mem
|
|
34
|
+
preference schedule.deep_work_mornings {
|
|
35
|
+
subject: User
|
|
36
|
+
claim: "Prefers deep work in the morning; meetings after 2pm."
|
|
37
|
+
force: strong
|
|
38
|
+
scope: scheduling
|
|
39
|
+
evidence { source: chat quote: "Stop booking me into morning meetings." }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
boundary privacy.no_family_in_public {
|
|
43
|
+
subject: User
|
|
44
|
+
rule: "Never include family member names or details in public-facing content."
|
|
45
|
+
force: hard
|
|
46
|
+
scope: global
|
|
47
|
+
exceptions: [user_explicit_override]
|
|
48
|
+
evidence { source: chat quote: "Anything about my family stays out of blog posts. Always." }
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The difference matters: a preference shapes suggestions; a boundary binds.
|
|
53
|
+
Flat embeddings of "user said X" erase exactly this distinction, which is
|
|
54
|
+
why agents violate rules their memory technically "contains".
|
|
55
|
+
|
|
56
|
+
### 30 seconds: same question, one declaration apart
|
|
57
|
+
|
|
58
|
+
Ask an agent to *"draft a public blog post about building Aurora as a
|
|
59
|
+
working parent."* A similarity-ranked memory gives it the old chats where
|
|
60
|
+
the kids' names appear — and nothing that ranks a rule above a reminiscence.
|
|
61
|
+
The retrieved snippets are all just CONTEXT, so the names end up in the post:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
retrieved: "...shipped the sync fix after bedtime, Theo finally sleeping..."
|
|
65
|
+
retrieved: "aurora beta feedback thread..."
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
With the boundary declared, the evidence pack puts the rule where it cannot
|
|
69
|
+
be missed — in MUST, above every piece of context, whether or not the query
|
|
70
|
+
lexically matched it:
|
|
71
|
+
|
|
72
|
+
```console
|
|
73
|
+
$ memdsl query examples/alex/ -q "draft a public blog post about aurora"
|
|
74
|
+
MUST
|
|
75
|
+
- [boundary:privacy.no_family_in_public] Never include family member names
|
|
76
|
+
or details in public-facing content. (exceptions: ['user_explicit_override'])
|
|
77
|
+
|
|
78
|
+
CONTEXT
|
|
79
|
+
- [state:aurora.beta_progress] Private beta with 40 testers; ...
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Feed the pack to the LLM as context and the compliant behavior is to write
|
|
83
|
+
the post *without* family details — and to be able to cite
|
|
84
|
+
`boundary:privacy.no_family_in_public` as the reason. The pack is the
|
|
85
|
+
prompt; the MUST layer is what changes the answer.
|
|
86
|
+
|
|
87
|
+
### Lint it, query it
|
|
88
|
+
|
|
89
|
+
Memory that can be wrong deserves a linter:
|
|
90
|
+
|
|
91
|
+
```console
|
|
92
|
+
$ memdsl lint examples/lint-demo/
|
|
93
|
+
broken.mem:7: error[unresolved_symbol] subject 'User.Barista' is not a declared entity
|
|
94
|
+
broken.mem:20: error[missing_evidence] active fact 'home.timezone' has no evidence block
|
|
95
|
+
broken.mem:28: warning[type_force_mismatch] preference uses force: hard; promote it to a boundary
|
|
96
|
+
broken.mem:41: warning[boundary_without_exception] confirm it is truly unconditional
|
|
97
|
+
broken.mem:53: warning[stale_state] as_of 2025-11-02 is older than 180 days
|
|
98
|
+
|
|
99
|
+
6 declarations, 2 error(s), 3 warning(s)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Queries return a **layered evidence pack**, not a hit list. Hard
|
|
103
|
+
boundaries surface even when the query doesn't lexically match them;
|
|
104
|
+
declared conflicts are shown, not averaged away; open issues surface as
|
|
105
|
+
gaps instead of being hallucinated over:
|
|
106
|
+
|
|
107
|
+
```console
|
|
108
|
+
$ memdsl query examples/alex/ -q "should aurora keep the free tier"
|
|
109
|
+
# resolved subjects: Project.Aurora
|
|
110
|
+
MUST
|
|
111
|
+
- [boundary:privacy.no_family_in_public] Never include family member names ...
|
|
112
|
+
|
|
113
|
+
SHOULD
|
|
114
|
+
- (none)
|
|
115
|
+
|
|
116
|
+
CONTEXT
|
|
117
|
+
- [decision:aurora.pricing_free_tier] Keep a permanent free tier.
|
|
118
|
+
- [state:aurora.beta_progress] Private beta with 40 testers; sync is the top complaint. (as_of 2026-06-20)
|
|
119
|
+
- [goal:aurora.revenue_target_2026] Reach $2k MRR from Aurora by end of 2026.
|
|
120
|
+
|
|
121
|
+
CONFLICT
|
|
122
|
+
- [decision:aurora.pricing_free_tier] conflicts_with [aurora.revenue_target_2026]
|
|
123
|
+
|
|
124
|
+
MISSING
|
|
125
|
+
- open issue [open_issue:aurora.pricing_undecided]: Paid tier pricing is undecided: $5 flat vs usage-based.
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Feed that pack — MUST/SHOULD/CONTEXT/CONFLICT/MISSING — to your LLM as
|
|
129
|
+
context. Every line carries a declaration id, so answers are citable and
|
|
130
|
+
auditable back to source and evidence.
|
|
131
|
+
|
|
132
|
+
### Install
|
|
133
|
+
|
|
134
|
+
```console
|
|
135
|
+
pip install memdsl # or: pip install -e . from a checkout
|
|
136
|
+
memdsl lint examples/alex/
|
|
137
|
+
memdsl query examples/alex/ -q "plan tomorrow morning"
|
|
138
|
+
memdsl explain examples/alex/ decision:aurora.db_postgres_migration
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Zero runtime dependencies. Python 3.9+.
|
|
142
|
+
|
|
143
|
+
Note: `memdsl lint examples/alex/` reports **one intentional warning** —
|
|
144
|
+
Alex's `schedule.no_meetings_before_10` boundary declares no `exceptions`,
|
|
145
|
+
and the linter asks you to confirm it is truly unconditional. That nudge
|
|
146
|
+
is the feature; a clean run is `examples/mira/`.
|
|
147
|
+
|
|
148
|
+
### What's in the box
|
|
149
|
+
|
|
150
|
+
- **A tiny declarative language** (`.mem`): typed declarations
|
|
151
|
+
(`entity`, `fact`, `preference`, `boundary`, `principle`, `decision`,
|
|
152
|
+
`state`, `open_issue`) with force, scope, evidence, relations
|
|
153
|
+
(`supersedes`, `conflicts_with`, `refines`, ...), and lifecycle status.
|
|
154
|
+
Full grammar and semantics in [docs/SPEC.md](docs/SPEC.md).
|
|
155
|
+
- **A linter** with ten diagnostics: dangling symbols, missing evidence,
|
|
156
|
+
ambiguous aliases, stale states, boundaries without exceptions,
|
|
157
|
+
preferences masquerading as laws, unmarked supersede chains.
|
|
158
|
+
- **A query executor** implementing the EvidencePack contract, plus
|
|
159
|
+
`explain` for tracing one declaration's relations and provenance.
|
|
160
|
+
- **Synthetic example personas** (`examples/`) — fictional users "Alex"
|
|
161
|
+
and "Mira" — and a deliberately broken file for the linter demo.
|
|
162
|
+
|
|
163
|
+
### What memdsl is *not*
|
|
164
|
+
|
|
165
|
+
- **Not a replacement for [Mem0](https://github.com/mem0ai/mem0),
|
|
166
|
+
[Zep](https://www.getzep.com/), or
|
|
167
|
+
[LangMem](https://langchain-ai.github.io/langmem/).** Those are
|
|
168
|
+
retrieval/extraction platforms. memdsl is a *source format and
|
|
169
|
+
contract* for the layer above: what memory means, how strongly it
|
|
170
|
+
binds, and how it is maintained. You could compile `.mem` files into
|
|
171
|
+
any of them.
|
|
172
|
+
- **Not a retrieval engine.** The reference executor is deliberately
|
|
173
|
+
naive lexical matching — enough to demonstrate the contract. Production
|
|
174
|
+
use should plug BM25/embeddings behind the same EvidencePack interface.
|
|
175
|
+
Do not benchmark toy retrieval and conclude the format failed.
|
|
176
|
+
- **Not an auto-writer.** v0.1 has no write pipeline. The spec (§10)
|
|
177
|
+
describes a gated, human-reviewed write path; automation should be
|
|
178
|
+
earned with audited metrics, not assumed.
|
|
179
|
+
|
|
180
|
+
### Does the approach work?
|
|
181
|
+
|
|
182
|
+
Early evidence from the private system this was extracted from
|
|
183
|
+
(DigitalSelf, single-user): on a 100-question eval over the author's real
|
|
184
|
+
long-term memory, DSL-structured retrieval nearly doubled top-1 precision
|
|
185
|
+
against the same system's tuned RAG baseline (**0.57 vs 0.30**; hit rate
|
|
186
|
+
0.67 vs 0.53). On public conversational benchmarks (LongMemEval, LoCoMo)
|
|
187
|
+
it performs at parity with baselines under a retrieval-only harness whose
|
|
188
|
+
target mapping is still being audited — we explicitly do *not* claim
|
|
189
|
+
public-benchmark wins. Current honest costs: seconds-level query latency
|
|
190
|
+
at scale in the private implementation (being moved to write-time
|
|
191
|
+
compilation), and n=1 personalization. A reproducible benchmark report
|
|
192
|
+
will be published separately.
|
|
193
|
+
|
|
194
|
+
The interesting unmeasured dimension — and the reason this exists — is
|
|
195
|
+
**compliance, not recall**: existing memory benchmarks test whether an
|
|
196
|
+
agent can *find* a fact, none test whether it *respects* a boundary. A
|
|
197
|
+
boundary-compliance benchmark is the roadmap's centerpiece.
|
|
198
|
+
|
|
199
|
+
### Related work
|
|
200
|
+
|
|
201
|
+
Typed/structured agent memory is converging fast:
|
|
202
|
+
[MemIR](https://arxiv.org/abs/2605.25869) (typed memory IR, provenance-role
|
|
203
|
+
separation), [Zep/Graphiti](https://www.getzep.com/) (temporal knowledge
|
|
204
|
+
graphs with fact validity windows), [A-Mem](https://arxiv.org/abs/2502.12110)
|
|
205
|
+
(Zettelkasten-style linked notes), [MemOS](https://arxiv.org/abs/2507.03724)
|
|
206
|
+
(memory scheduling), and the `CLAUDE.md`/`AGENTS.md` culture of local,
|
|
207
|
+
reviewable context files. memdsl's position in that landscape: local-first
|
|
208
|
+
plain-text source, an explicit **normative layer** (force + boundaries +
|
|
209
|
+
exceptions + MUST/SHOULD rendering), and code-style diagnostics as a
|
|
210
|
+
first-class surface.
|
|
211
|
+
|
|
212
|
+
### Roadmap
|
|
213
|
+
|
|
214
|
+
- Target-mapping audit + reproducible benchmark report
|
|
215
|
+
- Boundary-compliance benchmark (does the agent *respect* MUST items?)
|
|
216
|
+
- Pluggable retrieval backends (BM25, embeddings) behind the EvidencePack contract
|
|
217
|
+
- Module directory compilation for query planning
|
|
218
|
+
- Gated write pipeline with review queue
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
Today, memdsl defines memory as typed, auditable source code. Future
|
|
223
|
+
runtimes can navigate these declarations the way developers navigate
|
|
224
|
+
code — following relations, inspecting evidence, tracing history, and
|
|
225
|
+
asking for missing information instead of guessing.
|
|
226
|
+
|
|
227
|
+
### License
|
|
228
|
+
|
|
229
|
+
Code: [MIT](LICEN
|
memdsl-0.1.0/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# memdsl
|
|
2
|
+
|
|
3
|
+
[English](#english) | [中文](#中文)
|
|
4
|
+
|
|
5
|
+
## English
|
|
6
|
+
|
|
7
|
+
**Agent memory as normative source code.**
|
|
8
|
+
|
|
9
|
+
Most agent memory systems store what you said. Almost none of them
|
|
10
|
+
distinguish what an agent *must obey* from what it *may consider*. memdsl
|
|
11
|
+
treats long-term memory as a small, typed, lintable source language —
|
|
12
|
+
`.mem` files you can read, review, diff, version, and test — where a
|
|
13
|
+
`boundary` is a rule to enforce, not a fact to recall.
|
|
14
|
+
|
|
15
|
+
```mem
|
|
16
|
+
preference schedule.deep_work_mornings {
|
|
17
|
+
subject: User
|
|
18
|
+
claim: "Prefers deep work in the morning; meetings after 2pm."
|
|
19
|
+
force: strong
|
|
20
|
+
scope: scheduling
|
|
21
|
+
evidence { source: chat quote: "Stop booking me into morning meetings." }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
boundary privacy.no_family_in_public {
|
|
25
|
+
subject: User
|
|
26
|
+
rule: "Never include family member names or details in public-facing content."
|
|
27
|
+
force: hard
|
|
28
|
+
scope: global
|
|
29
|
+
exceptions: [user_explicit_override]
|
|
30
|
+
evidence { source: chat quote: "Anything about my family stays out of blog posts. Always." }
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The difference matters: a preference shapes suggestions; a boundary binds.
|
|
35
|
+
Flat embeddings of "user said X" erase exactly this distinction, which is
|
|
36
|
+
why agents violate rules their memory technically "contains".
|
|
37
|
+
|
|
38
|
+
### 30 seconds: same question, one declaration apart
|
|
39
|
+
|
|
40
|
+
Ask an agent to *"draft a public blog post about building Aurora as a
|
|
41
|
+
working parent."* A similarity-ranked memory gives it the old chats where
|
|
42
|
+
the kids' names appear — and nothing that ranks a rule above a reminiscence.
|
|
43
|
+
The retrieved snippets are all just CONTEXT, so the names end up in the post:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
retrieved: "...shipped the sync fix after bedtime, Theo finally sleeping..."
|
|
47
|
+
retrieved: "aurora beta feedback thread..."
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
With the boundary declared, the evidence pack puts the rule where it cannot
|
|
51
|
+
be missed — in MUST, above every piece of context, whether or not the query
|
|
52
|
+
lexically matched it:
|
|
53
|
+
|
|
54
|
+
```console
|
|
55
|
+
$ memdsl query examples/alex/ -q "draft a public blog post about aurora"
|
|
56
|
+
MUST
|
|
57
|
+
- [boundary:privacy.no_family_in_public] Never include family member names
|
|
58
|
+
or details in public-facing content. (exceptions: ['user_explicit_override'])
|
|
59
|
+
|
|
60
|
+
CONTEXT
|
|
61
|
+
- [state:aurora.beta_progress] Private beta with 40 testers; ...
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Feed the pack to the LLM as context and the compliant behavior is to write
|
|
65
|
+
the post *without* family details — and to be able to cite
|
|
66
|
+
`boundary:privacy.no_family_in_public` as the reason. The pack is the
|
|
67
|
+
prompt; the MUST layer is what changes the answer.
|
|
68
|
+
|
|
69
|
+
### Lint it, query it
|
|
70
|
+
|
|
71
|
+
Memory that can be wrong deserves a linter:
|
|
72
|
+
|
|
73
|
+
```console
|
|
74
|
+
$ memdsl lint examples/lint-demo/
|
|
75
|
+
broken.mem:7: error[unresolved_symbol] subject 'User.Barista' is not a declared entity
|
|
76
|
+
broken.mem:20: error[missing_evidence] active fact 'home.timezone' has no evidence block
|
|
77
|
+
broken.mem:28: warning[type_force_mismatch] preference uses force: hard; promote it to a boundary
|
|
78
|
+
broken.mem:41: warning[boundary_without_exception] confirm it is truly unconditional
|
|
79
|
+
broken.mem:53: warning[stale_state] as_of 2025-11-02 is older than 180 days
|
|
80
|
+
|
|
81
|
+
6 declarations, 2 error(s), 3 warning(s)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Queries return a **layered evidence pack**, not a hit list. Hard
|
|
85
|
+
boundaries surface even when the query doesn't lexically match them;
|
|
86
|
+
declared conflicts are shown, not averaged away; open issues surface as
|
|
87
|
+
gaps instead of being hallucinated over:
|
|
88
|
+
|
|
89
|
+
```console
|
|
90
|
+
$ memdsl query examples/alex/ -q "should aurora keep the free tier"
|
|
91
|
+
# resolved subjects: Project.Aurora
|
|
92
|
+
MUST
|
|
93
|
+
- [boundary:privacy.no_family_in_public] Never include family member names ...
|
|
94
|
+
|
|
95
|
+
SHOULD
|
|
96
|
+
- (none)
|
|
97
|
+
|
|
98
|
+
CONTEXT
|
|
99
|
+
- [decision:aurora.pricing_free_tier] Keep a permanent free tier.
|
|
100
|
+
- [state:aurora.beta_progress] Private beta with 40 testers; sync is the top complaint. (as_of 2026-06-20)
|
|
101
|
+
- [goal:aurora.revenue_target_2026] Reach $2k MRR from Aurora by end of 2026.
|
|
102
|
+
|
|
103
|
+
CONFLICT
|
|
104
|
+
- [decision:aurora.pricing_free_tier] conflicts_with [aurora.revenue_target_2026]
|
|
105
|
+
|
|
106
|
+
MISSING
|
|
107
|
+
- open issue [open_issue:aurora.pricing_undecided]: Paid tier pricing is undecided: $5 flat vs usage-based.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Feed that pack — MUST/SHOULD/CONTEXT/CONFLICT/MISSING — to your LLM as
|
|
111
|
+
context. Every line carries a declaration id, so answers are citable and
|
|
112
|
+
auditable back to source and evidence.
|
|
113
|
+
|
|
114
|
+
### Install
|
|
115
|
+
|
|
116
|
+
```console
|
|
117
|
+
pip install memdsl # or: pip install -e . from a checkout
|
|
118
|
+
memdsl lint examples/alex/
|
|
119
|
+
memdsl query examples/alex/ -q "plan tomorrow morning"
|
|
120
|
+
memdsl explain examples/alex/ decision:aurora.db_postgres_migration
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Zero runtime dependencies. Python 3.9+.
|
|
124
|
+
|
|
125
|
+
Note: `memdsl lint examples/alex/` reports **one intentional warning** —
|
|
126
|
+
Alex's `schedule.no_meetings_before_10` boundary declares no `exceptions`,
|
|
127
|
+
and the linter asks you to confirm it is truly unconditional. That nudge
|
|
128
|
+
is the feature; a clean run is `examples/mira/`.
|
|
129
|
+
|
|
130
|
+
### What's in the box
|
|
131
|
+
|
|
132
|
+
- **A tiny declarative language** (`.mem`): typed declarations
|
|
133
|
+
(`entity`, `fact`, `preference`, `boundary`, `principle`, `decision`,
|
|
134
|
+
`state`, `open_issue`) with force, scope, evidence, relations
|
|
135
|
+
(`supersedes`, `conflicts_with`, `refines`, ...), and lifecycle status.
|
|
136
|
+
Full grammar and semantics in [docs/SPEC.md](docs/SPEC.md).
|
|
137
|
+
- **A linter** with ten diagnostics: dangling symbols, missing evidence,
|
|
138
|
+
ambiguous aliases, stale states, boundaries without exceptions,
|
|
139
|
+
preferences masquerading as laws, unmarked supersede chains.
|
|
140
|
+
- **A query executor** implementing the EvidencePack contract, plus
|
|
141
|
+
`explain` for tracing one declaration's relations and provenance.
|
|
142
|
+
- **Synthetic example personas** (`examples/`) — fictional users "Alex"
|
|
143
|
+
and "Mira" — and a deliberately broken file for the linter demo.
|
|
144
|
+
|
|
145
|
+
### What memdsl is *not*
|
|
146
|
+
|
|
147
|
+
- **Not a replacement for [Mem0](https://github.com/mem0ai/mem0),
|
|
148
|
+
[Zep](https://www.getzep.com/), or
|
|
149
|
+
[LangMem](https://langchain-ai.github.io/langmem/).** Those are
|
|
150
|
+
retrieval/extraction platforms. memdsl is a *source format and
|
|
151
|
+
contract* for the layer above: what memory means, how strongly it
|
|
152
|
+
binds, and how it is maintained. You could compile `.mem` files into
|
|
153
|
+
any of them.
|
|
154
|
+
- **Not a retrieval engine.** The reference executor is deliberately
|
|
155
|
+
naive lexical matching — enough to demonstrate the contract. Production
|
|
156
|
+
use should plug BM25/embeddings behind the same EvidencePack interface.
|
|
157
|
+
Do not benchmark toy retrieval and conclude the format failed.
|
|
158
|
+
- **Not an auto-writer.** v0.1 has no write pipeline. The spec (§10)
|
|
159
|
+
describes a gated, human-reviewed write path; automation should be
|
|
160
|
+
earned with audited metrics, not assumed.
|
|
161
|
+
|
|
162
|
+
### Does the approach work?
|
|
163
|
+
|
|
164
|
+
Early evidence from the private system this was extracted from
|
|
165
|
+
(DigitalSelf, single-user): on a 100-question eval over the author's real
|
|
166
|
+
long-term memory, DSL-structured retrieval nearly doubled top-1 precision
|
|
167
|
+
against the same system's tuned RAG baseline (**0.57 vs 0.30**; hit rate
|
|
168
|
+
0.67 vs 0.53). On public conversational benchmarks (LongMemEval, LoCoMo)
|
|
169
|
+
it performs at parity with baselines under a retrieval-only harness whose
|
|
170
|
+
target mapping is still being audited — we explicitly do *not* claim
|
|
171
|
+
public-benchmark wins. Current honest costs: seconds-level query latency
|
|
172
|
+
at scale in the private implementation (being moved to write-time
|
|
173
|
+
compilation), and n=1 personalization. A reproducible benchmark report
|
|
174
|
+
will be published separately.
|
|
175
|
+
|
|
176
|
+
The interesting unmeasured dimension — and the reason this exists — is
|
|
177
|
+
**compliance, not recall**: existing memory benchmarks test whether an
|
|
178
|
+
agent can *find* a fact, none test whether it *respects* a boundary. A
|
|
179
|
+
boundary-compliance benchmark is the roadmap's centerpiece.
|
|
180
|
+
|
|
181
|
+
### Related work
|
|
182
|
+
|
|
183
|
+
Typed/structured agent memory is converging fast:
|
|
184
|
+
[MemIR](https://arxiv.org/abs/2605.25869) (typed memory IR, provenance-role
|
|
185
|
+
separation), [Zep/Graphiti](https://www.getzep.com/) (temporal knowledge
|
|
186
|
+
graphs with fact validity windows), [A-Mem](https://arxiv.org/abs/2502.12110)
|
|
187
|
+
(Zettelkasten-style linked notes), [MemOS](https://arxiv.org/abs/2507.03724)
|
|
188
|
+
(memory scheduling), and the `CLAUDE.md`/`AGENTS.md` culture of local,
|
|
189
|
+
reviewable context files. memdsl's position in that landscape: local-first
|
|
190
|
+
plain-text source, an explicit **normative layer** (force + boundaries +
|
|
191
|
+
exceptions + MUST/SHOULD rendering), and code-style diagnostics as a
|
|
192
|
+
first-class surface.
|
|
193
|
+
|
|
194
|
+
### Roadmap
|
|
195
|
+
|
|
196
|
+
- Target-mapping audit + reproducible benchmark report
|
|
197
|
+
- Boundary-compliance benchmark (does the agent *respect* MUST items?)
|
|
198
|
+
- Pluggable retrieval backends (BM25, embeddings) behind the EvidencePack contract
|
|
199
|
+
- Module directory compilation for query planning
|
|
200
|
+
- Gated write pipeline with review queue
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
Today, memdsl defines memory as typed, auditable source code. Future
|
|
205
|
+
runtimes can navigate these declarations the way developers navigate
|
|
206
|
+
code — following relations, inspecting evidence, tracing history, and
|
|
207
|
+
asking for missing information instead of guessing.
|
|
208
|
+
|
|
209
|
+
### License
|
|
210
|
+
|
|
211
|
+
Code: [MIT](LICEN
|