@psiclawops/hypermem 0.8.2 → 0.8.3
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/INSTALL.md +129 -42
- package/README.md +29 -4
- package/docs/API_STABILITY.md +33 -0
- package/docs/KNOWN_LIMITATIONS.md +35 -0
- package/docs/MEMORY_MD_AUTHORING.md +243 -0
- package/docs/MIGRATION.md +56 -0
- package/docs/MIGRATION_GUIDE.md +1083 -0
- package/docs/PHASE1-VALIDATION.md +132 -0
- package/docs/RELEASE_0.8.0_VALIDATION.md +70 -0
- package/docs/RELEASE_PROCESS.md +10 -0
- package/docs/ROADMAP.md +39 -0
- package/docs/SLASH_COMMANDS.md +93 -0
- package/docs/TUNING.md +866 -0
- package/install.sh +516 -0
- package/memory-plugin/dist/index.d.ts +24 -0
- package/memory-plugin/dist/index.d.ts.map +1 -0
- package/memory-plugin/dist/index.js +300 -0
- package/memory-plugin/dist/index.js.map +1 -0
- package/memory-plugin/openclaw.plugin.json +13 -0
- package/memory-plugin/package.json +64 -0
- package/package.json +13 -2
- package/plugin/dist/index.d.ts +153 -0
- package/plugin/dist/index.d.ts.map +1 -0
- package/plugin/dist/index.js +3127 -0
- package/plugin/dist/index.js.map +1 -0
- package/plugin/openclaw.plugin.json +13 -0
- package/plugin/package.json +65 -0
- package/scripts/install-runtime.mjs +81 -0
package/INSTALL.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Prerequisites
|
|
4
4
|
|
|
5
5
|
- **Node.js 22+** (uses built-in `node:sqlite`)
|
|
6
|
-
- **OpenClaw** must already be installed, onboarded, and running.
|
|
6
|
+
- **OpenClaw** must already be installed, onboarded, and running. HyperMem is a plugin for an existing OpenClaw deployment -- it does not bootstrap OpenClaw itself. If you have never run `openclaw gateway start` or completed OpenClaw onboarding, do that first. The HyperMem install guide picks up after OpenClaw is operational.
|
|
7
7
|
- **Disk space:** allow at least 2 GB free. Plugin builds pull OpenClaw as a dev dependency.
|
|
8
8
|
|
|
9
9
|
**Verify before starting:**
|
|
@@ -17,21 +17,20 @@ If `gateway status` shows "disabled" or "not configured", complete OpenClaw onbo
|
|
|
17
17
|
|
|
18
18
|
## Quick Start
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
```bash
|
|
21
|
+
npm install @psiclawops/hypermem
|
|
22
|
+
npx hypermem-install
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`hypermem-install` stages the plugin runtime into `~/.openclaw/plugins/hypermem`. It does **not** modify your OpenClaw config and does **not** restart the gateway.
|
|
26
|
+
|
|
27
|
+
> **Prerequisites:** OpenClaw must be installed and onboarded. Run `openclaw gateway status` to confirm. If the gateway is not configured, complete OpenClaw setup first.
|
|
25
28
|
>
|
|
26
|
-
> **Config merge warning:** if you already have values in `plugins.load.paths` or `plugins.allow`, merge them instead of overwriting
|
|
29
|
+
> **Config merge warning:** if you already have values in `plugins.load.paths` or `plugins.allow`, merge them instead of overwriting blindly.
|
|
30
|
+
|
|
31
|
+
Create the config directory and set the embedding provider:
|
|
27
32
|
|
|
28
33
|
```bash
|
|
29
|
-
git clone https://github.com/PsiClawOps/hypermem.git
|
|
30
|
-
cd hypermem
|
|
31
|
-
npm install && npm run build
|
|
32
|
-
npm --prefix plugin install && npm --prefix plugin run build # ~1 min on a clean machine
|
|
33
|
-
npm --prefix memory-plugin install && npm --prefix memory-plugin run build
|
|
34
|
-
npm run install:runtime
|
|
35
34
|
mkdir -p ~/.openclaw/hypermem
|
|
36
35
|
cat > ~/.openclaw/hypermem/config.json <<'JSON'
|
|
37
36
|
{
|
|
@@ -42,19 +41,41 @@ cat > ~/.openclaw/hypermem/config.json <<'JSON'
|
|
|
42
41
|
JSON
|
|
43
42
|
```
|
|
44
43
|
|
|
45
|
-
`install:runtime` stages the built plugin files into `~/.openclaw/plugins/hypermem`. It does **not** modify your OpenClaw config. The commands below wire the plugins manually.
|
|
46
|
-
|
|
47
44
|
Wire both plugins into OpenClaw:
|
|
48
45
|
|
|
46
|
+
**Step 1: Check your existing config (mandatory — do this before wiring).**
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
openclaw config get plugins.load.paths
|
|
50
|
+
openclaw config get plugins.allow
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Note any existing values. You must include them in the commands below.
|
|
54
|
+
|
|
55
|
+
**Step 2: Wire plugins.**
|
|
56
|
+
|
|
49
57
|
```bash
|
|
50
|
-
|
|
58
|
+
# Wire plugin load paths — merge with any existing paths from Step 1:
|
|
59
|
+
openclaw config set plugins.load.paths "[\"${HOME}/.openclaw/plugins/hypermem/plugin\",\"${HOME}/.openclaw/plugins/hypermem/memory-plugin\"]" --strict-json
|
|
60
|
+
|
|
61
|
+
# Set the context engine and memory slots:
|
|
51
62
|
openclaw config set plugins.slots.contextEngine hypercompositor
|
|
52
63
|
openclaw config set plugins.slots.memory hypermem
|
|
53
|
-
|
|
64
|
+
|
|
65
|
+
# Allow both plugins — merge with any existing allowed plugins from Step 1.
|
|
66
|
+
# Example (if "my-plugin" was already allowed):
|
|
67
|
+
ocplatform config set plugins.allow '["my-plugin","hypercompositor","hypermem"]' --strict-json
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
> **⚠️ Merge, don't replace.** The command above sets `plugins.allow` to whatever you specify. If `plugins.allow` was non-empty in Step 1, include those entries in the array. Replacing it drops existing plugins (including bundled OpenClaw CLI surfaces and channel plugins).
|
|
71
|
+
|
|
72
|
+
**Step 3: Restart.**
|
|
73
|
+
|
|
74
|
+
```bash
|
|
54
75
|
openclaw gateway restart
|
|
55
76
|
```
|
|
56
77
|
|
|
57
|
-
|
|
78
|
+
OpenClaw loads the plugin runtime from `~/.openclaw/plugins/hypermem/`.
|
|
58
79
|
|
|
59
80
|
### Verification checkpoints
|
|
60
81
|
|
|
@@ -342,7 +363,9 @@ Then:
|
|
|
342
363
|
|
|
343
364
|
## Installation Steps
|
|
344
365
|
|
|
345
|
-
### Step 1 —
|
|
366
|
+
### Step 1 — Source Build (contributors)
|
|
367
|
+
|
|
368
|
+
> **Most users should use the npm Quick Start above.** This section is for contributors or users who need to modify HyperMem source.
|
|
346
369
|
|
|
347
370
|
```bash
|
|
348
371
|
git clone https://github.com/PsiClawOps/hypermem.git
|
|
@@ -351,7 +374,7 @@ npm install
|
|
|
351
374
|
npm run build
|
|
352
375
|
```
|
|
353
376
|
|
|
354
|
-
Build both plugins, then install the runtime payload into
|
|
377
|
+
Build both plugins, then install the runtime payload into OCPlatform's durable plugin directory:
|
|
355
378
|
|
|
356
379
|
```bash
|
|
357
380
|
npm --prefix plugin install && npm --prefix plugin run build
|
|
@@ -365,32 +388,29 @@ Verify:
|
|
|
365
388
|
npm test
|
|
366
389
|
```
|
|
367
390
|
|
|
368
|
-
The full suite takes 30–60 seconds. When complete, output ends with `
|
|
391
|
+
The full suite takes 30–60 seconds. When complete, output ends with `N passed, 0 failed`. If you see `ENOSPC`, free up disk space and retry.
|
|
369
392
|
|
|
370
393
|
### Step 2 — Wire the plugins
|
|
371
394
|
|
|
372
395
|
Use the OpenClaw CLI. **Do not edit `openclaw.json` directly.**
|
|
373
396
|
|
|
374
397
|
```bash
|
|
375
|
-
#
|
|
376
|
-
|
|
398
|
+
# Check existing values first — merge if non-empty:
|
|
399
|
+
ocplatform config get plugins.load.paths
|
|
400
|
+
openclaw config get plugins.allow
|
|
377
401
|
|
|
378
|
-
#
|
|
379
|
-
openclaw config set plugins.
|
|
402
|
+
# Wire plugin load paths (merge with any existing paths):
|
|
403
|
+
openclaw config set plugins.load.paths "[\"${HOME}/.openclaw/plugins/hypermem/plugin\",\"${HOME}/.openclaw/plugins/hypermem/memory-plugin\"]" --strict-json
|
|
380
404
|
|
|
381
|
-
# Set the memory
|
|
405
|
+
# Set the context engine and memory slots:
|
|
406
|
+
openclaw config set plugins.slots.contextEngine hypercompositor
|
|
382
407
|
openclaw config set plugins.slots.memory hypermem
|
|
383
408
|
|
|
384
|
-
# Allow both plugins
|
|
385
|
-
|
|
409
|
+
# Allow both plugins — merge with any existing allowed plugins (example includes "my-plugin"):
|
|
410
|
+
ocplatform config set plugins.allow '["my-plugin","hypercompositor","hypermem"]' --strict-json
|
|
386
411
|
```
|
|
387
412
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
```bash
|
|
391
|
-
openclaw config get plugins.allow
|
|
392
|
-
openclaw config get plugins.load.paths
|
|
393
|
-
```
|
|
413
|
+
> **⚠️ Merge, don't replace.** Check `openclaw config get plugins.allow` before running this command and include all existing entries in the array.
|
|
394
414
|
|
|
395
415
|
### Step 3 — Choose embedding provider
|
|
396
416
|
|
|
@@ -422,7 +442,7 @@ Expected:
|
|
|
422
442
|
[hypermem:compose] agent=main triggers=0 fallback=true facts=3 semantic=2 ...
|
|
423
443
|
```
|
|
424
444
|
|
|
425
|
-
Full health check (run from the repo clone directory):
|
|
445
|
+
Full health check (run from the repo clone directory — `bin/` is a relative path):
|
|
426
446
|
|
|
427
447
|
```bash
|
|
428
448
|
node bin/hypermem-status.mjs # full dashboard
|
|
@@ -430,6 +450,8 @@ node bin/hypermem-status.mjs --health # health checks only (exit 1 on failur
|
|
|
430
450
|
```
|
|
431
451
|
|
|
432
452
|
> **Note:** The health check requires the data directory to exist. It is created on first gateway restart with the plugin active. Run the `openclaw logs` check first to confirm initialization, then run the health check.
|
|
453
|
+
>
|
|
454
|
+
> **Empty results on fresh installs are normal.** If the health check shows `facts=0`, `episodes=0`, or `no agent messages.db found`, that means the install worked but no conversations have happened yet. Data populates after real agent sessions.
|
|
433
455
|
|
|
434
456
|
If the plugin didn't load:
|
|
435
457
|
|
|
@@ -549,23 +571,66 @@ npm --prefix memory-plugin run build
|
|
|
549
571
|
|
|
550
572
|
---
|
|
551
573
|
|
|
552
|
-
## OpenClaw Settings
|
|
574
|
+
## OpenClaw Platform Settings
|
|
575
|
+
|
|
576
|
+
HyperMem manages its own context pressure, memory injection, and compaction. Several OpenClaw defaults conflict with this or are too conservative for memory-augmented agents. Apply these after plugin installation, before the gateway restart.
|
|
577
|
+
|
|
578
|
+
### Disable OpenClaw context pruning (required)
|
|
579
|
+
|
|
580
|
+
OpenClaw has a built-in context pruning system (`cache-ttl` mode) that independently truncates and clears tool results from the message history based on time and context-window ratio thresholds. When HyperMem is active, these two systems fight each other: OpenClaw prunes tool results to free space, then HyperMem injects context that refills it, triggering aggressive compaction on the next turn. The result is unpredictable amnesia.
|
|
581
|
+
|
|
582
|
+
Disable OpenClaw's pruning and let HyperMem handle context pressure exclusively:
|
|
583
|
+
|
|
584
|
+
```bash
|
|
585
|
+
openclaw config set agents.defaults.contextPruning.mode off
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
### Startup context (recommended)
|
|
553
589
|
|
|
554
|
-
|
|
590
|
+
Controls how much daily memory context agents receive on session start. The defaults are very conservative (2 days, 2800 chars total). For memory-augmented agents, increase these so agents wake up with meaningful context:
|
|
591
|
+
|
|
592
|
+
```bash
|
|
593
|
+
openclaw config set agents.defaults.startupContext.dailyMemoryDays 4 --strict-json
|
|
594
|
+
openclaw config set agents.defaults.startupContext.maxFileChars 4000 --strict-json
|
|
595
|
+
openclaw config set agents.defaults.startupContext.maxTotalChars 12000 --strict-json
|
|
596
|
+
openclaw config set agents.defaults.startupContext.maxFileBytes 32768 --strict-json
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
This gives agents 4 days of working memory at startup (~12k chars total). Still under 10% of a 128k context window.
|
|
600
|
+
|
|
601
|
+
### Bootstrap max chars (recommended)
|
|
602
|
+
|
|
603
|
+
Controls the maximum size of bootstrap files (AGENTS.md, SOUL.md, etc.) injected on session start. The default (12000) is tight for agents with governance rules, tool references, and identity docs:
|
|
604
|
+
|
|
605
|
+
```bash
|
|
606
|
+
ocplatform config set agents.defaults.bootstrapMaxChars 20000 --strict-json
|
|
607
|
+
```
|
|
555
608
|
|
|
556
|
-
###
|
|
609
|
+
### Compaction safety net
|
|
557
610
|
|
|
558
|
-
|
|
611
|
+
OpenClaw's built-in compaction (`safeguard` mode) serves as a last-resort safety net. Keep it enabled but tuned so it only fires when HyperMem's own pressure management is insufficient:
|
|
559
612
|
|
|
560
613
|
```bash
|
|
561
|
-
|
|
614
|
+
ocplatform config set agents.defaults.compaction.mode safeguard
|
|
615
|
+
openclaw config set agents.defaults.compaction.reserveTokens 16384 --strict-json
|
|
616
|
+
ocplatform config set agents.defaults.compaction.keepRecentTokens 6000 --strict-json
|
|
617
|
+
ocplatform config set agents.defaults.compaction.reserveTokensFloor 15000 --strict-json
|
|
618
|
+
openclaw config set agents.defaults.compaction.maxHistoryShare 0.65 --strict-json
|
|
562
619
|
```
|
|
563
620
|
|
|
564
|
-
This
|
|
621
|
+
This reserves 16k tokens for reply generation. HyperMem's own pressure system (afterTurn at 80%, nuclear at 85%) fires first in normal operation. OpenClaw's safeguard catches edge cases.
|
|
622
|
+
|
|
623
|
+
### LLM idle timeout
|
|
624
|
+
|
|
625
|
+
Tool-heavy sessions with large outputs can stall during streaming. Raise the idle timeout from the default (120s):
|
|
626
|
+
|
|
627
|
+
```bash
|
|
628
|
+
openclaw config set agents.defaults.llm.idleTimeoutSeconds 300 --strict-json
|
|
629
|
+
```
|
|
565
630
|
|
|
566
631
|
### Tighter session store retention
|
|
567
632
|
|
|
568
|
-
With
|
|
633
|
+
With HyperMem active, SQLite is the durable record. JSONL transcripts provide no memory benefit:
|
|
569
634
|
|
|
570
635
|
```bash
|
|
571
636
|
openclaw config set sessions.maintenance.pruneAfter "14d"
|
|
@@ -744,6 +809,10 @@ The background indexer runs on a 5-minute interval. After the first cycle, check
|
|
|
744
809
|
|
|
745
810
|
Expected on fresh installs. Facts and episodes accumulate over real conversations. After a few sessions these numbers grow. Workspace files can be seeded manually via the seeder API.
|
|
746
811
|
|
|
812
|
+
**Lost bundled plugins after setting `plugins.allow`**
|
|
813
|
+
|
|
814
|
+
If you set `plugins.allow` to only `["hypercompositor","hypermem"]` without including your pre-existing allowed plugins, OpenClaw will stop loading everything else (including built-in CLI surfaces and bundled channel plugins). Fix: re-read your OpenClaw defaults (`openclaw config get plugins.allow`), merge hypermem entries back into the full list, and `openclaw gateway restart`.
|
|
815
|
+
|
|
747
816
|
**Plugin not found**
|
|
748
817
|
|
|
749
818
|
Confirm the installed runtime artifacts exist:
|
|
@@ -797,4 +866,22 @@ Data in `~/.openclaw/hypermem/` is untouched. Re-enable by switching back.
|
|
|
797
866
|
|
|
798
867
|
---
|
|
799
868
|
|
|
869
|
+
## Environment Variables
|
|
870
|
+
|
|
871
|
+
| Variable | Default | Description |
|
|
872
|
+
|---|---|---|
|
|
873
|
+
| `HYPERMEM_DATA_DIR` | `~/.openclaw/hypermem` | Override the data directory where hypermem stores `library.db`, per-agent `messages.db` files, and `vectors.db`. Useful when you want data on a separate volume, need isolated test data dirs, or run multiple hypermem instances. The directory is created automatically if it does not exist. |
|
|
874
|
+
|
|
875
|
+
Example:
|
|
876
|
+
|
|
877
|
+
```bash
|
|
878
|
+
# Point hypermem at a different data location:
|
|
879
|
+
export HYPERMEM_DATA_DIR=/mnt/data/hypermem
|
|
880
|
+
openclaw gateway restart
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
> The config file path (`~/.openclaw/hypermem/config.json`) is separate from the data directory. Moving `HYPERMEM_DATA_DIR` does not move the config file.
|
|
884
|
+
|
|
885
|
+
---
|
|
886
|
+
|
|
800
887
|
_Questions or issues: file against [the repo](https://github.com/PsiClawOps/hypermem) or ask in `#hypermem`._
|
package/README.md
CHANGED
|
@@ -8,10 +8,20 @@
|
|
|
8
8
|
|
|
9
9
|
hypermem is a SQLite-backed runtime context engine for OpenClaw agents.
|
|
10
10
|
|
|
11
|
+
**Quick install** (interactive, detects hardware, writes config):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @psiclawops/hypermem && npx hypermem-install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or via the shell installer:
|
|
18
|
+
|
|
11
19
|
```bash
|
|
12
20
|
curl -fsSL https://raw.githubusercontent.com/PsiClawOps/hypermem/main/install.sh | bash
|
|
13
21
|
```
|
|
14
22
|
|
|
23
|
+
Or install manually via `npm install @psiclawops/hypermem` — see [Installation](#installation) for plugin wiring, embedding setup, and step-by-step paths.
|
|
24
|
+
|
|
15
25
|
|
|
16
26
|
---
|
|
17
27
|
|
|
@@ -376,7 +386,7 @@ Slot-level budget allocation is shown in the [hypercompositor diagram](#what-the
|
|
|
376
386
|
|
|
377
387
|
## Requirements
|
|
378
388
|
|
|
379
|
-
**Current release: hypermem 0.8.
|
|
389
|
+
**Current release: hypermem 0.8.2.** Changelog: [CHANGELOG.md](./CHANGELOG.md)
|
|
380
390
|
|
|
381
391
|
| Requirement | Version | Notes |
|
|
382
392
|
|---|---|---|
|
|
@@ -389,7 +399,7 @@ SQLite is a library, not a service. All four layers run in-process with no exter
|
|
|
389
399
|
**Runtime version constants** (importable from the package):
|
|
390
400
|
```typescript
|
|
391
401
|
import {
|
|
392
|
-
ENGINE_VERSION, // '0.8.
|
|
402
|
+
ENGINE_VERSION, // '0.8.2'
|
|
393
403
|
MIN_NODE_VERSION, // '22.0.0'
|
|
394
404
|
SQLITE_VEC_VERSION, // '0.1.9'
|
|
395
405
|
MAIN_SCHEMA_VERSION, // 10 (messages.db)
|
|
@@ -465,15 +475,30 @@ This sets lightweight mode (FTS5 keyword search, no embedding provider needed).
|
|
|
465
475
|
|
|
466
476
|
Wire the plugins into OpenClaw:
|
|
467
477
|
|
|
478
|
+
> **⚠️ Merge, don't overwrite.** If you already have values in `plugins.load.paths` or `plugins.allow`, check them first and include your existing entries alongside the new ones. Replacing the list drops whatever was there before.
|
|
479
|
+
>
|
|
480
|
+
> ```bash
|
|
481
|
+
> openclaw config get plugins.allow
|
|
482
|
+
> openclaw config get plugins.load.paths
|
|
483
|
+
> ```
|
|
484
|
+
|
|
468
485
|
```bash
|
|
469
|
-
|
|
486
|
+
# Use a variable to avoid shell quote-escaping issues with $HOME:
|
|
487
|
+
HYPERMEM_PATHS="[\"${HOME}/.openclaw/plugins/hypermem/plugin\",\"${HOME}/.openclaw/plugins/hypermem/memory-plugin\"]"
|
|
488
|
+
openclaw config set plugins.load.paths "$HYPERMEM_PATHS" --strict-json
|
|
489
|
+
# If you have existing load paths, merge them into the array in HYPERMEM_PATHS.
|
|
490
|
+
|
|
470
491
|
openclaw config set plugins.slots.contextEngine hypercompositor
|
|
471
492
|
openclaw config set plugins.slots.memory hypermem
|
|
493
|
+
|
|
494
|
+
# ⚠️ Add to your existing plugins.allow — do not replace your current list.
|
|
495
|
+
# Edit the array below to include any plugins you already have allowed:
|
|
472
496
|
openclaw config set plugins.allow '["hypercompositor","hypermem"]' --strict-json
|
|
497
|
+
|
|
473
498
|
openclaw gateway restart
|
|
474
499
|
```
|
|
475
500
|
|
|
476
|
-
Verify (run from the repo clone directory):
|
|
501
|
+
Verify (run these commands from the repo clone directory — `bin/` is a relative path):
|
|
477
502
|
|
|
478
503
|
```bash
|
|
479
504
|
openclaw plugins list # hypercompositor and hypermem should show as loaded
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# API Stability — hypermem
|
|
2
|
+
|
|
3
|
+
## Public API (frozen at 0.5.0)
|
|
4
|
+
|
|
5
|
+
The following four methods are the stable public surface of hypermem. They are
|
|
6
|
+
frozen as of 0.5.0. Breaking changes require a 1.0.0 semver bump — no exceptions.
|
|
7
|
+
|
|
8
|
+
| Method | Signature | Description |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| `create` | `create(config: HypermemConfig): HypermemInstance` | Initialize a hypermem instance |
|
|
11
|
+
| `record` | `record(agentId, sessionKey, message): Promise<void>` | Store a message in the session store |
|
|
12
|
+
| `compose` | `compose(agentId, sessionKey, opts?): Promise<ComposedContext>` | Assemble context for a prompt |
|
|
13
|
+
| `close` | `close(): Promise<void>` | Gracefully shut down, flush, close DB connections |
|
|
14
|
+
|
|
15
|
+
## What "frozen" means
|
|
16
|
+
|
|
17
|
+
- No argument removal or rename
|
|
18
|
+
- No return type narrowing that breaks existing consumers
|
|
19
|
+
- No behavior change that breaks existing consumers without a deprecation cycle
|
|
20
|
+
- Additive changes (new optional args, new fields in return type) are allowed
|
|
21
|
+
|
|
22
|
+
## Internal APIs
|
|
23
|
+
|
|
24
|
+
Everything else — `FactStore`, `CacheLayer`, `Compositor`, `HybridRetrieval`,
|
|
25
|
+
`DreamingPromoter`, etc. — is internal and may change between minor versions.
|
|
26
|
+
These are exported for advanced use but carry no stability guarantee until 1.0.
|
|
27
|
+
|
|
28
|
+
## Versioning policy
|
|
29
|
+
|
|
30
|
+
| Version range | Policy |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `0.x.y` | Public API frozen, internal APIs may change on minor bumps |
|
|
33
|
+
| `1.0.0+` | Full semver — breaking changes require major bump |
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Known Limitations — HyperMem 0.8.0
|
|
2
|
+
|
|
3
|
+
## Global-scope fact write authorization
|
|
4
|
+
|
|
5
|
+
Facts written with `scope='global'` are readable fleet-wide at L4 priority. The write path has no authorization gate — any agent with access to the HyperMem API can write a global-scope fact.
|
|
6
|
+
|
|
7
|
+
**Impact:** In a trusted single-operator deployment (the intended target), this is acceptable. All agents are operator-controlled and share the same trust boundary.
|
|
8
|
+
|
|
9
|
+
**Planned fix:** Introduce a write-authority model that gates global-scope writes to designated agents (council seats or explicitly allowlisted agent IDs). See [docs/ROADMAP.md](ROADMAP.md).
|
|
10
|
+
|
|
11
|
+
**Workaround:** Restrict HyperMem API access to trusted agents only. Do not expose the API to untrusted external agents.
|
|
12
|
+
|
|
13
|
+
## Cross-agent org registry is hardcoded
|
|
14
|
+
|
|
15
|
+
`visibilityFilter()` in `cross-agent.ts` resolves agent tiers and visibility from a hardcoded `defaultOrgRegistry()`. This duplicates fleet topology that lives authoritatively in `fleet_agents` + `fleet_orgs` in library.db.
|
|
16
|
+
|
|
17
|
+
**Impact:** New agents added to library.db but not the hardcoded registry get fleet-only visibility until the registry is updated in code.
|
|
18
|
+
|
|
19
|
+
**Planned fix:** Live-load registry from library.db on startup, hardcoded as cold-start fallback only. See [docs/ROADMAP.md](ROADMAP.md).
|
|
20
|
+
|
|
21
|
+
## Cursor durability across restarts
|
|
22
|
+
|
|
23
|
+
The compositor writes a session cursor to hot cache (SQLite `:memory:`) with a 24h TTL. On gateway restart, the cursor is lost until the next `compose()` call repopulates it.
|
|
24
|
+
|
|
25
|
+
**Impact:** Background indexer may miss the cursor on the first turn after a restart, falling back to full-history scan.
|
|
26
|
+
|
|
27
|
+
**Planned fix:** Dual-write cursor to messages.db so it survives restarts. See [docs/ROADMAP.md](ROADMAP.md).
|
|
28
|
+
|
|
29
|
+
## Cross-session context has no boundary markers
|
|
30
|
+
|
|
31
|
+
`buildCrossSessionContext()` renders flat previews with no per-message boundaries or sender identity labels.
|
|
32
|
+
|
|
33
|
+
**Impact:** Context from different sessions blends together, making attribution ambiguous in multi-agent scenarios.
|
|
34
|
+
|
|
35
|
+
**Planned fix:** WQ-20260402-001. See [docs/ROADMAP.md](ROADMAP.md).
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# MEMORY.md authoring
|
|
2
|
+
|
|
3
|
+
`MEMORY.md` is an index, not a dump.
|
|
4
|
+
|
|
5
|
+
Use it to preserve durable signal the agent should keep noticing across sessions: decisions, operating rules, important architecture facts, stable paths, active plans, and search pointers into deeper history.
|
|
6
|
+
|
|
7
|
+
Do not use it as a transcript, changelog, or a second database. hypermem already stores the raw history. `MEMORY.md` should make the right things easy to find again.
|
|
8
|
+
|
|
9
|
+
## What belongs in MEMORY.md
|
|
10
|
+
|
|
11
|
+
Keep items that are still likely to matter after the current session ends:
|
|
12
|
+
|
|
13
|
+
- stable architectural facts
|
|
14
|
+
- standing rules and constraints
|
|
15
|
+
- current project plans worth reloading next session
|
|
16
|
+
- important decisions with enough context to recover why they happened
|
|
17
|
+
- durable paths, repo locations, and operational references
|
|
18
|
+
- search pointers for deeper recall
|
|
19
|
+
|
|
20
|
+
Good rule: if losing the item would make the next session slower, riskier, or more error-prone, it probably belongs.
|
|
21
|
+
|
|
22
|
+
## What does not belong
|
|
23
|
+
|
|
24
|
+
Do not put these in `MEMORY.md`:
|
|
25
|
+
|
|
26
|
+
- full conversation summaries
|
|
27
|
+
- test logs and build output
|
|
28
|
+
- one-off debugging notes with no ongoing value
|
|
29
|
+
- temporary status that belongs in a daily checkpoint
|
|
30
|
+
- long implementation detail blocks copied from code or specs
|
|
31
|
+
- duplicate facts already obvious from repo structure
|
|
32
|
+
|
|
33
|
+
If the value is only "this happened today," it usually belongs in the daily file, not the index.
|
|
34
|
+
|
|
35
|
+
## Authoring style
|
|
36
|
+
|
|
37
|
+
Write pointer-first entries. One line should stand on its own, and one search pointer should reopen the deeper context.
|
|
38
|
+
|
|
39
|
+
Preferred format:
|
|
40
|
+
|
|
41
|
+
```md
|
|
42
|
+
- TUNE-011: indexer quality gate, 33% fact noise removed (2527→1707 facts)
|
|
43
|
+
→ memory_search("TUNE-011 indexer quality")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Avoid this:
|
|
47
|
+
|
|
48
|
+
```md
|
|
49
|
+
- TUNE-011
|
|
50
|
+
- changed isQualityFact()
|
|
51
|
+
- added guards for code blocks
|
|
52
|
+
- adjusted token thresholds
|
|
53
|
+
- updated tests
|
|
54
|
+
- shipped at 11:42 PM
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The first format reloads context fast. The second turns `MEMORY.md` into a bad replica of history.
|
|
58
|
+
|
|
59
|
+
## Recommended sections
|
|
60
|
+
|
|
61
|
+
Most agents do well with some version of these:
|
|
62
|
+
|
|
63
|
+
- Identity
|
|
64
|
+
- Domain priming
|
|
65
|
+
- Key specs and plans
|
|
66
|
+
- Standing rules
|
|
67
|
+
- Key decisions
|
|
68
|
+
- Recent actions or active facts, if they are still durable enough to matter
|
|
69
|
+
|
|
70
|
+
Use only the sections that actually carry signal.
|
|
71
|
+
|
|
72
|
+
## Recency checking
|
|
73
|
+
|
|
74
|
+
Some facts are true now but should not be treated like permanent law.
|
|
75
|
+
|
|
76
|
+
Examples:
|
|
77
|
+
|
|
78
|
+
- current default model provider
|
|
79
|
+
- active fallback model
|
|
80
|
+
- temporary deployment workarounds
|
|
81
|
+
- known incidents, freezes, or suspensions
|
|
82
|
+
- "current release" statements
|
|
83
|
+
- performance numbers tied to a recent benchmark
|
|
84
|
+
|
|
85
|
+
For these, add recency cues and review them on a cadence.
|
|
86
|
+
|
|
87
|
+
### Mark temporal facts clearly
|
|
88
|
+
|
|
89
|
+
When a fact is time-bound, include one or more of:
|
|
90
|
+
|
|
91
|
+
- an explicit date, such as `as of 2026-04-18`
|
|
92
|
+
- a condition, such as `until Copilot is restored`
|
|
93
|
+
- a review trigger, such as `recheck after next deploy`
|
|
94
|
+
- a search pointer to the deeper event history
|
|
95
|
+
|
|
96
|
+
Example:
|
|
97
|
+
|
|
98
|
+
```md
|
|
99
|
+
- Fleet model drift checks suspended as of 2026-04-14, until Copilot is restored
|
|
100
|
+
→ memory_search("model drift suspension Copilot restored")
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Use a stale-question test
|
|
104
|
+
|
|
105
|
+
Before adding an item, ask:
|
|
106
|
+
|
|
107
|
+
1. Will this still be true in 30 days?
|
|
108
|
+
2. If it changed silently, would stale memory cause a bad decision?
|
|
109
|
+
3. Does the entry tell the next session how to verify freshness?
|
|
110
|
+
|
|
111
|
+
If the answer pattern is `no / yes / no`, the item needs recency metadata or it belongs somewhere else.
|
|
112
|
+
|
|
113
|
+
### Review cadence
|
|
114
|
+
|
|
115
|
+
A simple operating rule works well:
|
|
116
|
+
|
|
117
|
+
- review "current state" lines every 7 to 14 days
|
|
118
|
+
- review release, benchmark, and provider facts after each upgrade or deployment change
|
|
119
|
+
- remove or rewrite any entry whose time condition no longer holds
|
|
120
|
+
|
|
121
|
+
### Prefer ranges over false permanence
|
|
122
|
+
|
|
123
|
+
Bad:
|
|
124
|
+
|
|
125
|
+
```md
|
|
126
|
+
- Forge runs copilot-local/claude-sonnet-4.6
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Better:
|
|
130
|
+
|
|
131
|
+
```md
|
|
132
|
+
- Forge standard model was copilot-local/claude-sonnet-4.6 as of 2026-04-11; recheck after provider routing changes
|
|
133
|
+
→ memory_search("Forge standard model 2026-04-11 provider routing")
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Relationship to daily memory files
|
|
137
|
+
|
|
138
|
+
Use daily files for checkpoint logging: what changed, what blocked, what to resume.
|
|
139
|
+
|
|
140
|
+
Use `MEMORY.md` for the compact map of durable context.
|
|
141
|
+
|
|
142
|
+
A good daily file helps you resume tomorrow. A good `MEMORY.md` helps you resume next month.
|
|
143
|
+
|
|
144
|
+
## Maintenance rule
|
|
145
|
+
|
|
146
|
+
If an entry no longer earns its place, delete it.
|
|
147
|
+
|
|
148
|
+
A shorter `MEMORY.md` with current signal beats a larger one full of expired truth.
|
|
149
|
+
|
|
150
|
+
## Static index vs runtime tail (compositor contract)
|
|
151
|
+
|
|
152
|
+
`MEMORY.md` has two regions. The contract between them is enforced by the
|
|
153
|
+
compositor and must be preserved by anyone editing the file.
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
┌─────────────────────────────────────────────┐
|
|
157
|
+
│ Static curated index (human-authored) │
|
|
158
|
+
│ • identity, pointers, durable facts │
|
|
159
|
+
│ • edit this region by hand │
|
|
160
|
+
├─────────────────────────────────────────────┤
|
|
161
|
+
│ <!-- OPENCLAW_CACHE_BOUNDARY --> │
|
|
162
|
+
├─────────────────────────────────────────────┤
|
|
163
|
+
│ Runtime tail (compositor-generated) │
|
|
164
|
+
│ • Active Facts │
|
|
165
|
+
│ • Temporal Context │
|
|
166
|
+
│ • Other Active Sessions │
|
|
167
|
+
│ • Recent Actions │
|
|
168
|
+
│ • Dynamic Project Context │
|
|
169
|
+
└─────────────────────────────────────────────┘
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Rules
|
|
173
|
+
|
|
174
|
+
1. **On-disk `MEMORY.md` is the curated static index.** It holds identity
|
|
175
|
+
anchors, pointer entries with `memory_search()` hints, and durable facts
|
|
176
|
+
that earn their place long-term.
|
|
177
|
+
|
|
178
|
+
2. **Everything below `<!-- OPENCLAW_CACHE_BOUNDARY -->` is the compositor's
|
|
179
|
+
runtime tail.** It is regenerated on session warm from live stores: the
|
|
180
|
+
fact table, contradiction audits, topic activity, recent tool actions,
|
|
181
|
+
and dynamic project context. Treat the text below the boundary as a
|
|
182
|
+
snapshot, not a source of truth.
|
|
183
|
+
|
|
184
|
+
3. **Do not hand-edit the runtime tail.** Anything you write there will be
|
|
185
|
+
overwritten on the next compositor pass.
|
|
186
|
+
|
|
187
|
+
4. **Do not copy runtime tail content back up into the static index.**
|
|
188
|
+
Facts in the runtime tail originate from the fact store. Copying them
|
|
189
|
+
into the static region:
|
|
190
|
+
- duplicates the content between two layers,
|
|
191
|
+
- hardens a temporary state into a durable record,
|
|
192
|
+
- and bypasses the promoter's quality filters and temporal-marker screen.
|
|
193
|
+
|
|
194
|
+
If a runtime fact genuinely belongs in the durable index, let the
|
|
195
|
+
dreaming promoter handle it, or re-author the claim manually with the
|
|
196
|
+
durability rules above.
|
|
197
|
+
|
|
198
|
+
5. **The compositor owns the boundary marker.** Do not delete, move, or
|
|
199
|
+
relabel `<!-- OPENCLAW_CACHE_BOUNDARY -->`. Deleting it makes the entire
|
|
200
|
+
file look static to the compositor and breaks the runtime tail rebuild.
|
|
201
|
+
|
|
202
|
+
### Why this matters
|
|
203
|
+
|
|
204
|
+
The runtime tail exists to surface what is live right now: active facts,
|
|
205
|
+
recent actions, other sessions, current project context. The static index
|
|
206
|
+
exists to hold what will still be true next month. Conflating the two
|
|
207
|
+
produces the exact failure mode the temporal-marker screen guards against:
|
|
208
|
+
temporary state hardens into durable memory, and the agent loses the
|
|
209
|
+
ability to tell "fresh right now" from "true forever."
|
|
210
|
+
|
|
211
|
+
## Promoter temporal-marker screen
|
|
212
|
+
|
|
213
|
+
The dreaming promoter (`src/dreaming-promoter.ts`) uses a second line of
|
|
214
|
+
defense to keep time-bound facts out of durable memory: the
|
|
215
|
+
temporal-marker screen.
|
|
216
|
+
|
|
217
|
+
**How it works.** When `isPromotable()` evaluates a candidate fact, it
|
|
218
|
+
checks the content against a centralized list of temporal markers:
|
|
219
|
+
|
|
220
|
+
- explicit time bounds: `as of`, `until`, `currently`, `for now`
|
|
221
|
+
- transitional states: `suspended`, `pending`, `paused`, `blocked`, `frozen`
|
|
222
|
+
- rollout language: `rollout`, `phase`, `migration ongoing`, `pre-release`
|
|
223
|
+
- experimental language: `temporary`, `trial`, `experiment(al)`, `exploratory period`, `override`, `hotfix`, `workaround`, `recheck`
|
|
224
|
+
- conditional scope: `in effect during`, `active while … continues/ongoing/rolling out`
|
|
225
|
+
|
|
226
|
+
If any marker matches, the fact must carry structured recency metadata
|
|
227
|
+
(`validFrom` or `invalidAt` on the facts row) to be eligible for durable
|
|
228
|
+
promotion. Plain ISO dates in the content text are **not** a bypass: a
|
|
229
|
+
sentence like `suspended pending X as of 2026-04-18` still contains the
|
|
230
|
+
temporal markers `suspended` and `pending`, and the date only confirms
|
|
231
|
+
that the claim is time-bound.
|
|
232
|
+
|
|
233
|
+
**Extending the marker list.** The list is exported from
|
|
234
|
+
`src/dreaming-promoter.ts` as `TEMPORAL_MARKERS`. Keep it centralized.
|
|
235
|
+
Tests in `test/dreaming-promoter-temporal.mjs` exercise coverage on both
|
|
236
|
+
direct and disguised phrasing; add new fixtures there when adding markers.
|
|
237
|
+
|
|
238
|
+
**Implications for hand-written `MEMORY.md` entries.** The same
|
|
239
|
+
discipline applies at the authoring layer. If you find yourself writing
|
|
240
|
+
"currently," "for now," "pending X," or "in effect during Y" in the
|
|
241
|
+
static index, add an explicit date-stamped condition or move the note to
|
|
242
|
+
a daily file. The promoter's screen is a safety net, not a substitute
|
|
243
|
+
for good authoring.
|