@pentatonic-ai/ai-agent-sdk 0.6.0 → 0.7.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.
Files changed (94) hide show
  1. package/README.md +170 -69
  2. package/bin/__tests__/callback-server.test.js +4 -1
  3. package/bin/cli.js +41 -164
  4. package/bin/commands/config.js +251 -0
  5. package/package.json +2 -1
  6. package/packages/doctor/__tests__/detect.test.js +2 -6
  7. package/packages/doctor/src/checks/local-memory.js +164 -196
  8. package/packages/doctor/src/detect.js +11 -3
  9. package/packages/memory/src/corpus/adapters.js +104 -0
  10. package/packages/memory/src/corpus/cli.js +72 -7
  11. package/packages/memory/src/corpus/index.js +1 -1
  12. package/packages/memory-engine/.env.example +13 -0
  13. package/packages/memory-engine/README.md +131 -0
  14. package/packages/memory-engine/bench/README.md +99 -0
  15. package/packages/memory-engine/bench/scorecards-engine/agent-coding__pentatonic-baseline__20260427-142523.json +1115 -0
  16. package/packages/memory-engine/bench/scorecards-engine/chat-recall__pentatonic-baseline__20260427-142648.json +819 -0
  17. package/packages/memory-engine/bench/scorecards-engine/circular-economy__pentatonic-baseline__20260427-142757.json +1278 -0
  18. package/packages/memory-engine/bench/scorecards-engine/customer-support__pentatonic-baseline__20260427-142900.json +1018 -0
  19. package/packages/memory-engine/bench/scorecards-engine/marketplace-ops__pentatonic-baseline__20260427-142957.json +1038 -0
  20. package/packages/memory-engine/bench/scorecards-engine/product-catalogue__pentatonic-baseline__20260427-143122.json +961 -0
  21. package/packages/memory-engine/bench/scorecards-engine-via-docker/agent-coding__pentatonic-memory__20260427-161812.json +1115 -0
  22. package/packages/memory-engine/bench/scorecards-engine-via-docker/chat-recall__pentatonic-memory__20260427-161701.json +819 -0
  23. package/packages/memory-engine/bench/scorecards-engine-via-docker/circular-economy__pentatonic-memory__20260427-161713.json +1278 -0
  24. package/packages/memory-engine/bench/scorecards-engine-via-docker/customer-support__pentatonic-memory__20260427-161723.json +1018 -0
  25. package/packages/memory-engine/bench/scorecards-engine-via-docker/marketplace-ops__pentatonic-memory__20260427-161732.json +1038 -0
  26. package/packages/memory-engine/bench/scorecards-engine-via-docker/product-catalogue__pentatonic-memory__20260427-161741.json +937 -0
  27. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/agent-coding__pentatonic-memory__20260427-184718.json +1115 -0
  28. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/chat-recall__pentatonic-memory__20260427-184614.json +819 -0
  29. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/circular-economy__pentatonic-memory__20260427-184809.json +1278 -0
  30. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/customer-support__pentatonic-memory__20260427-184854.json +1018 -0
  31. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/marketplace-ops__pentatonic-memory__20260427-184929.json +1038 -0
  32. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/product-catalogue__pentatonic-memory__20260427-185015.json +961 -0
  33. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/agent-coding__pentatonic-memory__20260427-175252.json +1115 -0
  34. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/chat-recall__pentatonic-memory__20260427-175312.json +819 -0
  35. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/circular-economy__pentatonic-memory__20260427-175335.json +1278 -0
  36. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/customer-support__pentatonic-memory__20260427-175355.json +1018 -0
  37. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/marketplace-ops__pentatonic-memory__20260427-175413.json +1038 -0
  38. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/product-catalogue__pentatonic-memory__20260427-175430.json +883 -0
  39. package/packages/memory-engine/bench/scorecards-engine-via-shim/agent-coding__pentatonic-memory__20260427-155409.json +1115 -0
  40. package/packages/memory-engine/bench/scorecards-engine-via-shim/chat-recall__pentatonic-memory__20260427-155421.json +819 -0
  41. package/packages/memory-engine/bench/scorecards-engine-via-shim/circular-economy__pentatonic-memory__20260427-155433.json +1278 -0
  42. package/packages/memory-engine/bench/scorecards-engine-via-shim/customer-support__pentatonic-memory__20260427-155443.json +1018 -0
  43. package/packages/memory-engine/bench/scorecards-engine-via-shim/marketplace-ops__pentatonic-memory__20260427-155453.json +1038 -0
  44. package/packages/memory-engine/bench/scorecards-engine-via-shim/product-catalogue__pentatonic-memory__20260427-155503.json +937 -0
  45. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/agent-coding__pentatonic-memory-latest__20260427-145103.json +1115 -0
  46. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/agent-coding__pentatonic-memory__20260427-144909.json +1115 -0
  47. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/chat-recall__pentatonic-memory-latest__20260427-145153.json +819 -0
  48. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/chat-recall__pentatonic-memory__20260427-145120.json +542 -0
  49. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/circular-economy__pentatonic-memory-latest__20260427-145313.json +1278 -0
  50. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/circular-economy__pentatonic-memory__20260427-145207.json +894 -0
  51. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/customer-support__pentatonic-memory-latest__20260427-145412.json +1018 -0
  52. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/customer-support__pentatonic-memory__20260427-145327.json +680 -0
  53. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/marketplace-ops__pentatonic-memory-latest__20260427-145517.json +1038 -0
  54. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/marketplace-ops__pentatonic-memory__20260427-145422.json +693 -0
  55. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/product-catalogue__pentatonic-memory-latest__20260427-145616.json +961 -0
  56. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/product-catalogue__pentatonic-memory__20260427-145528.json +727 -0
  57. package/packages/memory-engine/compat/Dockerfile +11 -0
  58. package/packages/memory-engine/compat/server.py +680 -0
  59. package/packages/memory-engine/docker-compose.yml +243 -0
  60. package/packages/memory-engine/docs/MIGRATION.md +178 -0
  61. package/packages/memory-engine/docs/RUNBOOK-AWS.md +375 -0
  62. package/packages/memory-engine/docs/why-v05-underperforms.md +138 -0
  63. package/packages/memory-engine/engine/README.md +52 -0
  64. package/packages/memory-engine/engine/l2-hybridrag-proxy.py +1543 -0
  65. package/packages/memory-engine/engine/l5-comms-layer.py +663 -0
  66. package/packages/memory-engine/engine/l6-document-store.py +1018 -0
  67. package/packages/memory-engine/engine/services/l2/Dockerfile +41 -0
  68. package/packages/memory-engine/engine/services/l2/init_databases.py +81 -0
  69. package/packages/memory-engine/engine/services/l2/l2-hybridrag-proxy.py +1543 -0
  70. package/packages/memory-engine/engine/services/l4/Dockerfile +15 -0
  71. package/packages/memory-engine/engine/services/l4/server.py +235 -0
  72. package/packages/memory-engine/engine/services/l5/Dockerfile +9 -0
  73. package/packages/memory-engine/engine/services/l5/l5-comms-layer.py +678 -0
  74. package/packages/memory-engine/engine/services/l6/Dockerfile +11 -0
  75. package/packages/memory-engine/engine/services/l6/l6-document-store.py +1016 -0
  76. package/packages/memory-engine/engine/services/nv-embed/Dockerfile +28 -0
  77. package/packages/memory-engine/engine/services/nv-embed/server.py +152 -0
  78. package/packages/memory-engine/pme_memory/__init__.py +0 -0
  79. package/packages/memory-engine/pme_memory/__main__.py +129 -0
  80. package/packages/memory-engine/pme_memory/artifacts.py +95 -0
  81. package/packages/memory-engine/pme_memory/embed.py +74 -0
  82. package/packages/memory-engine/pme_memory/health.py +36 -0
  83. package/packages/memory-engine/pme_memory/hygiene.py +159 -0
  84. package/packages/memory-engine/pme_memory/indexer.py +200 -0
  85. package/packages/memory-engine/pme_memory/needs.py +55 -0
  86. package/packages/memory-engine/pme_memory/provenance.py +80 -0
  87. package/packages/memory-engine/pme_memory/scoring.py +168 -0
  88. package/packages/memory-engine/pme_memory/search.py +52 -0
  89. package/packages/memory-engine/pme_memory/store.py +86 -0
  90. package/packages/memory-engine/pme_memory/synthesis.py +114 -0
  91. package/packages/memory-engine/pyproject.toml +65 -0
  92. package/packages/memory-engine/scripts/kg-extractor.py +557 -0
  93. package/packages/memory-engine/scripts/kg-preflexor-v2.py +738 -0
  94. package/packages/memory-engine/tests/test_api_contract.sh +57 -0
