formative-memory 0.1.0

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jari Mustonen
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.
package/README.md ADDED
@@ -0,0 +1,246 @@
1
+ # Formative Memory
2
+
3
+ **Memory that forgets, so it remembers better what matters. It forms with you and your needs.**
4
+
5
+ Formative Memory is an open source memory plugin for [OpenClaw](https://openclaw.ai). Memories form associations, strengthen through use, decay without reinforcement, and consolidate during sleep.
6
+
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
+ ![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue)
9
+ ![Node.js](https://img.shields.io/badge/Node.js-%E2%89%A522.12-green)
10
+ ![OpenClaw](https://img.shields.io/badge/OpenClaw-%E2%89%A52026.4.5-purple)
11
+
12
+ ---
13
+
14
+ ## Why
15
+
16
+ Traditional memory systems treat all information equally and rely on recency to decide what's relevant. Over time, noise accumulates: duplicates pile up, outdated facts coexist with corrections, and important patterns get buried under recent but trivial details. The more you use memory, the harder it becomes to find what matters. You end up teaching the same lessons over and over.
17
+
18
+ Formative Memory inverts this. Memories that prove useful get stronger. Unused ones fade. Related memories form connections. The system maintains itself through automatic consolidation — no manual curation needed.
19
+
20
+ ## Quick Start
21
+
22
+ ```bash
23
+ npm install formative-memory
24
+ ```
25
+
26
+ Add to your OpenClaw configuration:
27
+
28
+ ```json
29
+ {
30
+ "extensions": ["formative-memory"]
31
+ }
32
+ ```
33
+
34
+ That's it. The plugin works automatically:
35
+
36
+ - **Auto-recall** surfaces relevant memories before every response
37
+ - **Agent tools** let the agent store, search, and rate memories
38
+ - **Consolidation** runs automatically to maintain memory quality
39
+
40
+ No configuration needed — sensible defaults are built in.
41
+
42
+ ## How It Works
43
+
44
+ ### Store
45
+
46
+ When your agent learns something, it creates a content-addressed memory object. Same content always produces the same ID — no duplicates by design.
47
+
48
+ ```
49
+ Agent: "I'll remember that."
50
+ → memory_store(content: "Project uses Tailwind, not styled-components", type: "preference")
51
+ → id: a3f2c9e1, strength: 1.0, type: preference
52
+ ```
53
+
54
+ ### Associate
55
+
56
+ Memories don't exist in isolation. When two memories are retrieved together, they form a weighted bidirectional link. The more often they co-occur, the stronger the connection.
57
+
58
+ ```
59
+ "Tailwind preference" ←0.7→ "Tailwind v4 migration"
60
+ "Tailwind preference" ←0.4→ "tailwind.config.ts in project root"
61
+ "Tailwind v4 migration" ←0.3→ "CSS specificity bug"
62
+ ```
63
+
64
+ ### Recall
65
+
66
+ Retrieval combines semantic similarity and keyword matching, weighted by memory strength. Important memories surface first. Every retrieval makes the memory stronger. Every miss lets it fade.
67
+
68
+ ```
69
+ Agent thinking: "What CSS framework do we use?"
70
+ → memory_search(query: "CSS framework")
71
+ → 1. "Project uses Tailwind exclusively" (strength: 0.92, score: 0.87)
72
+ 2. "Migrated to Tailwind v4 last week" (strength: 0.71, score: 0.64)
73
+ 3. "tailwind.config.ts in project root" (strength: 0.68, score: 0.51)
74
+ ```
75
+
76
+ ### Consolidate
77
+
78
+ A background consolidation process maintains the memory system automatically:
79
+
80
+ | Step | What happens |
81
+ |------|-------------|
82
+ | **Reinforce** | Memories that influenced responses gain strength |
83
+ | **Decay** | All strengths decrease — working memory fades faster than consolidated |
84
+ | **Associate** | Co-retrieved memories form or strengthen links; transitive paths are discovered |
85
+ | **Temporal shift** | Future memories transition to present or past based on anchor dates |
86
+ | **Prune** | Very weak memories and associations are deleted |
87
+ | **Merge** | Similar memories are combined via LLM into coherent summaries |
88
+ | **Cleanup** | Old provenance records are garbage collected |
89
+
90
+ Live chat stays fast and predictable. All mutation happens during consolidation.
91
+
92
+ ## Memory Tools
93
+
94
+ The plugin registers five tools the agent can use during conversation:
95
+
96
+ | Tool | What it does |
97
+ |------|-------------|
98
+ | `memory_store` | Store a new memory with type and optional temporal anchor |
99
+ | `memory_search` | Search by meaning and keywords, ranked by relevance × strength |
100
+ | `memory_get` | Retrieve a specific memory by ID |
101
+ | `memory_feedback` | Rate a memory's usefulness — feeds into reinforcement |
102
+ | `memory_browse` | Browse all memories sorted by importance |
103
+
104
+ Memory types: `fact`, `preference`, `decision`, `plan`, `observation`.
105
+
106
+ ## Configuration
107
+
108
+ All settings are optional:
109
+
110
+ ```json
111
+ {
112
+ "memory-associative": {
113
+ "autoRecall": true,
114
+ "autoCapture": false,
115
+ "embedding": {
116
+ "provider": "auto",
117
+ "model": null
118
+ },
119
+ "dbPath": "~/.openclaw/memory/associative",
120
+ "verbose": false,
121
+ "logQueries": false
122
+ }
123
+ }
124
+ ```
125
+
126
+ | Key | Default | Description |
127
+ |-----|---------|-------------|
128
+ | `autoRecall` | `true` | Inject relevant memories into context before every response |
129
+ | `autoCapture` | `false` | Automatically capture conversations for consolidation |
130
+ | `embedding.provider` | `"auto"` | Embedding provider: `auto`, `openai`, `gemini`, `voyage`, `mistral`, `ollama` |
131
+ | `embedding.model` | — | Override the provider's default embedding model |
132
+ | `dbPath` | `~/.openclaw/memory/associative` | SQLite database location |
133
+ | `verbose` | `false` | Enable debug-level logging (also via `FORMATIVE_MEMORY_DEBUG=1`) |
134
+ | `logQueries` | `false` | Include raw query text in debug logs (disabled by default for privacy) |
135
+
136
+ The `"auto"` provider selects the best available embedding provider from your configured API keys. If no provider is available, the plugin degrades gracefully to keyword-only search.
137
+
138
+ ### Logging
139
+
140
+ The plugin has centralized logging with configurable verbosity. By default only significant events are logged (info level): memory stores, context injection, and circuit breaker state changes.
141
+
142
+ Enable debug logging for full diagnostics:
143
+
144
+ ```json
145
+ { "verbose": true }
146
+ ```
147
+
148
+ Or via environment variable (no config change needed):
149
+
150
+ ```bash
151
+ FORMATIVE_MEMORY_DEBUG=1
152
+ ```
153
+
154
+ **What gets logged at each level:**
155
+
156
+ | Level | What |
157
+ |-------|------|
158
+ | **info** | Memory stored, memories injected into context, circuit breaker state changes |
159
+ | **debug** | Search result count and top score, embedding fallback reasons, cache hit/miss, consolidation timing, provenance counts, duplicate store skips |
160
+ | **warn** | Circuit breaker opening (degraded to keyword-only), recall failures, migration issues |
161
+
162
+ All log lines are prefixed with `[formative-memory] [level]` for easy filtering.
163
+
164
+ **Privacy:** Query text is never included in logs by default. Set `logQueries: true` to opt in — useful for debugging retrieval quality, but queries may contain personal data.
165
+
166
+ ## Architecture
167
+
168
+ ```
169
+ OpenClaw Runtime
170
+
171
+ ├── Context Engine ─── assemble() → auto-recall into context
172
+ │ (budget-aware) afterTurn() → log exposures + attributions
173
+
174
+ ├── Memory Tools ───── memory_store — create memory
175
+ │ (agent-initiated) memory_search — hybrid search
176
+ │ memory_get — lookup by ID
177
+ │ memory_feedback — rate usefulness
178
+ │ memory_browse — browse by importance
179
+
180
+ └── Consolidation ──── reinforce → decay → associate → transition
181
+ (automatic) → prune → merge (LLM) → cleanup
182
+ ```
183
+
184
+ **Storage:** SQLite with FTS5 for full-text search. Single file, no external services.
185
+
186
+ **Embedding:** Auto-detected from configured API keys. Supports OpenAI, Gemini, Voyage, Mistral, Ollama. Circuit breaker with graceful fallback to keyword-only search.
187
+
188
+ **Consolidation LLM:** Uses Anthropic (Claude) or OpenAI for memory merging. Runs only during consolidation, not during normal chat.
189
+
190
+ ## Trust & Security
191
+
192
+ Automatically recalled memories are framed as reference data, not instructions. This reduces prompt injection risk from stored memory content, but memory remains untrusted input — the framing is probabilistic, not a hard security boundary.
193
+
194
+ Do not store secrets (API keys, passwords) in memories. They will be surfaced to the model during recall.
195
+
196
+ ## CLI
197
+
198
+ A standalone diagnostic CLI operates directly on the SQLite database — no OpenClaw runtime needed:
199
+
200
+ ```bash
201
+ memory stats <memory-dir> # Database overview
202
+ memory list <memory-dir> # List memories (filterable)
203
+ memory inspect <memory-dir> <id> # Detailed view of a single memory
204
+ memory search <memory-dir> <q> # Search by content
205
+ memory export <memory-dir> # Export to JSON
206
+ memory history <memory-dir> # Retrieval history
207
+ memory graph <memory-dir> # Association graph
208
+ ```
209
+
210
+ ## Roadmap
211
+
212
+ - [ ] Association-boosted retrieval (graph structure influences search ranking)
213
+ - [ ] Memory-type-specific search strategies
214
+ - [ ] Visual memory graph explorer
215
+ - [ ] Cross-project memory sharing
216
+
217
+ ## Documentation
218
+
219
+ - [How Associative Memory Works](docs/how-memory-works.md) — conceptual guide
220
+ - [Architecture](docs/architecture.md) — storage, retrieval, provenance, consolidation
221
+ - [Comparison with OpenClaw built-in memory](docs/comparison-openclaw-memory.md) — technical comparison
222
+ - [Glossary](docs/glossary.md) — terminology
223
+
224
+ ## Development
225
+
226
+ ```bash
227
+ pnpm install # Install dependencies
228
+ pnpm build # Build (tsdown)
229
+ pnpm test # Run tests (vitest)
230
+ pnpm lint # Lint (oxlint)
231
+ pnpm check # Full check (format + typecheck + lint)
232
+ ```
233
+
234
+ Requires Node.js >= 22.12.0, pnpm 10.x.
235
+
236
+ ## Contributing
237
+
238
+ Contributions welcome. Areas where help is especially useful:
239
+
240
+ - Consolidation algorithm tuning and evaluation
241
+ - Embedding model benchmarks
242
+ - Documentation and examples
243
+
244
+ ## License
245
+
246
+ [MIT](LICENSE)