formative-memory 0.1.0 → 0.2.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/README.md CHANGED
@@ -1,93 +1,118 @@
1
1
  # Formative Memory
2
2
 
3
- **Memory that forgets, so it remembers better what matters. It forms with you and your needs.**
3
+ **Memory that actively forms around what matters.**
4
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.
5
+ Formative Memory is an [OpenClaw](https://openclaw.ai) plugin that gives your agent a self-optimizing memory. It strengthens relevant context through use, weakens unused details, and automatically builds associations between related concepts. In each session, it helps by injecting relevant memories into context before every response. It also evaluates memory quality — each retrieval affects the strength of the memory, so useful ones rise and unused ones fade. Every night, your agent sleeps: a consolidation process prunes and combines memories to keep the quality of recalled context high.
6
6
 
7
+ Over time, this combination process builds beyond raw facts into interpretations, nuanced awareness, and deeper understanding.
8
+
9
+ [![npm version](https://img.shields.io/npm/v/formative-memory)](https://www.npmjs.com/package/formative-memory)
7
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
11
  ![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue)
9
12
  ![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
13
 
12
14
  ---
13
15
 
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.
16
+ ## How It Works
17
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.
18
+ ### Recall
19
19
 
20
- ## Quick Start
20
+ Before every response, the plugin searches for memories relevant to
21
+ the current conversation using hybrid search (embedding similarity +
22
+ BM25 full-text), ranked by memory strength. Matching memories are
23
+ injected into the agent's context automatically. Each retrieval
24
+ strengthens the memories that were surfaced.
21
25
 
22
- ```bash
23
- npm install formative-memory
24
26
  ```
27
+ User: "Do you remember that restaurant? The one by the beach
28
+ last summer. I'm trying to book for our anniversary."
25
29
 
26
- Add to your OpenClaw configuration:
30
+ Injected memories:
31
+ [a3f2|fact|strength=0.82] "Dinner at Maininki, Hanko, July 2024"
32
+ [b7d1|event|2026-07-04] "Wedding anniversary — 12 years"
33
+ [c9f3|preference|str=0.74] "Sanna loves peonies"
34
+ [d2e6|fact|2026-07-02] "Sanna: private doctor's appointment"
27
35
 
28
- ```json
29
- {
30
- "extensions": ["formative-memory"]
31
- }
36
+ Agent: "Of course! It was Maininki, in Hanko. Shall I book a table?
37
+ Your 12th anniversary is coming up on July 4th."
32
38
  ```
33
39
 
34
- That's it. The plugin works automatically:
40
+ The agent sees recalled memories as context, not instructions — this
41
+ reduces prompt injection risk from stored content.
35
42
 
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
43
+ ### Capture
39
44
 
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.
45
+ Memories are collected in two ways. The agent can store a memory
46
+ explicitly with `memory_store`, and auto-capture extracts durable
47
+ facts from conversations automatically after each turn.
47
48
 
48
49
  ```
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
50
+ After the turn above, auto-capture extracts:
51
+ store("Booking anniversary dinner at Maininki", type: event,
52
+ temporal_anchor: 2026-07-04, temporal_state: future)
53
+
54
+ A later turn — user asks for Sanna's favorite foods:
55
+ Agent explicitly stores:
56
+ → memory_store("Sanna's favorites: salmon soup (her mother's recipe,
57
+ no cream), pistachio ice cream, meat pies from Market Hall
58
+ on Saturdays", type: preference)
59
+ → id: e8b2a1f4, strength: 1.0
52
60
  ```
53
61
 
54
- ### Associate
62
+ Each memory is content-addressed (SHA-256) — same content always
63
+ produces the same ID, so duplicates are prevented by design.
64
+
65
+ ### Consolidate
55
66
 
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.
67
+ Every night, the agent sleeps. A consolidation process runs through
68
+ the accumulated memories:
69
+
70
+ | Step | What happens |
71
+ |------|-------------|
72
+ | **Reinforce** | Memories that influenced responses gain strength |
73
+ | **Decay** | All strengths decrease — recent memories fade faster than established ones |
74
+ | **Associate** | Memories retrieved together form links; connections grow stronger with co-occurrence |
75
+ | **Temporal shift** | Future memories transition to present or past based on anchor dates |
76
+ | **Prune** | Weak memories and associations are removed |
77
+ | **Merge** | Similar memories are combined into coherent summaries |
57
78
 
58
79
  ```
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"
80
+ Before consolidation:
81
+ [a3f2|strength=0.82] "Dinner at Maininki, Hanko, July 2024"
82
+ [f1c4|strength=0.65] "Maininki beachfront restaurant, good wine list"
83
+ [a9b3|strength=0.41] "Tried booking Maininki in June, fully booked"
84
+
85
+ After consolidation:
86
+ [g7e2|strength=1.00] "Maininki, Hanko: beachfront restaurant with good
87
+ wine list. Visited July 2024. Book early — fills up in summer."
88
+
89
+ Associations formed:
90
+ "Maininki" ←0.7→ "Wedding anniversary"
91
+ "Maininki" ←0.4→ "Sanna loves peonies"
62
92
  ```
63
93
 
64
- ### Recall
94
+ All mutation happens during consolidation — live chat stays fast and
95
+ predictable. Over time, simple facts combine into richer structures:
96
+ merged summaries, connected associations, and deeper understanding.
97
+
98
+ ## Quick Start
65
99
 
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.
100
+ Install the plugin:
67
101
 
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)
102
+ ```bash
103
+ openclaw plugins install formative-memory
74
104
  ```
75
105
 
76
- ### Consolidate
106
+ This installs from npm, enables the plugin, and assigns it the memory
107
+ slot automatically. Restart the gateway to load the plugin.
77
108
 
78
- A background consolidation process maintains the memory system automatically:
109
+ That's it. The plugin works out of the box:
79
110
 
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 |
111
+ - **Auto-capture** records conversations for consolidation
112
+ - **Auto-recall** surfaces relevant memories before every response
113
+ - **Consolidation** runs automatically to maintain memory quality
89
114
 
90
- Live chat stays fast and predictable. All mutation happens during consolidation.
115
+ No configuration needed sensible defaults are built in.
91
116
 
92
117
  ## Memory Tools
93
118
 
@@ -96,29 +121,34 @@ The plugin registers five tools the agent can use during conversation:
96
121
  | Tool | What it does |
97
122
  |------|-------------|
98
123
  | `memory_store` | Store a new memory with type and optional temporal anchor |
99
- | `memory_search` | Search by meaning and keywords, ranked by relevance × strength |
124
+ | `memory_search` | Search by meaning and keywords, ranked by relevance x strength |
100
125
  | `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 |
126
+ | `memory_feedback` | Rate a memory's usefulness (1-5) — feeds into reinforcement |
127
+ | `memory_browse` | Browse all memories sorted by importance, with type diversity |
103
128
 
104
129
  Memory types: `fact`, `preference`, `decision`, `plan`, `observation`.
105
130
 
106
131
  ## Configuration
107
132
 
108
- All settings are optional:
133
+ All settings are optional — defaults are designed to work out of the box.
134
+ Configuration goes in `openclaw.json` under the plugin entry:
109
135
 
110
136
  ```json
111
137
  {
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
138
+ "plugins": {
139
+ "entries": {
140
+ "formative-memory": {
141
+ "enabled": true,
142
+ "config": {
143
+ "autoRecall": true,
144
+ "autoCapture": true,
145
+ "requireEmbedding": true,
146
+ "embedding": {
147
+ "provider": "auto"
148
+ }
149
+ }
150
+ }
151
+ }
122
152
  }
123
153
  }
124
154
  ```
@@ -126,76 +156,61 @@ All settings are optional:
126
156
  | Key | Default | Description |
127
157
  |-----|---------|-------------|
128
158
  | `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` |
159
+ | `autoCapture` | `true` | Automatically capture conversations for consolidation |
160
+ | `requireEmbedding` | `true` | Require a working embedding provider. Set `false` to allow BM25-only fallback |
161
+ | `embedding.provider` | `"auto"` | Embedding provider: `auto`, `openai`, `gemini`, `voyage`, `mistral`, `ollama`, `local` |
131
162
  | `embedding.model` | — | Override the provider's default embedding model |
132
163
  | `dbPath` | `~/.openclaw/memory/associative` | SQLite database location |
133
- | `verbose` | `false` | Enable debug-level logging (also via `FORMATIVE_MEMORY_DEBUG=1`) |
164
+ | `verbose` | `false` | Enable debug logging (also via `FORMATIVE_MEMORY_DEBUG=1`) |
134
165
  | `logQueries` | `false` | Include raw query text in debug logs (disabled by default for privacy) |
135
166
 
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.
167
+ The `"auto"` provider selects the best available embedding provider from
168
+ your configured API keys. When `requireEmbedding` is `true` (the
169
+ default), the plugin will not start without a working embedding provider.
170
+ Set it to `false` to allow graceful degradation to keyword-only search.
165
171
 
166
172
  ## Architecture
167
173
 
168
174
  ```
169
175
  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
176
+ |
177
+ |-- Context Engine --- assemble() -> auto-recall into context
178
+ | (budget-aware) afterTurn() -> log exposures + attributions
179
+ |
180
+ |-- Memory Tools ----- memory_store - create memory
181
+ | (agent-initiated) memory_search - hybrid search
182
+ | memory_get - lookup by ID
183
+ | memory_feedback - rate usefulness
184
+ | memory_browse - browse by importance
185
+ |
186
+ +-- Consolidation ---- reinforce -> decay -> associate -> transition
187
+ (automatic) -> prune -> merge (LLM) -> cleanup
182
188
  ```
183
189
 
184
- **Storage:** SQLite with FTS5 for full-text search. Single file, no external services.
190
+ **Storage:** SQLite with FTS5 for full-text search. Single file, no
191
+ external services.
185
192
 
186
- **Embedding:** Auto-detected from configured API keys. Supports OpenAI, Gemini, Voyage, Mistral, Ollama. Circuit breaker with graceful fallback to keyword-only search.
193
+ **Embedding:** Auto-detected from configured API keys. Supports OpenAI,
194
+ Gemini, Voyage, Mistral, Ollama. Circuit breaker with graceful fallback
195
+ to keyword-only search when `requireEmbedding` is `false`.
187
196
 
188
- **Consolidation LLM:** Uses Anthropic (Claude) or OpenAI for memory merging. Runs only during consolidation, not during normal chat.
197
+ **Consolidation LLM:** Uses Anthropic (Claude) or OpenAI for memory
198
+ merging. Runs only during consolidation, not during normal chat.
189
199
 
190
200
  ## Trust & Security
191
201
 
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.
202
+ Automatically recalled memories are framed as reference data, not
203
+ instructions. This reduces prompt injection risk from stored memory
204
+ content, but memory remains untrusted input — the framing is
205
+ probabilistic, not a hard security boundary.
193
206
 
194
- Do not store secrets (API keys, passwords) in memories. They will be surfaced to the model during recall.
207
+ Do not store secrets (API keys, passwords) in memories. They will be
208
+ surfaced to the model during recall.
195
209
 
196
210
  ## CLI
197
211
 
198
- A standalone diagnostic CLI operates directly on the SQLite database — no OpenClaw runtime needed:
212
+ A standalone diagnostic CLI operates directly on the SQLite database —
213
+ no OpenClaw runtime needed:
199
214
 
200
215
  ```bash
201
216
  memory stats <memory-dir> # Database overview
@@ -207,12 +222,32 @@ memory history <memory-dir> # Retrieval history
207
222
  memory graph <memory-dir> # Association graph
208
223
  ```
209
224
 
210
- ## Roadmap
225
+ ## Logging
226
+
227
+ Centralized logging with configurable verbosity. By default only
228
+ significant events are logged (info level).
229
+
230
+ Enable debug logging:
231
+
232
+ ```json
233
+ { "verbose": true }
234
+ ```
235
+
236
+ Or via environment variable:
237
+
238
+ ```bash
239
+ FORMATIVE_MEMORY_DEBUG=1
240
+ ```
241
+
242
+ | Level | What |
243
+ |-------|------|
244
+ | **info** | Memory stored, memories injected into context, circuit breaker state changes |
245
+ | **debug** | Search results, embedding fallback reasons, cache hit/miss, consolidation timing |
246
+ | **warn** | Circuit breaker opening (degraded to keyword-only), recall failures |
211
247
 
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
248
+ All log lines are prefixed with `[formative-memory] [level]` for easy
249
+ filtering. Query text is never included in logs by default — set
250
+ `logQueries: true` to opt in.
216
251
 
217
252
  ## Documentation
218
253
 
@@ -239,6 +274,7 @@ Contributions welcome. Areas where help is especially useful:
239
274
 
240
275
  - Consolidation algorithm tuning and evaluation
241
276
  - Embedding model benchmarks
277
+ - Adapters for other AI coding agents
242
278
  - Documentation and examples
243
279
 
244
280
  ## License
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as MemorySourceGuard, r as TemporalStateGuard, t as MemoryDatabase } from "./db-D2pzT6fw.js";
2
+ import { n as MemorySourceGuard, r as TemporalStateGuard, t as MemoryDatabase } from "./db-D1Sc76VE.js";
3
3
  import { join } from "node:path";
4
4
  import { existsSync, readFileSync } from "node:fs";
5
5
  //#region src/cli.ts
@@ -8,7 +8,7 @@ const TEMPORAL_STATES = [
8
8
  ];
9
9
  const MEMORY_SOURCES = [
10
10
  "agent_tool",
11
- "hook_capture",
11
+ "auto_capture",
12
12
  "consolidation",
13
13
  "import"
14
14
  ];