@@ -0,0 +1,243 @@
1
+ name: pentatonic-memory-engine
2
+
3
+ # pentatonic-memory-engine v0.1
4
+ #
5
+ # Drop-in HTTP-compatible replacement for `pentatonic-memory` v0.5,
6
+ # backed by the 7-layer hybrid retrieval engine.
7
+ #
8
+ # Bring up: docker compose up -d
9
+ # API surface: http://localhost:8099 (matches pentatonic-memory v0.5)
10
+ # Health: curl http://localhost:8099/health
11
+ #
12
+ # Layers:
13
+ # l0 (in-process) — BM25 over SQLite FTS5 (inside L2 + L6)
14
+ # l1 (in-process) — Always-loaded core files (inside L2)
15
+ # l2 :8031 — HybridRAG proxy (RRF fusion)
16
+ # l3 :7474 — Knowledge Graph (Neo4j Community)
17
+ # l4 :8042 — sqlite-vec vector index
18
+ # l5 :8034 — Milvus comms layer
19
+ # l6 :8037 — Document store + cross-encoder reranker
20
+ # compat :8099 — pentatonic-memory v0.5 API translation shim
21
+ #
22
+ # nv-embed :8041 — NV-Embed-v2 4096d embedding service
23
+ #
24
+ # The nv-embed service requires a GPU. If running without GPU,
25
+ # override NV_EMBED_URL to point at an external embedding endpoint:
26
+ # - OpenAI's /v1/embeddings (text-embedding-3-large)
27
+ # - the Pentatonic AI Gateway
28
+ # - any OpenAI-compat embedding endpoint
29
+
30
+ x-engine-base: &engine-base
31
+ restart: unless-stopped
32
+ networks:
33
+ - engine-net
34
+
35
+ services:
36
+ # --------------------------------------------------------------------
37
+ # NV-Embed-v2 — 4096-dim embedding service (GPU required)
38
+ # --------------------------------------------------------------------
39
+ nv-embed:
40
+ <<: *engine-base
41
+ build:
42
+ context: ./engine/services/nv-embed
43
+ dockerfile: Dockerfile
44
+ container_name: pme-nv-embed
45
+ ports: ["127.0.0.1:${PME_NV_EMBED_PORT:-8041}:8041"]
46
+ volumes:
47
+ - pme-nv-embed-cache:/cache
48
+ deploy:
49
+ resources:
50
+ reservations:
51
+ devices:
52
+ - driver: nvidia
53
+ count: 1
54
+ capabilities: [gpu]
55
+ healthcheck:
56
+ test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8041/health',timeout=3)"]
57
+ interval: 15s
58
+ timeout: 10s
59
+ retries: 20
60
+ start_period: 120s
61
+
62
+ # --------------------------------------------------------------------
63
+ # L3 — Knowledge Graph (Neo4j Community)
64
+ # --------------------------------------------------------------------
65
+ l3:
66
+ <<: *engine-base
67
+ image: neo4j:5-community
68
+ container_name: pme-l3
69
+ ports:
70
+ - "127.0.0.1:${PME_L3_HTTP_PORT:-7475}:7474" # HTTP browser
71
+ - "127.0.0.1:${PME_L3_BOLT_PORT:-7688}:7687" # bolt protocol
72
+ environment:
73
+ NEO4J_AUTH: ${NEO4J_AUTH:-neo4j/local-dev-pw}
74
+ NEO4J_PLUGINS: '["apoc"]'
75
+ NEO4J_dbms_memory_heap_max__size: 512m
76
+ volumes:
77
+ - pme-l3-data:/data
78
+ healthcheck:
79
+ test: ["CMD-SHELL", "wget -qO- http://localhost:7474 >/dev/null 2>&1 || exit 1"]
80
+ interval: 10s
81
+ timeout: 5s
82
+ retries: 30
83
+ start_period: 30s
84
+
85
+ # --------------------------------------------------------------------
86
+ # L4 — sqlite-vec sidecar
87
+ # --------------------------------------------------------------------
88
+ l4:
89
+ <<: *engine-base
90
+ build:
91
+ context: ./engine/services/l4
92
+ dockerfile: Dockerfile
93
+ container_name: pme-l4
94
+ # Default 18042 to avoid port collisions on 8042.
95
+ # Override via PME_L4_PORT for bench setups that intentionally replace it.
96
+ ports: ["127.0.0.1:${PME_L4_PORT:-18042}:8042"]
97
+ environment:
98
+ L4_NV_EMBED_URL: ${NV_EMBED_URL:-http://host.docker.internal:8041/v1/embeddings}
99
+ L4_EMBED_MODEL: ${EMBED_MODEL_NAME:-nv-embed-v2}
100
+ L4_EMBED_API_KEY: ${EMBED_API_KEY:-}
101
+ L4_EMBED_DIM: ${EMBED_DIM:-4096}
102
+ L4_DB_PATH: /data/vec.db
103
+ extra_hosts:
104
+ - "host.docker.internal:host-gateway"
105
+ volumes:
106
+ - pme-l4-data:/data
107
+ healthcheck:
108
+ test: ["CMD", "python", "-c", "import urllib.request,sys; urllib.request.urlopen('http://localhost:8042/health',timeout=3)"]
109
+ interval: 10s
110
+ timeout: 5s
111
+ retries: 30
112
+
113
+ # --------------------------------------------------------------------
114
+ # L5 — Qdrant comms layer
115
+ # --------------------------------------------------------------------
116
+ l5:
117
+ <<: *engine-base
118
+ build:
119
+ context: ./engine/services/l5
120
+ dockerfile: Dockerfile
121
+ container_name: pme-l5
122
+ # Default 18034 to avoid port collisions on 8034.
123
+ # Override via PME_L5_PORT for bench setups that intentionally replace it.
124
+ ports: ["127.0.0.1:${PME_L5_PORT:-18034}:8034"]
125
+ environment:
126
+ L5_NV_EMBED_URL: ${NV_EMBED_URL:-http://host.docker.internal:8041/v1/embeddings}
127
+ L5_EMBED_MODEL: ${EMBED_MODEL_NAME:-nv-embed-v2}
128
+ L5_EMBED_API_KEY: ${EMBED_API_KEY:-}
129
+ L5_EMBED_DIM: ${EMBED_DIM:-4096}
130
+ L5_OLLAMA_DIM: ${OLLAMA_DIM:-768}
131
+ L5_OLLAMA_EMBED_URL: ${L5_OLLAMA_EMBED_URL:-http://host.docker.internal:11434/api/embed}
132
+ L5_OLLAMA_EMBED_MODEL: ${L5_OLLAMA_EMBED_MODEL:-nomic-embed-text}
133
+ L5_DB_PATH: /data/comms.db
134
+ PME_WORKSPACE: /data/workspace
135
+ extra_hosts:
136
+ - "host.docker.internal:host-gateway"
137
+ volumes:
138
+ - pme-l5-data:/data
139
+
140
+ # --------------------------------------------------------------------
141
+ # L6 — Document store + cross-encoder reranker
142
+ # --------------------------------------------------------------------
143
+ l6:
144
+ <<: *engine-base
145
+ build:
146
+ context: ./engine/services/l6
147
+ dockerfile: Dockerfile
148
+ container_name: pme-l6
149
+ # Default 18037 to avoid colliding with Spark Core L6 doc-store on 8037.
150
+ # Override via PME_L6_PORT for bench setups that intentionally replace it.
151
+ ports: ["127.0.0.1:${PME_L6_PORT:-18037}:8037"]
152
+ environment:
153
+ L6_NV_EMBED_URL: ${NV_EMBED_URL:-http://host.docker.internal:8041/v1/embeddings}
154
+ L6_EMBED_MODEL: ${EMBED_MODEL_NAME:-nv-embed-v2}
155
+ L6_EMBED_API_KEY: ${EMBED_API_KEY:-}
156
+ L6_EMBED_DIM: ${EMBED_DIM:-4096}
157
+ L6_DATA_DIR: /data
158
+ extra_hosts:
159
+ - "host.docker.internal:host-gateway"
160
+ volumes:
161
+ - pme-l6-data:/data
162
+
163
+ # --------------------------------------------------------------------
164
+ # L2 — HybridRAG orchestrator (RRF fusion across all layers)
165
+ # --------------------------------------------------------------------
166
+ l2:
167
+ <<: *engine-base
168
+ build:
169
+ context: ./engine/services/l2
170
+ dockerfile: Dockerfile
171
+ container_name: pme-l2
172
+ ports: ["127.0.0.1:${PME_L2_PORT:-8131}:8031"]
173
+ environment:
174
+ PME_NV_EMBED_URL: ${NV_EMBED_URL:-http://host.docker.internal:8041/v1/embeddings}
175
+ PME_NEO4J_URI: bolt://l3:7687
176
+ PME_NEO4J_PASSWORD: ${NEO4J_PASSWORD:-local-dev-pw}
177
+ NEO4J_PASSWORD: ${NEO4J_PASSWORD:-local-dev-pw}
178
+ PME_L5_URL: http://l5:8034
179
+ PME_L6_URL: http://l6:8037
180
+ # HyDE off (deliberate — hurts precision on retrieval-graded benches)
181
+ PME_HYDE_ENABLED: "false"
182
+ # Cross-encoder reranker on (boosts top-K precision)
183
+ PME_RERANK_ENABLED: "true"
184
+ PME_WORKSPACE: /data/workspace
185
+ PME_QMD_DB: /data/qmd.sqlite
186
+ PME_MEMORY_DB: /data/workspace.db
187
+ extra_hosts:
188
+ - "host.docker.internal:host-gateway"
189
+ volumes:
190
+ - pme-l2-data:/data
191
+ depends_on:
192
+ l3: { condition: service_healthy }
193
+ l5: { condition: service_started }
194
+ l6: { condition: service_started }
195
+
196
+ # --------------------------------------------------------------------
197
+ # Compat shim — exposes pentatonic-memory v0.5 API on :8099
198
+ #
199
+ # Now routes /search through the L2 7-layer proxy by default. L6-only
200
+ # bypass (BYPASS_L2_PROXY=1) is still available for isolated testing.
201
+ # --------------------------------------------------------------------
202
+ compat:
203
+ <<: *engine-base
204
+ build:
205
+ context: ./compat
206
+ dockerfile: Dockerfile
207
+ container_name: pme-compat
208
+ ports:
209
+ - "127.0.0.1:${PME_PORT:-8099}:8099"
210
+ environment:
211
+ L0_URL: http://l2:8031
212
+ L2_PROXY_URL: http://l2:8031
213
+ L3_KG_URL: http://l3:7474
214
+ L4_VEC_URL: http://l4:8042
215
+ L5_MILVUS_URL: http://l5:8034
216
+ L6_DOC_URL: http://l6:8037
217
+ NV_EMBED_URL: ${NV_EMBED_URL:-http://host.docker.internal:8041/v1/embeddings}
218
+ CLIENT_ID: ${CLIENT_ID:-default}
219
+ BYPASS_L2_PROXY: ${BYPASS_L2_PROXY:-0}
220
+ extra_hosts:
221
+ - "host.docker.internal:host-gateway"
222
+ depends_on:
223
+ l2: { condition: service_started }
224
+ l4: { condition: service_started }
225
+ l5: { condition: service_started }
226
+ l6: { condition: service_started }
227
+ healthcheck:
228
+ test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8099/health',timeout=3)"]
229
+ interval: 10s
230
+ timeout: 5s
231
+ retries: 30
232
+ start_period: 60s
233
+
234
+ networks:
235
+ engine-net:
236
+
237
+ volumes:
238
+ pme-nv-embed-cache:
239
+ pme-l2-data:
240
+ pme-l3-data:
241
+ pme-l4-data:
242
+ pme-l5-data:
243
+ pme-l6-data:
@@ -0,0 +1,178 @@
1
+ # Migration Guide
2
+
3
+ ## From `pentatonic-memory` v0.5.x → `pentatonic-memory-engine`
4
+
5
+ ### TL;DR
6
+
7
+ ```diff
8
+ - export PENTATONIC_MEMORY_URL=http://your-pm-host:8099
9
+ + export PENTATONIC_MEMORY_URL=http://your-engine-host:8099
10
+ ```
11
+
12
+ That's it. Same SDK, same code, same `/store` `/search` `/health` calls. Engine returns the same response shape with one optional addition (`engine_layer` field on results, naming which layer carried the hit — purely informational).
13
+
14
+ ### Detailed wire-format compatibility
15
+
16
+ #### `POST /store`
17
+
18
+ Request:
19
+ ```json
20
+ { "content": "...", "metadata": { "key": "value" } }
21
+ ```
22
+
23
+ Response (v0.5.x):
24
+ ```json
25
+ { "id": "mem_abc...", "content": "...", "layerId": "ml_default_episodic" }
26
+ ```
27
+
28
+ Response (engine):
29
+ ```json
30
+ {
31
+ "id": "abc...",
32
+ "content": "...",
33
+ "layerId": "ml_default_episodic",
34
+ "engine": { "l5": 1, "l6": 1 } // ← new, optional
35
+ }
36
+ ```
37
+
38
+ The `engine` field is informational only. Existing SDK clients that ignore unknown fields (the default for both Node.js and Python clients) work without modification.
39
+
40
+ #### `POST /search`
41
+
42
+ Request:
43
+ ```json
44
+ { "query": "...", "limit": 10, "min_score": 0.0001 }
45
+ ```
46
+
47
+ Response (v0.5.x):
48
+ ```json
49
+ {
50
+ "results": [
51
+ {
52
+ "id": "mem_abc...", "content": "...", "metadata": {},
53
+ "similarity": 0.81, "layer_id": "ml_default_episodic", "client_id": "default"
54
+ }
55
+ ]
56
+ }
57
+ ```
58
+
59
+ Response (engine):
60
+ ```json
61
+ {
62
+ "results": [
63
+ {
64
+ "id": "abc...", "content": "...", "metadata": {},
65
+ "similarity": 0.81, "layer_id": "ml_default_episodic", "client_id": "default",
66
+ "source": "doc1.md", // ← passes through engine's source_file
67
+ "engine_layer": "L4 vec" // ← new, optional, names the winning layer
68
+ }
69
+ ]
70
+ }
71
+ ```
72
+
73
+ #### `GET /health`
74
+
75
+ Request: no body.
76
+
77
+ Response (v0.5.x):
78
+ ```json
79
+ { "status": "ok", "client": "default", "version": "0.5.6", "memories": 249 }
80
+ ```
81
+
82
+ Response (engine):
83
+ ```json
84
+ {
85
+ "status": "ok",
86
+ "client": "default",
87
+ "version": "0.1.0",
88
+ "engine": "pentatonic-memory-engine",
89
+ "layers": {
90
+ "l0": "ok", "l1": "ok", "l2": "ok", "l3": "ok",
91
+ "l4": "ok", "l5": "ok", "l6": "ok",
92
+ "nv_embed": "ok"
93
+ },
94
+ "memories": 249
95
+ }
96
+ ```
97
+
98
+ Reports per-layer status across all 7 layers of the `sequential-hybridrag-7-layer` engine.
99
+
100
+ #### `POST /store-batch` (NEW — not in v0.5.x)
101
+
102
+ ```json
103
+ // Request
104
+ {
105
+ "records": [
106
+ { "id": "doc1", "content": "...", "metadata": {} },
107
+ { "id": "doc2", "content": "...", "metadata": {} }
108
+ ],
109
+ "arena": "general"
110
+ }
111
+
112
+ // Response
113
+ {
114
+ "status": "ok",
115
+ "inserted": 2,
116
+ "ids": ["doc1", "doc2"],
117
+ "engine": { "l5": 2, "l6": 2 },
118
+ "duration_ms": 234.5
119
+ }
120
+ ```
121
+
122
+ 30-50× faster than calling `/store` N times when ingesting more than ~5 records.
123
+
124
+ #### `POST /forget` (RESTORED — was in v0.4.x, removed in v0.5.x)
125
+
126
+ ```json
127
+ // Delete one record
128
+ { "id": "doc1" }
129
+
130
+ // Or delete all records matching a metadata filter
131
+ { "metadata_contains": { "bench_tag": "test-run-12345" } }
132
+
133
+ // Response
134
+ { "deleted": 17, "engine": "pentatonic-memory-engine" }
135
+ ```
136
+
137
+ Required for: test pollution control, GDPR data deletion, multi-tenant isolation, bench harnesses.
138
+
139
+ ### Data migration
140
+
141
+ There is no automated dump-and-replay tool. Two paths:
142
+
143
+ **Path A — Re-ingest from source.**
144
+ If your Pentatonic deployment was populated from a known source (chat archives, document repository, TES events), re-run the ingestion against the engine. Use `/store-batch` for speed.
145
+
146
+ **Path B — Dump-and-replay from Postgres.**
147
+ If you only have the v0.5 Postgres database:
148
+
149
+ ```bash
150
+ # Dump as JSONL
151
+ psql $DATABASE_URL -A -t -c \
152
+ "SELECT json_build_object('id', id, 'content', content, 'metadata', metadata)::text
153
+ FROM memory_nodes WHERE client_id = 'your-client'" \
154
+ > export.jsonl
155
+
156
+ # Replay against the engine
157
+ python tools/replay.py export.jsonl --target http://your-engine-host:8099
158
+ ```
159
+
160
+ A `tools/replay.py` reference implementation lives under `tools/` in this package.
161
+
162
+ ### What you lose
163
+
164
+ - **The `metadata.hypothetical_queries` field stops being generated at ingest time.** The engine generates HyDE queries at SEARCH time instead, against the user's actual query (better matching, faster ingest).
165
+ - **`metadata.distilled_from` atoms are no longer auto-generated.** If you were relying on the v0.5+ atomic-fact distillation behaviour, that's a feature of v0.5+ specifically — not a portable feature. The engine treats memories as canonical raw chunks. You can still run distillation as a separate post-processing step if needed.
166
+
167
+ ### What you gain
168
+
169
+ - ~5× retrieval accuracy on substring/exact-match benches (~17.6% → ~82.4% mean)
170
+ - 30-50× faster bulk ingest via `/store-batch`
171
+ - Restored `/forget` endpoint
172
+ - Cross-encoder reranking on top-50
173
+ - Knowledge-graph-aware retrieval (entity overlap signal)
174
+ - Per-layer health visibility
175
+
176
+ ### Rollback
177
+
178
+ The engine doesn't write to your existing Postgres. Roll back by switching the env var back. No data lost.