// Tests for the memory scratchpad's pure half (web/static/apps/memory.js — // docs/eleven-memory.md). node test/memory.test.mjs import assert from "node:assert/strict"; import { sanitizeMemory, MAX_FACTS, MAX_FACT_CHARS } from "../web/static/apps/memory.js"; // sanitizeMemory clamps whatever the slot held — the sidecar and the panel // share it unsigned, so read-side clamping is the invariant (mirror of the Go // side's clampMemory; keep the two in step). { const raw = { facts: [ { id: "m1", text: " keeps replies short " }, { text: "no id — repaired" }, { id: "m3", text: " " }, // blank — dropped { id: "bad id!", text: "hostile id — replaced" }, { id: "m5", text: "x".repeat(MAX_FACT_CHARS + 50) }, "not an object", ], }; const m = sanitizeMemory(raw); assert.equal(m.v, 1); assert.equal(m.facts.length, 4); assert.equal(m.facts[0].text, "keeps replies short"); assert.ok(m.facts[1].id, "missing id repaired"); assert.match(m.facts[2].id, /^[A-Za-z0-9_-]+$/, "hostile id replaced"); assert.equal(m.facts[3].text.length, MAX_FACT_CHARS, "overlong fact clamped"); } // The fact cap holds however many the blob carried. { const raw = { facts: Array.from({ length: MAX_FACTS + 10 }, (_, i) => ({ id: "m" + i, text: "fact " + i })) }; assert.equal(sanitizeMemory(raw).facts.length, MAX_FACTS); } // Hopeless shapes fold to empty, never throw. for (const raw of [null, undefined, {}, { facts: "nope" }, { facts: 42 }]) { const m = sanitizeMemory(raw); assert.equal(m.v, 1); assert.deepEqual(m.facts, []); } console.log("memory.test.mjs: ALL PASSED");