@mnemoai/core 1.1.0 → 1.1.1
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/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +7 -0
- package/dist/index.d.ts +128 -0
- package/dist/index.d.ts.map +1 -0
- package/{index.ts → dist/index.js} +526 -1333
- package/dist/index.js.map +7 -0
- package/dist/src/access-tracker.d.ts +97 -0
- package/dist/src/access-tracker.d.ts.map +1 -0
- package/dist/src/access-tracker.js +184 -0
- package/dist/src/access-tracker.js.map +7 -0
- package/dist/src/adapters/chroma.d.ts +31 -0
- package/dist/src/adapters/chroma.d.ts.map +1 -0
- package/{src/adapters/chroma.ts → dist/src/adapters/chroma.js} +45 -107
- package/dist/src/adapters/chroma.js.map +7 -0
- package/dist/src/adapters/lancedb.d.ts +29 -0
- package/dist/src/adapters/lancedb.d.ts.map +1 -0
- package/{src/adapters/lancedb.ts → dist/src/adapters/lancedb.js} +41 -109
- package/dist/src/adapters/lancedb.js.map +7 -0
- package/dist/src/adapters/pgvector.d.ts +33 -0
- package/dist/src/adapters/pgvector.d.ts.map +1 -0
- package/{src/adapters/pgvector.ts → dist/src/adapters/pgvector.js} +42 -104
- package/dist/src/adapters/pgvector.js.map +7 -0
- package/dist/src/adapters/qdrant.d.ts +34 -0
- package/dist/src/adapters/qdrant.d.ts.map +1 -0
- package/dist/src/adapters/qdrant.js +132 -0
- package/dist/src/adapters/qdrant.js.map +7 -0
- package/dist/src/adaptive-retrieval.d.ts +14 -0
- package/dist/src/adaptive-retrieval.d.ts.map +1 -0
- package/dist/src/adaptive-retrieval.js +52 -0
- package/dist/src/adaptive-retrieval.js.map +7 -0
- package/dist/src/audit-log.d.ts +56 -0
- package/dist/src/audit-log.d.ts.map +1 -0
- package/dist/src/audit-log.js +139 -0
- package/dist/src/audit-log.js.map +7 -0
- package/dist/src/chunker.d.ts +45 -0
- package/dist/src/chunker.d.ts.map +1 -0
- package/dist/src/chunker.js +157 -0
- package/dist/src/chunker.js.map +7 -0
- package/dist/src/config.d.ts +70 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +142 -0
- package/dist/src/config.js.map +7 -0
- package/dist/src/decay-engine.d.ts +73 -0
- package/dist/src/decay-engine.d.ts.map +1 -0
- package/dist/src/decay-engine.js +119 -0
- package/dist/src/decay-engine.js.map +7 -0
- package/dist/src/embedder.d.ts +94 -0
- package/dist/src/embedder.d.ts.map +1 -0
- package/{src/embedder.ts → dist/src/embedder.js} +119 -317
- package/dist/src/embedder.js.map +7 -0
- package/dist/src/extraction-prompts.d.ts +12 -0
- package/dist/src/extraction-prompts.d.ts.map +1 -0
- package/dist/src/extraction-prompts.js +311 -0
- package/dist/src/extraction-prompts.js.map +7 -0
- package/dist/src/license.d.ts +29 -0
- package/dist/src/license.d.ts.map +1 -0
- package/{src/license.ts → dist/src/license.js} +42 -113
- package/dist/src/license.js.map +7 -0
- package/dist/src/llm-client.d.ts +23 -0
- package/dist/src/llm-client.d.ts.map +1 -0
- package/{src/llm-client.ts → dist/src/llm-client.js} +22 -55
- package/dist/src/llm-client.js.map +7 -0
- package/dist/src/logger.d.ts +33 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +35 -0
- package/dist/src/logger.js.map +7 -0
- package/dist/src/mcp-server.d.ts +16 -0
- package/dist/src/mcp-server.d.ts.map +1 -0
- package/{src/mcp-server.ts → dist/src/mcp-server.js} +81 -181
- package/dist/src/mcp-server.js.map +7 -0
- package/dist/src/memory-categories.d.ts +40 -0
- package/dist/src/memory-categories.d.ts.map +1 -0
- package/dist/src/memory-categories.js +33 -0
- package/dist/src/memory-categories.js.map +7 -0
- package/dist/src/memory-upgrader.d.ts +71 -0
- package/dist/src/memory-upgrader.d.ts.map +1 -0
- package/dist/src/memory-upgrader.js +238 -0
- package/dist/src/memory-upgrader.js.map +7 -0
- package/dist/src/migrate.d.ts +47 -0
- package/dist/src/migrate.d.ts.map +1 -0
- package/{src/migrate.ts → dist/src/migrate.js} +57 -165
- package/dist/src/migrate.js.map +7 -0
- package/dist/src/mnemo.d.ts +67 -0
- package/dist/src/mnemo.d.ts.map +1 -0
- package/dist/src/mnemo.js +66 -0
- package/dist/src/mnemo.js.map +7 -0
- package/dist/src/noise-filter.d.ts +23 -0
- package/dist/src/noise-filter.d.ts.map +1 -0
- package/dist/src/noise-filter.js +62 -0
- package/dist/src/noise-filter.js.map +7 -0
- package/dist/src/noise-prototypes.d.ts +40 -0
- package/dist/src/noise-prototypes.d.ts.map +1 -0
- package/dist/src/noise-prototypes.js +116 -0
- package/dist/src/noise-prototypes.js.map +7 -0
- package/dist/src/observability.d.ts +16 -0
- package/dist/src/observability.d.ts.map +1 -0
- package/dist/src/observability.js +53 -0
- package/dist/src/observability.js.map +7 -0
- package/dist/src/query-tracker.d.ts +27 -0
- package/dist/src/query-tracker.d.ts.map +1 -0
- package/dist/src/query-tracker.js +32 -0
- package/dist/src/query-tracker.js.map +7 -0
- package/dist/src/reflection-event-store.d.ts +44 -0
- package/dist/src/reflection-event-store.d.ts.map +1 -0
- package/dist/src/reflection-event-store.js +50 -0
- package/dist/src/reflection-event-store.js.map +7 -0
- package/dist/src/reflection-item-store.d.ts +58 -0
- package/dist/src/reflection-item-store.d.ts.map +1 -0
- package/dist/src/reflection-item-store.js +69 -0
- package/dist/src/reflection-item-store.js.map +7 -0
- package/dist/src/reflection-mapped-metadata.d.ts +47 -0
- package/dist/src/reflection-mapped-metadata.d.ts.map +1 -0
- package/dist/src/reflection-mapped-metadata.js +40 -0
- package/dist/src/reflection-mapped-metadata.js.map +7 -0
- package/dist/src/reflection-metadata.d.ts +11 -0
- package/dist/src/reflection-metadata.d.ts.map +1 -0
- package/dist/src/reflection-metadata.js +24 -0
- package/dist/src/reflection-metadata.js.map +7 -0
- package/dist/src/reflection-ranking.d.ts +13 -0
- package/dist/src/reflection-ranking.d.ts.map +1 -0
- package/{src/reflection-ranking.ts → dist/src/reflection-ranking.js} +12 -21
- package/dist/src/reflection-ranking.js.map +7 -0
- package/dist/src/reflection-retry.d.ts +30 -0
- package/dist/src/reflection-retry.d.ts.map +1 -0
- package/{src/reflection-retry.ts → dist/src/reflection-retry.js} +24 -64
- package/dist/src/reflection-retry.js.map +7 -0
- package/dist/src/reflection-slices.d.ts +42 -0
- package/dist/src/reflection-slices.d.ts.map +1 -0
- package/{src/reflection-slices.ts → dist/src/reflection-slices.js} +60 -136
- package/dist/src/reflection-slices.js.map +7 -0
- package/dist/src/reflection-store.d.ts +85 -0
- package/dist/src/reflection-store.d.ts.map +1 -0
- package/dist/src/reflection-store.js +407 -0
- package/dist/src/reflection-store.js.map +7 -0
- package/dist/src/resonance-state.d.ts +19 -0
- package/dist/src/resonance-state.d.ts.map +1 -0
- package/{src/resonance-state.ts → dist/src/resonance-state.js} +13 -42
- package/dist/src/resonance-state.js.map +7 -0
- package/dist/src/retriever.d.ts +228 -0
- package/dist/src/retriever.d.ts.map +1 -0
- package/dist/src/retriever.js +1006 -0
- package/dist/src/retriever.js.map +7 -0
- package/dist/src/scopes.d.ts +58 -0
- package/dist/src/scopes.d.ts.map +1 -0
- package/dist/src/scopes.js +252 -0
- package/dist/src/scopes.js.map +7 -0
- package/dist/src/self-improvement-files.d.ts +20 -0
- package/dist/src/self-improvement-files.d.ts.map +1 -0
- package/{src/self-improvement-files.ts → dist/src/self-improvement-files.js} +24 -49
- package/dist/src/self-improvement-files.js.map +7 -0
- package/dist/src/semantic-gate.d.ts +24 -0
- package/dist/src/semantic-gate.d.ts.map +1 -0
- package/dist/src/semantic-gate.js +86 -0
- package/dist/src/semantic-gate.js.map +7 -0
- package/dist/src/session-recovery.d.ts +9 -0
- package/dist/src/session-recovery.d.ts.map +1 -0
- package/{src/session-recovery.ts → dist/src/session-recovery.js} +40 -57
- package/dist/src/session-recovery.js.map +7 -0
- package/dist/src/smart-extractor.d.ts +107 -0
- package/dist/src/smart-extractor.d.ts.map +1 -0
- package/{src/smart-extractor.ts → dist/src/smart-extractor.js} +130 -383
- package/dist/src/smart-extractor.js.map +7 -0
- package/dist/src/smart-metadata.d.ts +103 -0
- package/dist/src/smart-metadata.d.ts.map +1 -0
- package/dist/src/smart-metadata.js +361 -0
- package/dist/src/smart-metadata.js.map +7 -0
- package/dist/src/storage-adapter.d.ts +102 -0
- package/dist/src/storage-adapter.d.ts.map +1 -0
- package/dist/src/storage-adapter.js +22 -0
- package/dist/src/storage-adapter.js.map +7 -0
- package/dist/src/store.d.ts +108 -0
- package/dist/src/store.d.ts.map +1 -0
- package/dist/src/store.js +939 -0
- package/dist/src/store.js.map +7 -0
- package/dist/src/tier-manager.d.ts +57 -0
- package/dist/src/tier-manager.d.ts.map +1 -0
- package/dist/src/tier-manager.js +80 -0
- package/dist/src/tier-manager.js.map +7 -0
- package/dist/src/tools.d.ts +43 -0
- package/dist/src/tools.d.ts.map +1 -0
- package/dist/src/tools.js +1075 -0
- package/dist/src/tools.js.map +7 -0
- package/dist/src/wal-recovery.d.ts +30 -0
- package/dist/src/wal-recovery.d.ts.map +1 -0
- package/{src/wal-recovery.ts → dist/src/wal-recovery.js} +26 -79
- package/dist/src/wal-recovery.js.map +7 -0
- package/package.json +21 -2
- package/openclaw.plugin.json +0 -815
- package/src/access-tracker.ts +0 -341
- package/src/adapters/README.md +0 -78
- package/src/adapters/qdrant.ts +0 -191
- package/src/adaptive-retrieval.ts +0 -90
- package/src/audit-log.ts +0 -238
- package/src/chunker.ts +0 -254
- package/src/config.ts +0 -271
- package/src/decay-engine.ts +0 -238
- package/src/extraction-prompts.ts +0 -339
- package/src/memory-categories.ts +0 -71
- package/src/memory-upgrader.ts +0 -388
- package/src/mnemo.ts +0 -142
- package/src/noise-filter.ts +0 -97
- package/src/noise-prototypes.ts +0 -164
- package/src/observability.ts +0 -81
- package/src/query-tracker.ts +0 -57
- package/src/reflection-event-store.ts +0 -98
- package/src/reflection-item-store.ts +0 -112
- package/src/reflection-mapped-metadata.ts +0 -84
- package/src/reflection-metadata.ts +0 -23
- package/src/reflection-store.ts +0 -602
- package/src/retriever.ts +0 -1510
- package/src/scopes.ts +0 -375
- package/src/semantic-gate.ts +0 -121
- package/src/smart-metadata.ts +0 -561
- package/src/storage-adapter.ts +0 -153
- package/src/store.ts +0 -1330
- package/src/tier-manager.ts +0 -189
- package/src/tools.ts +0 -1292
- package/test/core.test.mjs +0 -301
package/test/core.test.mjs
DELETED
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mnemo Core — Test Suite
|
|
3
|
-
* Using Node.js built-in test runner (node --test)
|
|
4
|
-
* No external test framework needed.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it } from "node:test";
|
|
8
|
-
import assert from "node:assert/strict";
|
|
9
|
-
import { createHash, generateKeyPairSync, sign, verify, createPublicKey, createPrivateKey } from "node:crypto";
|
|
10
|
-
import { hostname, arch, cpus, platform } from "node:os";
|
|
11
|
-
|
|
12
|
-
// ============================================================================
|
|
13
|
-
// Group 1: SQL Injection Prevention
|
|
14
|
-
// ============================================================================
|
|
15
|
-
|
|
16
|
-
describe("escapeSqlLiteral (allowlist sanitizer)", () => {
|
|
17
|
-
// Re-implement the function here for testing (same logic as store.ts)
|
|
18
|
-
function escapeSqlLiteral(value) {
|
|
19
|
-
if (typeof value !== "string") return "";
|
|
20
|
-
return value.replace(/[^a-zA-Z0-9\-_.:@ \u4e00-\u9fff\u3400-\u4dbf]/g, "");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
it("passes normal ID through", () => {
|
|
24
|
-
assert.equal(escapeSqlLiteral("abc-123-def"), "abc-123-def");
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("passes UUID through", () => {
|
|
28
|
-
assert.equal(
|
|
29
|
-
escapeSqlLiteral("550e8400-e29b-41d4-a716-446655440000"),
|
|
30
|
-
"550e8400-e29b-41d4-a716-446655440000"
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("passes Chinese text through", () => {
|
|
35
|
-
assert.equal(escapeSqlLiteral("用户偏好"), "用户偏好");
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("strips single quotes (SQL injection)", () => {
|
|
39
|
-
assert.equal(escapeSqlLiteral("'; DROP TABLE memories; --"), " DROP TABLE memories --");
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("strips parentheses", () => {
|
|
43
|
-
assert.equal(escapeSqlLiteral("id = '1' OR (1=1)"), "id 1 OR 11");
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("strips backticks", () => {
|
|
47
|
-
assert.equal(escapeSqlLiteral("`memories`"), "memories");
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("strips semicolons", () => {
|
|
51
|
-
assert.equal(escapeSqlLiteral("abc; DELETE FROM x"), "abc DELETE FROM x");
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("handles empty string", () => {
|
|
55
|
-
assert.equal(escapeSqlLiteral(""), "");
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("handles non-string input", () => {
|
|
59
|
-
assert.equal(escapeSqlLiteral(null), "");
|
|
60
|
-
assert.equal(escapeSqlLiteral(undefined), "");
|
|
61
|
-
assert.equal(escapeSqlLiteral(123), "");
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("preserves scope format", () => {
|
|
65
|
-
assert.equal(escapeSqlLiteral("agent:bot3"), "agent:bot3");
|
|
66
|
-
assert.equal(escapeSqlLiteral("global"), "global");
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it("preserves email-like strings", () => {
|
|
70
|
-
assert.equal(escapeSqlLiteral("user@example.com"), "user@example.com");
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// ============================================================================
|
|
75
|
-
// Group 2: License Key System
|
|
76
|
-
// ============================================================================
|
|
77
|
-
|
|
78
|
-
describe("License Key (Ed25519)", () => {
|
|
79
|
-
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
80
|
-
const pubDer = publicKey.export({ type: "spki", format: "der" });
|
|
81
|
-
const privDer = privateKey.export({ type: "pkcs8", format: "der" });
|
|
82
|
-
|
|
83
|
-
function signPayload(payload) {
|
|
84
|
-
const buf = Buffer.from(JSON.stringify(payload));
|
|
85
|
-
const sig = sign(null, buf, privateKey);
|
|
86
|
-
return buf.toString("base64") + "." + sig.toString("base64");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function verifyKey(key) {
|
|
90
|
-
const dot = key.indexOf(".");
|
|
91
|
-
if (dot < 1) return null;
|
|
92
|
-
try {
|
|
93
|
-
const payloadBuf = Buffer.from(key.slice(0, dot), "base64");
|
|
94
|
-
const sigBuf = Buffer.from(key.slice(dot + 1), "base64");
|
|
95
|
-
const valid = verify(null, payloadBuf, publicKey, sigBuf);
|
|
96
|
-
if (!valid) return null;
|
|
97
|
-
return JSON.parse(payloadBuf.toString());
|
|
98
|
-
} catch { return null; }
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
it("valid key verifies correctly", () => {
|
|
102
|
-
const key = signPayload({ licensee: "Test", plan: "indie" });
|
|
103
|
-
const payload = verifyKey(key);
|
|
104
|
-
assert.notEqual(payload, null);
|
|
105
|
-
assert.equal(payload.licensee, "Test");
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("tampered payload fails", () => {
|
|
109
|
-
const key = signPayload({ licensee: "Test" });
|
|
110
|
-
const parts = key.split(".");
|
|
111
|
-
const original = JSON.parse(Buffer.from(parts[0], "base64").toString());
|
|
112
|
-
original.licensee = "Hacked";
|
|
113
|
-
const tampered = Buffer.from(JSON.stringify(original)).toString("base64") + "." + parts[1];
|
|
114
|
-
assert.equal(verifyKey(tampered), null);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it("tampered signature fails", () => {
|
|
118
|
-
const key = signPayload({ licensee: "Test" });
|
|
119
|
-
const parts = key.split(".");
|
|
120
|
-
const sigBuf = Buffer.from(parts[1], "base64");
|
|
121
|
-
sigBuf[0] ^= 0xff;
|
|
122
|
-
const tampered = parts[0] + "." + sigBuf.toString("base64");
|
|
123
|
-
assert.equal(verifyKey(tampered), null);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("empty string fails", () => {
|
|
127
|
-
assert.equal(verifyKey(""), null);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("wrong key pair fails", () => {
|
|
131
|
-
const { privateKey: otherPriv } = generateKeyPairSync("ed25519");
|
|
132
|
-
const buf = Buffer.from(JSON.stringify({ licensee: "Evil" }));
|
|
133
|
-
const sig = sign(null, buf, otherPriv);
|
|
134
|
-
const key = buf.toString("base64") + "." + sig.toString("base64");
|
|
135
|
-
assert.equal(verifyKey(key), null);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it("expired key detected", () => {
|
|
139
|
-
const payload = { licensee: "Test", expires: "2020-01-01" };
|
|
140
|
-
const key = signPayload(payload);
|
|
141
|
-
const decoded = verifyKey(key);
|
|
142
|
-
assert.notEqual(decoded, null);
|
|
143
|
-
assert.ok(new Date(decoded.expires).getTime() < Date.now());
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// ============================================================================
|
|
148
|
-
// Group 3: Machine Fingerprint
|
|
149
|
-
// ============================================================================
|
|
150
|
-
|
|
151
|
-
describe("Machine Fingerprint", () => {
|
|
152
|
-
function getMachineFingerprint() {
|
|
153
|
-
const cpu = cpus()[0]?.model || "unknown";
|
|
154
|
-
const raw = `${hostname()}:${arch()}:${cpu}:${platform()}`;
|
|
155
|
-
return createHash("sha256").update(raw).digest("hex");
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
it("produces SHA-256 hex (64 chars)", () => {
|
|
159
|
-
const fp = getMachineFingerprint();
|
|
160
|
-
assert.match(fp, /^[a-f0-9]{64}$/);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it("is deterministic", () => {
|
|
164
|
-
assert.equal(getMachineFingerprint(), getMachineFingerprint());
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// ============================================================================
|
|
169
|
-
// Group 4: Storage Adapter Interface
|
|
170
|
-
// ============================================================================
|
|
171
|
-
|
|
172
|
-
describe("StorageAdapter Registry", async () => {
|
|
173
|
-
// Dynamic import to test the module
|
|
174
|
-
let registerAdapter, createAdapter, listAdapters;
|
|
175
|
-
try {
|
|
176
|
-
const mod = await import("../src/storage-adapter.js");
|
|
177
|
-
registerAdapter = mod.registerAdapter;
|
|
178
|
-
createAdapter = mod.createAdapter;
|
|
179
|
-
listAdapters = mod.listAdapters;
|
|
180
|
-
} catch {
|
|
181
|
-
// Skip if module can't be loaded (TS not compiled)
|
|
182
|
-
console.log(" ⚠ Skipping adapter tests (TS modules not compiled)");
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
it("registerAdapter + createAdapter round-trip", () => {
|
|
187
|
-
registerAdapter("test-backend", () => ({ name: "test-backend" }));
|
|
188
|
-
const adapter = createAdapter("test-backend");
|
|
189
|
-
assert.equal(adapter.name, "test-backend");
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("listAdapters includes registered backends", () => {
|
|
193
|
-
const list = listAdapters();
|
|
194
|
-
assert.ok(list.includes("test-backend"));
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it("createAdapter throws for unknown backend", () => {
|
|
198
|
-
assert.throws(() => createAdapter("nonexistent"), /not found/);
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
// ============================================================================
|
|
203
|
-
// Group 5: Audit Log
|
|
204
|
-
// ============================================================================
|
|
205
|
-
|
|
206
|
-
describe("Audit Log Entry Format", () => {
|
|
207
|
-
it("audit entry has required fields", () => {
|
|
208
|
-
const entry = {
|
|
209
|
-
timestamp: new Date().toISOString(),
|
|
210
|
-
action: "create",
|
|
211
|
-
actor: "agent:default",
|
|
212
|
-
memoryIds: ["mem_001"],
|
|
213
|
-
scope: "global",
|
|
214
|
-
reason: "auto-capture",
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
assert.ok(entry.timestamp);
|
|
218
|
-
assert.ok(["create", "update", "delete", "expire", "recall"].includes(entry.action));
|
|
219
|
-
assert.ok(Array.isArray(entry.memoryIds));
|
|
220
|
-
assert.ok(entry.actor);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it("audit entry serializes to valid JSON", () => {
|
|
224
|
-
const entry = {
|
|
225
|
-
timestamp: "2026-03-23T10:00:00Z",
|
|
226
|
-
action: "update",
|
|
227
|
-
actor: "system",
|
|
228
|
-
memoryIds: ["mem_001", "mem_002"],
|
|
229
|
-
reason: "contradiction",
|
|
230
|
-
details: JSON.stringify({ old: "age 30", new: "age 31" }),
|
|
231
|
-
};
|
|
232
|
-
const json = JSON.stringify(entry);
|
|
233
|
-
const parsed = JSON.parse(json);
|
|
234
|
-
assert.deepEqual(parsed, entry);
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// ============================================================================
|
|
239
|
-
// Group 6: Weibull Decay Model
|
|
240
|
-
// ============================================================================
|
|
241
|
-
|
|
242
|
-
describe("Weibull Decay", () => {
|
|
243
|
-
function weibull(t, beta, halflife) {
|
|
244
|
-
const lam = halflife / Math.pow(Math.LN2, 1 / beta);
|
|
245
|
-
return Math.exp(-Math.pow(t / lam, beta));
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
it("score is 1.0 at t=0", () => {
|
|
249
|
-
assert.equal(weibull(0, 1.0, 30), 1.0);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it("score is ~0.5 at t=halflife for beta=1.0", () => {
|
|
253
|
-
const score = weibull(30, 1.0, 30);
|
|
254
|
-
assert.ok(Math.abs(score - 0.5) < 0.01);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
it("Core (beta=0.8) retains more than Working after 2x halflife", () => {
|
|
258
|
-
const core = weibull(60, 0.8, 30);
|
|
259
|
-
const working = weibull(60, 1.0, 30);
|
|
260
|
-
assert.ok(core > working, `Core ${core} should be > Working ${working} at t=2*halflife`);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it("Peripheral (beta=1.3) retains less than Working after 2x halflife", () => {
|
|
264
|
-
const peripheral = weibull(60, 1.3, 30);
|
|
265
|
-
const working = weibull(60, 1.0, 30);
|
|
266
|
-
assert.ok(peripheral < working, `Peripheral ${peripheral} should be < Working ${working} at t=2*halflife`);
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
it("score approaches 0 for very old memories", () => {
|
|
270
|
-
const score = weibull(365, 1.0, 30);
|
|
271
|
-
assert.ok(score < 0.001);
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
it("Core memories retain >50% at 90 days", () => {
|
|
275
|
-
const score = weibull(90, 0.8, 90);
|
|
276
|
-
assert.ok(score > 0.45);
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
// ============================================================================
|
|
281
|
-
// Group 7: Config Path Resolution
|
|
282
|
-
// ============================================================================
|
|
283
|
-
|
|
284
|
-
describe("Config Path Defaults", () => {
|
|
285
|
-
it("MNEMO_DB_PATH env overrides default", () => {
|
|
286
|
-
const original = process.env.MNEMO_DB_PATH;
|
|
287
|
-
process.env.MNEMO_DB_PATH = "/custom/path";
|
|
288
|
-
// The function checks env first
|
|
289
|
-
assert.equal(process.env.MNEMO_DB_PATH, "/custom/path");
|
|
290
|
-
if (original) process.env.MNEMO_DB_PATH = original;
|
|
291
|
-
else delete process.env.MNEMO_DB_PATH;
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it("MNEMO_CONFIG env is respected", () => {
|
|
295
|
-
const original = process.env.MNEMO_CONFIG;
|
|
296
|
-
process.env.MNEMO_CONFIG = "/custom/config.json";
|
|
297
|
-
assert.equal(process.env.MNEMO_CONFIG, "/custom/config.json");
|
|
298
|
-
if (original) process.env.MNEMO_CONFIG = original;
|
|
299
|
-
else delete process.env.MNEMO_CONFIG;
|
|
300
|
-
});
|
|
301
|
-
});
|