agent-working-memory 0.13.1 → 0.14.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 +200 -238
- package/dist/adapters/common.d.ts +6 -0
- package/dist/adapters/common.d.ts.map +1 -1
- package/dist/adapters/common.js +457 -362
- package/dist/adapters/common.js.map +1 -1
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +24 -8
- package/dist/api/routes.js.map +1 -1
- package/dist/core/alias-map.d.ts +16 -0
- package/dist/core/alias-map.d.ts.map +1 -0
- package/dist/core/alias-map.js +102 -0
- package/dist/core/alias-map.js.map +1 -0
- package/dist/core/embeddings.d.ts +17 -0
- package/dist/core/embeddings.d.ts.map +1 -1
- package/dist/core/embeddings.js +50 -1
- package/dist/core/embeddings.js.map +1 -1
- package/dist/core/recall-config.d.ts +52 -0
- package/dist/core/recall-config.d.ts.map +1 -0
- package/dist/core/recall-config.js +110 -0
- package/dist/core/recall-config.js.map +1 -0
- package/dist/core/rerank-window.d.ts +61 -0
- package/dist/core/rerank-window.d.ts.map +1 -0
- package/dist/core/rerank-window.js +153 -0
- package/dist/core/rerank-window.js.map +1 -0
- package/dist/core/rerank2.d.ts +62 -0
- package/dist/core/rerank2.d.ts.map +1 -0
- package/dist/core/rerank2.js +75 -0
- package/dist/core/rerank2.js.map +1 -0
- package/dist/core/retrieval-text.d.ts +55 -0
- package/dist/core/retrieval-text.d.ts.map +1 -0
- package/dist/core/retrieval-text.js +87 -0
- package/dist/core/retrieval-text.js.map +1 -0
- package/dist/core/temporal-query.d.ts +61 -0
- package/dist/core/temporal-query.d.ts.map +1 -0
- package/dist/core/temporal-query.js +168 -0
- package/dist/core/temporal-query.js.map +1 -0
- package/dist/core/token-budget.d.ts +75 -0
- package/dist/core/token-budget.d.ts.map +1 -0
- package/dist/core/token-budget.js +136 -0
- package/dist/core/token-budget.js.map +1 -0
- package/dist/core/whoami.d.ts +11 -0
- package/dist/core/whoami.d.ts.map +1 -1
- package/dist/core/whoami.js +10 -0
- package/dist/core/whoami.js.map +1 -1
- package/dist/core/write-pipeline.d.ts.map +1 -1
- package/dist/core/write-pipeline.js +6 -3
- package/dist/core/write-pipeline.js.map +1 -1
- package/dist/engine/activation.d.ts.map +1 -1
- package/dist/engine/activation.js +135 -32
- package/dist/engine/activation.js.map +1 -1
- package/dist/hooks/prime.d.ts +77 -0
- package/dist/hooks/prime.d.ts.map +1 -0
- package/dist/hooks/prime.js +92 -0
- package/dist/hooks/prime.js.map +1 -0
- package/dist/hooks/sidecar.d.ts.map +1 -1
- package/dist/hooks/sidecar.js +39 -0
- package/dist/hooks/sidecar.js.map +1 -1
- package/dist/mcp.js +134 -102
- package/dist/mcp.js.map +1 -1
- package/dist/storage/pglite.d.ts.map +1 -1
- package/dist/storage/pglite.js +10 -2
- package/dist/storage/pglite.js.map +1 -1
- package/dist/storage/postgres.d.ts.map +1 -1
- package/dist/storage/postgres.js +10 -2
- package/dist/storage/postgres.js.map +1 -1
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +12 -2
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/types/engram.d.ts +7 -0
- package/dist/types/engram.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/adapters/common.ts +666 -567
- package/src/api/routes.ts +1015 -999
- package/src/core/alias-map.ts +97 -0
- package/src/core/embeddings.ts +172 -115
- package/src/core/recall-config.ts +115 -0
- package/src/core/rerank-window.ts +158 -0
- package/src/core/rerank2.ts +82 -0
- package/src/core/retrieval-text.ts +82 -0
- package/src/core/temporal-query.ts +193 -0
- package/src/core/token-budget.ts +160 -0
- package/src/core/whoami.ts +110 -92
- package/src/core/write-pipeline.ts +6 -3
- package/src/engine/activation.ts +1568 -1468
- package/src/hooks/prime.ts +136 -0
- package/src/hooks/sidecar.ts +43 -0
- package/src/mcp.ts +1422 -1387
- package/src/storage/pglite.ts +10 -2
- package/src/storage/postgres.ts +10 -2
- package/src/storage/sqlite.ts +12 -2
- package/src/types/engram.ts +7 -0
package/README.md
CHANGED
|
@@ -137,96 +137,90 @@ Two structural advantages a file or a flat vector store cannot match:
|
|
|
137
137
|
Two kinds of tests, both reproducible (see [Testing & Evaluation](#testing--evaluation)).
|
|
138
138
|
First, **recall quality** — does the pipeline return the right memory? Second,
|
|
139
139
|
**behavior under stress** — does it stay honest, filter noise, and hold up as the
|
|
140
|
-
store grows and ages?
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
|
155
|
-
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
An earlier build reported ~56% on the oracle bar, but that was an **artifact**: pre-v0.8.5,
|
|
225
|
-
reinforce-on-duplicate silently *discarded* memory content, so recalls were artificially tiny.
|
|
226
|
-
v0.8.5 fixed the data loss (accuracy ~72% → 97.5%); better recall now fills all five slots,
|
|
227
|
-
which *lowers* the oracle-bar number while *raising* correctness. Net: the at-scale structural
|
|
228
|
-
win above is the real story; the oracle bar shows AWM roughly matches perfect manual scoping
|
|
229
|
-
even on a corpus far too small to play to its strengths.
|
|
140
|
+
store grows and ages?
|
|
141
|
+
|
|
142
|
+
### 1 · The 0.13.x retrieval wins
|
|
143
|
+
|
|
144
|
+
Three changes shipped in 0.13.4–0.13.6. Each row names **the corpus it was measured
|
|
145
|
+
on** — they are not the same, and the difference matters. Enable all three together:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
AWM_RERANK2=1 AWM_RERANK_WINDOW=query AWM_RERANK_TAGS=1
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
| Change | Flag | Measured result | Measured on |
|
|
152
|
+
|---|---|---|---|
|
|
153
|
+
| **Second-stage rerank** — let the cross-encoder's own score decide final order, instead of a blend that capped its vote at 70% | `AWM_RERANK2=1` | **+9.7pp success@1** (37.8 → 47.6), p<0.001, paired McNemar. Costs no extra inference — the scores already existed and were being partly discarded. | 616 LoCoMo probes — ⚠ the benchmark retired below |
|
|
154
|
+
| **Query-aware rerank window** — spend the same 400-char budget on the window densest in query terms instead of the prefix | `AWM_RERANK_WINDOW=query` | **25.0% → 87.5%** long-memory success@1 (3.5×), at **+0.07%** CPU and **zero** added tokens. | Generated long-memory corpus, calibrated to real-store statistics, answer planted at a controlled offset |
|
|
155
|
+
| **Tags into the rerank passage** — put words that exist only as tags in front of the component that decides | `AWM_RERANK_TAGS=1` | **+7.4pp success@1** (56.4 → 63.8) on category queries. | 450 probes on a **frozen real-store snapshot** |
|
|
156
|
+
|
|
157
|
+
**Combined, on the real store** (450 category probes, frozen 11,294-engram snapshot):
|
|
158
|
+
**s@1 56.4 → 63.8%**, **s@5 66.2 → 68.4%**, **MRR 60.6 → 66.0%** — with adversarial
|
|
159
|
+
abstention held at **90.0%** in every arm. Selectivity was not traded away to buy accuracy.
|
|
160
|
+
|
|
161
|
+
> **On the +9.7pp figure.** It comes from LoCoMo, which this page retires two sections
|
|
162
|
+
> below. Reported as-measured rather than quietly dropped, because the provenance is part
|
|
163
|
+
> of the story: LoCoMo's short passages are exactly why it could not see the 400-char
|
|
164
|
+
> truncation, and that blind spot is what made the standalone `AWM_RERANK2`
|
|
165
|
+
> recommendation wrong. The combined real-store number above is the one to trust.
|
|
166
|
+
|
|
167
|
+
> **End-to-end, this did not move the acceptance test.** See the gauntlet row below.
|
|
168
|
+
|
|
169
|
+
> **⚠ Enable them together.** `AWM_RERANK2` *alone* regresses long-memory s@5 from
|
|
170
|
+
> 91.7% to 25.0%. BM25 over full content had been quietly compensating for the
|
|
171
|
+
> reranker's 400-char blindness; making a blind reranker authoritative removes that
|
|
172
|
+
> cover. Ship both, or neither.
|
|
173
|
+
|
|
174
|
+
The finding underneath all three: **a memory is unreachable when a word it needs was
|
|
175
|
+
never written into its body.** On this store, 66.2% of topical tag terms never appear
|
|
176
|
+
in the text at all. Three other approaches to the same defect were tested and
|
|
177
|
+
rejected — re-embedding with tags (+0.3pp), mined dialect aliases (−0.2pp), and a
|
|
178
|
+
larger 768d embedder (+0.7pp alone, −1.1pp combined). You cannot recover a word that
|
|
179
|
+
was never written; you can only put the word that *is* recorded in front of the ranker.
|
|
180
|
+
That is also why 0.13.6 rewrote the **writing guidance**, not just the ranker.
|
|
181
|
+
|
|
182
|
+
Full evidence, protocol, and the rejected arms: [`docs/archive/`](docs/archive/README.md).
|
|
183
|
+
|
|
184
|
+
### 2 · Everything else, in one table
|
|
185
|
+
|
|
186
|
+
| What | Result | Detail |
|
|
187
|
+
|---|---|---|
|
|
188
|
+
| **Eval harness** (retrieval / associative / redundancy / temporal) | Recall@5 **0.980** · success@10 **1.000** · dedup F1 **0.966** · Spearman **0.932** — all four above threshold | [`docs/benchmarks.md`](docs/benchmarks.md) |
|
|
189
|
+
| **Unit + subsystem** | `test:run` **715/715** · `test:self` **93.9%** · `test:edge` **~32/34** · `test:mcp` **5/5** | [`docs/benchmarks.md`](docs/benchmarks.md) |
|
|
190
|
+
| **Adversarial / noise rejection** | `test:pilot` **14/15** (5/5 distractors rejected) · `test:ab` **AWM 10/11 vs keyword 8/11** | [`docs/benchmarks.md`](docs/benchmarks.md) |
|
|
191
|
+
| **End-to-end ablation** (the gauntlet) | **74%±5pp memory-dependent vs 0% no-memory control** (0.11.x baseline); only the memory substrate varies. Both arms complete at k=10: baseline **74.0%** vs **81.0%** with the flags (**+7.0pp**, Fisher p=0.31 — not significant, but directionally matching the +7.4pp fixture result). **All 10 probes flip between identical runs**, and `multihop` has never passed at any k | [`gauntlet-baseline`](docs/archive/gauntlet-baseline-2026-07-30.md) |
|
|
192
|
+
| **Consolidation under stress** | Recall **holds 90–100%** across 100 cycles; edges grow to ~2,300 then self-prune to ~1,500 | [`docs/benchmarks.md`](docs/benchmarks.md) |
|
|
193
|
+
| **Token economics** | **9.8× lower** aggregate cost than the Read/Grep/Glob rediscovery it replaces | [`docs/benchmarks.md`](docs/benchmarks.md) |
|
|
194
|
+
|
|
195
|
+
**The retrieval gains above have not yet shown up end-to-end, and the reason is now
|
|
196
|
+
understood.** Both arms now run complete at k=10: baseline **74.0%** against **81.0%**
|
|
197
|
+
with the flags — **+7.0pp**, Fisher exact **p = 0.31**. Not significant, but the direction
|
|
198
|
+
and magnitude match the fixture-level +7.4pp, so this is consistent with the gains
|
|
199
|
+
converting rather than evidence that they do. Resolving it is hard because **all 10 probes
|
|
200
|
+
flip between identical runs**, with `composite` passing 5/10 under an unchanged configuration, and `multihop` moving 2/10 to 6/10 with the flags — half of those passes at 2 steps or fewer, i.e. better ranking rather than the agent chaining. Raising k narrows the interval
|
|
201
|
+
around an unstable mean; it does not make the suite able to resolve a few-point
|
|
202
|
+
difference. The next step is probe determinism, not more repetitions. See
|
|
203
|
+
[`docs/benchmarks.md`](docs/benchmarks.md).
|
|
204
|
+
|
|
205
|
+
Two other numbers are easy to misread, so they are stated plainly:
|
|
206
|
+
|
|
207
|
+
- **`test:sleep` = 78.6% is a consolidation-*quality* score**, not recall falling to
|
|
208
|
+
78.6%. It asks "after the maintenance pass, is recall at least as good and the
|
|
209
|
+
structure better?" Recall is held flat across three cycles while the graph reorganizes.
|
|
210
|
+
- **Token savings depend entirely on the baseline you pick.** vs carrying the full
|
|
211
|
+
history (what a memoryless agent must actually do): **+67% at 97.5% accuracy**. vs an
|
|
212
|
+
oracle that pre-scoped context to the exactly-relevant task: **≈ −13%** — a
|
|
213
|
+
deliberately brutal bar that hands the baseline the very scoping retrieval exists to
|
|
214
|
+
do. 0.13.x added a third and stricter measure, **sufficiency**: does the delivered
|
|
215
|
+
text actually *contain* the answer, or merely point at it?
|
|
216
|
+
|
|
217
|
+
> **LoCoMo was retired in 0.13.x.** It was useful for learning how to benchmark this
|
|
218
|
+
> product but does not represent it: median 115-char passages against a real store's
|
|
219
|
+
> 1,965; seeded in one shot, so decay, Hebbian weights and salience contribute nothing;
|
|
220
|
+
> no supersession, no cross-session use; it *rewards* indiscriminate retention, so the
|
|
221
|
+
> salience filter — the product — caps its score regardless of ranking quality; and it
|
|
222
|
+
> is structurally blind to the 400-char truncation that turned out to affect 79% of real
|
|
223
|
+
> ground-truth identifiers. `tests/realstore-eval/` replaces it.
|
|
230
224
|
|
|
231
225
|
---
|
|
232
226
|
|
|
@@ -361,71 +355,32 @@ awm serve # From npm install
|
|
|
361
355
|
npx tsx src/index.ts # From source
|
|
362
356
|
```
|
|
363
357
|
|
|
364
|
-
Write a memory:
|
|
365
|
-
|
|
366
|
-
```bash
|
|
367
|
-
curl -X POST http://localhost:8400/memory/write \
|
|
368
|
-
-H "Content-Type: application/json" \
|
|
369
|
-
-d '{
|
|
370
|
-
"agentId": "my-agent",
|
|
371
|
-
"concept": "Express error handling",
|
|
372
|
-
"content": "Use centralized error middleware as the last app.use()",
|
|
373
|
-
"eventType": "causal",
|
|
374
|
-
"surprise": 0.5,
|
|
375
|
-
"causalDepth": 0.7
|
|
376
|
-
}'
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
Recall:
|
|
380
|
-
|
|
381
358
|
```bash
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### Substrate primitives (new in 0.8)
|
|
391
|
-
|
|
392
|
-
For long-running structured projects — novels, codebases, investigations,
|
|
393
|
-
design docs — where the agent needs to track typed state across hundreds
|
|
394
|
-
of writes without polluting cognitive retrieval. Full reference at
|
|
395
|
-
[`docs/reference.md`](https://github.com/CompleteIdeas/agent-working-memory/blob/master/docs/reference.md).
|
|
396
|
-
|
|
397
|
-
```bash
|
|
398
|
-
# "Latest emotional state per character" — one round trip
|
|
399
|
-
curl -X POST http://localhost:8400/memory/latest-by-tag -d '{
|
|
400
|
-
"agentId": "novel-x", "tagKey": "character=",
|
|
401
|
-
"scopeTagsAll": ["topic=emotional-state"], "sortBy": "sequence"
|
|
359
|
+
# Write
|
|
360
|
+
curl -X POST http://localhost:8400/memory/write -H "Content-Type: application/json" -d '{
|
|
361
|
+
"agentId": "my-agent",
|
|
362
|
+
"concept": "Express error handling",
|
|
363
|
+
"content": "Use centralized error middleware as the last app.use()",
|
|
364
|
+
"eventType": "causal", "surprise": 0.5, "causalDepth": 0.7
|
|
402
365
|
}'
|
|
403
366
|
|
|
404
|
-
#
|
|
405
|
-
curl -X POST http://localhost:8400/memory/
|
|
406
|
-
"agentId": "
|
|
407
|
-
"
|
|
408
|
-
"filterTagsNone": ["kind=advancement"], "limit": 40
|
|
367
|
+
# Recall
|
|
368
|
+
curl -X POST http://localhost:8400/memory/activate -H "Content-Type: application/json" -d '{
|
|
369
|
+
"agentId": "my-agent",
|
|
370
|
+
"context": "How should I handle errors in my Express API?"
|
|
409
371
|
}'
|
|
410
|
-
|
|
411
|
-
# Atomic write-and-supersede by concept match (Form B)
|
|
412
|
-
curl -X POST http://localhost:8400/memory/supersede -d '{
|
|
413
|
-
"agentId": "novel-x",
|
|
414
|
-
"matchConcept": "Mara's deferred disclosure",
|
|
415
|
-
"newEngram": {
|
|
416
|
-
"concept": "Mara's disclosure — RESOLVED in Ch 3",
|
|
417
|
-
"content": "...", "memory_class": "structural"
|
|
418
|
-
}
|
|
419
|
-
}'
|
|
420
|
-
|
|
421
|
-
# Race-free chronology
|
|
422
|
-
curl http://localhost:8400/memory/sequence/novel-x/next
|
|
423
372
|
```
|
|
424
373
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
374
|
+
**Substrate primitives (0.8+)** — for long-running structured projects (novels,
|
|
375
|
+
codebases, investigations) where an agent tracks typed state across hundreds of writes
|
|
376
|
+
without polluting cognitive retrieval: `/memory/latest-by-tag` (latest per tag key),
|
|
377
|
+
`/memory/top-by` (native filter + sort), `/memory/supersede` (atomic write-and-supersede
|
|
378
|
+
by concept match), `/memory/sequence/:agentId/next` (race-free chronology). The
|
|
379
|
+
`memory_class: "structural"` class keeps high-volume system-written records out of
|
|
380
|
+
cognitive `/activate` while preserving them at canonical salience.
|
|
381
|
+
|
|
382
|
+
Every endpoint, with request/response schemas and worked examples:
|
|
383
|
+
[`docs/reference.md`](https://github.com/CompleteIdeas/agent-working-memory/blob/master/docs/reference.md).
|
|
429
384
|
|
|
430
385
|
---
|
|
431
386
|
|
|
@@ -491,76 +446,75 @@ For detailed architecture including pipeline phases, database schema, and system
|
|
|
491
446
|
|
|
492
447
|
## Testing & Evaluation
|
|
493
448
|
|
|
494
|
-
### Unit Tests
|
|
495
|
-
|
|
496
449
|
```bash
|
|
497
|
-
npx vitest run
|
|
450
|
+
npx vitest run # Unit: salience, decay, hebbian, supersession
|
|
451
|
+
npm run eval # 4 benchmark suites
|
|
452
|
+
npm run eval -- --suite=retrieval # One suite
|
|
453
|
+
npm run eval -- --bm25-only # Ablation: isolate a channel's contribution
|
|
498
454
|
```
|
|
499
455
|
|
|
500
|
-
###
|
|
456
|
+
### Real-store benchmark (0.13.x — replaces LoCoMo)
|
|
457
|
+
|
|
458
|
+
Measures the pipeline against a **frozen snapshot of a real store**, so passage lengths,
|
|
459
|
+
decay, supersession and Hebbian weights are all real rather than synthetic. Ground truth
|
|
460
|
+
is a unique-identifier hold-out verified through FTS, so it needs no hand labeling. And
|
|
461
|
+
correct **abstention scores positively** — selectivity is the product, so a benchmark
|
|
462
|
+
that punishes silence is measuring the wrong system.
|
|
501
463
|
|
|
502
464
|
```bash
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
465
|
+
node tests/realstore-eval/snapshot.mjs # freeze a copy of the live store
|
|
466
|
+
npx tsx tests/realstore-eval/runner.ts # identifier fixture (regression guard)
|
|
467
|
+
REALSTORE_FIXTURE=fixture-category.json \
|
|
468
|
+
npx tsx tests/realstore-eval/runner.ts # category fixture (retrievability)
|
|
469
|
+
bash tests/realstore-eval/campaign/full-comparison.sh # baseline vs recommended, all suites
|
|
507
470
|
```
|
|
508
471
|
|
|
509
|
-
|
|
472
|
+
Each run works on a **copy** — activation mutates access counts, and a benchmark must
|
|
473
|
+
not drift the thing it measures. The runner prints the active flag fingerprint, so every
|
|
474
|
+
result records which configuration produced it.
|
|
475
|
+
|
|
476
|
+
Per-suite methodology, scoring, and the remaining `test:*` scripts:
|
|
477
|
+
[`docs/benchmarks.md`](docs/benchmarks.md).
|
|
510
478
|
|
|
511
|
-
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## Environment Variables
|
|
482
|
+
|
|
483
|
+
**Recommended recall configuration (0.13.x)** — default-OFF, but measured wins. Enable
|
|
484
|
+
all three together (see [Benchmarks](#benchmarks)):
|
|
512
485
|
|
|
513
486
|
```bash
|
|
514
|
-
|
|
515
|
-
npm run test:self # Pipeline component checks (94.1%)
|
|
516
|
-
npm run test:edge # 9 adversarial failure modes
|
|
517
|
-
npm run test:stress # 500 memories, 100 consolidation cycles (96.2%)
|
|
518
|
-
npm run test:workday # 4-session production simulation (93.3%)
|
|
519
|
-
npm run test:ab # AWM vs baseline comparison
|
|
520
|
-
npm run test:sleep # Consolidation impact measurement
|
|
521
|
-
npm run test:tokens # Token savings analysis (56.3% savings)
|
|
522
|
-
npm run test:pilot # Production-like query validation (14/15)
|
|
523
|
-
npm run test:locomo # LoCoMo industry benchmark (28.2%)
|
|
487
|
+
AWM_RERANK2=1 AWM_RERANK_WINDOW=query AWM_RERANK_TAGS=1
|
|
524
488
|
```
|
|
525
489
|
|
|
526
|
-
|
|
490
|
+
| Variable | Effect |
|
|
491
|
+
|---|---|
|
|
492
|
+
| `AWM_RERANK2=1` | Second-stage reorder of the returned window by cross-encoder score alone, after the abstention gate. **+9.7pp s@1.** Must be paired with `AWM_RERANK_WINDOW=query` |
|
|
493
|
+
| `AWM_RERANK_WINDOW=query` | Spend the rerank char budget on the window densest in query terms instead of the first N chars. **25% → 87.5%** long-memory s@1 |
|
|
494
|
+
| `AWM_RERANK_TAGS=1` | Append structured tags to the rerank passage, so category words that exist only as tags reach the deciding stage. **+7.4pp s@1** |
|
|
527
495
|
|
|
528
|
-
|
|
496
|
+
Verify what a running process actually has — `memory_whoami` prints a `Recall config:`
|
|
497
|
+
line and `GET /health` reports the same fingerprint. A submodule bump can report a new
|
|
498
|
+
version while the flags never reached the process; on version alone that looks like success.
|
|
499
|
+
|
|
500
|
+
**Core settings:**
|
|
529
501
|
|
|
530
502
|
| Variable | Default | Purpose |
|
|
531
503
|
|----------|---------|---------|
|
|
532
|
-
| `
|
|
533
|
-
| `
|
|
534
|
-
| `AWM_AGENT_ID` | `claude-code` | Agent
|
|
535
|
-
| `AWM_EMBED_MODEL` | `Xenova/bge-small-en-v1.5` | Embedding model (retrieval-optimized) |
|
|
536
|
-
| `AWM_EMBED_DIMS` | `384` | Embedding dimensions |
|
|
537
|
-
| `AWM_RERANKER_MODEL` | `Xenova/ms-marco-MiniLM-L-6-v2` | Reranker model |
|
|
538
|
-
| `AWM_HOOK_PORT` | `8401` | Hook sidecar port |
|
|
539
|
-
| `AWM_HOOK_SECRET` | *(none)* | Bearer token for hook auth |
|
|
540
|
-
| `AWM_API_KEY` | *(none)* | Bearer token for HTTP API auth |
|
|
541
|
-
| `AWM_INCOGNITO` | *(unset)* | Set to `1` to disable all tools |
|
|
542
|
-
| `AWM_COORDINATION` | *(unset)* | Set to `true` to enable hive coordination endpoints |
|
|
543
|
-
| `AWM_DISABLE_POOL_FILTER` | *(unset)* | Set to `1` to disable the candidate pool reduction (0.7.7+). Reverts recall to scoring all active candidates — slower but useful for A/B testing if a recall regression appears |
|
|
544
|
-
| `AWM_DISABLE_SLIM_CACHE` | *(unset)* | Set to `1` to disable the in-memory slim cache (0.7.10+). Reverts to per-recall SQL fetch — slower but useful if cache invariants are suspected of drift |
|
|
545
|
-
| `AWM_DISABLE_RERANK_SKIP` | *(unset)* | Set to `1` to disable the reranker skip on clear-winner queries (0.7.10+). Forces every recall through the cross-encoder |
|
|
546
|
-
| `AWM_DISABLE_EXPANSION_CACHE` | *(unset)* | Set to `1` to disable the query expansion skip heuristic + LRU cache (0.7.11+). Forces every recall through the flan-t5-small expander |
|
|
504
|
+
| `AWM_DB_PATH` | `memory.db` (SQLite) / `./memory-pglite` (PGlite) | Storage path — file for SQLite, directory for PGlite |
|
|
505
|
+
| `AWM_STORE_BACKEND` | `sqlite` | `sqlite` (WAL, multi-process safe) · `pglite` (single-process) · `postgres` (networked, **experimental**) |
|
|
506
|
+
| `AWM_AGENT_ID` | `claude-code` | Agent id — the memory namespace. Pin it explicitly; an unpinned session lands in a per-directory UUID space nothing else can recall |
|
|
547
507
|
| `AWM_WORKSPACE` | *(unset)* | Default workspace for cross-agent recall in hive setups |
|
|
548
|
-
| `
|
|
549
|
-
| `
|
|
550
|
-
| `
|
|
551
|
-
| `
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
| `AWM_FADE_KEEP_CHARS` | `150` | Chars retained in faded engram content (v0.8.5) |
|
|
559
|
-
| `AWM_FADE_MIN_CONTENT_LEN` | `250` | Don't fade engrams shorter than this — nothing to trim (v0.8.5) |
|
|
560
|
-
| `AWM_FADE_MAX_PER_CYCLE` | `25` | Max engrams faded per consolidation cycle — gradual, not sudden (v0.8.5) |
|
|
561
|
-
| `AWM_GRANULARITY_COMPACT_LEN` | `200` | Char cap for `granularity: 'compact'` summaries (v0.8.5) |
|
|
562
|
-
| `AWM_GRANULARITY_FULL_LEN` | `1000` | Char cap for top result under `granularity: 'auto'` when confidence ≥ threshold (v0.8.5) |
|
|
563
|
-
| `AWM_GRANULARITY_AUTO_THRESHOLD` | `0.4` | Recall-confidence threshold above which `'auto'` granularity gives the top result a long-form summary (v0.8.5) |
|
|
508
|
+
| `AWM_PORT` / `AWM_HOOK_PORT` | `8400` / `8401` | HTTP server and hook sidecar ports |
|
|
509
|
+
| `AWM_API_KEY` / `AWM_HOOK_SECRET` | *(none)* | Bearer tokens. Binding beyond loopback without an API key fails closed |
|
|
510
|
+
| `AWM_INCOGNITO` | *(unset)* | `1` disables all tools |
|
|
511
|
+
| `AWM_EMBED_MODEL` / `AWM_EMBED_DIMS` | `Xenova/bge-small-en-v1.5` / `384` | ⚠ `cosineSimilarity` returns **0** on dimension mismatch — migrate the whole corpus or not at all |
|
|
512
|
+
|
|
513
|
+
Every variable — including the salience, decay, fade, confidence, granularity and
|
|
514
|
+
diagnostic knobs, each with its measured effect and the **rejected** experiments and why
|
|
515
|
+
they lost — is documented in [`docs/reference.md`](https://github.com/CompleteIdeas/agent-working-memory/blob/master/docs/reference.md).
|
|
516
|
+
|
|
517
|
+
---
|
|
564
518
|
|
|
565
519
|
## Tech Stack
|
|
566
520
|
|
|
@@ -579,44 +533,50 @@ npm run test:locomo # LoCoMo industry benchmark (28.2%)
|
|
|
579
533
|
|
|
580
534
|
All three ML models run locally via ONNX. No external API calls for retrieval. The entire system is a single SQLite file + a Node.js process.
|
|
581
535
|
|
|
582
|
-
## What's New in v0.
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
- **
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
536
|
+
## What's New in v0.14.0 (latest)
|
|
537
|
+
|
|
538
|
+
Retrieval-quality releases, all additive. Corpus provenance differs per result and is
|
|
539
|
+
named in [Benchmarks](#benchmarks) — only the tags result and the combined figure come
|
|
540
|
+
from a real-store snapshot.
|
|
541
|
+
|
|
542
|
+
- **Second-stage rerank (`AWM_RERANK2`)** — final order was a blend that capped the
|
|
543
|
+
cross-encoder at 70% of the vote. It disagrees with that blend about rank 1 on 38.6%
|
|
544
|
+
of queries, and where the disagreement is decidable **the cross-encoder is right 77%
|
|
545
|
+
of the time**. Re-sorting by its score: **+9.7pp s@1**, no added inference. Placed
|
|
546
|
+
after the abstention gate so it cannot affect selectivity — predicted 0 broken / 0
|
|
547
|
+
fixed on adversarial, and measured exactly that.
|
|
548
|
+
- **Query-aware rerank window (`AWM_RERANK_WINDOW=query`)** — truncating passages to
|
|
549
|
+
the first 400 chars is necessary (cross-encoders pad to the longest passage in a
|
|
550
|
+
batch), but a *prefix* is the wrong 400. Real canonical memories are median 1,965
|
|
551
|
+
chars, 98.7% exceed 400, and **99.9%** of long ones carry their identifiers only
|
|
552
|
+
past char 400. Same budget, densest window: **25% → 87.5%**.
|
|
553
|
+
- **`memory_whoami` reports the effective recall config** — version alone does not
|
|
554
|
+
answer "what am I actually running". This caught a real deployment failure the day
|
|
555
|
+
it shipped: a project-level `.mcp.json` was overriding the config being edited, so
|
|
556
|
+
the new version reported success while the flags never reached the process.
|
|
557
|
+
- **Tags into the rerank passage (`AWM_RERANK_TAGS`)** — **+7.4pp s@1**, with no
|
|
558
|
+
re-embed, no new model and no write-path change; existing corpora benefit immediately
|
|
559
|
+
because the tags are already stored.
|
|
560
|
+
- **Writing guidance corrected at the source** — the shipped advice was *causing* the
|
|
561
|
+
problem it warned about. "Pick the most specific topic" pushed authors away from
|
|
562
|
+
category words, reliably producing memories that are maximally specific and
|
|
563
|
+
categorically anonymous. Two new rules: **name the CATEGORY as well as the
|
|
564
|
+
specifics**, and **tags are not a substitute for body text** (only BM25 indexes tags —
|
|
565
|
+
the embedding and the rerank passage are both built from `concept + content`, so a
|
|
566
|
+
tag-only word is invisible to two of three channels, including the one that now
|
|
567
|
+
decides ordering).
|
|
568
|
+
|
|
569
|
+
### Previously, in v0.12.x
|
|
570
|
+
|
|
571
|
+
`memory_whoami` instance identity · entity inverted index (`AWM_ENTITY_INDEX_FETCH=1`,
|
|
572
|
+
opt-in) · local-first security defaults (loopback bind, fail-closed without an API key)
|
|
573
|
+
· write-path slow-write telemetry · memory-spine provenance (`origin_class`,
|
|
574
|
+
`valid_from`/`valid_to`) · cognition recipes at `memory_task_end` · engram ids in
|
|
575
|
+
recall results · eager warm at MCP startup + sidecar warm recall.
|
|
614
576
|
|
|
615
577
|
Full version-by-version history — every release back to v0.6.0, including the
|
|
616
578
|
0.7.6→0.7.14 latency work (11s→300ms) and the 0.8.5 recall-quality hardening pass —
|
|
617
|
-
lives in
|
|
618
|
-
|
|
619
|
-
See [CHANGELOG.md](https://github.com/CompleteIdeas/agent-working-memory/blob/master/CHANGELOG.md) for full details.
|
|
579
|
+
lives in [CHANGELOG.md](https://github.com/CompleteIdeas/agent-working-memory/blob/master/CHANGELOG.md).
|
|
620
580
|
|
|
621
581
|
## Integrations
|
|
622
582
|
|
|
@@ -661,7 +621,7 @@ gotchas (incl. the Windows CRLF/s6 clone fix) — is in
|
|
|
661
621
|
|
|
662
622
|
## Project Status
|
|
663
623
|
|
|
664
|
-
AWM is in active development (v0.
|
|
624
|
+
AWM is in active development (v0.14.0). The core memory pipeline, consolidation
|
|
665
625
|
system, multi-agent coordination, and MCP integration are stable and used
|
|
666
626
|
daily in production coding workflows.
|
|
667
627
|
|
|
@@ -681,6 +641,8 @@ daily in production coding workflows.
|
|
|
681
641
|
- Backend-agnostic `import`/`export` (embeddings included, cross-backend port): **stable** (v0.10.0)
|
|
682
642
|
- Instance identity (`memory_whoami`), local-first security defaults, write-path telemetry, memory-spine provenance (`origin_class`/`valid_from`/`valid_to`), cognition recipes: **stable** (v0.12.0)
|
|
683
643
|
- Entity inverted index + guarded index-backed retrieval: **stable, opt-in** (`AWM_ENTITY_INDEX_FETCH=1`, default off pending broader eval) (v0.12.0)
|
|
644
|
+
- Second-stage rerank, query-aware rerank window, tags-into-rerank: **stable, opt-in** (`AWM_RERANK2=1 AWM_RERANK_WINDOW=query AWM_RERANK_TAGS=1` — enable together) (v0.13.4-0.13.6)
|
|
645
|
+
- Real-store benchmark (`tests/realstore-eval/`), replacing LoCoMo: **stable** (v0.13.x)
|
|
684
646
|
|
|
685
647
|
See [CHANGELOG.md](https://github.com/CompleteIdeas/agent-working-memory/blob/master/CHANGELOG.md) for version history.
|
|
686
648
|
|
|
@@ -44,9 +44,15 @@ export declare function homedir(): string;
|
|
|
44
44
|
*
|
|
45
45
|
* Returns a short human-readable status string for the setup command output.
|
|
46
46
|
*/
|
|
47
|
+
/** Opening marker for the generated block. Everything between the markers is replaced
|
|
48
|
+
* on upgrade; anything outside them is preserved. The text is deliberately addressed to
|
|
49
|
+
* whoever opens the file, because that is who needs to know. */
|
|
50
|
+
export declare const AWM_GEN_BEGIN: string;
|
|
51
|
+
export declare const AWM_GEN_END = "<!-- AWM:GENERATED:END -->";
|
|
47
52
|
export declare function upsertAwmSection(filePath: string, newContent: string, options?: {
|
|
48
53
|
titleIfNew?: string;
|
|
49
54
|
suffix?: string;
|
|
55
|
+
force?: boolean;
|
|
50
56
|
}): string;
|
|
51
57
|
export declare const AWM_INSTRUCTION_CONTENT: string;
|
|
52
58
|
//# sourceMappingURL=common.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/adapters/common.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,gEAAgE;AAChE,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAOnF;AAED,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,OAAO,GACjB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAkBA;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,YAAY,CA6Bf;AAED,sBAAsB;AACtB,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAID;;;GAGG;AACH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/adapters/common.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,gEAAgE;AAChE,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAOnF;AAED,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,OAAO,GACjB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAkBA;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,YAAY,CA6Bf;AAED,sBAAsB;AACtB,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAID;;;GAGG;AACH;;;;;;;;;;;;;GAaG;AACH;;iEAEiE;AACjE,eAAO,MAAM,aAAa,QAEsD,CAAC;AACjF,eAAO,MAAM,WAAW,+BAA+B,CAAC;AAOxD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GACtE,MAAM,CAkFR;AAED,eAAO,MAAM,uBAAuB,QAwZvB,CAAC"}
|