@alma-harness/testing 0.1.0 → 0.3.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/session-store-contract.ts","../src/episode-store-contract.ts","../src/profile-store-contract.ts","../src/memory-erasure-contract.ts","../src/spend-store-contract.ts","../src/turn-store-contract.ts"],"sourcesContent":["import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport { toWellFormedDeep, type Msg, type Scope, type SessionStore } from \"@alma-harness/core\";\n\n/**\n * Shared `SessionStore` contract suite — §6: storage contracts are\n * backend-neutral by construction; every adapter (in-memory, Postgres,\n * Firestore emulator) runs this exact suite in CI, so no backend idiom\n * fossilizes into the contract.\n *\n * Usage, from an adapter's test file:\n *\n * ```ts\n * import { describeSessionStoreContract } from \"@alma-harness/testing\";\n *\n * describeSessionStoreContract(\"PostgresSessionStore\", {\n * create: () => makeStoreOnFreshSchema(),\n * destroy: (store) => dropSchema(store),\n * });\n * ```\n */\nexport interface SessionStoreFactory {\n /** Must return a store with NO data visible to the scopes used by the suite. */\n create(): Promise<SessionStore> | SessionStore;\n /** Optional teardown, called after each test. */\n destroy?(store: SessionStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\nconst OTHER_ORG: Scope = { org: \"org-b\", uid: \"user-alice\" };\n\nfunction text(role: Msg[\"role\"], body: string): Msg {\n return {\n role,\n blocks: [{ type: \"text\", text: body }],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n };\n}\n\n/** A turn's worth of blocks: what the person saw, plus the tool traffic. */\nfunction withTools(at: string): Msg[] {\n return [\n { role: \"user\", blocks: [{ type: \"text\", text: \"check my notes\" }], meta: { at } },\n {\n role: \"assistant\",\n blocks: [\n { type: \"text\", text: \"one moment\" },\n { type: \"tool_call\", id: \"c1\", name: \"listNotes\", input: {} },\n ],\n meta: { at },\n },\n {\n role: \"tool\",\n blocks: [{ type: \"tool_result\", callId: \"c1\", output: \"two notes\" }],\n meta: { at },\n },\n { role: \"assistant\", blocks: [{ type: \"text\", text: \"you have two\" }], meta: { at } },\n ];\n}\n\nconst kinds = (history: Msg[]): string[][] =>\n history.map((m) => m.blocks.map((b) => b.type));\n\nfunction bodies(history: Msg[]): unknown[] {\n return history.map((m) => (m.blocks[0]?.type === \"text\" ? m.blocks[0].text : m.blocks[0]));\n}\n\nexport function describeSessionStoreContract(name: string, factory: SessionStoreFactory): void {\n describe(`SessionStore contract: ${name}`, () => {\n let store: SessionStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n it(\"round-trips appended messages, preserving content and order\", async () => {\n const entries = [text(\"user\", \"hello\"), text(\"assistant\", \"hi there\")];\n await store.append(ALICE, \"s1\", entries);\n\n const history = await store.load(ALICE, \"s1\");\n expect(history).toEqual(entries);\n });\n\n it(\"round-trips astral-plane text unchanged — emoji and CJK, not just ASCII\", async () => {\n // Four-byte UTF-8, two UTF-16 code units per character. A backend that\n // mangles these mangles what a patient actually types (spec:\n // well-formed-text), and no other case in this suite would notice.\n const entries = [\n text(\"user\", \"não aguento mais 🙂🇧🇷 — 家族と話しました\"),\n text(\"assistant\", \"𝔘𝔫𝔦𝔠𝔬𝔡𝔢 ✅\"),\n ];\n await store.append(ALICE, \"s1\", entries);\n\n const history = await store.load(ALICE, \"s1\");\n expect(history).toEqual(entries);\n for (const body of bodies(history)) expect(String(body).isWellFormed()).toBe(true);\n });\n\n it(\"preserves order across sequential appends (transactional seq)\", async () => {\n await store.append(ALICE, \"s1\", [text(\"user\", \"1\")]);\n await store.append(ALICE, \"s1\", [text(\"assistant\", \"2\"), text(\"user\", \"3\")]);\n await store.append(ALICE, \"s1\", [text(\"assistant\", \"4\")]);\n\n expect(bodies(await store.load(ALICE, \"s1\"))).toEqual([\"1\", \"2\", \"3\", \"4\"]);\n });\n\n it(\"resolves an unknown session to an empty history\", async () => {\n await expect(store.load(ALICE, \"never-created\")).resolves.toEqual([]);\n });\n\n it(\"isolates sessions by sessionId\", async () => {\n await store.append(ALICE, \"s1\", [text(\"user\", \"in s1\")]);\n await store.append(ALICE, \"s2\", [text(\"user\", \"in s2\")]);\n\n expect(bodies(await store.load(ALICE, \"s1\"))).toEqual([\"in s1\"]);\n expect(bodies(await store.load(ALICE, \"s2\"))).toEqual([\"in s2\"]);\n });\n\n it(\"isolates scopes by uid and by org, even for identical session ids\", async () => {\n await store.append(ALICE, \"shared-id\", [text(\"user\", \"alice's\")]);\n\n await expect(store.load(BOB, \"shared-id\")).resolves.toEqual([]);\n await expect(store.load(OTHER_ORG, \"shared-id\")).resolves.toEqual([]);\n });\n\n it(\"load with limit returns the most recent messages, still in order\", async () => {\n await store.append(ALICE, \"s1\", [\n text(\"user\", \"1\"),\n text(\"assistant\", \"2\"),\n text(\"user\", \"3\"),\n text(\"assistant\", \"4\"),\n ]);\n\n expect(bodies(await store.load(ALICE, \"s1\", { limit: 2 }))).toEqual([\"3\", \"4\"]);\n });\n\n it(\"erase(scope, sessionId) removes only that session\", async () => {\n await store.append(ALICE, \"doomed\", [text(\"user\", \"bye\")]);\n await store.append(ALICE, \"kept\", [text(\"user\", \"stay\")]);\n\n await store.erase(ALICE, \"doomed\");\n\n await expect(store.load(ALICE, \"doomed\")).resolves.toEqual([]);\n expect(bodies(await store.load(ALICE, \"kept\"))).toEqual([\"stay\"]);\n });\n\n it(\"erase(scope) purges every session in the scope and nothing outside it\", async () => {\n await store.append(ALICE, \"s1\", [text(\"user\", \"a1\")]);\n await store.append(ALICE, \"s2\", [text(\"user\", \"a2\")]);\n await store.append(BOB, \"s1\", [text(\"user\", \"b1\")]);\n\n await store.erase(ALICE);\n\n await expect(store.load(ALICE, \"s1\")).resolves.toEqual([]);\n await expect(store.load(ALICE, \"s2\")).resolves.toEqual([]);\n expect(bodies(await store.load(BOB, \"s1\"))).toEqual([\"b1\"]);\n });\n\n it(\"rejects an invalid scope even on no-op calls (empty append, non-positive limit)\", async () => {\n // Pins backend neutrality (§6): no adapter may skip central scope\n // validation on early-return paths.\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.append(bad, \"s1\", [])).rejects.toThrow();\n await expect(store.load(bad, \"s1\", { limit: 0 })).rejects.toThrow();\n await expect(store.erase(bad)).rejects.toThrow();\n });\n\n it(\"expires a stale session's tool traffic and keeps everything the person saw\", async () => {\n await store.append(ALICE, \"s1\", withTools(\"2026-01-01T00:00:00.000Z\"));\n\n const report = await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n expect(report).toEqual({ blocks: 2, messages: 1, expired: true });\n // The tool-role message held nothing else and is gone; the assistant's\n // text survives without its tool_call.\n expect(kinds(await store.load(ALICE, \"s1\"))).toEqual([[\"text\"], [\"text\"], [\"text\"]]);\n expect(bodies(await store.load(ALICE, \"s1\"))).toEqual([\n \"check my notes\",\n \"one moment\",\n \"you have two\",\n ]);\n });\n\n it(\"refuses an ACTIVE session and touches nothing — a live prefix must not be rewritten\", async () => {\n // Removing blocks mid-history rewrites the cached prefix: a consuming\n // product measured total cost +27% and cache writes +99% doing exactly\n // that (§6.6). The refusal is the whole reason `inactiveSince` exists,\n // and it reports rather than throws — an active session in a sweep is\n // the normal case, and a throw would be caught and swallowed per session.\n const entries = withTools(\"2026-07-01T00:00:00.000Z\");\n await store.append(ALICE, \"s1\", entries);\n\n const report = await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n expect(report).toEqual({ blocks: 0, messages: 0, expired: false });\n expect(await store.load(ALICE, \"s1\")).toEqual(entries);\n });\n\n it(\"never leaves a tool_call without its tool_result — the pairing a provider enforces with a 400\", async () => {\n // Spec 026 taught the loop to pair them on every exit path; an expiry\n // that took one side would manufacture the dangling tool_use it exists\n // to prevent. All-or-nothing is what makes this true by construction.\n await store.append(ALICE, \"s1\", withTools(\"2026-01-01T00:00:00.000Z\"));\n\n await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n const flat = (await store.load(ALICE, \"s1\")).flatMap((m) => m.blocks.map((b) => b.type));\n expect(flat).not.toContain(\"tool_call\");\n expect(flat).not.toContain(\"tool_result\");\n });\n\n it(\"keeps media blocks — a pointer the user saw, not tool traffic\", async () => {\n await store.append(ALICE, \"s1\", [\n {\n role: \"user\",\n blocks: [\n { type: \"media\", kind: \"image\", ref: { uri: \"gs://bucket/x.png\" } },\n { type: \"tool_call\", id: \"c1\", name: \"describe\", input: {} },\n ],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n },\n ]);\n\n await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n expect(kinds(await store.load(ALICE, \"s1\"))).toEqual([[\"media\"]]);\n });\n\n it(\"expires only the named session, and validates the scope\", async () => {\n await store.append(ALICE, \"s1\", withTools(\"2026-01-01T00:00:00.000Z\"));\n await store.append(ALICE, \"s2\", withTools(\"2026-01-01T00:00:00.000Z\"));\n\n await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n expect(kinds(await store.load(ALICE, \"s2\"))).toEqual([\n [\"text\"],\n [\"text\", \"tool_call\"],\n [\"tool_result\"],\n [\"text\"],\n ]);\n await expect(\n store.expireToolTraffic({ org: \"../evil\", uid: \"u\" }, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n }),\n ).rejects.toThrow();\n });\n\n it(\"round-trips a MediaRef whole, filename included\", async () => {\n // Spec 040. One store the first port migrates repeats the file name in\n // the message text; another carries it ONLY here. An adapter that\n // dropped unknown ref keys would lose the second one's only copy.\n const ref = {\n uri: \"gs://bucket/laudo.pdf\",\n contentType: \"application/pdf\",\n bytes: 20_480,\n filename: \"laudo — 2026.pdf\",\n };\n await store.append(ALICE, \"s1\", [\n {\n role: \"user\",\n blocks: [{ type: \"media\", kind: \"document\", ref }],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n },\n ]);\n\n const block = (await store.load(ALICE, \"s1\"))[0]?.blocks[0];\n expect(block?.type === \"media\" ? block.ref : null).toEqual(ref);\n });\n\n it(\"round-trips a MediaRef with no filename — the field is optional\", async () => {\n const ref = { uri: \"gs://bucket/x.png\" };\n await store.append(ALICE, \"s1\", [\n {\n role: \"user\",\n blocks: [{ type: \"media\", kind: \"image\", ref }],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n },\n ]);\n\n const block = (await store.load(ALICE, \"s1\"))[0]?.blocks[0];\n expect(block?.type === \"media\" ? block.ref : null).toEqual(ref);\n expect(block?.type === \"media\" ? \"filename\" in block.ref : true).toBe(false);\n });\n\n it(\"expires by the message's own meta.at, not by when the row was written\", async () => {\n // Spec 040, and the case spec 039's suite cannot be: those stamp\n // `meta.at` moments before asserting, so the message clock and the row\n // clock agree and neither can distinguish the other. A migrated session\n // is written TODAY carrying stamps from a year ago — if an adapter ever\n // reads its own `created_at`, every migrated session looks freshly\n // active and expiry refuses all of them, forever, reporting success.\n await store.append(ALICE, \"s1\", withTools(\"2025-01-01T00:00:00.000Z\"));\n\n const report = await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2025-06-01T00:00:00.000Z\",\n });\n\n expect(report).toEqual({ blocks: 2, messages: 1, expired: true });\n });\n\n it(\"treats a message with no meta.at as ACTIVE — an age that cannot be established is not old\", async () => {\n // A pin (§3.3): true before spec 040 and after. It is here so the case\n // above cannot be \"fixed\" by quietly making unstamped messages\n // expirable, which would invert the safe direction.\n const undated: Msg = {\n role: \"assistant\",\n blocks: [{ type: \"tool_call\", id: \"c1\", name: \"x\", input: {} }],\n };\n await store.append(ALICE, \"s1\", [...withTools(\"2025-01-01T00:00:00.000Z\"), undated]);\n\n const report = await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2025-06-01T00:00:00.000Z\",\n });\n\n expect(report).toEqual({ blocks: 0, messages: 0, expired: false });\n });\n\n it(\"refuses malformed UTF-16 identically on every adapter, naming the entry\", async () => {\n // Spec 040. Until then the adapters DIVERGED — in-memory kept the lone\n // surrogate, Postgres refused the write — and both contracts said \"do\n // not rely on either behaviour\". `runTurn` repairs on the way in, but\n // best-effort; a migration writing here directly has no such pass.\n const lone = `broken \\ud83d end`;\n expect(lone.isWellFormed()).toBe(false);\n\n await expect(\n store.append(ALICE, \"s1\", [text(\"user\", \"fine\"), text(\"assistant\", lone)]),\n ).rejects.toThrow(/entries\\[1\\]/);\n // Refused whole: nothing from the batch landed.\n await expect(store.load(ALICE, \"s1\")).resolves.toEqual([]);\n });\n\n it(\"accepts the same value once toWellFormedDeep has run — the documented remedy works\", async () => {\n const repaired = toWellFormedDeep(text(\"assistant\", `broken \\ud83d end`));\n\n await store.append(ALICE, \"s1\", [repaired]);\n\n const [loaded] = await store.load(ALICE, \"s1\");\n expect(loaded).toEqual(repaired);\n expect(String(bodies([loaded as Msg])[0]).isWellFormed()).toBe(true);\n });\n\n it(\"returns defensive copies — mutating a loaded history never corrupts the store\", async () => {\n await store.append(ALICE, \"s1\", [text(\"user\", \"original\")]);\n\n const first = await store.load(ALICE, \"s1\");\n first.pop();\n const block = (await store.load(ALICE, \"s1\"))[0]?.blocks[0];\n if (block?.type === \"text\") block.text = \"mutated\";\n\n expect(bodies(await store.load(ALICE, \"s1\"))).toEqual([\"original\"]);\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type { EpisodeStore, Scope } from \"@alma-harness/core\";\nimport { deriveEpisodeId, isRecallable } from \"@alma-harness/memory\";\n\n/**\n * Shared `EpisodeStore` contract suite — §6, spec 011. Every adapter\n * (in-memory, Postgres, Firestore emulator) runs this exact suite in CI, so no\n * backend idiom fossilizes into the contract and the normative rules of spec\n * 010 hold everywhere: deterministic ids, three states never conflated,\n * budget at the reader, declared copy surfaces.\n *\n * ```ts\n * describeEpisodeStoreContract(\"PostgresEpisodeStore\", { create: () => … });\n * ```\n */\nexport interface EpisodeStoreFactory {\n /** Must return a store with NO data visible to the scopes used by the suite. */\n create(): Promise<EpisodeStore> | EpisodeStore;\n destroy?(store: EpisodeStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\nconst OTHER_ORG: Scope = { org: \"org-b\", uid: \"user-alice\" };\n\n/** Pinned timestamps keep ranking deterministic across backends. */\nconst T = {\n old: \"2026-01-01T00:00:00.000Z\",\n mid: \"2026-06-01T00:00:00.000Z\",\n recent: \"2026-08-01T00:00:00.000Z\",\n} as const;\n\nfunction summaries(episodes: readonly { summary: string }[]): string[] {\n return episodes.map((e) => e.summary);\n}\n\nexport function describeEpisodeStoreContract(name: string, factory: EpisodeStoreFactory): void {\n describe(`EpisodeStore contract: ${name}`, () => {\n let store: EpisodeStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n it(\"round-trips an appended episode, defaulting importance and state\", async () => {\n const stored = await store.append(ALICE, {\n kind: \"conversation\",\n summary: \"prefers morning appointments\",\n at: T.recent,\n source: { sessionId: \"s1\", turnId: \"t1\" },\n });\n\n expect(stored).toMatchObject({\n kind: \"conversation\",\n summary: \"prefers morning appointments\",\n at: T.recent,\n importance: 0.5,\n state: \"active\",\n source: { sessionId: \"s1\", turnId: \"t1\" },\n });\n expect(isRecallable(stored)).toBe(true);\n\n const found = await store.get(ALICE, [stored.id]);\n expect(found).toEqual([stored]);\n });\n\n it(\"addresses episodes by a deterministic id, so re-extraction overwrites and never duplicates\", async () => {\n // Spec 010 normative: \"candidates and runs are addressed by\n // content/scope hashes — re-extraction overwrites, never duplicates\".\n const input = {\n kind: \"note\",\n summary: \"runs 5k on saturdays\",\n source: { sessionId: \"s1\", turnId: \"t1\" },\n };\n const first = await store.append(ALICE, { ...input, at: T.old });\n const second = await store.append(ALICE, { ...input, at: T.recent });\n\n expect(second.id).toBe(first.id);\n expect(second.id).toBe(deriveEpisodeId(ALICE, input));\n const { episodes } = await store.query(ALICE, {});\n expect(episodes).toHaveLength(1);\n });\n\n it(\"derives different ids for the same content in different scopes\", async () => {\n const input = { kind: \"note\", summary: \"same words\" };\n const mine = await store.append(ALICE, input);\n const theirs = await store.append(BOB, input);\n\n expect(mine.id).not.toBe(theirs.id);\n });\n\n it(\"dedupeKey separates two genuinely distinct episodes with identical content\", async () => {\n const input = { kind: \"note\", summary: \"checked in\", source: { turnId: \"t1\" } };\n await store.append(ALICE, { ...input, dedupeKey: \"a\" });\n await store.append(ALICE, { ...input, dedupeKey: \"b\" });\n\n const { episodes } = await store.query(ALICE, {});\n expect(episodes).toHaveLength(2);\n });\n\n it(\"keeps a dedupeKey scoped to its content: reuse in a later turn never overwrites\", async () => {\n // The key's job is to SPLIT identical content within one turn. Derived\n // from the key alone, a stable key like \"choice\" reused next turn landed\n // on the earlier turn's id and silently replaced that episode (review of\n // spec 013).\n const first = await store.append(ALICE, {\n kind: \"note\",\n summary: \"chose the morning slot\",\n source: { turnId: \"t1\" },\n dedupeKey: \"choice\",\n });\n const second = await store.append(ALICE, {\n kind: \"note\",\n summary: \"chose the evening slot\",\n source: { turnId: \"t2\" },\n dedupeKey: \"choice\",\n });\n\n expect(second.id).not.toBe(first.id);\n expect((await store.get(ALICE, [first.id]))[0]).toMatchObject({\n summary: \"chose the morning slot\",\n });\n });\n\n it(\"normalizes timestamps to canonical UTC, so backends never disagree\", async () => {\n const stored = await store.append(ALICE, {\n kind: \"note\",\n summary: \"written with an offset\",\n at: \"2026-08-01T02:00:00+02:00\",\n });\n\n expect(stored.at).toBe(\"2026-08-01T00:00:00.000Z\");\n expect((await store.get(ALICE, [stored.id]))[0]?.at).toBe(\"2026-08-01T00:00:00.000Z\");\n });\n\n it(\"isolates scopes by uid and by org\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"alice's memory\" });\n\n await expect(store.query(BOB, {})).resolves.toMatchObject({ episodes: [] });\n await expect(store.query(OTHER_ORG, {})).resolves.toMatchObject({ episodes: [] });\n });\n\n it(\"filters by kind and by time range\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"note one\", at: T.old });\n await store.append(ALICE, { kind: \"observation\", summary: \"observed thing\", at: T.mid });\n await store.append(ALICE, { kind: \"note\", summary: \"note two\", at: T.recent });\n\n const byKind = await store.query(ALICE, { kinds: [\"observation\"] });\n expect(summaries(byKind.episodes)).toEqual([\"observed thing\"]);\n\n const byRange = await store.query(ALICE, { since: T.mid, until: T.recent });\n expect(summaries(byRange.episodes).sort()).toEqual([\"note two\", \"observed thing\"]);\n });\n\n it(\"ranks a term match above a non-match, and excludes non-matches entirely\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"loves kayaking\", at: T.old });\n await store.append(ALICE, { kind: \"note\", summary: \"dislikes crowds\", at: T.recent });\n\n const { episodes } = await store.query(ALICE, { text: \"kayaking\" });\n expect(summaries(episodes)).toEqual([\"loves kayaking\"]);\n });\n\n it(\"finds a term deep in a long summary, past the query tokenizer's cap\", async () => {\n // The 32-term cap bounds QUERY patterns; applied to the summary side of\n // the overlap score, it made any summary longer than ~32 distinct words\n // unsearchable past its opening words (the 011–013 review).\n const filler = Array.from({ length: 40 }, (_, i) => `filler${i}`).join(\" \");\n await store.append(ALICE, { kind: \"note\", summary: `${filler} chocolate` });\n\n const { episodes } = await store.query(ALICE, { text: \"chocolate\" });\n expect(episodes).toHaveLength(1);\n });\n\n it(\"matches case-insensitively beyond ASCII, whatever locale the backend runs under\", async () => {\n // Folding is the ADAPTER's job, in one consistent locale: Postgres\n // `ilike` under lc_ctype of C folds ASCII only, so 'CAFÉ' silently\n // stopped matching 'café' there while this reference matched it —\n // breaking the candidate-superset property the ranker composes with\n // (the 011–013 review).\n await store.append(ALICE, { kind: \"note\", summary: \"Adora CAFÉ da manhã\" });\n\n const { episodes } = await store.query(ALICE, { text: \"café\" });\n expect(summaries(episodes)).toEqual([\"Adora CAFÉ da manhã\"]);\n });\n\n it(\"breaks a ranking tie toward the more recent episode\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"coffee order\", at: T.old });\n await store.append(ALICE, { kind: \"note\", summary: \"coffee order\", dedupeKey: \"b\", at: T.recent });\n\n const { episodes } = await store.query(ALICE, { text: \"coffee\" });\n expect(episodes.map((e) => e.at)).toEqual([T.recent, T.old]);\n });\n\n it(\"ranks higher importance above lower at equal overlap and age\", async () => {\n await store.append(ALICE, {\n kind: \"note\",\n summary: \"allergy penicillin\",\n dedupeKey: \"low\",\n at: T.mid,\n importance: 0.1,\n });\n await store.append(ALICE, {\n kind: \"note\",\n summary: \"allergy penicillin\",\n dedupeKey: \"high\",\n at: T.mid,\n importance: 0.9,\n });\n\n const { episodes } = await store.query(ALICE, { text: \"allergy\" });\n expect(episodes.map((e) => e.importance)).toEqual([0.9, 0.1]);\n });\n\n it(\"caps the read at the budget and says it truncated\", async () => {\n // Spec 010, third consumer: an uncapped reader is a latent leak even\n // under a global budget.\n for (const n of [\"one\", \"two\", \"three\"]) {\n await store.append(ALICE, { kind: \"note\", summary: `budget ${n}`, dedupeKey: n, at: T.mid });\n }\n\n const capped = await store.query(ALICE, { text: \"budget\", budget: { maxItems: 1 } });\n expect(capped.episodes).toHaveLength(1);\n expect(capped.truncated).toBe(true);\n\n const uncapped = await store.query(ALICE, { text: \"budget\" });\n expect(uncapped.episodes).toHaveLength(3);\n expect(uncapped.truncated).toBe(false);\n });\n\n it(\"drops whole items rather than overflowing a character budget\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"x\".repeat(30), dedupeKey: \"big\", at: T.mid });\n\n const result = await store.query(ALICE, { budget: { maxChars: 10 } });\n expect(result.episodes).toEqual([]);\n expect(result.truncated).toBe(true);\n });\n\n it(\"resolves a non-positive limit to an empty result\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"present\" });\n\n await expect(store.query(ALICE, { limit: 0 })).resolves.toMatchObject({ episodes: [] });\n });\n\n it(\"archives an episode out of hot recall while keeping its content intact\", async () => {\n const ep = await store.append(ALICE, { kind: \"note\", summary: \"seasonal detail\", at: T.mid });\n\n await expect(store.archive(ALICE, [ep.id])).resolves.toBe(1);\n\n const hot = await store.query(ALICE, { text: \"seasonal\" });\n expect(hot.episodes).toEqual([]);\n\n const cold = await store.query(ALICE, { text: \"seasonal\", includeArchived: true });\n expect(summaries(cold.episodes)).toEqual([\"seasonal detail\"]);\n expect(isRecallable(cold.episodes[0]!)).toBe(false);\n });\n\n it(\"keeps an archived episode archived when it is re-appended\", async () => {\n // Re-observation is not a reason to undo a product's salience decision.\n const input = { kind: \"note\", summary: \"seasonal detail\", source: { turnId: \"t1\" } };\n const ep = await store.append(ALICE, input);\n await store.archive(ALICE, [ep.id]);\n\n const reappended = await store.append(ALICE, input);\n\n expect(reappended.state).toBe(\"archived\");\n });\n\n it(\"tombstones an episode: content gone, position kept, never recalled again\", async () => {\n // Spec 010 AC 4 and \"isRecallable excludes tombstones — an erased memory\n // must not surface as a blank line that leaks its own existence\".\n const ep = await store.append(ALICE, {\n kind: \"note\",\n summary: \"sensitive detail\",\n at: T.mid,\n source: { sessionId: \"s1\" },\n });\n\n const result = await store.tombstone(ALICE, { kind: \"episodes\", episodeIds: [ep.id] }, T.recent);\n expect(result.episodeIds).toEqual([ep.id]);\n\n const [stored] = await store.get(ALICE, [ep.id]);\n expect(stored).toMatchObject({\n id: ep.id,\n kind: \"\", // the label goes too — nothing enforces that it is not content\n summary: \"\",\n state: \"tombstoned\",\n erasedAt: T.recent,\n });\n expect(isRecallable(stored!)).toBe(false);\n\n await expect(store.query(ALICE, { text: \"sensitive\" })).resolves.toMatchObject({\n episodes: [],\n });\n await expect(\n store.query(ALICE, { text: \"sensitive\", includeArchived: true }),\n ).resolves.toMatchObject({ episodes: [] });\n });\n\n it(\"never resurrects a tombstoned episode on re-append\", async () => {\n // Terminal states are create-only (spec 010).\n const input = { kind: \"note\", summary: \"erased content\", source: { turnId: \"t1\" } };\n const ep = await store.append(ALICE, input);\n await store.tombstone(ALICE, { kind: \"episodes\", episodeIds: [ep.id] }, T.recent);\n\n const reappended = await store.append(ALICE, input);\n\n expect(reappended.state).toBe(\"tombstoned\");\n expect(reappended.summary).toBe(\"\");\n await expect(store.query(ALICE, { text: \"erased\" })).resolves.toMatchObject({ episodes: [] });\n });\n\n it(\"refuses to archive a tombstoned episode\", async () => {\n // Terminal states are create-only: an erased episode has no state left\n // to move to, and 'archived' would imply recoverable content.\n const ep = await store.append(ALICE, { kind: \"note\", summary: \"erased\" });\n await store.tombstone(ALICE, { kind: \"episodes\", episodeIds: [ep.id] }, T.recent);\n\n await expect(store.archive(ALICE, [ep.id])).resolves.toBe(0);\n expect((await store.get(ALICE, [ep.id]))[0]).toMatchObject({ state: \"tombstoned\" });\n });\n\n it(\"tombstones every episode of a session, and nothing outside it\", async () => {\n const doomed = await store.append(ALICE, {\n kind: \"note\",\n summary: \"in the doomed session\",\n source: { sessionId: \"doomed\" },\n });\n const kept = await store.append(ALICE, {\n kind: \"note\",\n summary: \"in another session\",\n source: { sessionId: \"kept\" },\n });\n\n const result = await store.tombstone(ALICE, { kind: \"sessions\", sessionIds: [\"doomed\"] }, T.recent);\n\n expect(result.episodeIds).toEqual([doomed.id]);\n expect((await store.get(ALICE, [kept.id]))[0]).toMatchObject({ state: \"active\" });\n });\n\n it(\"tombstones the whole scope on the 'all' selector, and nothing outside the scope\", async () => {\n const mine = await store.append(ALICE, { kind: \"note\", summary: \"mine\" });\n const theirs = await store.append(BOB, { kind: \"note\", summary: \"theirs\" });\n\n const result = await store.tombstone(ALICE, { kind: \"all\" }, T.recent);\n\n expect(result.episodeIds).toEqual([mine.id]);\n expect((await store.get(BOB, [theirs.id]))[0]).toMatchObject({ state: \"active\" });\n });\n\n it(\"reports every copy surface it declares, so erasure can be proven\", async () => {\n // Spec 010: \"provenance columns without a written delete are not\n // erasure\" — the declaration is checked against what erasure wrote.\n await store.append(ALICE, { kind: \"note\", summary: \"anything\" });\n\n const result = await store.tombstone(ALICE, { kind: \"all\" }, T.recent);\n\n expect(store.copySurfaces.length).toBeGreaterThan(0);\n for (const surface of store.copySurfaces) {\n expect(result.surfaces).toContain(surface.name);\n }\n });\n\n it(\"cannot be pinned to the top of every ranking by a future timestamp\", async () => {\n // Recency decayed from age clamped at zero, so a far-future `at` scored\n // the maximum forever — and `at` is caller-supplied.\n await store.append(ALICE, { kind: \"note\", summary: \"honest coffee note\", at: T.recent });\n await store.append(ALICE, {\n kind: \"note\",\n summary: \"coffee spam\",\n dedupeKey: \"future\",\n at: \"9999-01-01T00:00:00.000Z\",\n });\n\n const { episodes } = await store.query(ALICE, { text: \"coffee\" });\n expect(episodes[0]?.summary).toBe(\"honest coffee note\");\n });\n\n it(\"returns nothing for a search whose text carries no usable term\", async () => {\n // Treating an empty token set as \"no text\" turned search into \"dump\n // whatever is most recent\" — the opposite of searching.\n await store.append(ALICE, { kind: \"note\", summary: \"private detail\", at: T.recent });\n\n await expect(store.query(ALICE, { text: \"a\" })).resolves.toMatchObject({ episodes: [] });\n await expect(store.query(ALICE, { text: \"???\" })).resolves.toMatchObject({ episodes: [] });\n });\n\n it(\"normalizes query bounds, so a bound without a timezone means one thing\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"in range\", at: \"2026-06-15T00:00:00.000Z\" });\n\n const found = await store.query(ALICE, { since: \"2026-06-01T00:00:00Z\" });\n expect(summaries(found.episodes)).toEqual([\"in range\"]);\n await expect(store.query(ALICE, { since: \"not a date\" })).rejects.toThrow();\n });\n\n it(\"bounds every caller-controlled size\", async () => {\n await expect(\n store.append(ALICE, { kind: \"note\", summary: \"x\".repeat(100_000) }),\n ).rejects.toThrow();\n await expect(store.append(ALICE, { kind: \"NOT A SLUG\", summary: \"x\" })).rejects.toThrow();\n await expect(store.append(ALICE, { kind: \"note\", summary: \"x\", importance: 42 })).rejects.toThrow();\n await expect(store.query(ALICE, { limit: 10_000_000 })).rejects.toThrow();\n await expect(store.query(ALICE, { limit: 1.5 })).rejects.toThrow();\n });\n\n it(\"rejects content carrying control characters no backend can store alike\", async () => {\n await expect(\n store.append(ALICE, { kind: \"note\", summary: \"before\\u0000after\" }),\n ).rejects.toThrow();\n });\n\n it(\"rejects a lone surrogate no backend can store alike\", async () => {\n // Half a character: `jsonb` refuses it outright, an in-memory store would\n // keep it, and a store that diverges here diverges on what a product can\n // write (spec: well-formed-text). Refused rather than repaired, because a\n // memory write is a tool call and the refusal is data for the model.\n await expect(\n store.append(ALICE, { kind: \"note\", summary: \"before\\ud83dafter\" }),\n ).rejects.toThrow();\n });\n\n it(\"keeps a dedupeKey from ever colliding with a content-derived id\", async () => {\n // dedupeKey used to REPLACE the id material, so anyone who knew a\n // target's (kind, summary, session, turn) could reconstruct it and\n // overwrite that episode.\n const target = await store.append(ALICE, {\n kind: \"clinical\",\n summary: \"severe penicillin allergy\",\n source: { sessionId: \"s1\", turnId: \"t1\" },\n });\n\n const forged = await store.append(ALICE, {\n kind: \"note\",\n summary: \"no known allergies\",\n dedupeKey: JSON.stringify([\"clinical\", \"severe penicillin allergy\", \"s1\", \"t1\"]),\n });\n\n expect(forged.id).not.toBe(target.id);\n expect((await store.get(ALICE, [target.id]))[0]).toMatchObject({\n summary: \"severe penicillin allergy\",\n });\n });\n\n it(\"rejects an invalid scope even on no-op calls\", async () => {\n // Backend neutrality (§6): no adapter may skip central scope validation\n // on early-return paths.\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.append(bad, { kind: \"note\", summary: \"x\" })).rejects.toThrow();\n await expect(store.query(bad, { limit: 0 })).rejects.toThrow();\n await expect(store.get(bad, [])).rejects.toThrow();\n await expect(store.tombstone(bad, { kind: \"episodes\", episodeIds: [] }, T.recent)).rejects.toThrow();\n await expect(store.archive(bad, [])).rejects.toThrow();\n });\n\n it(\"returns defensive copies — mutating a result never corrupts the store\", async () => {\n const ep = await store.append(ALICE, { kind: \"note\", summary: \"original\", at: T.mid });\n\n const first = await store.query(ALICE, {});\n const mutable = first.episodes[0] as { summary: string };\n mutable.summary = \"mutated\";\n\n const [reread] = await store.get(ALICE, [ep.id]);\n expect(reread?.summary).toBe(\"original\");\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type { ProfileFact, ProfileStore, Scope } from \"@alma-harness/core\";\nimport { isCurrentFact } from \"@alma-harness/memory\";\n\n/**\n * Shared `ProfileStore` contract suite — §6, spec 011. Pins the normative\n * rules of spec 010 that no adapter may reinterpret: identity is never\n * extracted, terminal states are create-only, the three-case confidence rule,\n * derived invalidation via provenance, and a budget on every read.\n */\nexport interface ProfileStoreFactory {\n create(): Promise<ProfileStore> | ProfileStore;\n destroy?(store: ProfileStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\n\nconst T = {\n t1: \"2026-06-01T00:00:00.000Z\",\n t2: \"2026-07-01T00:00:00.000Z\",\n t3: \"2026-08-01T00:00:00.000Z\",\n} as const;\n\nfunction byKey(facts: readonly ProfileFact[], key: string): ProfileFact[] {\n return facts.filter((f) => f.key === key);\n}\n\nexport function describeProfileStoreContract(name: string, factory: ProfileStoreFactory): void {\n describe(`ProfileStore contract: ${name}`, () => {\n let store: ProfileStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n it(\"resolves an empty scope to an empty profile\", async () => {\n await expect(store.get(ALICE)).resolves.toMatchObject({ facts: [], truncated: false });\n });\n\n it(\"inserts a first observation as the current fact\", async () => {\n const [result] = await store.observe(ALICE, [\n { key: \"diet.preference\", value: \"vegetarian\", confidence: 0.8, at: T.t1 },\n ]);\n\n expect(result).toMatchObject({ key: \"diet.preference\", outcome: \"inserted\" });\n const { facts } = await store.get(ALICE);\n expect(facts).toHaveLength(1);\n expect(facts[0]).toMatchObject({\n key: \"diet.preference\",\n value: \"vegetarian\",\n confidence: 0.8,\n observedAt: T.t1,\n lastSeenAt: T.t1,\n });\n expect(isCurrentFact(facts[0]!)).toBe(true);\n });\n\n it(\"refreshes a re-observed value instead of versioning it, unioning provenance\", async () => {\n // Spec 010 normative: \"terminal states are create-only — a re-observed\n // fact refreshes lastSeenAt only\".\n await store.observe(ALICE, [\n { key: \"city\", value: \"lisbon\", confidence: 0.6, sourceEpisodeIds: [\"ep-1\"], at: T.t1 },\n ]);\n const [result] = await store.observe(ALICE, [\n { key: \"city\", value: \"lisbon\", confidence: 0.9, sourceEpisodeIds: [\"ep-2\"], at: T.t2 },\n ]);\n\n expect(result?.outcome).toBe(\"refreshed\");\n const { facts } = await store.get(ALICE, { includeHistory: true });\n expect(facts).toHaveLength(1);\n expect(facts[0]).toMatchObject({\n value: \"lisbon\",\n confidence: 0.9, // corroboration raises confidence, never lowers it\n observedAt: T.t1,\n lastSeenAt: T.t2,\n });\n expect([...facts[0]!.sourceEpisodeIds].sort()).toEqual([\"ep-1\", \"ep-2\"]);\n });\n\n it(\"supersedes the current value when a different one arrives at no less confidence\", async () => {\n await store.observe(ALICE, [{ key: \"city\", value: \"lisbon\", confidence: 0.6, at: T.t1 }]);\n const [result] = await store.observe(ALICE, [\n { key: \"city\", value: \"porto\", confidence: 0.7, at: T.t2 },\n ]);\n\n expect(result?.outcome).toBe(\"superseded\");\n const current = await store.get(ALICE);\n expect(current.facts).toHaveLength(1);\n expect(current.facts[0]).toMatchObject({ value: \"porto\" });\n\n const history = await store.get(ALICE, { includeHistory: true });\n const closed = history.facts.find((f) => f.value === \"lisbon\");\n expect(closed).toMatchObject({ supersededAt: T.t2, supersededBy: result?.factId });\n });\n\n it(\"records a lower-confidence contradiction already closed and keeps the current fact\", async () => {\n // The third-case rule (spec 010, third consumer): full history,\n // contradiction handling, and audit in ONE write — no candidate queue.\n await store.observe(ALICE, [{ key: \"city\", value: \"lisbon\", confidence: 0.9, at: T.t1 }]);\n const [result] = await store.observe(ALICE, [\n { key: \"city\", value: \"madrid\", confidence: 0.3, at: T.t2 },\n ]);\n\n expect(result?.outcome).toBe(\"conflict\");\n expect(result?.detail).toBeTruthy();\n\n const current = await store.get(ALICE);\n expect(current.facts).toHaveLength(1);\n expect(current.facts[0]).toMatchObject({ value: \"lisbon\" });\n\n const history = await store.get(ALICE, { includeHistory: true });\n const rejected = history.facts.find((f) => f.value === \"madrid\");\n expect(rejected).toMatchObject({ supersededAt: T.t2 });\n expect(isCurrentFact(rejected!)).toBe(false);\n });\n\n it(\"never resurrects a closed version when an old value returns\", async () => {\n await store.observe(ALICE, [{ key: \"city\", value: \"lisbon\", confidence: 0.5, at: T.t1 }]);\n await store.observe(ALICE, [{ key: \"city\", value: \"porto\", confidence: 0.6, at: T.t2 }]);\n await store.observe(ALICE, [{ key: \"city\", value: \"lisbon\", confidence: 0.7, at: T.t3 }]);\n\n const current = await store.get(ALICE);\n expect(current.facts).toHaveLength(1);\n expect(current.facts[0]).toMatchObject({ value: \"lisbon\", observedAt: T.t3 });\n\n const history = await store.get(ALICE, { includeHistory: true });\n expect(byKey(history.facts, \"city\")).toHaveLength(3);\n const closedLisbon = history.facts.find((f) => f.value === \"lisbon\" && f.observedAt === T.t1);\n expect(closedLisbon?.supersededAt).toBe(T.t2);\n });\n\n it(\"refuses to write a protected profile key through the model path, writing nothing\", async () => {\n // Spec 010 normative, promoted from the identity poisoning incident:\n // identity is NEVER extracted.\n const results = await store.observe(ALICE, [\n { key: \"identity.uid\", value: \"user-bob\", confidence: 1, at: T.t1 },\n { key: \"hobby\", value: \"climbing\", confidence: 0.5, at: T.t1 },\n ]);\n\n expect(results[0]).toMatchObject({ key: \"identity.uid\", outcome: \"refused\" });\n expect(results[0]?.factId).toBeUndefined();\n expect(results[1]?.outcome).toBe(\"inserted\");\n\n const { facts } = await store.get(ALICE, { includeHistory: true });\n expect(byKey(facts, \"identity.uid\")).toEqual([]);\n expect(byKey(facts, \"hobby\")).toHaveLength(1);\n });\n\n it(\"lets the product write protected keys, and lets them outrank a confident extraction\", async () => {\n await store.observe(ALICE, [{ key: \"name\", value: \"wrong\", confidence: 0.99, at: T.t1 }]);\n\n const results = await store.setProtected(ALICE, [\n { key: \"identity.uid\", value: \"user-alice\", at: T.t2 },\n { key: \"name\", value: \"right\", confidence: 0.1, at: T.t2 },\n ]);\n\n expect(results.map((r) => r.outcome)).toEqual([\"inserted\", \"superseded\"]);\n const { facts } = await store.get(ALICE);\n expect(facts.find((f) => f.key === \"identity.uid\")).toMatchObject({ value: \"user-alice\" });\n expect(facts.find((f) => f.key === \"name\")).toMatchObject({ value: \"right\" });\n });\n\n it(\"caps the read at the budget, keeping the most trusted facts\", async () => {\n await store.observe(ALICE, [\n { key: \"a\", value: \"low\", confidence: 0.2, at: T.t1 },\n { key: \"b\", value: \"high\", confidence: 0.9, at: T.t1 },\n { key: \"c\", value: \"mid\", confidence: 0.5, at: T.t1 },\n ]);\n\n const capped = await store.get(ALICE, { budget: { maxItems: 2 } });\n expect(capped.facts.map((f) => f.key)).toEqual([\"b\", \"c\"]);\n expect(capped.truncated).toBe(true);\n\n const uncapped = await store.get(ALICE);\n expect(uncapped.facts).toHaveLength(3);\n expect(uncapped.truncated).toBe(false);\n });\n\n it(\"invalidates every fact whose provenance intersects the erased episodes\", async () => {\n // Derived invalidation via provenance — §6.7, spec 010 AC 4.\n await store.observe(ALICE, [\n { key: \"derived\", value: \"from ep-1\", sourceEpisodeIds: [\"ep-1\"], at: T.t1 },\n { key: \"independent\", value: \"from ep-2\", sourceEpisodeIds: [\"ep-2\"], at: T.t1 },\n ]);\n\n const result = await store.invalidateBySource(ALICE, [\"ep-1\"], T.t3);\n\n expect(result.invalidated).toBe(1);\n const { facts } = await store.get(ALICE);\n expect(facts.map((f) => f.key)).toEqual([\"independent\"]);\n\n // Invalidation blanks key AND value, so the surviving version is found\n // by its state, not by a label it no longer carries.\n const history = await store.get(ALICE, { includeHistory: true });\n const erased = history.facts.filter((f) => f.invalidatedAt !== undefined);\n expect(erased).toHaveLength(1);\n expect(erased[0]).toMatchObject({ key: \"\", value: \"\", invalidatedAt: T.t3 });\n });\n\n it(\"invalidates the whole scope on 'all', without walking provenance\", async () => {\n await store.observe(ALICE, [{ key: \"unsourced\", value: \"no provenance\", at: T.t1 }]);\n await store.observe(BOB, [{ key: \"theirs\", value: \"untouched\", at: T.t1 }]);\n\n const result = await store.invalidateBySource(ALICE, \"all\", T.t3);\n\n expect(result.invalidated).toBe(1);\n await expect(store.get(ALICE)).resolves.toMatchObject({ facts: [] });\n const theirs = await store.get(BOB);\n expect(theirs.facts).toHaveLength(1);\n });\n\n it(\"reports every copy surface it declares, so erasure can be proven\", async () => {\n await store.observe(ALICE, [{ key: \"any\", value: \"thing\", at: T.t1 }]);\n\n const result = await store.invalidateBySource(ALICE, \"all\", T.t3);\n\n expect(store.copySurfaces.length).toBeGreaterThan(0);\n for (const surface of store.copySurfaces) {\n expect(result.surfaces).toContain(surface.name);\n }\n });\n\n it(\"normalizes timestamps to canonical UTC, so backends never disagree\", async () => {\n await store.observe(ALICE, [{ key: \"k\", value: \"v\", at: \"2026-07-01T02:00:00+02:00\" }]);\n\n const { facts } = await store.get(ALICE);\n expect(facts[0]).toMatchObject({\n observedAt: \"2026-07-01T00:00:00.000Z\",\n lastSeenAt: \"2026-07-01T00:00:00.000Z\",\n });\n });\n\n it(\"isolates scopes by uid\", async () => {\n await store.observe(ALICE, [{ key: \"secret\", value: \"alice's\", at: T.t1 }]);\n\n await expect(store.get(BOB)).resolves.toMatchObject({ facts: [] });\n });\n\n it(\"isolates scopes by org, even for the same uid\", async () => {\n // The uid case alone let an org-scoping bug hide behind uid scoping\n // working — the suites pinned only half the tenancy boundary (the\n // 011–013 review).\n await store.observe(ALICE, [{ key: \"secret\", value: \"alice's\", at: T.t1 }]);\n\n await expect(store.get({ org: \"org-b\", uid: ALICE.uid })).resolves.toMatchObject({\n facts: [],\n });\n const result = await store.invalidateBySource({ org: \"org-b\", uid: ALICE.uid }, \"all\", T.t2);\n expect(result.invalidated).toBe(0);\n await expect(store.get(ALICE)).resolves.toMatchObject({\n facts: [expect.objectContaining({ key: \"secret\" })],\n });\n });\n\n it(\"leaves exactly one current version under concurrent observations of one key\", async () => {\n await Promise.all(\n [\"a\", \"b\", \"c\", \"d\", \"e\"].map((value, i) =>\n store.observe(ALICE, [\n { key: \"contended\", value, confidence: 0.5, at: `2026-08-0${i + 1}T00:00:00.000Z` },\n ]),\n ),\n );\n\n const { facts } = await store.get(ALICE);\n expect(byKey(facts, \"contended\")).toHaveLength(1);\n });\n\n it(\"survives concurrent multi-key observations naming the keys in opposite orders\", async () => {\n // Every key lands, from both writers, with one current version each.\n //\n // This is deliberately the OBSERVABLE assertion, not a deadlock probe:\n // an adapter that takes per-key locks lazily in caller order really can\n // deadlock on this shape (Postgres 40P01, reproduced directly), but the\n // window is too short to trigger reliably through the store API, and a\n // test that passes either way would only look like protection. The\n // ordering discipline that avoids it lives in the adapter, with its\n // rationale; this pins what a product is entitled to rely on.\n const keys = [\"k1\", \"k2\", \"k3\", \"k4\", \"k5\", \"k6\", \"k7\", \"k8\"];\n const forward = keys.map((key) => ({ key, value: `${key}-forward`, at: T.t1 }));\n const reverse = [...keys].reverse().map((key) => ({ key, value: `${key}-reverse`, at: T.t2 }));\n\n await Promise.all([store.observe(ALICE, forward), store.observe(ALICE, reverse)]);\n\n const { facts } = await store.get(ALICE);\n expect(facts.map((f) => f.key).sort()).toEqual(keys);\n });\n\n it(\"refuses every spelling of a protected key, not just the canonical one\", async () => {\n // A prefix guard is only as strong as the key charset. Each of these\n // renders indistinguishably from `identity.uid` in a recall block, and\n // each was accepted before keys were constrained to a single spelling.\n for (const key of [\n \"identity.uid\",\n \" identity.uid\",\n \"Identity.uid\",\n \"IDENTITY.uid\",\n \"identity\\u2024uid\", // U+2024 ONE DOT LEADER\n \"\\u0131dentity.uid\", // U+0131 LATIN SMALL LETTER DOTLESS I\n ]) {\n const attempt = store.observe(ALICE, [{ key, value: \"user-bob\", confidence: 1, at: T.t1 }]);\n const written = await attempt.then(\n (results) => results[0]?.outcome === \"refused\" ? false : true,\n () => false, // rejected outright by key validation\n );\n expect(written, `key ${JSON.stringify(key)} must not be writable`).toBe(false);\n }\n\n const { facts } = await store.get(ALICE, { includeHistory: true });\n expect(facts).toEqual([]);\n });\n\n it(\"admits one canonical spelling per key, so no two facts look identical\", async () => {\n // NFC and NFD renderings of the same word produced two current facts\n // under an apparently identical key, with contradictory values.\n await expect(store.observe(ALICE, [{ key: \"pref.caf\\u00e9\", value: \"x\" }])).rejects.toThrow();\n await expect(store.observe(ALICE, [{ key: \"pref.cafe\\u0301\", value: \"x\" }])).rejects.toThrow();\n });\n\n it(\"rejects a confidence outside 0..1, which would pin a fact forever\", async () => {\n // `observe` is the MODEL path. An out-of-range confidence outranks every\n // honest observation, so a single poisoned write could make a false\n // health fact permanent; NaN is worse, since every comparison fails.\n await store.observe(ALICE, [{ key: \"allergy\", value: \"severe\", confidence: 0.9, at: T.t1 }]);\n\n for (const confidence of [999, -1, Number.NaN, Number.POSITIVE_INFINITY]) {\n await expect(\n store.observe(ALICE, [{ key: \"allergy\", value: \"none\", confidence, at: T.t2 }]),\n ).rejects.toThrow();\n }\n\n expect((await store.get(ALICE)).facts[0]).toMatchObject({ value: \"severe\" });\n });\n\n it(\"chains two observations of ONE key inside a single batch\", async () => {\n // The batch writer decides the whole call against one read of the\n // current versions, so a key observed twice must still see the first\n // observation's result — the second closes the version the first\n // inserted, which is why writes go out in rounds (the 011-013 review).\n const results = await store.observe(ALICE, [\n { key: \"city\", value: \"lisbon\", confidence: 0.5, at: T.t1 },\n { key: \"city\", value: \"porto\", confidence: 0.9, at: T.t2 },\n ]);\n\n expect(results.map((r) => r.outcome)).toEqual([\"inserted\", \"superseded\"]);\n const current = await store.get(ALICE);\n expect(byKey(current.facts, \"city\")).toHaveLength(1);\n expect(current.facts[0]).toMatchObject({ value: \"porto\" });\n\n const history = await store.get(ALICE, { includeHistory: true });\n expect(byKey(history.facts, \"city\")).toHaveLength(2);\n expect(history.facts.find((f) => f.value === \"lisbon\")).toMatchObject({\n supersededAt: T.t2,\n supersededBy: results[1]?.factId,\n });\n });\n\n it(\"refreshes inside a single batch the version that batch just inserted\", async () => {\n const results = await store.observe(ALICE, [\n { key: \"diet\", value: \"vegetarian\", confidence: 0.4, at: T.t1 },\n { key: \"diet\", value: \"vegetarian\", confidence: 0.8, at: T.t2 },\n ]);\n\n expect(results.map((r) => r.outcome)).toEqual([\"inserted\", \"refreshed\"]);\n const { facts } = await store.get(ALICE, { includeHistory: true });\n expect(byKey(facts, \"diet\")).toHaveLength(1);\n expect(facts[0]).toMatchObject({\n confidence: 0.8, // corroboration raises it\n observedAt: T.t1,\n lastSeenAt: T.t2,\n });\n });\n\n it(\"applies every outcome a mixed batch calls for, in one pass\", async () => {\n await store.observe(ALICE, [\n { key: \"a\", value: \"keep\", confidence: 0.9, at: T.t1 },\n { key: \"b\", value: \"old\", confidence: 0.3, at: T.t1 },\n { key: \"c\", value: \"strong\", confidence: 0.9, at: T.t1 },\n ]);\n\n const results = await store.observe(ALICE, [\n { key: \"a\", value: \"keep\", confidence: 0.95, at: T.t2 },\n { key: \"b\", value: \"new\", confidence: 0.6, at: T.t2 },\n { key: \"c\", value: \"weak\", confidence: 0.1, at: T.t2 },\n { key: \"d\", value: \"fresh\", confidence: 0.5, at: T.t2 },\n ]);\n\n expect(results.map((r) => r.outcome)).toEqual([\n \"refreshed\",\n \"superseded\",\n \"conflict\",\n \"inserted\",\n ]);\n const { facts } = await store.get(ALICE);\n expect(facts.map((f) => `${f.key}=${f.value}`).sort()).toEqual([\n \"a=keep\",\n \"b=new\",\n \"c=strong\",\n \"d=fresh\",\n ]);\n });\n\n it(\"applies a batch atomically: one invalid observation writes none of them\", async () => {\n await expect(\n store.observe(ALICE, [\n { key: \"good\", value: \"written?\", at: T.t1 },\n { key: \"bad\", value: \"x\", confidence: 42, at: T.t1 },\n ]),\n ).rejects.toThrow();\n\n await expect(store.get(ALICE)).resolves.toMatchObject({ facts: [] });\n });\n\n it(\"reports a replay as a replay, never as a refresh of the current belief\", async () => {\n // Replaying an old observation resolves to a CLOSED version. Calling\n // that `refreshed` told the caller its value was current when another\n // value was.\n await store.observe(ALICE, [{ key: \"city\", value: \"lisbon\", confidence: 0.5, at: T.t1 }]);\n await store.observe(ALICE, [{ key: \"city\", value: \"porto\", confidence: 0.6, at: T.t2 }]);\n\n const [result] = await store.observe(ALICE, [\n { key: \"city\", value: \"lisbon\", confidence: 0.5, at: T.t1 },\n ]);\n\n expect(result?.outcome).toBe(\"replayed\");\n expect((await store.get(ALICE)).facts[0]).toMatchObject({ value: \"porto\" });\n });\n\n it(\"bounds every caller-controlled size\", async () => {\n await expect(\n store.observe(ALICE, [{ key: \"k\", value: \"x\".repeat(100_000) }]),\n ).rejects.toThrow();\n await expect(\n store.observe(\n ALICE,\n Array.from({ length: 5_000 }, (_, i) => ({ key: `k${i}`, value: \"v\" })),\n ),\n ).rejects.toThrow();\n await expect(store.observe(ALICE, [{ key: \"k\", value: \"v\", ttlDays: 0.5 }])).rejects.toThrow();\n await expect(store.observe(ALICE, [{ key: \"k\", value: \"v\", ttlDays: -1 }])).rejects.toThrow();\n });\n\n it(\"accepts a batch whose observations are each within the citation limit\", async () => {\n // The per-observation limit is idsPerCall (1000); a batch of two such\n // observations is legal even though their citations SUM past it. The\n // in-memory reference pooled every citation into one bounded lookup and\n // rejected batches the Postgres adapter — which checks provenance per\n // observation — accepts, so a job tested green against the double\n // crashed against the real backend (the 011–013 review).\n const cite = (prefix: string) => Array.from({ length: 600 }, (_, i) => `${prefix}-${i}`);\n const results = await store.observe(ALICE, [\n { key: \"wide.a\", value: \"v\", sourceEpisodeIds: cite(\"a\") },\n { key: \"wide.b\", value: \"v\", sourceEpisodeIds: cite(\"b\") },\n ]);\n\n expect(results.map((r) => r.outcome)).toEqual([\"inserted\", \"inserted\"]);\n });\n\n it(\"rejects an invalid scope even on no-op calls\", async () => {\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.get(bad)).rejects.toThrow();\n await expect(store.observe(bad, [])).rejects.toThrow();\n await expect(store.setProtected(bad, [])).rejects.toThrow();\n await expect(store.invalidateBySource(bad, [], T.t3)).rejects.toThrow();\n });\n\n it(\"returns defensive copies — mutating a result never corrupts the store\", async () => {\n await store.observe(ALICE, [{ key: \"stable\", value: \"original\", at: T.t1 }]);\n\n const first = await store.get(ALICE);\n (first.facts[0] as { value: string }).value = \"mutated\";\n\n const second = await store.get(ALICE);\n expect(second.facts[0]?.value).toBe(\"original\");\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type {\n AccessEvent,\n EpisodeStore,\n ErasureWatermarkStore,\n MemoryErasure,\n ProfileStore,\n Scope,\n} from \"@alma-harness/core\";\n\n/**\n * Shared `MemoryErasure` contract suite — §6.7, §10, spec 011.\n *\n * The caller supplies the wired implementation (the orchestrator from\n * `@alma-harness/memory` over its own stores) plus the stores themselves, so\n * the suite can arrange data and verify the outcome through the same seams a\n * product would use. This is the LGPD/GDPR story as a test: content gone,\n * derived data invalidated, every declared copy surface reached.\n */\nexport interface MemoryErasureFactory {\n create(): Promise<MemoryErasureFixture> | MemoryErasureFixture;\n destroy?(fixture: MemoryErasureFixture): Promise<void> | void;\n}\n\nexport interface MemoryErasureFixture {\n erasure: MemoryErasure;\n episodes: EpisodeStore;\n profile: ProfileStore;\n watermarks?: ErasureWatermarkStore;\n /** Events the wired `AuditLog` received — the erasure trail (§6.8, §10). */\n accessEvents?: readonly AccessEvent[];\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\n\nexport function describeMemoryErasureContract(name: string, factory: MemoryErasureFactory): void {\n describe(`MemoryErasure contract: ${name}`, () => {\n let fx: MemoryErasureFixture;\n\n beforeEach(async () => {\n fx = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(fx);\n });\n\n /** An episode plus a profile fact that cites it — the provenance chain. */\n async function seedSupportedFact(scope: Scope, sessionId: string, marker: string) {\n const episode = await fx.episodes.append(scope, {\n kind: \"conversation\",\n summary: `${marker} disclosed something sensitive`,\n source: { sessionId },\n });\n await fx.profile.observe(scope, [\n { key: `derived.${marker}`, value: marker, sourceEpisodeIds: [episode.id] },\n ]);\n return episode;\n }\n\n it(\"erases an episode: content blanked, out of recall, and its derived facts invalidated\", async () => {\n // Spec 010 AC 4 — the whole chain in one assertion block, because\n // deleting \"just the doc\" lies (§6.7).\n const doomed = await seedSupportedFact(ALICE, \"s1\", \"doomed\");\n const kept = await seedSupportedFact(ALICE, \"s2\", \"kept\");\n\n const report = await fx.erasure.erase(ALICE, {\n kind: \"episodes\",\n episodeIds: [doomed.id],\n });\n\n expect(report.tombstonesWritten).toBe(1);\n expect(report.derivedInvalidated).toBe(1);\n expect(report.complete).toBe(true);\n\n const [tombstone] = await fx.episodes.get(ALICE, [doomed.id]);\n expect(tombstone).toMatchObject({ summary: \"\", state: \"tombstoned\", erasedAt: report.erasedAt });\n\n await expect(fx.episodes.query(ALICE, { text: \"doomed\" })).resolves.toMatchObject({\n episodes: [],\n });\n\n const { facts } = await fx.profile.get(ALICE);\n expect(facts.map((f) => f.key)).toEqual([\"derived.kept\"]);\n expect((await fx.episodes.get(ALICE, [kept.id]))[0]).toMatchObject({ state: \"active\" });\n });\n\n it(\"erases a session's episodes and nothing outside it\", async () => {\n const doomed = await seedSupportedFact(ALICE, \"doomed-session\", \"alpha\");\n const kept = await seedSupportedFact(ALICE, \"kept-session\", \"beta\");\n\n const report = await fx.erasure.erase(ALICE, {\n kind: \"sessions\",\n sessionIds: [\"doomed-session\"],\n });\n\n expect(report.tombstonesWritten).toBe(1);\n expect((await fx.episodes.get(ALICE, [doomed.id]))[0]).toMatchObject({ state: \"tombstoned\" });\n expect((await fx.episodes.get(ALICE, [kept.id]))[0]).toMatchObject({ state: \"active\" });\n expect((await fx.profile.get(ALICE)).facts.map((f) => f.key)).toEqual([\"derived.beta\"]);\n });\n\n it(\"erases the whole scope, invalidating even facts with no provenance link\", async () => {\n await seedSupportedFact(ALICE, \"s1\", \"sourced\");\n await fx.profile.observe(ALICE, [{ key: \"unsourced\", value: \"orphan fact\" }]);\n const theirs = await seedSupportedFact(BOB, \"s1\", \"theirs\");\n\n const report = await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n expect(report.derivedInvalidated).toBe(2);\n await expect(fx.profile.get(ALICE)).resolves.toMatchObject({ facts: [] });\n await expect(fx.episodes.query(ALICE, {})).resolves.toMatchObject({ episodes: [] });\n\n // Erasure is scoped: another user's memory is untouched.\n expect((await fx.episodes.get(BOB, [theirs.id]))[0]).toMatchObject({ state: \"active\" });\n expect((await fx.profile.get(BOB)).facts).toHaveLength(1);\n });\n\n it(\"names every copy surface both stores declare, and reports the erasure complete\", async () => {\n // Spec 010: adapters must DECLARE their copy surfaces so erase()\n // provably reaches all of them — \"provenance columns without a written\n // delete are not erasure\".\n await seedSupportedFact(ALICE, \"s1\", \"gamma\");\n\n const report = await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n const declared = [...fx.episodes.copySurfaces, ...fx.profile.copySurfaces];\n expect(declared.length).toBeGreaterThan(0);\n for (const surface of declared) {\n expect(report.surfaces).toContainEqual({\n name: surface.name,\n kind: surface.kind,\n reached: true,\n });\n }\n expect(report.complete).toBe(true);\n });\n\n it(\"stamps the scope's erasure watermark for the in-flight job guard\", async () => {\n // Spec 010: a batch result submitted before an erasure timestamp is\n // discarded — one timestamp comparison. Slice 013 does the comparing;\n // this tier owes it a durable, scoped timestamp.\n if (!fx.watermarks) return;\n await expect(fx.watermarks.get(ALICE)).resolves.toBeNull();\n\n const report = await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n await expect(fx.watermarks.get(ALICE)).resolves.toBe(report.erasedAt);\n await expect(fx.watermarks.get(BOB)).resolves.toBeNull();\n });\n\n it(\"stops at the ORG boundary: erasing a uid in one org never touches its twin elsewhere\", async () => {\n // The suites pinned uid isolation but not org isolation — half the\n // tenancy boundary (the 011–013 review).\n const TWIN: Scope = { org: \"org-b\", uid: ALICE.uid };\n await seedSupportedFact(ALICE, \"s1\", \"mine\");\n const twin = await seedSupportedFact(TWIN, \"s1\", \"twin\");\n\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n expect((await fx.episodes.get(TWIN, [twin.id]))[0]).toMatchObject({ state: \"active\" });\n expect((await fx.profile.get(TWIN)).facts).toHaveLength(1);\n if (fx.watermarks) await expect(fx.watermarks.get(TWIN)).resolves.toBeNull();\n });\n\n it(\"never moves the watermark backwards, whatever clock stamps the second erasure\", async () => {\n // Two servers, one lagging clock: erasure B stamped 10s earlier than\n // erasure A must not LOWER the watermark — that re-admitted in-flight\n // writes A's guard had already refused as stale (the 011–013 review).\n if (!fx.watermarks) return;\n await fx.watermarks.set(ALICE, \"2026-06-01T00:00:10.000Z\");\n await fx.watermarks.set(ALICE, \"2026-06-01T00:00:00.000Z\");\n\n await expect(fx.watermarks.get(ALICE)).resolves.toBe(\"2026-06-01T00:00:10.000Z\");\n });\n\n it(\"removes the CONTENT of every derived fact, not just its current flag\", async () => {\n // The failure this contract exists to catch: an invalidation that only\n // set a flag left the fact's value — content propagated upward from the\n // episode — readable through the export surface below, while the report\n // said the erasure was complete.\n const ep = await seedSupportedFact(ALICE, \"s1\", \"diagnosis\");\n\n await fx.erasure.erase(ALICE, { kind: \"episodes\", episodeIds: [ep.id] });\n\n const history = await fx.profile.get(ALICE, { includeHistory: true });\n expect(history.facts).toHaveLength(1);\n // The KEY goes too: keys are model-chosen, so a surviving\n // `health.hiv_status` would disclose the nature of what was erased on\n // the very surface a data subject is handed. What proves the erasure ran\n // is the audit trail, not a label left behind in the data.\n expect(history.facts[0]).toMatchObject({ key: \"\", value: \"\" });\n expect(JSON.stringify(history.facts[0])).not.toContain(\"diagnosis\");\n });\n\n it(\"leaves no label behind on a tombstoned episode either\", async () => {\n const ep = await fx.episodes.append(ALICE, {\n kind: \"clinical\",\n summary: \"disclosed something sensitive\",\n });\n\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n const [tombstone] = await fx.episodes.get(ALICE, [ep.id]);\n expect(tombstone).toMatchObject({ kind: \"\", summary: \"\", state: \"tombstoned\" });\n });\n\n it(\"discloses nothing about WHEN the erased data was last touched\", async () => {\n // Same standard episodes already meet: an erased memory must not leak\n // its own existence and timing.\n await fx.profile.observe(ALICE, [\n { key: \"sensitive\", value: \"content\", at: \"2026-06-01T00:00:00.000Z\" },\n ]);\n\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n const profile = await fx.profile.get(ALICE);\n expect(profile.facts).toEqual([]);\n expect(profile.updatedAt).not.toContain(\"2026-06-01\");\n });\n\n it(\"invalidates derived facts on a RE-RUN, so a half-failed erasure self-heals\", async () => {\n // The crash-recovery hole: if the tombstone pass commits and the\n // invalidation pass does not, the retry must still reach the profile\n // tier. Simulated by invalidating nothing on the first pass.\n const ep = await seedSupportedFact(ALICE, \"s1\", \"epsilon\");\n await fx.episodes.tombstone(ALICE, { kind: \"episodes\", episodeIds: [ep.id] }, new Date().toISOString());\n\n const recovery = await fx.erasure.erase(ALICE, { kind: \"episodes\", episodeIds: [ep.id] });\n\n expect(recovery.tombstonesWritten).toBe(0); // already blanked by the partial run\n expect(recovery.derivedInvalidated).toBe(1); // but the derived tier is reached\n await expect(fx.profile.get(ALICE)).resolves.toMatchObject({ facts: [] });\n });\n\n it(\"refuses an observation submitted from before the erasure\", async () => {\n // In-flight protection: work that started before an erasure must never\n // re-materialize what the erasure removed.\n if (!fx.watermarks) return;\n const before = new Date(Date.now() - 60_000).toISOString();\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n const [result] = await fx.profile.observe(ALICE, [\n { key: \"resurrected\", value: \"erased content\", at: before },\n ]);\n\n expect(result?.outcome).toBe(\"stale\");\n await expect(fx.profile.get(ALICE)).resolves.toMatchObject({ facts: [] });\n });\n\n it(\"refuses a write that cites an episode this erasure removed\", async () => {\n // Backend-neutral because the timestamp guard is not enough: `at`\n // defaults to write time, so an in-flight job that omits it — the\n // documented default — is never stale by the clock. Provenance is the\n // guard that does not depend on the caller (spec 013 review).\n const ep = await fx.episodes.append(ALICE, { kind: \"clinical\", summary: \"disclosed\" });\n\n await fx.erasure.erase(ALICE, { kind: \"episodes\", episodeIds: [ep.id] });\n\n const [result] = await fx.profile.observe(ALICE, [\n // No `at` — \"now\", which the watermark comparison would wave through.\n { key: \"health.status\", value: \"positive\", sourceEpisodeIds: [ep.id] },\n ]);\n\n expect(result?.outcome).toBe(\"stale\");\n await expect(fx.profile.get(ALICE)).resolves.toMatchObject({ facts: [] });\n });\n\n it(\"refuses an episode stamped before the erasure, not only a fact\", async () => {\n // The episode tier was outside the guard entirely: an extraction in\n // flight during an erasure inserted a new derived id after the tombstone\n // pass, and the user's verbatim summary survived a `complete: true`.\n if (!fx.watermarks) return;\n const before = new Date(Date.now() - 60_000).toISOString();\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n await expect(\n fx.episodes.append(ALICE, { kind: \"note\", summary: \"in flight\", at: before }),\n ).rejects.toThrow();\n });\n\n it(\"records a trail even when the erasure fails partway\", async () => {\n // Erasure destroys content across several transactions, and §6.8/§10\n // make the trail the proof a request was honored — a run cancelled\n // between them used to leave content gone and no durable evidence.\n if (!fx.accessEvents) return;\n const before = fx.accessEvents.length;\n\n await expect(\n fx.erasure.erase(ALICE, {\n kind: \"episodes\",\n episodeIds: Array.from({ length: 5_000 }, (_, i) => `id-${i}`),\n }),\n ).rejects.toThrow();\n\n // Rejected before anything was stamped or destroyed, so no trail is due.\n expect(fx.accessEvents.length).toBe(before);\n if (fx.watermarks) await expect(fx.watermarks.get(ALICE)).resolves.toBeNull();\n });\n\n it(\"leaves an audit trail proving the erasure ran, carrying no content\", async () => {\n // §6.8/§10: the watermark is overwritten by the next erasure, so without\n // a trail there is no durable evidence a data-subject request was met.\n if (!fx.accessEvents) return;\n await seedSupportedFact(ALICE, \"s1\", \"zeta\");\n\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n const erasures = fx.accessEvents.filter((e) => e.action === \"delete\");\n expect(erasures).toHaveLength(1);\n expect(erasures[0]).toMatchObject({ scope: ALICE, action: \"delete\" });\n expect(JSON.stringify(erasures[0])).not.toContain(\"zeta\");\n });\n\n it(\"is idempotent: erasing twice writes no second tombstone\", async () => {\n const ep = await seedSupportedFact(ALICE, \"s1\", \"delta\");\n\n await fx.erasure.erase(ALICE, { kind: \"episodes\", episodeIds: [ep.id] });\n const second = await fx.erasure.erase(ALICE, { kind: \"episodes\", episodeIds: [ep.id] });\n\n expect(second.tombstonesWritten).toBe(0);\n expect(second.derivedInvalidated).toBe(0);\n });\n\n it(\"rejects an invalid scope\", async () => {\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(fx.erasure.erase(bad, { kind: \"all\" })).rejects.toThrow();\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type { Scope, SpendStore } from \"@alma-harness/core\";\n\n/**\n * Shared `SpendStore` contract suite — spec: spend-store. Pins what budget\n * enforcement is entitled to rely on, on any backend: atomic\n * increment-and-return, UTC day bucketing, session isolation by full scope,\n * org-wide day aggregation, and no lost increments under concurrency.\n *\n * Deliberately absent: any erasure surface. Spend counters are content-free\n * aggregates retained through scoped purge (spec: spend-store) — a store that\n * grows one is offering a budget reset, not a feature.\n *\n * ```ts\n * describeSpendStoreContract(\"PostgresSpendStore\", { create: () => … });\n * ```\n */\nexport interface SpendStoreFactory {\n /** Must return a store with ZERO totals for the scopes used by the suite. */\n create(): Promise<SpendStore> | SpendStore;\n destroy?(store: SpendStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\nconst OTHER_ORG: Scope = { org: \"org-b\", uid: \"user-alice\" };\n\n/** Pinned instants around one UTC midnight keep bucketing deterministic. */\nconst T = {\n day1: \"2026-08-24T10:00:00.000Z\",\n day1Late: \"2026-08-24T23:59:59.000Z\",\n day2: \"2026-08-25T00:00:00.000Z\",\n /** 01:00+02:00 on the 25th IS 23:00Z on the 24th. */\n day1ByOffset: \"2026-08-25T01:00:00+02:00\",\n} as const;\n\nexport function describeSpendStoreContract(name: string, factory: SpendStoreFactory): void {\n describe(`SpendStore contract: ${name}`, () => {\n let store: SpendStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n it(\"starts every counter at zero\", async () => {\n await expect(store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 })).resolves.toEqual({\n sessionUsd: 0,\n tenantDayUsd: 0,\n });\n });\n\n it(\"add returns the post-add totals and accumulates both counters\", async () => {\n const first = await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 0.5 });\n expect(first.sessionUsd).toBeCloseTo(0.5, 9);\n expect(first.tenantDayUsd).toBeCloseTo(0.5, 9);\n\n const second = await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 0.25 });\n expect(second.sessionUsd).toBeCloseTo(0.75, 9);\n expect(second.tenantDayUsd).toBeCloseTo(0.75, 9);\n\n const peeked = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n expect(peeked.sessionUsd).toBeCloseTo(0.75, 9);\n expect(peeked.tenantDayUsd).toBeCloseTo(0.75, 9);\n });\n\n it(\"isolates the session counter by sessionId, uid, and org — while the day counter aggregates the org\", async () => {\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 1 });\n await store.add({ scope: ALICE, sessionId: \"s2\", at: T.day1, usd: 2 });\n await store.add({ scope: BOB, sessionId: \"s1\", at: T.day1, usd: 4 });\n await store.add({ scope: OTHER_ORG, sessionId: \"s1\", at: T.day1, usd: 8 });\n\n const aliceS1 = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n // Same sessionId as BOB's and OTHER_ORG's — the full scope keys it.\n expect(aliceS1.sessionUsd).toBeCloseTo(1, 9);\n // The org's day: alice s1 + alice s2 + bob s1, across uids and sessions.\n expect(aliceS1.tenantDayUsd).toBeCloseTo(7, 9);\n\n const otherOrg = await store.peek({ scope: OTHER_ORG, sessionId: \"s1\", at: T.day1 });\n expect(otherOrg.sessionUsd).toBeCloseTo(8, 9);\n expect(otherOrg.tenantDayUsd).toBeCloseTo(8, 9);\n });\n\n it(\"buckets the day counter by UTC calendar day — the session counter has no day dimension\", async () => {\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 1 });\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1Late, usd: 2 });\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day2, usd: 4 });\n\n const onDay1 = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n expect(onDay1.tenantDayUsd).toBeCloseTo(3, 9); // day2's spend not here\n expect(onDay1.sessionUsd).toBeCloseTo(7, 9); // the session spans days\n\n const onDay2 = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day2 });\n expect(onDay2.tenantDayUsd).toBeCloseTo(4, 9); // the kill-switch resets at UTC midnight\n expect(onDay2.sessionUsd).toBeCloseTo(7, 9);\n });\n\n it(\"derives the day from the UTC instant, never from the timestamp's local offset\", async () => {\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1ByOffset, usd: 1 });\n\n const day1 = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n expect(day1.tenantDayUsd).toBeCloseTo(1, 9); // 01:00+02:00 on the 25th is the 24th in UTC\n const day2 = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day2 });\n expect(day2.tenantDayUsd).toBe(0);\n });\n\n it(\"accumulates fractional-cent amounts without rounding them away\", async () => {\n // A single step costs fractions of a cent; a backend column rounding to\n // cents would zero every real charge.\n for (let i = 0; i < 3; i++) {\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 0.000002 });\n }\n\n const totals = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n expect(totals.sessionUsd).toBeCloseTo(0.000006, 9);\n });\n\n it(\"loses no increment under concurrent adds, and every returned total is a distinct running sum\", async () => {\n // Increment-and-return must be ATOMIC: two turns reading a stale total\n // and both proceeding is exactly the race the guard cannot fix from\n // outside the store (spec: spend-store).\n const results = await Promise.all(\n Array.from({ length: 20 }, () =>\n store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 0.01 }),\n ),\n );\n\n const totals = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n expect(totals.sessionUsd).toBeCloseTo(0.2, 9);\n expect(totals.tenantDayUsd).toBeCloseTo(0.2, 9);\n const distinct = new Set(results.map((r) => r.sessionUsd.toFixed(8)));\n expect(distinct.size).toBe(20); // no two adds observed the same total\n });\n\n it(\"rejects a negative or non-finite spend, which would poison both counters\", async () => {\n // x + NaN = NaN, forever — and there is deliberately no delete surface\n // to reset a poisoned counter with.\n for (const usd of [-1, Number.NaN, Number.POSITIVE_INFINITY]) {\n await expect(\n store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd }),\n ).rejects.toThrow();\n }\n await expect(store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 })).resolves.toEqual({\n sessionUsd: 0,\n tenantDayUsd: 0,\n });\n });\n\n it(\"buckets an offset-less timestamp identically on every backend — by the process clock, never the server's\", async () => {\n // JS reads an offset-less date-time as process-local; a backend that\n // let its OWN server interpret the string could put the same charge on\n // a different day than the reference store (the bug the episode tier\n // fixed once already).\n const local = \"2026-08-24T12:00:00\"; // no offset\n const day = new Date(Date.parse(local)).toISOString().slice(0, 10);\n await store.add({ scope: ALICE, sessionId: \"s1\", at: local, usd: 1 });\n\n const totals = await store.peek({\n scope: ALICE,\n sessionId: \"s1\",\n at: `${day}T12:00:00.000Z`,\n });\n expect(totals.tenantDayUsd).toBeCloseTo(1, 9);\n });\n\n it(\"rejects an invalid scope even on reads\", async () => {\n // Backend neutrality (§6): no adapter may skip central scope validation.\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.add({ scope: bad, sessionId: \"s1\", at: T.day1, usd: 1 })).rejects.toThrow();\n await expect(store.peek({ scope: bad, sessionId: \"s1\", at: T.day1 })).rejects.toThrow();\n });\n\n it(\"rejects an unparseable timestamp instead of inventing a bucket\", async () => {\n await expect(\n store.add({ scope: ALICE, sessionId: \"s1\", at: \"not a date\", usd: 1 }),\n ).rejects.toThrow();\n await expect(store.peek({ scope: ALICE, sessionId: \"s1\", at: \"not a date\" })).rejects.toThrow();\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type { CompletedTurn, Scope, TurnStore } from \"@alma-harness/core\";\n\n/**\n * Shared `TurnStore` contract suite — spec 030. Pins what the loop's turn\n * coordination is entitled to rely on, on any backend: exactly one winner per\n * session, a lease that expires so a crashed holder never blocks forever, a\n * stale release that touches nothing, a claim that replays a finished turn,\n * and erasure that reaches the stored reply.\n *\n * Timing is exercised with REAL time and small TTLs, deliberately. A fake\n * clock cannot reach a Postgres `now()`, and one that desynchronizes from the\n * `setTimeout` a wait is built on makes the reference store and the adapter\n * prove different things.\n *\n * ```ts\n * describeTurnStoreContract(\"PostgresTurnStore\", { create: () => … });\n * ```\n */\nexport interface TurnStoreFactory {\n /** Must return a store holding NO leases or claims for the scopes below. */\n create(): Promise<TurnStore> | TurnStore;\n destroy?(store: TurnStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\nconst OTHER_ORG: Scope = { org: \"org-b\", uid: \"user-alice\" };\n\nconst NEVER_EXPIRES = { ttlMs: 60_000, waitMs: 0 } as const;\n\nfunction completedTurn(over: Partial<CompletedTurn> = {}): CompletedTurn {\n return {\n reply: { role: \"assistant\", blocks: [{ type: \"text\", text: \"the reply\" }] },\n terminalReason: \"completed\",\n stopReason: \"end_turn\",\n usage: { inputTokens: 10, outputTokens: 5 },\n costUsd: 0.00003,\n steps: 2,\n durationMs: 1234,\n turnId: \"turn-1\",\n at: \"2026-08-26T10:00:00.000Z\",\n ...over,\n };\n}\n\nconst key = (scope: Scope, sessionId: string, idempotencyKey: string) => ({\n scope,\n sessionId,\n idempotencyKey,\n});\n\nexport function describeTurnStoreContract(name: string, factory: TurnStoreFactory): void {\n describe(`TurnStore contract: ${name}`, () => {\n let store: TurnStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n // ---- The lease -------------------------------------------------------\n\n it(\"hands a free session to the caller, and refuses a held one once the wait expires\", async () => {\n const held = await store.acquire(ALICE, \"s1\", NEVER_EXPIRES);\n expect(held).not.toBeNull();\n\n // waitMs 0 is the fail-fast expression of the same call.\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.toBeNull();\n });\n\n it(\"picks exactly ONE winner among concurrent acquirers\", async () => {\n // The property the whole seam stands on: a lease handed to two holders\n // serializes nothing, and every other guarantee here rests on this one.\n const results = await Promise.all(\n Array.from({ length: 10 }, () => store.acquire(ALICE, \"s1\", NEVER_EXPIRES)),\n );\n\n expect(results.filter((r) => r !== null)).toHaveLength(1);\n });\n\n it(\"isolates leases by session, uid, and org\", async () => {\n await store.acquire(ALICE, \"s1\", NEVER_EXPIRES);\n\n // Same sessionId under a different uid and a different org, plus a\n // different session under the same uid — none of them is taken.\n for (const [scope, sessionId] of [\n [ALICE, \"s2\"],\n [BOB, \"s1\"],\n [OTHER_ORG, \"s1\"],\n ] as const) {\n await expect(store.acquire(scope, sessionId, NEVER_EXPIRES)).resolves.not.toBeNull();\n }\n });\n\n it(\"frees the session on release, so the next caller gets it\", async () => {\n const lease = (await store.acquire(ALICE, \"s1\", NEVER_EXPIRES))!;\n await store.release(ALICE, \"s1\", lease);\n\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.not.toBeNull();\n });\n\n it(\"ignores a STALE release instead of freeing the current holder's session\", async () => {\n // The failure this prevents: a holder whose lease expired releases the\n // lease the NEXT turn is holding, and the session serializes nothing\n // while appearing to.\n const stale = (await store.acquire(ALICE, \"s1\", { ttlMs: 20, waitMs: 0 }))!;\n await new Promise((r) => setTimeout(r, 60));\n const current = (await store.acquire(ALICE, \"s1\", { ttlMs: 60_000, waitMs: 200 }))!;\n expect(current.token).not.toBe(stale.token);\n\n await store.release(ALICE, \"s1\", stale);\n\n // Still held by `current`.\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.toBeNull();\n await store.release(ALICE, \"s1\", current);\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.not.toBeNull();\n });\n\n it(\"lets a later caller take a lease whose TTL expired — a crashed holder never blocks a session forever\", async () => {\n await store.acquire(ALICE, \"s1\", { ttlMs: 20, waitMs: 0 }); // never released\n await new Promise((r) => setTimeout(r, 60));\n\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.not.toBeNull();\n });\n\n it(\"WAITS for a busy session and takes it when the holder releases inside the window\", async () => {\n const lease = (await store.acquire(ALICE, \"s1\", { ttlMs: 60_000, waitMs: 0 }))!;\n const waiting = store.acquire(ALICE, \"s1\", { ttlMs: 60_000, waitMs: 2_000 });\n // Released well inside the wait; the waiter must get it rather than\n // burning its whole window.\n setTimeout(() => void store.release(ALICE, \"s1\", lease), 30);\n\n await expect(waiting).resolves.not.toBeNull();\n });\n\n it(\"releases idempotently — a second release is not another holder's release\", async () => {\n const lease = (await store.acquire(ALICE, \"s1\", NEVER_EXPIRES))!;\n await store.release(ALICE, \"s1\", lease);\n const next = (await store.acquire(ALICE, \"s1\", NEVER_EXPIRES))!;\n\n await store.release(ALICE, \"s1\", lease); // the first holder, again\n\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.toBeNull();\n await store.release(ALICE, \"s1\", next);\n });\n\n // ---- The claim -------------------------------------------------------\n\n it(\"reports a first claim fresh, and replays it once completed\", async () => {\n const k = key(ALICE, \"s1\", \"wamid-1\");\n await expect(store.claim(k)).resolves.toEqual({ status: \"fresh\" });\n\n const completed = completedTurn();\n await store.complete(k, completed);\n\n const claim = await store.claim(k);\n expect(claim.status).toBe(\"replay\");\n expect(claim.status === \"replay\" && claim.completed).toEqual(completed);\n });\n\n it(\"replays a FAILED turn as faithfully as a successful one\", async () => {\n // A failed turn is a RESULT. Replaying it is what stops a retry from\n // re-running and re-charging.\n const k = key(ALICE, \"s1\", \"wamid-err\");\n await store.claim(k);\n const completed = completedTurn({\n terminalReason: \"error\",\n stopReason: null,\n reply: { role: \"assistant\", blocks: [] },\n });\n await store.complete(k, completed);\n\n const claim = await store.claim(k);\n expect(claim.status === \"replay\" && claim.completed).toEqual(completed);\n });\n\n it(\"reports an IN-FLIGHT claim fresh — a crashed turn must be runnable again\", async () => {\n // Only reachable after a crash: the lease makes concurrency impossible.\n // The turn produced no result, so there is nothing to replay and\n // re-running is the correct answer (spec 030's named crash window).\n const k = key(ALICE, \"s1\", \"wamid-crash\");\n await store.claim(k);\n\n await expect(store.claim(k)).resolves.toEqual({ status: \"fresh\" });\n });\n\n it(\"refuses a malformed reply identically on every adapter\", async () => {\n // Spec 040, the sibling of `SessionStore.append`'s case and the reason\n // that slice fixed the CLASS: the same divergence was documented in two\n // contracts and closed in neither. The loop repairs before it gets here,\n // but best-effort — its catch keeps the unrepaired message.\n const k = key(ALICE, \"s1\", \"wamid-malformed\");\n await store.claim(k);\n\n await expect(\n store.complete(k, completedTurn({\n reply: { role: \"assistant\", blocks: [{ type: \"text\", text: `bad \\ud83d end` }] },\n })),\n ).rejects.toThrow(/completed/);\n // The claim is untouched: a refused write leaves the turn re-runnable\n // rather than half-recorded.\n await expect(store.claim(k)).resolves.toEqual({ status: \"fresh\" });\n });\n\n it(\"refuses a malformed reply even for a claim that no longer exists\", async () => {\n // The ordering that keeps the two adapters honest: Postgres parses\n // `$5::jsonb` whether or not the UPDATE matches a row, so the guard runs\n // before the update-only test in the in-memory reference too. Checking\n // after it would have closed one divergence by opening another.\n const k = key(ALICE, \"s-erased\", \"wamid-gone\");\n await store.claim(k);\n await store.erase(ALICE, \"s-erased\");\n\n await expect(\n store.complete(k, completedTurn({\n reply: { role: \"assistant\", blocks: [{ type: \"text\", text: `bad \\ud83d end` }] },\n })),\n ).rejects.toThrow(/completed/);\n });\n\n it(\"makes a claim runnable again after abandon\", async () => {\n const k = key(ALICE, \"s1\", \"wamid-2\");\n await store.claim(k);\n await store.complete(k, completedTurn());\n await store.abandon(k);\n\n await expect(store.claim(k)).resolves.toEqual({ status: \"fresh\" });\n });\n\n it(\"isolates claims by key, session, uid, and org\", async () => {\n const k = key(ALICE, \"s1\", \"shared-key\");\n await store.claim(k);\n await store.complete(k, completedTurn());\n\n // The same idempotency key is only unique within the transport that\n // issued it; a global key space would let one tenant's retry collide\n // with another's.\n for (const other of [\n key(ALICE, \"s1\", \"different-key\"),\n key(ALICE, \"s2\", \"shared-key\"),\n key(BOB, \"s1\", \"shared-key\"),\n key(OTHER_ORG, \"s1\", \"shared-key\"),\n ]) {\n await expect(store.claim(other)).resolves.toEqual({ status: \"fresh\" });\n }\n });\n\n it(\"round-trips a reply with astral characters intact\", async () => {\n // The reply is stored verbatim and read back into a model request; a\n // backend that mangles surrogate pairs would corrupt it (spec 025).\n const k = key(ALICE, \"s1\", \"wamid-emoji\");\n await store.claim(k);\n const completed = completedTurn({\n reply: { role: \"assistant\", blocks: [{ type: \"text\", text: \"até logo 👋🏽 家\" }] },\n });\n await store.complete(k, completed);\n\n const claim = await store.claim(k);\n expect(claim.status === \"replay\" && claim.completed.reply).toEqual(completed.reply);\n });\n\n it(\"does not resurrect a claim erased while its turn was still running\", async () => {\n // Erasure wins over work that started before it — the rule the memory\n // tier spells out as the `stale` observe outcome (spec 011). A\n // `complete` that re-created the row would put the erased reply back.\n const k = key(ALICE, \"s1\", \"wamid-erased\");\n await store.claim(k);\n await store.erase(ALICE, \"s1\");\n\n await store.complete(k, completedTurn());\n\n await expect(store.claim(k)).resolves.toEqual({ status: \"fresh\" });\n });\n\n // ---- Erasure (§10) ---------------------------------------------------\n\n it(\"erases one session's claims and lease, leaving its siblings alone\", async () => {\n const target = key(ALICE, \"s1\", \"wamid-3\");\n const sibling = key(ALICE, \"s2\", \"wamid-3\");\n for (const k of [target, sibling]) {\n await store.claim(k);\n await store.complete(k, completedTurn());\n }\n await store.acquire(ALICE, \"s1\", NEVER_EXPIRES);\n\n await store.erase(ALICE, \"s1\");\n\n // The stored reply is gone — the record holds content, so §10 must reach it.\n await expect(store.claim(target)).resolves.toEqual({ status: \"fresh\" });\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.not.toBeNull();\n const siblingClaim = await store.claim(sibling);\n expect(siblingClaim.status).toBe(\"replay\");\n });\n\n it(\"erases ONLY the named session, even when a sibling's id extends it\", async () => {\n // `sessionId` is not validated and never should be — a product using a\n // composite id (`\"platform/thread\"`, a migration's `\"s1/legacy\"`) is\n // making a reasonable choice. The reference store keyed claims as one\n // flat `scope/session/key` string and erased by prefix, so erasing `\"s1\"`\n // deleted `\"s1/legacy\"`'s stored reply; Postgres compares `session_id` by\n // SQL equality and was immune. The two adapters DIVERGED on erasure,\n // which is the one thing this suite exists to prevent — and the\n // sibling-session case above missed it because neither `\"s1\"` nor `\"s2\"`\n // is a prefix of the other (spec 033).\n const target = key(ALICE, \"s1\", \"wamid-5\");\n const extended = key(ALICE, \"s1/legacy\", \"wamid-5\");\n for (const k of [target, extended]) {\n await store.claim(k);\n await store.complete(k, completedTurn());\n }\n\n await store.erase(ALICE, \"s1\");\n\n await expect(store.claim(target)).resolves.toEqual({ status: \"fresh\" });\n const survivor = await store.claim(extended);\n expect(survivor.status).toBe(\"replay\");\n });\n\n it(\"erases every session in a scope without a sessionId, and stops at the scope boundary\", async () => {\n for (const [scope, sessionId] of [\n [ALICE, \"s1\"],\n [ALICE, \"s2\"],\n [BOB, \"s1\"],\n [OTHER_ORG, \"s1\"],\n ] as const) {\n const k = key(scope, sessionId, \"wamid-4\");\n await store.claim(k);\n await store.complete(k, completedTurn());\n }\n\n await store.erase(ALICE);\n\n await expect(store.claim(key(ALICE, \"s1\", \"wamid-4\"))).resolves.toEqual({ status: \"fresh\" });\n await expect(store.claim(key(ALICE, \"s2\", \"wamid-4\"))).resolves.toEqual({ status: \"fresh\" });\n for (const scope of [BOB, OTHER_ORG]) {\n const claim = await store.claim(key(scope, \"s1\", \"wamid-4\"));\n expect(claim.status).toBe(\"replay\");\n }\n });\n\n // ---- Scope validation ------------------------------------------------\n\n it(\"rejects an invalid scope on every surface\", async () => {\n // Backend neutrality (§6): no adapter may skip central scope validation.\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.acquire(bad, \"s1\", NEVER_EXPIRES)).rejects.toThrow();\n await expect(store.claim(key(bad, \"s1\", \"k\"))).rejects.toThrow();\n await expect(store.complete(key(bad, \"s1\", \"k\"), completedTurn())).rejects.toThrow();\n await expect(store.abandon(key(bad, \"s1\", \"k\"))).rejects.toThrow();\n await expect(store.erase(bad)).rejects.toThrow();\n });\n\n it(\"rejects a non-finite or negative lease duration instead of holding forever\", async () => {\n // A NaN ttl makes every expiry comparison false, so the lease reads as\n // live forever and the session is blocked until the process restarts.\n for (const opts of [\n { ttlMs: Number.NaN, waitMs: 0 },\n { ttlMs: -1, waitMs: 0 },\n { ttlMs: 1_000, waitMs: Number.NaN },\n ]) {\n await expect(store.acquire(ALICE, \"s1\", opts)).rejects.toThrow();\n }\n });\n });\n}\n"],"mappings":"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","names":["afterEach","beforeEach","describe","expect","it","ALICE","BOB","OTHER_ORG","afterEach","beforeEach","describe","expect","it","ALICE","BOB","T","key","afterEach","beforeEach","describe","expect","it","ALICE","BOB","afterEach","beforeEach","describe","expect","it","ALICE","BOB","OTHER_ORG","T","afterEach","beforeEach","describe","expect","it","ALICE","BOB","OTHER_ORG"]}
1
+ {"version":3,"sources":["../src/session-store-contract.ts","../src/episode-store-contract.ts","../src/profile-store-contract.ts","../src/memory-erasure-contract.ts","../src/spend-store-contract.ts","../src/turn-store-contract.ts","../src/routine-run-store-contract.ts","../src/routine-store-contract.ts"],"sourcesContent":["import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport { toWellFormedDeep, type Msg, type Scope, type SessionStore } from \"@alma-harness/core\";\n\n/**\n * Shared `SessionStore` contract suite — §6: storage contracts are\n * backend-neutral by construction; every adapter (in-memory, Postgres,\n * Firestore emulator) runs this exact suite in CI, so no backend idiom\n * fossilizes into the contract.\n *\n * Usage, from an adapter's test file:\n *\n * ```ts\n * import { describeSessionStoreContract } from \"@alma-harness/testing\";\n *\n * describeSessionStoreContract(\"PostgresSessionStore\", {\n * create: () => makeStoreOnFreshSchema(),\n * destroy: (store) => dropSchema(store),\n * });\n * ```\n */\nexport interface SessionStoreFactory {\n /** Must return a store with NO data visible to the scopes used by the suite. */\n create(): Promise<SessionStore> | SessionStore;\n /** Optional teardown, called after each test. */\n destroy?(store: SessionStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\nconst OTHER_ORG: Scope = { org: \"org-b\", uid: \"user-alice\" };\n\nfunction text(role: Msg[\"role\"], body: string): Msg {\n return {\n role,\n blocks: [{ type: \"text\", text: body }],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n };\n}\n\n/** A turn's worth of blocks: what the person saw, plus the tool traffic. */\nfunction withTools(at: string): Msg[] {\n return [\n { role: \"user\", blocks: [{ type: \"text\", text: \"check my notes\" }], meta: { at } },\n {\n role: \"assistant\",\n blocks: [\n { type: \"text\", text: \"one moment\" },\n { type: \"tool_call\", id: \"c1\", name: \"listNotes\", input: {} },\n ],\n meta: { at },\n },\n {\n role: \"tool\",\n blocks: [{ type: \"tool_result\", callId: \"c1\", output: \"two notes\" }],\n meta: { at },\n },\n { role: \"assistant\", blocks: [{ type: \"text\", text: \"you have two\" }], meta: { at } },\n ];\n}\n\nconst kinds = (history: Msg[]): string[][] =>\n history.map((m) => m.blocks.map((b) => b.type));\n\nfunction bodies(history: Msg[]): unknown[] {\n return history.map((m) => (m.blocks[0]?.type === \"text\" ? m.blocks[0].text : m.blocks[0]));\n}\n\nexport function describeSessionStoreContract(name: string, factory: SessionStoreFactory): void {\n describe(`SessionStore contract: ${name}`, () => {\n let store: SessionStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n it(\"round-trips appended messages, preserving content and order\", async () => {\n const entries = [text(\"user\", \"hello\"), text(\"assistant\", \"hi there\")];\n await store.append(ALICE, \"s1\", entries);\n\n const history = await store.load(ALICE, \"s1\");\n expect(history).toEqual(entries);\n });\n\n it(\"round-trips astral-plane text unchanged — emoji and CJK, not just ASCII\", async () => {\n // Four-byte UTF-8, two UTF-16 code units per character. A backend that\n // mangles these mangles what a patient actually types (spec:\n // well-formed-text), and no other case in this suite would notice.\n const entries = [\n text(\"user\", \"não aguento mais 🙂🇧🇷 — 家族と話しました\"),\n text(\"assistant\", \"𝔘𝔫𝔦𝔠𝔬𝔡𝔢 ✅\"),\n ];\n await store.append(ALICE, \"s1\", entries);\n\n const history = await store.load(ALICE, \"s1\");\n expect(history).toEqual(entries);\n for (const body of bodies(history)) expect(String(body).isWellFormed()).toBe(true);\n });\n\n it(\"preserves order across sequential appends (transactional seq)\", async () => {\n await store.append(ALICE, \"s1\", [text(\"user\", \"1\")]);\n await store.append(ALICE, \"s1\", [text(\"assistant\", \"2\"), text(\"user\", \"3\")]);\n await store.append(ALICE, \"s1\", [text(\"assistant\", \"4\")]);\n\n expect(bodies(await store.load(ALICE, \"s1\"))).toEqual([\"1\", \"2\", \"3\", \"4\"]);\n });\n\n it(\"lands every message of concurrent appends on one session exactly once\", async () => {\n // The pin the changelog's \"transactional seq via atomic upsert\" never\n // had (spec: erasure-reaches-the-claims). Twelve appenders race on one\n // session: nothing lost, nothing duplicated, and each append's pair\n // stays adjacent — the seq range is claimed whole, never interleaved.\n await Promise.all(\n Array.from({ length: 12 }, (_, i) =>\n store.append(ALICE, \"s1\", [text(\"user\", `q${i}`), text(\"assistant\", `a${i}`)]),\n ),\n );\n\n const seen = bodies(await store.load(ALICE, \"s1\")).map(String);\n expect(seen).toHaveLength(24);\n expect(new Set(seen).size).toBe(24);\n for (let i = 0; i < seen.length; i += 2) expect(seen[i + 1]).toBe(seen[i]!.replace(\"q\", \"a\"));\n });\n\n it(\"resolves an unknown session to an empty history\", async () => {\n await expect(store.load(ALICE, \"never-created\")).resolves.toEqual([]);\n });\n\n it(\"isolates sessions by sessionId\", async () => {\n await store.append(ALICE, \"s1\", [text(\"user\", \"in s1\")]);\n await store.append(ALICE, \"s2\", [text(\"user\", \"in s2\")]);\n\n expect(bodies(await store.load(ALICE, \"s1\"))).toEqual([\"in s1\"]);\n expect(bodies(await store.load(ALICE, \"s2\"))).toEqual([\"in s2\"]);\n });\n\n it(\"isolates scopes by uid and by org, even for identical session ids\", async () => {\n await store.append(ALICE, \"shared-id\", [text(\"user\", \"alice's\")]);\n\n await expect(store.load(BOB, \"shared-id\")).resolves.toEqual([]);\n await expect(store.load(OTHER_ORG, \"shared-id\")).resolves.toEqual([]);\n });\n\n it(\"load with limit returns the most recent messages, still in order\", async () => {\n await store.append(ALICE, \"s1\", [\n text(\"user\", \"1\"),\n text(\"assistant\", \"2\"),\n text(\"user\", \"3\"),\n text(\"assistant\", \"4\"),\n ]);\n\n expect(bodies(await store.load(ALICE, \"s1\", { limit: 2 }))).toEqual([\"3\", \"4\"]);\n });\n\n it(\"erase(scope, sessionId) removes only that session\", async () => {\n await store.append(ALICE, \"doomed\", [text(\"user\", \"bye\")]);\n await store.append(ALICE, \"kept\", [text(\"user\", \"stay\")]);\n\n await store.erase(ALICE, \"doomed\");\n\n await expect(store.load(ALICE, \"doomed\")).resolves.toEqual([]);\n expect(bodies(await store.load(ALICE, \"kept\"))).toEqual([\"stay\"]);\n });\n\n it(\"erase(scope) purges every session in the scope and nothing outside it\", async () => {\n await store.append(ALICE, \"s1\", [text(\"user\", \"a1\")]);\n await store.append(ALICE, \"s2\", [text(\"user\", \"a2\")]);\n await store.append(BOB, \"s1\", [text(\"user\", \"b1\")]);\n\n await store.erase(ALICE);\n\n await expect(store.load(ALICE, \"s1\")).resolves.toEqual([]);\n await expect(store.load(ALICE, \"s2\")).resolves.toEqual([]);\n expect(bodies(await store.load(BOB, \"s1\"))).toEqual([\"b1\"]);\n });\n\n it(\"rejects an invalid scope even on no-op calls (empty append, non-positive limit)\", async () => {\n // Pins backend neutrality (§6): no adapter may skip central scope\n // validation on early-return paths.\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.append(bad, \"s1\", [])).rejects.toThrow();\n await expect(store.load(bad, \"s1\", { limit: 0 })).rejects.toThrow();\n await expect(store.erase(bad)).rejects.toThrow();\n });\n\n it(\"expires a stale session's tool traffic and keeps everything the person saw\", async () => {\n await store.append(ALICE, \"s1\", withTools(\"2026-01-01T00:00:00.000Z\"));\n\n const report = await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n expect(report).toEqual({ blocks: 2, messages: 1, expired: true });\n // The tool-role message held nothing else and is gone; the assistant's\n // text survives without its tool_call.\n expect(kinds(await store.load(ALICE, \"s1\"))).toEqual([[\"text\"], [\"text\"], [\"text\"]]);\n expect(bodies(await store.load(ALICE, \"s1\"))).toEqual([\n \"check my notes\",\n \"one moment\",\n \"you have two\",\n ]);\n });\n\n it(\"refuses an ACTIVE session and touches nothing — a live prefix must not be rewritten\", async () => {\n // Removing blocks mid-history rewrites the cached prefix: a consuming\n // product measured total cost +27% and cache writes +99% doing exactly\n // that (§6.6). The refusal is the whole reason `inactiveSince` exists,\n // and it reports rather than throws — an active session in a sweep is\n // the normal case, and a throw would be caught and swallowed per session.\n const entries = withTools(\"2026-07-01T00:00:00.000Z\");\n await store.append(ALICE, \"s1\", entries);\n\n const report = await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n expect(report).toEqual({ blocks: 0, messages: 0, expired: false });\n expect(await store.load(ALICE, \"s1\")).toEqual(entries);\n });\n\n it(\"never leaves a tool_call without its tool_result — the pairing a provider enforces with a 400\", async () => {\n // Spec 026 taught the loop to pair them on every exit path; an expiry\n // that took one side would manufacture the dangling tool_use it exists\n // to prevent. All-or-nothing is what makes this true by construction.\n await store.append(ALICE, \"s1\", withTools(\"2026-01-01T00:00:00.000Z\"));\n\n await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n const flat = (await store.load(ALICE, \"s1\")).flatMap((m) => m.blocks.map((b) => b.type));\n expect(flat).not.toContain(\"tool_call\");\n expect(flat).not.toContain(\"tool_result\");\n });\n\n it(\"expires reasoning blocks with the tool traffic — backstage, not what the person saw\", async () => {\n // The model's reasoning is the diagnostic half of spec 039's split\n // (spec: reasoning-blocks): richer and more sensitive than what the\n // person read, and gone with the tool traffic it belongs to.\n await store.append(ALICE, \"s1\", [\n {\n role: \"assistant\",\n blocks: [\n { type: \"reasoning\", provider: \"anthropic\", text: \"the patient asked twice\", opaque: { signature: \"sig\" } },\n { type: \"tool_call\", id: \"c1\", name: \"list\", input: {} },\n ],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n },\n {\n role: \"tool\",\n blocks: [{ type: \"tool_result\", callId: \"c1\", output: \"two\" }],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n },\n {\n role: \"assistant\",\n blocks: [\n { type: \"reasoning\", provider: \"anthropic\", text: \"answer briefly\", opaque: { signature: \"sig2\" } },\n { type: \"text\", text: \"you have two\" },\n ],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n },\n ]);\n\n const report = await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n expect(report).toEqual({ blocks: 4, messages: 2, expired: true });\n expect(kinds(await store.load(ALICE, \"s1\"))).toEqual([[\"text\"]]);\n expect(JSON.stringify(await store.load(ALICE, \"s1\"))).not.toContain(\"the patient asked twice\");\n });\n\n it(\"keeps media blocks — a pointer the user saw, not tool traffic\", async () => {\n await store.append(ALICE, \"s1\", [\n {\n role: \"user\",\n blocks: [\n { type: \"media\", kind: \"image\", ref: { uri: \"gs://bucket/x.png\" } },\n { type: \"tool_call\", id: \"c1\", name: \"describe\", input: {} },\n ],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n },\n ]);\n\n await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n expect(kinds(await store.load(ALICE, \"s1\"))).toEqual([[\"media\"]]);\n });\n\n it(\"expires only the named session, and validates the scope\", async () => {\n await store.append(ALICE, \"s1\", withTools(\"2026-01-01T00:00:00.000Z\"));\n await store.append(ALICE, \"s2\", withTools(\"2026-01-01T00:00:00.000Z\"));\n\n await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n });\n\n expect(kinds(await store.load(ALICE, \"s2\"))).toEqual([\n [\"text\"],\n [\"text\", \"tool_call\"],\n [\"tool_result\"],\n [\"text\"],\n ]);\n await expect(\n store.expireToolTraffic({ org: \"../evil\", uid: \"u\" }, \"s1\", {\n inactiveSince: \"2026-06-01T00:00:00.000Z\",\n }),\n ).rejects.toThrow();\n });\n\n it(\"round-trips a MediaRef whole, filename included\", async () => {\n // Spec 040. One store the first port migrates repeats the file name in\n // the message text; another carries it ONLY here. An adapter that\n // dropped unknown ref keys would lose the second one's only copy.\n const ref = {\n uri: \"gs://bucket/laudo.pdf\",\n contentType: \"application/pdf\",\n bytes: 20_480,\n filename: \"laudo — 2026.pdf\",\n };\n await store.append(ALICE, \"s1\", [\n {\n role: \"user\",\n blocks: [{ type: \"media\", kind: \"document\", ref }],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n },\n ]);\n\n const block = (await store.load(ALICE, \"s1\"))[0]?.blocks[0];\n expect(block?.type === \"media\" ? block.ref : null).toEqual(ref);\n });\n\n it(\"round-trips a MediaRef with no filename — the field is optional\", async () => {\n const ref = { uri: \"gs://bucket/x.png\" };\n await store.append(ALICE, \"s1\", [\n {\n role: \"user\",\n blocks: [{ type: \"media\", kind: \"image\", ref }],\n meta: { at: \"2026-01-01T00:00:00.000Z\" },\n },\n ]);\n\n const block = (await store.load(ALICE, \"s1\"))[0]?.blocks[0];\n expect(block?.type === \"media\" ? block.ref : null).toEqual(ref);\n expect(block?.type === \"media\" ? \"filename\" in block.ref : true).toBe(false);\n });\n\n it(\"expires by the message's own meta.at, not by when the row was written\", async () => {\n // Spec 040, and the case spec 039's suite cannot be: those stamp\n // `meta.at` moments before asserting, so the message clock and the row\n // clock agree and neither can distinguish the other. A migrated session\n // is written TODAY carrying stamps from a year ago — if an adapter ever\n // reads its own `created_at`, every migrated session looks freshly\n // active and expiry refuses all of them, forever, reporting success.\n await store.append(ALICE, \"s1\", withTools(\"2025-01-01T00:00:00.000Z\"));\n\n const report = await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2025-06-01T00:00:00.000Z\",\n });\n\n expect(report).toEqual({ blocks: 2, messages: 1, expired: true });\n });\n\n it(\"treats a message with no meta.at as ACTIVE — an age that cannot be established is not old\", async () => {\n // A pin (§3.3): true before spec 040 and after. It is here so the case\n // above cannot be \"fixed\" by quietly making unstamped messages\n // expirable, which would invert the safe direction.\n const undated: Msg = {\n role: \"assistant\",\n blocks: [{ type: \"tool_call\", id: \"c1\", name: \"x\", input: {} }],\n };\n await store.append(ALICE, \"s1\", [...withTools(\"2025-01-01T00:00:00.000Z\"), undated]);\n\n const report = await store.expireToolTraffic(ALICE, \"s1\", {\n inactiveSince: \"2025-06-01T00:00:00.000Z\",\n });\n\n expect(report).toEqual({ blocks: 0, messages: 0, expired: false });\n });\n\n it(\"refuses malformed UTF-16 identically on every adapter, naming the entry\", async () => {\n // Spec 040. Until then the adapters DIVERGED — in-memory kept the lone\n // surrogate, Postgres refused the write — and both contracts said \"do\n // not rely on either behaviour\". `runTurn` repairs on the way in, but\n // best-effort; a migration writing here directly has no such pass.\n const lone = `broken \\ud83d end`;\n expect(lone.isWellFormed()).toBe(false);\n\n await expect(\n store.append(ALICE, \"s1\", [text(\"user\", \"fine\"), text(\"assistant\", lone)]),\n ).rejects.toThrow(/entries\\[1\\]/);\n // Refused whole: nothing from the batch landed.\n await expect(store.load(ALICE, \"s1\")).resolves.toEqual([]);\n });\n\n it(\"accepts the same value once toWellFormedDeep has run — the documented remedy works\", async () => {\n const repaired = toWellFormedDeep(text(\"assistant\", `broken \\ud83d end`));\n\n await store.append(ALICE, \"s1\", [repaired]);\n\n const [loaded] = await store.load(ALICE, \"s1\");\n expect(loaded).toEqual(repaired);\n expect(String(bodies([loaded as Msg])[0]).isWellFormed()).toBe(true);\n });\n\n it(\"returns defensive copies — mutating a loaded history never corrupts the store\", async () => {\n await store.append(ALICE, \"s1\", [text(\"user\", \"original\")]);\n\n const first = await store.load(ALICE, \"s1\");\n first.pop();\n const block = (await store.load(ALICE, \"s1\"))[0]?.blocks[0];\n if (block?.type === \"text\") block.text = \"mutated\";\n\n expect(bodies(await store.load(ALICE, \"s1\"))).toEqual([\"original\"]);\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type { EpisodeStore, Scope } from \"@alma-harness/core\";\nimport { deriveEpisodeId, isRecallable } from \"@alma-harness/memory\";\n\n/**\n * Shared `EpisodeStore` contract suite — §6, spec 011. Every adapter\n * (in-memory, Postgres, Firestore emulator) runs this exact suite in CI, so no\n * backend idiom fossilizes into the contract and the normative rules of spec\n * 010 hold everywhere: deterministic ids, three states never conflated,\n * budget at the reader, declared copy surfaces.\n *\n * ```ts\n * describeEpisodeStoreContract(\"PostgresEpisodeStore\", { create: () => … });\n * ```\n */\nexport interface EpisodeStoreFactory {\n /** Must return a store with NO data visible to the scopes used by the suite. */\n create(): Promise<EpisodeStore> | EpisodeStore;\n destroy?(store: EpisodeStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\nconst OTHER_ORG: Scope = { org: \"org-b\", uid: \"user-alice\" };\n\n/** Pinned timestamps keep ranking deterministic across backends. */\nconst T = {\n old: \"2026-01-01T00:00:00.000Z\",\n mid: \"2026-06-01T00:00:00.000Z\",\n recent: \"2026-08-01T00:00:00.000Z\",\n} as const;\n\nfunction summaries(episodes: readonly { summary: string }[]): string[] {\n return episodes.map((e) => e.summary);\n}\n\nexport function describeEpisodeStoreContract(name: string, factory: EpisodeStoreFactory): void {\n describe(`EpisodeStore contract: ${name}`, () => {\n let store: EpisodeStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n it(\"round-trips an appended episode, defaulting importance and state\", async () => {\n const stored = await store.append(ALICE, {\n kind: \"conversation\",\n summary: \"prefers morning appointments\",\n at: T.recent,\n source: { sessionId: \"s1\", turnId: \"t1\" },\n });\n\n expect(stored).toMatchObject({\n kind: \"conversation\",\n summary: \"prefers morning appointments\",\n at: T.recent,\n importance: 0.5,\n state: \"active\",\n source: { sessionId: \"s1\", turnId: \"t1\" },\n });\n expect(isRecallable(stored)).toBe(true);\n\n const found = await store.get(ALICE, [stored.id]);\n expect(found).toEqual([stored]);\n });\n\n it(\"addresses episodes by a deterministic id, so re-extraction overwrites and never duplicates\", async () => {\n // Spec 010 normative: \"candidates and runs are addressed by\n // content/scope hashes — re-extraction overwrites, never duplicates\".\n const input = {\n kind: \"note\",\n summary: \"runs 5k on saturdays\",\n source: { sessionId: \"s1\", turnId: \"t1\" },\n };\n const first = await store.append(ALICE, { ...input, at: T.old });\n const second = await store.append(ALICE, { ...input, at: T.recent });\n\n expect(second.id).toBe(first.id);\n expect(second.id).toBe(deriveEpisodeId(ALICE, input));\n const { episodes } = await store.query(ALICE, {});\n expect(episodes).toHaveLength(1);\n });\n\n it(\"derives different ids for the same content in different scopes\", async () => {\n const input = { kind: \"note\", summary: \"same words\" };\n const mine = await store.append(ALICE, input);\n const theirs = await store.append(BOB, input);\n\n expect(mine.id).not.toBe(theirs.id);\n });\n\n it(\"dedupeKey separates two genuinely distinct episodes with identical content\", async () => {\n const input = { kind: \"note\", summary: \"checked in\", source: { turnId: \"t1\" } };\n await store.append(ALICE, { ...input, dedupeKey: \"a\" });\n await store.append(ALICE, { ...input, dedupeKey: \"b\" });\n\n const { episodes } = await store.query(ALICE, {});\n expect(episodes).toHaveLength(2);\n });\n\n it(\"keeps a dedupeKey scoped to its content: reuse in a later turn never overwrites\", async () => {\n // The key's job is to SPLIT identical content within one turn. Derived\n // from the key alone, a stable key like \"choice\" reused next turn landed\n // on the earlier turn's id and silently replaced that episode (review of\n // spec 013).\n const first = await store.append(ALICE, {\n kind: \"note\",\n summary: \"chose the morning slot\",\n source: { turnId: \"t1\" },\n dedupeKey: \"choice\",\n });\n const second = await store.append(ALICE, {\n kind: \"note\",\n summary: \"chose the evening slot\",\n source: { turnId: \"t2\" },\n dedupeKey: \"choice\",\n });\n\n expect(second.id).not.toBe(first.id);\n expect((await store.get(ALICE, [first.id]))[0]).toMatchObject({\n summary: \"chose the morning slot\",\n });\n });\n\n it(\"normalizes timestamps to canonical UTC, so backends never disagree\", async () => {\n const stored = await store.append(ALICE, {\n kind: \"note\",\n summary: \"written with an offset\",\n at: \"2026-08-01T02:00:00+02:00\",\n });\n\n expect(stored.at).toBe(\"2026-08-01T00:00:00.000Z\");\n expect((await store.get(ALICE, [stored.id]))[0]?.at).toBe(\"2026-08-01T00:00:00.000Z\");\n });\n\n it(\"isolates scopes by uid and by org\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"alice's memory\" });\n\n await expect(store.query(BOB, {})).resolves.toMatchObject({ episodes: [] });\n await expect(store.query(OTHER_ORG, {})).resolves.toMatchObject({ episodes: [] });\n });\n\n it(\"filters by kind and by time range\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"note one\", at: T.old });\n await store.append(ALICE, { kind: \"observation\", summary: \"observed thing\", at: T.mid });\n await store.append(ALICE, { kind: \"note\", summary: \"note two\", at: T.recent });\n\n const byKind = await store.query(ALICE, { kinds: [\"observation\"] });\n expect(summaries(byKind.episodes)).toEqual([\"observed thing\"]);\n\n const byRange = await store.query(ALICE, { since: T.mid, until: T.recent });\n expect(summaries(byRange.episodes).sort()).toEqual([\"note two\", \"observed thing\"]);\n });\n\n it(\"ranks a term match above a non-match, and excludes non-matches entirely\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"loves kayaking\", at: T.old });\n await store.append(ALICE, { kind: \"note\", summary: \"dislikes crowds\", at: T.recent });\n\n const { episodes } = await store.query(ALICE, { text: \"kayaking\" });\n expect(summaries(episodes)).toEqual([\"loves kayaking\"]);\n });\n\n it(\"finds an inflected form: a query in the singular matches a summary in the plural\", async () => {\n // spec: search-that-finds. The shared tokenizer stems both sides, and an\n // adapter's substring candidate filter must stay a superset of that —\n // which is what running this on Postgres proves.\n await store.append(ALICE, { kind: \"note\", summary: \"duas reuniões marcadas para terça\" });\n await store.append(ALICE, { kind: \"note\", summary: \"nada a ver com isso\", dedupeKey: \"other\" });\n\n const { episodes } = await store.query(ALICE, { text: \"reunião\" });\n expect(summaries(episodes)).toEqual([\"duas reuniões marcadas para terça\"]);\n });\n\n it(\"finds a term deep in a long summary, past the query tokenizer's cap\", async () => {\n // The 32-term cap bounds QUERY patterns; applied to the summary side of\n // the overlap score, it made any summary longer than ~32 distinct words\n // unsearchable past its opening words (the 011–013 review).\n const filler = Array.from({ length: 40 }, (_, i) => `filler${i}`).join(\" \");\n await store.append(ALICE, { kind: \"note\", summary: `${filler} chocolate` });\n\n const { episodes } = await store.query(ALICE, { text: \"chocolate\" });\n expect(episodes).toHaveLength(1);\n });\n\n it(\"matches case-insensitively beyond ASCII, whatever locale the backend runs under\", async () => {\n // Folding is the ADAPTER's job, in one consistent locale: Postgres\n // `ilike` under lc_ctype of C folds ASCII only, so 'CAFÉ' silently\n // stopped matching 'café' there while this reference matched it —\n // breaking the candidate-superset property the ranker composes with\n // (the 011–013 review).\n await store.append(ALICE, { kind: \"note\", summary: \"Adora CAFÉ da manhã\" });\n\n const { episodes } = await store.query(ALICE, { text: \"café\" });\n expect(summaries(episodes)).toEqual([\"Adora CAFÉ da manhã\"]);\n });\n\n it(\"breaks a ranking tie toward the more recent episode\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"coffee order\", at: T.old });\n await store.append(ALICE, { kind: \"note\", summary: \"coffee order\", dedupeKey: \"b\", at: T.recent });\n\n const { episodes } = await store.query(ALICE, { text: \"coffee\" });\n expect(episodes.map((e) => e.at)).toEqual([T.recent, T.old]);\n });\n\n it(\"ranks higher importance above lower at equal overlap and age\", async () => {\n await store.append(ALICE, {\n kind: \"note\",\n summary: \"allergy penicillin\",\n dedupeKey: \"low\",\n at: T.mid,\n importance: 0.1,\n });\n await store.append(ALICE, {\n kind: \"note\",\n summary: \"allergy penicillin\",\n dedupeKey: \"high\",\n at: T.mid,\n importance: 0.9,\n });\n\n const { episodes } = await store.query(ALICE, { text: \"allergy\" });\n expect(episodes.map((e) => e.importance)).toEqual([0.9, 0.1]);\n });\n\n it(\"caps the read at the budget and says it truncated\", async () => {\n // Spec 010, third consumer: an uncapped reader is a latent leak even\n // under a global budget.\n for (const n of [\"one\", \"two\", \"three\"]) {\n await store.append(ALICE, { kind: \"note\", summary: `budget ${n}`, dedupeKey: n, at: T.mid });\n }\n\n const capped = await store.query(ALICE, { text: \"budget\", budget: { maxItems: 1 } });\n expect(capped.episodes).toHaveLength(1);\n expect(capped.truncated).toBe(true);\n\n const uncapped = await store.query(ALICE, { text: \"budget\" });\n expect(uncapped.episodes).toHaveLength(3);\n expect(uncapped.truncated).toBe(false);\n });\n\n it(\"drops whole items rather than overflowing a character budget\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"x\".repeat(30), dedupeKey: \"big\", at: T.mid });\n\n const result = await store.query(ALICE, { budget: { maxChars: 10 } });\n expect(result.episodes).toEqual([]);\n expect(result.truncated).toBe(true);\n });\n\n it(\"resolves a non-positive limit to an empty result\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"present\" });\n\n await expect(store.query(ALICE, { limit: 0 })).resolves.toMatchObject({ episodes: [] });\n });\n\n it(\"archives an episode out of hot recall while keeping its content intact\", async () => {\n const ep = await store.append(ALICE, { kind: \"note\", summary: \"seasonal detail\", at: T.mid });\n\n await expect(store.archive(ALICE, [ep.id])).resolves.toBe(1);\n\n const hot = await store.query(ALICE, { text: \"seasonal\" });\n expect(hot.episodes).toEqual([]);\n\n const cold = await store.query(ALICE, { text: \"seasonal\", includeArchived: true });\n expect(summaries(cold.episodes)).toEqual([\"seasonal detail\"]);\n expect(isRecallable(cold.episodes[0]!)).toBe(false);\n });\n\n it(\"keeps an archived episode archived when it is re-appended\", async () => {\n // Re-observation is not a reason to undo a product's salience decision.\n const input = { kind: \"note\", summary: \"seasonal detail\", source: { turnId: \"t1\" } };\n const ep = await store.append(ALICE, input);\n await store.archive(ALICE, [ep.id]);\n\n const reappended = await store.append(ALICE, input);\n\n expect(reappended.state).toBe(\"archived\");\n });\n\n it(\"tombstones an episode: content gone, position kept, never recalled again\", async () => {\n // Spec 010 AC 4 and \"isRecallable excludes tombstones — an erased memory\n // must not surface as a blank line that leaks its own existence\".\n const ep = await store.append(ALICE, {\n kind: \"note\",\n summary: \"sensitive detail\",\n at: T.mid,\n source: { sessionId: \"s1\" },\n });\n\n const result = await store.tombstone(ALICE, { kind: \"episodes\", episodeIds: [ep.id] }, T.recent);\n expect(result.episodeIds).toEqual([ep.id]);\n\n const [stored] = await store.get(ALICE, [ep.id]);\n expect(stored).toMatchObject({\n id: ep.id,\n kind: \"\", // the label goes too — nothing enforces that it is not content\n summary: \"\",\n state: \"tombstoned\",\n erasedAt: T.recent,\n });\n expect(isRecallable(stored!)).toBe(false);\n\n await expect(store.query(ALICE, { text: \"sensitive\" })).resolves.toMatchObject({\n episodes: [],\n });\n await expect(\n store.query(ALICE, { text: \"sensitive\", includeArchived: true }),\n ).resolves.toMatchObject({ episodes: [] });\n });\n\n it(\"never resurrects a tombstoned episode on re-append\", async () => {\n // Terminal states are create-only (spec 010).\n const input = { kind: \"note\", summary: \"erased content\", source: { turnId: \"t1\" } };\n const ep = await store.append(ALICE, input);\n await store.tombstone(ALICE, { kind: \"episodes\", episodeIds: [ep.id] }, T.recent);\n\n const reappended = await store.append(ALICE, input);\n\n expect(reappended.state).toBe(\"tombstoned\");\n expect(reappended.summary).toBe(\"\");\n await expect(store.query(ALICE, { text: \"erased\" })).resolves.toMatchObject({ episodes: [] });\n });\n\n it(\"refuses to archive a tombstoned episode\", async () => {\n // Terminal states are create-only: an erased episode has no state left\n // to move to, and 'archived' would imply recoverable content.\n const ep = await store.append(ALICE, { kind: \"note\", summary: \"erased\" });\n await store.tombstone(ALICE, { kind: \"episodes\", episodeIds: [ep.id] }, T.recent);\n\n await expect(store.archive(ALICE, [ep.id])).resolves.toBe(0);\n expect((await store.get(ALICE, [ep.id]))[0]).toMatchObject({ state: \"tombstoned\" });\n });\n\n it(\"tombstones every episode of a session, and nothing outside it\", async () => {\n const doomed = await store.append(ALICE, {\n kind: \"note\",\n summary: \"in the doomed session\",\n source: { sessionId: \"doomed\" },\n });\n const kept = await store.append(ALICE, {\n kind: \"note\",\n summary: \"in another session\",\n source: { sessionId: \"kept\" },\n });\n\n const result = await store.tombstone(ALICE, { kind: \"sessions\", sessionIds: [\"doomed\"] }, T.recent);\n\n expect(result.episodeIds).toEqual([doomed.id]);\n expect((await store.get(ALICE, [kept.id]))[0]).toMatchObject({ state: \"active\" });\n });\n\n it(\"tombstones the whole scope on the 'all' selector, and nothing outside the scope\", async () => {\n const mine = await store.append(ALICE, { kind: \"note\", summary: \"mine\" });\n const theirs = await store.append(BOB, { kind: \"note\", summary: \"theirs\" });\n\n const result = await store.tombstone(ALICE, { kind: \"all\" }, T.recent);\n\n expect(result.episodeIds).toEqual([mine.id]);\n expect((await store.get(BOB, [theirs.id]))[0]).toMatchObject({ state: \"active\" });\n });\n\n it(\"reports every copy surface it declares, so erasure can be proven\", async () => {\n // Spec 010: \"provenance columns without a written delete are not\n // erasure\" — the declaration is checked against what erasure wrote.\n await store.append(ALICE, { kind: \"note\", summary: \"anything\" });\n\n const result = await store.tombstone(ALICE, { kind: \"all\" }, T.recent);\n\n expect(store.copySurfaces.length).toBeGreaterThan(0);\n for (const surface of store.copySurfaces) {\n expect(result.surfaces).toContain(surface.name);\n }\n });\n\n it(\"cannot be pinned to the top of every ranking by a future timestamp\", async () => {\n // Recency decayed from age clamped at zero, so a far-future `at` scored\n // the maximum forever — and `at` is caller-supplied.\n await store.append(ALICE, { kind: \"note\", summary: \"honest coffee note\", at: T.recent });\n await store.append(ALICE, {\n kind: \"note\",\n summary: \"coffee spam\",\n dedupeKey: \"future\",\n at: \"9999-01-01T00:00:00.000Z\",\n });\n\n const { episodes } = await store.query(ALICE, { text: \"coffee\" });\n expect(episodes[0]?.summary).toBe(\"honest coffee note\");\n });\n\n it(\"returns nothing for a search whose text carries no usable term\", async () => {\n // Treating an empty token set as \"no text\" turned search into \"dump\n // whatever is most recent\" — the opposite of searching.\n await store.append(ALICE, { kind: \"note\", summary: \"private detail\", at: T.recent });\n\n await expect(store.query(ALICE, { text: \"a\" })).resolves.toMatchObject({ episodes: [] });\n await expect(store.query(ALICE, { text: \"???\" })).resolves.toMatchObject({ episodes: [] });\n });\n\n it(\"normalizes query bounds, so a bound without a timezone means one thing\", async () => {\n await store.append(ALICE, { kind: \"note\", summary: \"in range\", at: \"2026-06-15T00:00:00.000Z\" });\n\n const found = await store.query(ALICE, { since: \"2026-06-01T00:00:00Z\" });\n expect(summaries(found.episodes)).toEqual([\"in range\"]);\n await expect(store.query(ALICE, { since: \"not a date\" })).rejects.toThrow();\n });\n\n it(\"bounds every caller-controlled size\", async () => {\n await expect(\n store.append(ALICE, { kind: \"note\", summary: \"x\".repeat(100_000) }),\n ).rejects.toThrow();\n await expect(store.append(ALICE, { kind: \"NOT A SLUG\", summary: \"x\" })).rejects.toThrow();\n await expect(store.append(ALICE, { kind: \"note\", summary: \"x\", importance: 42 })).rejects.toThrow();\n await expect(store.query(ALICE, { limit: 10_000_000 })).rejects.toThrow();\n await expect(store.query(ALICE, { limit: 1.5 })).rejects.toThrow();\n });\n\n it(\"rejects content carrying control characters no backend can store alike\", async () => {\n await expect(\n store.append(ALICE, { kind: \"note\", summary: \"before\\u0000after\" }),\n ).rejects.toThrow();\n });\n\n it(\"rejects a lone surrogate no backend can store alike\", async () => {\n // Half a character: `jsonb` refuses it outright, an in-memory store would\n // keep it, and a store that diverges here diverges on what a product can\n // write (spec: well-formed-text). Refused rather than repaired, because a\n // memory write is a tool call and the refusal is data for the model.\n await expect(\n store.append(ALICE, { kind: \"note\", summary: \"before\\ud83dafter\" }),\n ).rejects.toThrow();\n });\n\n it(\"keeps a dedupeKey from ever colliding with a content-derived id\", async () => {\n // dedupeKey used to REPLACE the id material, so anyone who knew a\n // target's (kind, summary, session, turn) could reconstruct it and\n // overwrite that episode.\n const target = await store.append(ALICE, {\n kind: \"clinical\",\n summary: \"severe penicillin allergy\",\n source: { sessionId: \"s1\", turnId: \"t1\" },\n });\n\n const forged = await store.append(ALICE, {\n kind: \"note\",\n summary: \"no known allergies\",\n dedupeKey: JSON.stringify([\"clinical\", \"severe penicillin allergy\", \"s1\", \"t1\"]),\n });\n\n expect(forged.id).not.toBe(target.id);\n expect((await store.get(ALICE, [target.id]))[0]).toMatchObject({\n summary: \"severe penicillin allergy\",\n });\n });\n\n it(\"rejects an invalid scope even on no-op calls\", async () => {\n // Backend neutrality (§6): no adapter may skip central scope validation\n // on early-return paths.\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.append(bad, { kind: \"note\", summary: \"x\" })).rejects.toThrow();\n await expect(store.query(bad, { limit: 0 })).rejects.toThrow();\n await expect(store.get(bad, [])).rejects.toThrow();\n await expect(store.tombstone(bad, { kind: \"episodes\", episodeIds: [] }, T.recent)).rejects.toThrow();\n await expect(store.archive(bad, [])).rejects.toThrow();\n });\n\n it(\"returns defensive copies — mutating a result never corrupts the store\", async () => {\n const ep = await store.append(ALICE, { kind: \"note\", summary: \"original\", at: T.mid });\n\n const first = await store.query(ALICE, {});\n const mutable = first.episodes[0] as { summary: string };\n mutable.summary = \"mutated\";\n\n const [reread] = await store.get(ALICE, [ep.id]);\n expect(reread?.summary).toBe(\"original\");\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type { ProfileFact, ProfileStore, Scope } from \"@alma-harness/core\";\nimport { isCurrentFact } from \"@alma-harness/memory\";\n\n/**\n * Shared `ProfileStore` contract suite — §6, spec 011. Pins the normative\n * rules of spec 010 that no adapter may reinterpret: identity is never\n * extracted, terminal states are create-only, the three-case confidence rule,\n * derived invalidation via provenance, and a budget on every read.\n */\nexport interface ProfileStoreFactory {\n create(): Promise<ProfileStore> | ProfileStore;\n destroy?(store: ProfileStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\n\nconst T = {\n t1: \"2026-06-01T00:00:00.000Z\",\n t2: \"2026-07-01T00:00:00.000Z\",\n t3: \"2026-08-01T00:00:00.000Z\",\n} as const;\n\nfunction byKey(facts: readonly ProfileFact[], key: string): ProfileFact[] {\n return facts.filter((f) => f.key === key);\n}\n\nexport function describeProfileStoreContract(name: string, factory: ProfileStoreFactory): void {\n describe(`ProfileStore contract: ${name}`, () => {\n let store: ProfileStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n it(\"resolves an empty scope to an empty profile\", async () => {\n await expect(store.get(ALICE)).resolves.toMatchObject({ facts: [], truncated: false });\n });\n\n it(\"inserts a first observation as the current fact\", async () => {\n const [result] = await store.observe(ALICE, [\n { key: \"diet.preference\", value: \"vegetarian\", confidence: 0.8, at: T.t1 },\n ]);\n\n expect(result).toMatchObject({ key: \"diet.preference\", outcome: \"inserted\" });\n const { facts } = await store.get(ALICE);\n expect(facts).toHaveLength(1);\n expect(facts[0]).toMatchObject({\n key: \"diet.preference\",\n value: \"vegetarian\",\n confidence: 0.8,\n observedAt: T.t1,\n lastSeenAt: T.t1,\n });\n expect(isCurrentFact(facts[0]!)).toBe(true);\n });\n\n it(\"refreshes a re-observed value instead of versioning it, unioning provenance\", async () => {\n // Spec 010 normative: \"terminal states are create-only — a re-observed\n // fact refreshes lastSeenAt only\".\n await store.observe(ALICE, [\n { key: \"city\", value: \"lisbon\", confidence: 0.6, sourceEpisodeIds: [\"ep-1\"], at: T.t1 },\n ]);\n const [result] = await store.observe(ALICE, [\n { key: \"city\", value: \"lisbon\", confidence: 0.9, sourceEpisodeIds: [\"ep-2\"], at: T.t2 },\n ]);\n\n expect(result?.outcome).toBe(\"refreshed\");\n const { facts } = await store.get(ALICE, { includeHistory: true });\n expect(facts).toHaveLength(1);\n expect(facts[0]).toMatchObject({\n value: \"lisbon\",\n confidence: 0.9, // corroboration raises confidence, never lowers it\n observedAt: T.t1,\n lastSeenAt: T.t2,\n });\n expect([...facts[0]!.sourceEpisodeIds].sort()).toEqual([\"ep-1\", \"ep-2\"]);\n });\n\n it(\"supersedes the current value when a different one arrives at no less confidence\", async () => {\n await store.observe(ALICE, [{ key: \"city\", value: \"lisbon\", confidence: 0.6, at: T.t1 }]);\n const [result] = await store.observe(ALICE, [\n { key: \"city\", value: \"porto\", confidence: 0.7, at: T.t2 },\n ]);\n\n expect(result?.outcome).toBe(\"superseded\");\n const current = await store.get(ALICE);\n expect(current.facts).toHaveLength(1);\n expect(current.facts[0]).toMatchObject({ value: \"porto\" });\n\n const history = await store.get(ALICE, { includeHistory: true });\n const closed = history.facts.find((f) => f.value === \"lisbon\");\n expect(closed).toMatchObject({ supersededAt: T.t2, supersededBy: result?.factId });\n });\n\n it(\"records a lower-confidence contradiction already closed and keeps the current fact\", async () => {\n // The third-case rule (spec 010, third consumer): full history,\n // contradiction handling, and audit in ONE write — no candidate queue.\n await store.observe(ALICE, [{ key: \"city\", value: \"lisbon\", confidence: 0.9, at: T.t1 }]);\n const [result] = await store.observe(ALICE, [\n { key: \"city\", value: \"madrid\", confidence: 0.3, at: T.t2 },\n ]);\n\n expect(result?.outcome).toBe(\"conflict\");\n expect(result?.detail).toBeTruthy();\n\n const current = await store.get(ALICE);\n expect(current.facts).toHaveLength(1);\n expect(current.facts[0]).toMatchObject({ value: \"lisbon\" });\n\n const history = await store.get(ALICE, { includeHistory: true });\n const rejected = history.facts.find((f) => f.value === \"madrid\");\n expect(rejected).toMatchObject({ supersededAt: T.t2 });\n expect(isCurrentFact(rejected!)).toBe(false);\n });\n\n it(\"never resurrects a closed version when an old value returns\", async () => {\n await store.observe(ALICE, [{ key: \"city\", value: \"lisbon\", confidence: 0.5, at: T.t1 }]);\n await store.observe(ALICE, [{ key: \"city\", value: \"porto\", confidence: 0.6, at: T.t2 }]);\n await store.observe(ALICE, [{ key: \"city\", value: \"lisbon\", confidence: 0.7, at: T.t3 }]);\n\n const current = await store.get(ALICE);\n expect(current.facts).toHaveLength(1);\n expect(current.facts[0]).toMatchObject({ value: \"lisbon\", observedAt: T.t3 });\n\n const history = await store.get(ALICE, { includeHistory: true });\n expect(byKey(history.facts, \"city\")).toHaveLength(3);\n const closedLisbon = history.facts.find((f) => f.value === \"lisbon\" && f.observedAt === T.t1);\n expect(closedLisbon?.supersededAt).toBe(T.t2);\n });\n\n it(\"refuses to write a protected profile key through the model path, writing nothing\", async () => {\n // Spec 010 normative, promoted from the identity poisoning incident:\n // identity is NEVER extracted.\n const results = await store.observe(ALICE, [\n { key: \"identity.uid\", value: \"user-bob\", confidence: 1, at: T.t1 },\n { key: \"hobby\", value: \"climbing\", confidence: 0.5, at: T.t1 },\n ]);\n\n expect(results[0]).toMatchObject({ key: \"identity.uid\", outcome: \"refused\" });\n expect(results[0]?.factId).toBeUndefined();\n expect(results[1]?.outcome).toBe(\"inserted\");\n\n const { facts } = await store.get(ALICE, { includeHistory: true });\n expect(byKey(facts, \"identity.uid\")).toEqual([]);\n expect(byKey(facts, \"hobby\")).toHaveLength(1);\n });\n\n it(\"lets the product write protected keys, and lets them outrank a confident extraction\", async () => {\n await store.observe(ALICE, [{ key: \"name\", value: \"wrong\", confidence: 0.99, at: T.t1 }]);\n\n const results = await store.setProtected(ALICE, [\n { key: \"identity.uid\", value: \"user-alice\", at: T.t2 },\n { key: \"name\", value: \"right\", confidence: 0.1, at: T.t2 },\n ]);\n\n expect(results.map((r) => r.outcome)).toEqual([\"inserted\", \"superseded\"]);\n const { facts } = await store.get(ALICE);\n expect(facts.find((f) => f.key === \"identity.uid\")).toMatchObject({ value: \"user-alice\" });\n expect(facts.find((f) => f.key === \"name\")).toMatchObject({ value: \"right\" });\n });\n\n it(\"caps the read at the budget, keeping the most trusted facts\", async () => {\n await store.observe(ALICE, [\n { key: \"a\", value: \"low\", confidence: 0.2, at: T.t1 },\n { key: \"b\", value: \"high\", confidence: 0.9, at: T.t1 },\n { key: \"c\", value: \"mid\", confidence: 0.5, at: T.t1 },\n ]);\n\n const capped = await store.get(ALICE, { budget: { maxItems: 2 } });\n expect(capped.facts.map((f) => f.key)).toEqual([\"b\", \"c\"]);\n expect(capped.truncated).toBe(true);\n\n const uncapped = await store.get(ALICE);\n expect(uncapped.facts).toHaveLength(3);\n expect(uncapped.truncated).toBe(false);\n });\n\n it(\"invalidates every fact whose provenance intersects the erased episodes\", async () => {\n // Derived invalidation via provenance — §6.7, spec 010 AC 4.\n await store.observe(ALICE, [\n { key: \"derived\", value: \"from ep-1\", sourceEpisodeIds: [\"ep-1\"], at: T.t1 },\n { key: \"independent\", value: \"from ep-2\", sourceEpisodeIds: [\"ep-2\"], at: T.t1 },\n ]);\n\n const result = await store.invalidateBySource(ALICE, [\"ep-1\"], T.t3);\n\n expect(result.invalidated).toBe(1);\n const { facts } = await store.get(ALICE);\n expect(facts.map((f) => f.key)).toEqual([\"independent\"]);\n\n // Invalidation blanks key AND value, so the surviving version is found\n // by its state, not by a label it no longer carries.\n const history = await store.get(ALICE, { includeHistory: true });\n const erased = history.facts.filter((f) => f.invalidatedAt !== undefined);\n expect(erased).toHaveLength(1);\n expect(erased[0]).toMatchObject({ key: \"\", value: \"\", invalidatedAt: T.t3 });\n });\n\n it(\"invalidates the whole scope on 'all', without walking provenance\", async () => {\n await store.observe(ALICE, [{ key: \"unsourced\", value: \"no provenance\", at: T.t1 }]);\n await store.observe(BOB, [{ key: \"theirs\", value: \"untouched\", at: T.t1 }]);\n\n const result = await store.invalidateBySource(ALICE, \"all\", T.t3);\n\n expect(result.invalidated).toBe(1);\n await expect(store.get(ALICE)).resolves.toMatchObject({ facts: [] });\n const theirs = await store.get(BOB);\n expect(theirs.facts).toHaveLength(1);\n });\n\n it(\"reports every copy surface it declares, so erasure can be proven\", async () => {\n await store.observe(ALICE, [{ key: \"any\", value: \"thing\", at: T.t1 }]);\n\n const result = await store.invalidateBySource(ALICE, \"all\", T.t3);\n\n expect(store.copySurfaces.length).toBeGreaterThan(0);\n for (const surface of store.copySurfaces) {\n expect(result.surfaces).toContain(surface.name);\n }\n });\n\n it(\"normalizes timestamps to canonical UTC, so backends never disagree\", async () => {\n await store.observe(ALICE, [{ key: \"k\", value: \"v\", at: \"2026-07-01T02:00:00+02:00\" }]);\n\n const { facts } = await store.get(ALICE);\n expect(facts[0]).toMatchObject({\n observedAt: \"2026-07-01T00:00:00.000Z\",\n lastSeenAt: \"2026-07-01T00:00:00.000Z\",\n });\n });\n\n it(\"isolates scopes by uid\", async () => {\n await store.observe(ALICE, [{ key: \"secret\", value: \"alice's\", at: T.t1 }]);\n\n await expect(store.get(BOB)).resolves.toMatchObject({ facts: [] });\n });\n\n it(\"isolates scopes by org, even for the same uid\", async () => {\n // The uid case alone let an org-scoping bug hide behind uid scoping\n // working — the suites pinned only half the tenancy boundary (the\n // 011–013 review).\n await store.observe(ALICE, [{ key: \"secret\", value: \"alice's\", at: T.t1 }]);\n\n await expect(store.get({ org: \"org-b\", uid: ALICE.uid })).resolves.toMatchObject({\n facts: [],\n });\n const result = await store.invalidateBySource({ org: \"org-b\", uid: ALICE.uid }, \"all\", T.t2);\n expect(result.invalidated).toBe(0);\n await expect(store.get(ALICE)).resolves.toMatchObject({\n facts: [expect.objectContaining({ key: \"secret\" })],\n });\n });\n\n it(\"leaves exactly one current version under concurrent observations of one key\", async () => {\n await Promise.all(\n [\"a\", \"b\", \"c\", \"d\", \"e\"].map((value, i) =>\n store.observe(ALICE, [\n { key: \"contended\", value, confidence: 0.5, at: `2026-08-0${i + 1}T00:00:00.000Z` },\n ]),\n ),\n );\n\n const { facts } = await store.get(ALICE);\n expect(byKey(facts, \"contended\")).toHaveLength(1);\n });\n\n it(\"survives concurrent multi-key observations naming the keys in opposite orders\", async () => {\n // Every key lands, from both writers, with one current version each.\n //\n // This is deliberately the OBSERVABLE assertion, not a deadlock probe:\n // an adapter that takes per-key locks lazily in caller order really can\n // deadlock on this shape (Postgres 40P01, reproduced directly), but the\n // window is too short to trigger reliably through the store API, and a\n // test that passes either way would only look like protection. The\n // ordering discipline that avoids it lives in the adapter, with its\n // rationale; this pins what a product is entitled to rely on.\n const keys = [\"k1\", \"k2\", \"k3\", \"k4\", \"k5\", \"k6\", \"k7\", \"k8\"];\n const forward = keys.map((key) => ({ key, value: `${key}-forward`, at: T.t1 }));\n const reverse = [...keys].reverse().map((key) => ({ key, value: `${key}-reverse`, at: T.t2 }));\n\n await Promise.all([store.observe(ALICE, forward), store.observe(ALICE, reverse)]);\n\n const { facts } = await store.get(ALICE);\n expect(facts.map((f) => f.key).sort()).toEqual(keys);\n });\n\n it(\"refuses every spelling of a protected key, not just the canonical one\", async () => {\n // A prefix guard is only as strong as the key charset. Each of these\n // renders indistinguishably from `identity.uid` in a recall block, and\n // each was accepted before keys were constrained to a single spelling.\n for (const key of [\n \"identity.uid\",\n \" identity.uid\",\n \"Identity.uid\",\n \"IDENTITY.uid\",\n \"identity\\u2024uid\", // U+2024 ONE DOT LEADER\n \"\\u0131dentity.uid\", // U+0131 LATIN SMALL LETTER DOTLESS I\n ]) {\n const attempt = store.observe(ALICE, [{ key, value: \"user-bob\", confidence: 1, at: T.t1 }]);\n const written = await attempt.then(\n (results) => results[0]?.outcome === \"refused\" ? false : true,\n () => false, // rejected outright by key validation\n );\n expect(written, `key ${JSON.stringify(key)} must not be writable`).toBe(false);\n }\n\n const { facts } = await store.get(ALICE, { includeHistory: true });\n expect(facts).toEqual([]);\n });\n\n it(\"admits one canonical spelling per key, so no two facts look identical\", async () => {\n // NFC and NFD renderings of the same word produced two current facts\n // under an apparently identical key, with contradictory values.\n await expect(store.observe(ALICE, [{ key: \"pref.caf\\u00e9\", value: \"x\" }])).rejects.toThrow();\n await expect(store.observe(ALICE, [{ key: \"pref.cafe\\u0301\", value: \"x\" }])).rejects.toThrow();\n });\n\n it(\"rejects a confidence outside 0..1, which would pin a fact forever\", async () => {\n // `observe` is the MODEL path. An out-of-range confidence outranks every\n // honest observation, so a single poisoned write could make a false\n // health fact permanent; NaN is worse, since every comparison fails.\n await store.observe(ALICE, [{ key: \"allergy\", value: \"severe\", confidence: 0.9, at: T.t1 }]);\n\n for (const confidence of [999, -1, Number.NaN, Number.POSITIVE_INFINITY]) {\n await expect(\n store.observe(ALICE, [{ key: \"allergy\", value: \"none\", confidence, at: T.t2 }]),\n ).rejects.toThrow();\n }\n\n expect((await store.get(ALICE)).facts[0]).toMatchObject({ value: \"severe\" });\n });\n\n it(\"chains two observations of ONE key inside a single batch\", async () => {\n // The batch writer decides the whole call against one read of the\n // current versions, so a key observed twice must still see the first\n // observation's result — the second closes the version the first\n // inserted, which is why writes go out in rounds (the 011-013 review).\n const results = await store.observe(ALICE, [\n { key: \"city\", value: \"lisbon\", confidence: 0.5, at: T.t1 },\n { key: \"city\", value: \"porto\", confidence: 0.9, at: T.t2 },\n ]);\n\n expect(results.map((r) => r.outcome)).toEqual([\"inserted\", \"superseded\"]);\n const current = await store.get(ALICE);\n expect(byKey(current.facts, \"city\")).toHaveLength(1);\n expect(current.facts[0]).toMatchObject({ value: \"porto\" });\n\n const history = await store.get(ALICE, { includeHistory: true });\n expect(byKey(history.facts, \"city\")).toHaveLength(2);\n expect(history.facts.find((f) => f.value === \"lisbon\")).toMatchObject({\n supersededAt: T.t2,\n supersededBy: results[1]?.factId,\n });\n });\n\n it(\"refreshes inside a single batch the version that batch just inserted\", async () => {\n const results = await store.observe(ALICE, [\n { key: \"diet\", value: \"vegetarian\", confidence: 0.4, at: T.t1 },\n { key: \"diet\", value: \"vegetarian\", confidence: 0.8, at: T.t2 },\n ]);\n\n expect(results.map((r) => r.outcome)).toEqual([\"inserted\", \"refreshed\"]);\n const { facts } = await store.get(ALICE, { includeHistory: true });\n expect(byKey(facts, \"diet\")).toHaveLength(1);\n expect(facts[0]).toMatchObject({\n confidence: 0.8, // corroboration raises it\n observedAt: T.t1,\n lastSeenAt: T.t2,\n });\n });\n\n it(\"applies every outcome a mixed batch calls for, in one pass\", async () => {\n await store.observe(ALICE, [\n { key: \"a\", value: \"keep\", confidence: 0.9, at: T.t1 },\n { key: \"b\", value: \"old\", confidence: 0.3, at: T.t1 },\n { key: \"c\", value: \"strong\", confidence: 0.9, at: T.t1 },\n ]);\n\n const results = await store.observe(ALICE, [\n { key: \"a\", value: \"keep\", confidence: 0.95, at: T.t2 },\n { key: \"b\", value: \"new\", confidence: 0.6, at: T.t2 },\n { key: \"c\", value: \"weak\", confidence: 0.1, at: T.t2 },\n { key: \"d\", value: \"fresh\", confidence: 0.5, at: T.t2 },\n ]);\n\n expect(results.map((r) => r.outcome)).toEqual([\n \"refreshed\",\n \"superseded\",\n \"conflict\",\n \"inserted\",\n ]);\n const { facts } = await store.get(ALICE);\n expect(facts.map((f) => `${f.key}=${f.value}`).sort()).toEqual([\n \"a=keep\",\n \"b=new\",\n \"c=strong\",\n \"d=fresh\",\n ]);\n });\n\n it(\"applies a batch atomically: one invalid observation writes none of them\", async () => {\n await expect(\n store.observe(ALICE, [\n { key: \"good\", value: \"written?\", at: T.t1 },\n { key: \"bad\", value: \"x\", confidence: 42, at: T.t1 },\n ]),\n ).rejects.toThrow();\n\n await expect(store.get(ALICE)).resolves.toMatchObject({ facts: [] });\n });\n\n it(\"reports a replay as a replay, never as a refresh of the current belief\", async () => {\n // Replaying an old observation resolves to a CLOSED version. Calling\n // that `refreshed` told the caller its value was current when another\n // value was.\n await store.observe(ALICE, [{ key: \"city\", value: \"lisbon\", confidence: 0.5, at: T.t1 }]);\n await store.observe(ALICE, [{ key: \"city\", value: \"porto\", confidence: 0.6, at: T.t2 }]);\n\n const [result] = await store.observe(ALICE, [\n { key: \"city\", value: \"lisbon\", confidence: 0.5, at: T.t1 },\n ]);\n\n expect(result?.outcome).toBe(\"replayed\");\n expect((await store.get(ALICE)).facts[0]).toMatchObject({ value: \"porto\" });\n });\n\n it(\"bounds every caller-controlled size\", async () => {\n await expect(\n store.observe(ALICE, [{ key: \"k\", value: \"x\".repeat(100_000) }]),\n ).rejects.toThrow();\n await expect(\n store.observe(\n ALICE,\n Array.from({ length: 5_000 }, (_, i) => ({ key: `k${i}`, value: \"v\" })),\n ),\n ).rejects.toThrow();\n await expect(store.observe(ALICE, [{ key: \"k\", value: \"v\", ttlDays: 0.5 }])).rejects.toThrow();\n await expect(store.observe(ALICE, [{ key: \"k\", value: \"v\", ttlDays: -1 }])).rejects.toThrow();\n });\n\n it(\"accepts a batch whose observations are each within the citation limit\", async () => {\n // The per-observation limit is idsPerCall (1000); a batch of two such\n // observations is legal even though their citations SUM past it. The\n // in-memory reference pooled every citation into one bounded lookup and\n // rejected batches the Postgres adapter — which checks provenance per\n // observation — accepts, so a job tested green against the double\n // crashed against the real backend (the 011–013 review).\n const cite = (prefix: string) => Array.from({ length: 600 }, (_, i) => `${prefix}-${i}`);\n const results = await store.observe(ALICE, [\n { key: \"wide.a\", value: \"v\", sourceEpisodeIds: cite(\"a\") },\n { key: \"wide.b\", value: \"v\", sourceEpisodeIds: cite(\"b\") },\n ]);\n\n expect(results.map((r) => r.outcome)).toEqual([\"inserted\", \"inserted\"]);\n });\n\n it(\"rejects an invalid scope even on no-op calls\", async () => {\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.get(bad)).rejects.toThrow();\n await expect(store.observe(bad, [])).rejects.toThrow();\n await expect(store.setProtected(bad, [])).rejects.toThrow();\n await expect(store.invalidateBySource(bad, [], T.t3)).rejects.toThrow();\n });\n\n it(\"returns defensive copies — mutating a result never corrupts the store\", async () => {\n await store.observe(ALICE, [{ key: \"stable\", value: \"original\", at: T.t1 }]);\n\n const first = await store.get(ALICE);\n (first.facts[0] as { value: string }).value = \"mutated\";\n\n const second = await store.get(ALICE);\n expect(second.facts[0]?.value).toBe(\"original\");\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type {\n AccessEvent,\n EpisodeStore,\n ErasureWatermarkStore,\n MemoryErasure,\n ProfileStore,\n Scope,\n} from \"@alma-harness/core\";\n\n/**\n * Shared `MemoryErasure` contract suite — §6.7, §10, spec 011.\n *\n * The caller supplies the wired implementation (the orchestrator from\n * `@alma-harness/memory` over its own stores) plus the stores themselves, so\n * the suite can arrange data and verify the outcome through the same seams a\n * product would use. This is the LGPD/GDPR story as a test: content gone,\n * derived data invalidated, every declared copy surface reached.\n */\nexport interface MemoryErasureFactory {\n create(): Promise<MemoryErasureFixture> | MemoryErasureFixture;\n destroy?(fixture: MemoryErasureFixture): Promise<void> | void;\n}\n\nexport interface MemoryErasureFixture {\n erasure: MemoryErasure;\n episodes: EpisodeStore;\n profile: ProfileStore;\n /**\n * REQUIRED — spec: erasure-reaches-the-claims. Both used to be optional and\n * six cases returned silently without them, so an adapter with no in-flight\n * guard and no trail was green on both. A fixture that cannot supply them\n * has nothing to prove here.\n */\n watermarks: ErasureWatermarkStore;\n /** Events the wired `AuditLog` received — the erasure trail (§6.8, §10). */\n accessEvents: readonly AccessEvent[];\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\n\nexport function describeMemoryErasureContract(name: string, factory: MemoryErasureFactory): void {\n describe(`MemoryErasure contract: ${name}`, () => {\n let fx: MemoryErasureFixture;\n\n beforeEach(async () => {\n fx = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(fx);\n });\n\n /** An episode plus a profile fact that cites it — the provenance chain. */\n async function seedSupportedFact(scope: Scope, sessionId: string, marker: string) {\n const episode = await fx.episodes.append(scope, {\n kind: \"conversation\",\n summary: `${marker} disclosed something sensitive`,\n source: { sessionId },\n });\n await fx.profile.observe(scope, [\n { key: `derived.${marker}`, value: marker, sourceEpisodeIds: [episode.id] },\n ]);\n return episode;\n }\n\n it(\"erases an episode: content blanked, out of recall, and its derived facts invalidated\", async () => {\n // Spec 010 AC 4 — the whole chain in one assertion block, because\n // deleting \"just the doc\" lies (§6.7).\n const doomed = await seedSupportedFact(ALICE, \"s1\", \"doomed\");\n const kept = await seedSupportedFact(ALICE, \"s2\", \"kept\");\n\n const report = await fx.erasure.erase(ALICE, {\n kind: \"episodes\",\n episodeIds: [doomed.id],\n });\n\n expect(report.tombstonesWritten).toBe(1);\n expect(report.derivedInvalidated).toBe(1);\n expect(report.complete).toBe(true);\n\n const [tombstone] = await fx.episodes.get(ALICE, [doomed.id]);\n expect(tombstone).toMatchObject({ summary: \"\", state: \"tombstoned\", erasedAt: report.erasedAt });\n\n await expect(fx.episodes.query(ALICE, { text: \"doomed\" })).resolves.toMatchObject({\n episodes: [],\n });\n\n const { facts } = await fx.profile.get(ALICE);\n expect(facts.map((f) => f.key)).toEqual([\"derived.kept\"]);\n expect((await fx.episodes.get(ALICE, [kept.id]))[0]).toMatchObject({ state: \"active\" });\n });\n\n it(\"erases a session's episodes and nothing outside it\", async () => {\n const doomed = await seedSupportedFact(ALICE, \"doomed-session\", \"alpha\");\n const kept = await seedSupportedFact(ALICE, \"kept-session\", \"beta\");\n\n const report = await fx.erasure.erase(ALICE, {\n kind: \"sessions\",\n sessionIds: [\"doomed-session\"],\n });\n\n expect(report.tombstonesWritten).toBe(1);\n expect((await fx.episodes.get(ALICE, [doomed.id]))[0]).toMatchObject({ state: \"tombstoned\" });\n expect((await fx.episodes.get(ALICE, [kept.id]))[0]).toMatchObject({ state: \"active\" });\n expect((await fx.profile.get(ALICE)).facts.map((f) => f.key)).toEqual([\"derived.beta\"]);\n });\n\n it(\"erases the whole scope, invalidating even facts with no provenance link\", async () => {\n await seedSupportedFact(ALICE, \"s1\", \"sourced\");\n await fx.profile.observe(ALICE, [{ key: \"unsourced\", value: \"orphan fact\" }]);\n const theirs = await seedSupportedFact(BOB, \"s1\", \"theirs\");\n\n const report = await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n expect(report.derivedInvalidated).toBe(2);\n await expect(fx.profile.get(ALICE)).resolves.toMatchObject({ facts: [] });\n await expect(fx.episodes.query(ALICE, {})).resolves.toMatchObject({ episodes: [] });\n\n // Erasure is scoped: another user's memory is untouched.\n expect((await fx.episodes.get(BOB, [theirs.id]))[0]).toMatchObject({ state: \"active\" });\n expect((await fx.profile.get(BOB)).facts).toHaveLength(1);\n });\n\n it(\"names every copy surface both stores declare, and reports the erasure complete\", async () => {\n // Spec 010: adapters must DECLARE their copy surfaces so erase()\n // provably reaches all of them — \"provenance columns without a written\n // delete are not erasure\".\n await seedSupportedFact(ALICE, \"s1\", \"gamma\");\n\n const report = await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n const declared = [...fx.episodes.copySurfaces, ...fx.profile.copySurfaces];\n expect(declared.length).toBeGreaterThan(0);\n for (const surface of declared) {\n expect(report.surfaces).toContainEqual({\n name: surface.name,\n kind: surface.kind,\n reached: true,\n });\n }\n expect(report.complete).toBe(true);\n });\n\n it(\"stamps the scope's erasure watermark for the in-flight job guard\", async () => {\n // Spec 010: a batch result submitted before an erasure timestamp is\n // discarded — one timestamp comparison. Slice 013 does the comparing;\n // this tier owes it a durable, scoped timestamp.\n await expect(fx.watermarks.get(ALICE)).resolves.toBeNull();\n\n const report = await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n await expect(fx.watermarks.get(ALICE)).resolves.toBe(report.erasedAt);\n await expect(fx.watermarks.get(BOB)).resolves.toBeNull();\n });\n\n it(\"stops at the ORG boundary: erasing a uid in one org never touches its twin elsewhere\", async () => {\n // The suites pinned uid isolation but not org isolation — half the\n // tenancy boundary (the 011–013 review).\n const TWIN: Scope = { org: \"org-b\", uid: ALICE.uid };\n await seedSupportedFact(ALICE, \"s1\", \"mine\");\n const twin = await seedSupportedFact(TWIN, \"s1\", \"twin\");\n\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n expect((await fx.episodes.get(TWIN, [twin.id]))[0]).toMatchObject({ state: \"active\" });\n expect((await fx.profile.get(TWIN)).facts).toHaveLength(1);\n await expect(fx.watermarks.get(TWIN)).resolves.toBeNull();\n });\n\n it(\"never moves the watermark backwards, whatever clock stamps the second erasure\", async () => {\n // Two servers, one lagging clock: erasure B stamped 10s earlier than\n // erasure A must not LOWER the watermark — that re-admitted in-flight\n // writes A's guard had already refused as stale (the 011–013 review).\n await fx.watermarks.set(ALICE, \"2026-06-01T00:00:10.000Z\");\n await fx.watermarks.set(ALICE, \"2026-06-01T00:00:00.000Z\");\n\n await expect(fx.watermarks.get(ALICE)).resolves.toBe(\"2026-06-01T00:00:10.000Z\");\n });\n\n it(\"removes the CONTENT of every derived fact, not just its current flag\", async () => {\n // The failure this contract exists to catch: an invalidation that only\n // set a flag left the fact's value — content propagated upward from the\n // episode — readable through the export surface below, while the report\n // said the erasure was complete.\n const ep = await seedSupportedFact(ALICE, \"s1\", \"diagnosis\");\n\n await fx.erasure.erase(ALICE, { kind: \"episodes\", episodeIds: [ep.id] });\n\n const history = await fx.profile.get(ALICE, { includeHistory: true });\n expect(history.facts).toHaveLength(1);\n // The KEY goes too: keys are model-chosen, so a surviving\n // `health.hiv_status` would disclose the nature of what was erased on\n // the very surface a data subject is handed. What proves the erasure ran\n // is the audit trail, not a label left behind in the data.\n expect(history.facts[0]).toMatchObject({ key: \"\", value: \"\" });\n expect(JSON.stringify(history.facts[0])).not.toContain(\"diagnosis\");\n });\n\n it(\"leaves no label behind on a tombstoned episode either\", async () => {\n const ep = await fx.episodes.append(ALICE, {\n kind: \"clinical\",\n summary: \"disclosed something sensitive\",\n });\n\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n const [tombstone] = await fx.episodes.get(ALICE, [ep.id]);\n expect(tombstone).toMatchObject({ kind: \"\", summary: \"\", state: \"tombstoned\" });\n });\n\n it(\"discloses nothing about WHEN the erased data was last touched\", async () => {\n // Same standard episodes already meet: an erased memory must not leak\n // its own existence and timing.\n await fx.profile.observe(ALICE, [\n { key: \"sensitive\", value: \"content\", at: \"2026-06-01T00:00:00.000Z\" },\n ]);\n\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n const profile = await fx.profile.get(ALICE);\n expect(profile.facts).toEqual([]);\n expect(profile.updatedAt).not.toContain(\"2026-06-01\");\n });\n\n it(\"invalidates derived facts on a RE-RUN, so a half-failed erasure self-heals\", async () => {\n // The crash-recovery hole: if the tombstone pass commits and the\n // invalidation pass does not, the retry must still reach the profile\n // tier. Simulated by invalidating nothing on the first pass.\n const ep = await seedSupportedFact(ALICE, \"s1\", \"epsilon\");\n await fx.episodes.tombstone(ALICE, { kind: \"episodes\", episodeIds: [ep.id] }, new Date().toISOString());\n\n const recovery = await fx.erasure.erase(ALICE, { kind: \"episodes\", episodeIds: [ep.id] });\n\n expect(recovery.tombstonesWritten).toBe(0); // already blanked by the partial run\n expect(recovery.derivedInvalidated).toBe(1); // but the derived tier is reached\n await expect(fx.profile.get(ALICE)).resolves.toMatchObject({ facts: [] });\n });\n\n it(\"refuses an observation submitted from before the erasure\", async () => {\n // In-flight protection: work that started before an erasure must never\n // re-materialize what the erasure removed.\n const before = new Date(Date.now() - 60_000).toISOString();\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n const [result] = await fx.profile.observe(ALICE, [\n { key: \"resurrected\", value: \"erased content\", at: before },\n ]);\n\n expect(result?.outcome).toBe(\"stale\");\n await expect(fx.profile.get(ALICE)).resolves.toMatchObject({ facts: [] });\n });\n\n it(\"refuses a write that cites an episode this erasure removed\", async () => {\n // Backend-neutral because the timestamp guard is not enough: `at`\n // defaults to write time, so an in-flight job that omits it — the\n // documented default — is never stale by the clock. Provenance is the\n // guard that does not depend on the caller (spec 013 review).\n const ep = await fx.episodes.append(ALICE, { kind: \"clinical\", summary: \"disclosed\" });\n\n await fx.erasure.erase(ALICE, { kind: \"episodes\", episodeIds: [ep.id] });\n\n const [result] = await fx.profile.observe(ALICE, [\n // No `at` — \"now\", which the watermark comparison would wave through.\n { key: \"health.status\", value: \"positive\", sourceEpisodeIds: [ep.id] },\n ]);\n\n expect(result?.outcome).toBe(\"stale\");\n await expect(fx.profile.get(ALICE)).resolves.toMatchObject({ facts: [] });\n });\n\n it(\"refuses an episode stamped before the erasure, not only a fact\", async () => {\n // The episode tier was outside the guard entirely: an extraction in\n // flight during an erasure inserted a new derived id after the tombstone\n // pass, and the user's verbatim summary survived a `complete: true`.\n const before = new Date(Date.now() - 60_000).toISOString();\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n await expect(\n fx.episodes.append(ALICE, { kind: \"note\", summary: \"in flight\", at: before }),\n ).rejects.toThrow();\n });\n\n it(\"records a trail even when the erasure fails partway\", async () => {\n // Erasure destroys content across several transactions, and §6.8/§10\n // make the trail the proof a request was honored — a run cancelled\n // between them used to leave content gone and no durable evidence.\n const before = fx.accessEvents.length;\n\n await expect(\n fx.erasure.erase(ALICE, {\n kind: \"episodes\",\n episodeIds: Array.from({ length: 5_000 }, (_, i) => `id-${i}`),\n }),\n ).rejects.toThrow();\n\n // Rejected before anything was stamped or destroyed, so no trail is due.\n expect(fx.accessEvents.length).toBe(before);\n await expect(fx.watermarks.get(ALICE)).resolves.toBeNull();\n });\n\n it(\"leaves an audit trail proving the erasure ran, carrying no content\", async () => {\n // §6.8/§10: the watermark is overwritten by the next erasure, so without\n // a trail there is no durable evidence a data-subject request was met.\n await seedSupportedFact(ALICE, \"s1\", \"zeta\");\n\n await fx.erasure.erase(ALICE, { kind: \"all\" });\n\n const erasures = fx.accessEvents.filter((e) => e.action === \"delete\");\n expect(erasures).toHaveLength(1);\n expect(erasures[0]).toMatchObject({ scope: ALICE, action: \"delete\" });\n expect(JSON.stringify(erasures[0])).not.toContain(\"zeta\");\n });\n\n it(\"is idempotent: erasing twice writes no second tombstone\", async () => {\n const ep = await seedSupportedFact(ALICE, \"s1\", \"delta\");\n\n await fx.erasure.erase(ALICE, { kind: \"episodes\", episodeIds: [ep.id] });\n const second = await fx.erasure.erase(ALICE, { kind: \"episodes\", episodeIds: [ep.id] });\n\n expect(second.tombstonesWritten).toBe(0);\n expect(second.derivedInvalidated).toBe(0);\n });\n\n it(\"rejects an invalid scope\", async () => {\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(fx.erasure.erase(bad, { kind: \"all\" })).rejects.toThrow();\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type { Scope, SpendStore } from \"@alma-harness/core\";\n\n/**\n * Shared `SpendStore` contract suite — spec: spend-store. Pins what budget\n * enforcement is entitled to rely on, on any backend: atomic\n * increment-and-return, UTC day bucketing, session isolation by full scope,\n * org-wide day aggregation, and no lost increments under concurrency.\n *\n * Deliberately absent: any erasure surface. Spend counters are content-free\n * aggregates retained through scoped purge (spec: spend-store) — a store that\n * grows one is offering a budget reset, not a feature.\n *\n * ```ts\n * describeSpendStoreContract(\"PostgresSpendStore\", { create: () => … });\n * ```\n */\nexport interface SpendStoreFactory {\n /** Must return a store with ZERO totals for the scopes used by the suite. */\n create(): Promise<SpendStore> | SpendStore;\n destroy?(store: SpendStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\nconst OTHER_ORG: Scope = { org: \"org-b\", uid: \"user-alice\" };\n\n/** Pinned instants around one UTC midnight keep bucketing deterministic. */\nconst T = {\n day1: \"2026-08-24T10:00:00.000Z\",\n day1Late: \"2026-08-24T23:59:59.000Z\",\n day2: \"2026-08-25T00:00:00.000Z\",\n /** 01:00+02:00 on the 25th IS 23:00Z on the 24th. */\n day1ByOffset: \"2026-08-25T01:00:00+02:00\",\n} as const;\n\nexport function describeSpendStoreContract(name: string, factory: SpendStoreFactory): void {\n describe(`SpendStore contract: ${name}`, () => {\n let store: SpendStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n it(\"starts every counter at zero\", async () => {\n await expect(store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 })).resolves.toEqual({\n sessionUsd: 0,\n tenantDayUsd: 0,\n });\n });\n\n it(\"add returns the post-add totals and accumulates both counters\", async () => {\n const first = await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 0.5 });\n expect(first.sessionUsd).toBeCloseTo(0.5, 9);\n expect(first.tenantDayUsd).toBeCloseTo(0.5, 9);\n\n const second = await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 0.25 });\n expect(second.sessionUsd).toBeCloseTo(0.75, 9);\n expect(second.tenantDayUsd).toBeCloseTo(0.75, 9);\n\n const peeked = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n expect(peeked.sessionUsd).toBeCloseTo(0.75, 9);\n expect(peeked.tenantDayUsd).toBeCloseTo(0.75, 9);\n });\n\n it(\"isolates the session counter by sessionId, uid, and org — while the day counter aggregates the org\", async () => {\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 1 });\n await store.add({ scope: ALICE, sessionId: \"s2\", at: T.day1, usd: 2 });\n await store.add({ scope: BOB, sessionId: \"s1\", at: T.day1, usd: 4 });\n await store.add({ scope: OTHER_ORG, sessionId: \"s1\", at: T.day1, usd: 8 });\n\n const aliceS1 = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n // Same sessionId as BOB's and OTHER_ORG's — the full scope keys it.\n expect(aliceS1.sessionUsd).toBeCloseTo(1, 9);\n // The org's day: alice s1 + alice s2 + bob s1, across uids and sessions.\n expect(aliceS1.tenantDayUsd).toBeCloseTo(7, 9);\n\n const otherOrg = await store.peek({ scope: OTHER_ORG, sessionId: \"s1\", at: T.day1 });\n expect(otherOrg.sessionUsd).toBeCloseTo(8, 9);\n expect(otherOrg.tenantDayUsd).toBeCloseTo(8, 9);\n });\n\n it(\"buckets the day counter by UTC calendar day — the session counter has no day dimension\", async () => {\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 1 });\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1Late, usd: 2 });\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day2, usd: 4 });\n\n const onDay1 = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n expect(onDay1.tenantDayUsd).toBeCloseTo(3, 9); // day2's spend not here\n expect(onDay1.sessionUsd).toBeCloseTo(7, 9); // the session spans days\n\n const onDay2 = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day2 });\n expect(onDay2.tenantDayUsd).toBeCloseTo(4, 9); // the kill-switch resets at UTC midnight\n expect(onDay2.sessionUsd).toBeCloseTo(7, 9);\n });\n\n it(\"derives the day from the UTC instant, never from the timestamp's local offset\", async () => {\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1ByOffset, usd: 1 });\n\n const day1 = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n expect(day1.tenantDayUsd).toBeCloseTo(1, 9); // 01:00+02:00 on the 25th is the 24th in UTC\n const day2 = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day2 });\n expect(day2.tenantDayUsd).toBe(0);\n });\n\n it(\"accumulates fractional-cent amounts without rounding them away\", async () => {\n // A single step costs fractions of a cent; a backend column rounding to\n // cents would zero every real charge.\n for (let i = 0; i < 3; i++) {\n await store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 0.000002 });\n }\n\n const totals = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n expect(totals.sessionUsd).toBeCloseTo(0.000006, 9);\n });\n\n it(\"loses no increment under concurrent adds, and every returned total is a distinct running sum\", async () => {\n // Increment-and-return must be ATOMIC: two turns reading a stale total\n // and both proceeding is exactly the race the guard cannot fix from\n // outside the store (spec: spend-store).\n const results = await Promise.all(\n Array.from({ length: 20 }, () =>\n store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd: 0.01 }),\n ),\n );\n\n const totals = await store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 });\n expect(totals.sessionUsd).toBeCloseTo(0.2, 9);\n expect(totals.tenantDayUsd).toBeCloseTo(0.2, 9);\n const distinct = new Set(results.map((r) => r.sessionUsd.toFixed(8)));\n expect(distinct.size).toBe(20); // no two adds observed the same total\n });\n\n it(\"rejects a negative or non-finite spend, which would poison both counters\", async () => {\n // x + NaN = NaN, forever — and there is deliberately no delete surface\n // to reset a poisoned counter with.\n for (const usd of [-1, Number.NaN, Number.POSITIVE_INFINITY]) {\n await expect(\n store.add({ scope: ALICE, sessionId: \"s1\", at: T.day1, usd }),\n ).rejects.toThrow();\n }\n await expect(store.peek({ scope: ALICE, sessionId: \"s1\", at: T.day1 })).resolves.toEqual({\n sessionUsd: 0,\n tenantDayUsd: 0,\n });\n });\n\n it(\"buckets an offset-less timestamp identically on every backend — by the process clock, never the server's\", async () => {\n // JS reads an offset-less date-time as process-local; a backend that\n // let its OWN server interpret the string could put the same charge on\n // a different day than the reference store (the bug the episode tier\n // fixed once already).\n const local = \"2026-08-24T12:00:00\"; // no offset\n const day = new Date(Date.parse(local)).toISOString().slice(0, 10);\n await store.add({ scope: ALICE, sessionId: \"s1\", at: local, usd: 1 });\n\n const totals = await store.peek({\n scope: ALICE,\n sessionId: \"s1\",\n at: `${day}T12:00:00.000Z`,\n });\n expect(totals.tenantDayUsd).toBeCloseTo(1, 9);\n });\n\n it(\"rejects an invalid scope even on reads\", async () => {\n // Backend neutrality (§6): no adapter may skip central scope validation.\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.add({ scope: bad, sessionId: \"s1\", at: T.day1, usd: 1 })).rejects.toThrow();\n await expect(store.peek({ scope: bad, sessionId: \"s1\", at: T.day1 })).rejects.toThrow();\n });\n\n it(\"rejects an unparseable timestamp instead of inventing a bucket\", async () => {\n await expect(\n store.add({ scope: ALICE, sessionId: \"s1\", at: \"not a date\", usd: 1 }),\n ).rejects.toThrow();\n await expect(store.peek({ scope: ALICE, sessionId: \"s1\", at: \"not a date\" })).rejects.toThrow();\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type { CompletedTurn, Scope, TurnStore } from \"@alma-harness/core\";\n\n/**\n * Shared `TurnStore` contract suite — spec 030. Pins what the loop's turn\n * coordination is entitled to rely on, on any backend: exactly one winner per\n * session, a lease that expires so a crashed holder never blocks forever, a\n * stale release that touches nothing, a claim that replays a finished turn,\n * and erasure that reaches the stored reply.\n *\n * Timing is exercised with REAL time and small TTLs, deliberately. A fake\n * clock cannot reach a Postgres `now()`, and one that desynchronizes from the\n * `setTimeout` a wait is built on makes the reference store and the adapter\n * prove different things. An expiry is waited for through `acquire`'s own\n * `waitMs`, never a fixed sleep (spec: close-review-part-two).\n *\n * ```ts\n * describeTurnStoreContract(\"PostgresTurnStore\", { create: () => … });\n * ```\n */\nexport interface TurnStoreFactory {\n /** Must return a store holding NO leases or claims for the scopes below. */\n create(): Promise<TurnStore> | TurnStore;\n destroy?(store: TurnStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\nconst OTHER_ORG: Scope = { org: \"org-b\", uid: \"user-alice\" };\n\nconst NEVER_EXPIRES = { ttlMs: 60_000, waitMs: 0 } as const;\n\nfunction completedTurn(over: Partial<CompletedTurn> = {}): CompletedTurn {\n return {\n reply: { role: \"assistant\", blocks: [{ type: \"text\", text: \"the reply\" }] },\n terminalReason: \"completed\",\n stopReason: \"end_turn\",\n usage: { inputTokens: 10, outputTokens: 5 },\n costUsd: 0.00003,\n steps: 2,\n durationMs: 1234,\n turnId: \"turn-1\",\n at: \"2026-08-26T10:00:00.000Z\",\n ...over,\n };\n}\n\nconst key = (scope: Scope, sessionId: string, idempotencyKey: string) => ({\n scope,\n sessionId,\n idempotencyKey,\n});\n\nexport function describeTurnStoreContract(name: string, factory: TurnStoreFactory): void {\n describe(`TurnStore contract: ${name}`, () => {\n let store: TurnStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n // ---- The lease -------------------------------------------------------\n\n it(\"hands a free session to the caller, and refuses a held one once the wait expires\", async () => {\n const held = await store.acquire(ALICE, \"s1\", NEVER_EXPIRES);\n expect(held).not.toBeNull();\n\n // waitMs 0 is the fail-fast expression of the same call.\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.toBeNull();\n });\n\n it(\"picks exactly ONE winner among concurrent acquirers\", async () => {\n // The property the whole seam stands on: a lease handed to two holders\n // serializes nothing, and every other guarantee here rests on this one.\n const results = await Promise.all(\n Array.from({ length: 10 }, () => store.acquire(ALICE, \"s1\", NEVER_EXPIRES)),\n );\n\n expect(results.filter((r) => r !== null)).toHaveLength(1);\n });\n\n it(\"isolates leases by session, uid, and org\", async () => {\n await store.acquire(ALICE, \"s1\", NEVER_EXPIRES);\n\n // Same sessionId under a different uid and a different org, plus a\n // different session under the same uid — none of them is taken.\n for (const [scope, sessionId] of [\n [ALICE, \"s2\"],\n [BOB, \"s1\"],\n [OTHER_ORG, \"s1\"],\n ] as const) {\n await expect(store.acquire(scope, sessionId, NEVER_EXPIRES)).resolves.not.toBeNull();\n }\n });\n\n it(\"frees the session on release, so the next caller gets it\", async () => {\n const lease = (await store.acquire(ALICE, \"s1\", NEVER_EXPIRES))!;\n await store.release(ALICE, \"s1\", lease);\n\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.not.toBeNull();\n });\n\n it(\"ignores a STALE release instead of freeing the current holder's session\", async () => {\n // The failure this prevents: a holder whose lease expired releases the\n // lease the NEXT turn is holding, and the session serializes nothing\n // while appearing to.\n const stale = (await store.acquire(ALICE, \"s1\", { ttlMs: 100, waitMs: 0 }))!;\n // Waits on the expiry through `waitMs` itself — no fixed sleep (spec: close-review-part-two).\n const current = (await store.acquire(ALICE, \"s1\", { ttlMs: 60_000, waitMs: 2_000 }))!;\n expect(current.token).not.toBe(stale.token);\n\n await store.release(ALICE, \"s1\", stale);\n\n // Still held by `current`.\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.toBeNull();\n await store.release(ALICE, \"s1\", current);\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.not.toBeNull();\n });\n\n it(\"lets a later caller take a lease whose TTL expired — a crashed holder never blocks a session forever\", async () => {\n await store.acquire(ALICE, \"s1\", { ttlMs: 100, waitMs: 0 }); // never released\n\n await expect(store.acquire(ALICE, \"s1\", { ttlMs: 60_000, waitMs: 2_000 })).resolves.not.toBeNull();\n });\n\n it(\"WAITS for a busy session and takes it when the holder releases inside the window\", async () => {\n const lease = (await store.acquire(ALICE, \"s1\", { ttlMs: 60_000, waitMs: 0 }))!;\n const waiting = store.acquire(ALICE, \"s1\", { ttlMs: 60_000, waitMs: 2_000 });\n // Released well inside the wait; the waiter must get it rather than\n // burning its whole window.\n setTimeout(() => void store.release(ALICE, \"s1\", lease), 30);\n\n await expect(waiting).resolves.not.toBeNull();\n });\n\n it(\"releases idempotently — a second release is not another holder's release\", async () => {\n const lease = (await store.acquire(ALICE, \"s1\", NEVER_EXPIRES))!;\n await store.release(ALICE, \"s1\", lease);\n const next = (await store.acquire(ALICE, \"s1\", NEVER_EXPIRES))!;\n\n await store.release(ALICE, \"s1\", lease); // the first holder, again\n\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.toBeNull();\n await store.release(ALICE, \"s1\", next);\n });\n\n // ---- The claim -------------------------------------------------------\n\n it(\"reports a first claim fresh, and replays it once completed\", async () => {\n const k = key(ALICE, \"s1\", \"wamid-1\");\n await expect(store.claim(k)).resolves.toEqual({ status: \"fresh\" });\n\n const completed = completedTurn();\n await store.complete(k, completed);\n\n const claim = await store.claim(k);\n expect(claim.status).toBe(\"replay\");\n expect(claim.status === \"replay\" && claim.completed).toEqual(completed);\n });\n\n it(\"replays a FAILED turn as faithfully as a successful one\", async () => {\n // A failed turn is a RESULT. Replaying it is what stops a retry from\n // re-running and re-charging.\n const k = key(ALICE, \"s1\", \"wamid-err\");\n await store.claim(k);\n const completed = completedTurn({\n terminalReason: \"error\",\n stopReason: null,\n reply: { role: \"assistant\", blocks: [] },\n });\n await store.complete(k, completed);\n\n const claim = await store.claim(k);\n expect(claim.status === \"replay\" && claim.completed).toEqual(completed);\n });\n\n it(\"reports an IN-FLIGHT claim fresh — a crashed turn must be runnable again\", async () => {\n // Only reachable after a crash: the lease makes concurrency impossible.\n // The turn produced no result, so there is nothing to replay and\n // re-running is the correct answer (spec 030's named crash window).\n const k = key(ALICE, \"s1\", \"wamid-crash\");\n await store.claim(k);\n\n await expect(store.claim(k)).resolves.toEqual({ status: \"fresh\" });\n });\n\n it(\"refuses a malformed reply identically on every adapter\", async () => {\n // Spec 040, the sibling of `SessionStore.append`'s case and the reason\n // that slice fixed the CLASS: the same divergence was documented in two\n // contracts and closed in neither. The loop repairs before it gets here,\n // but best-effort — its catch keeps the unrepaired message.\n const k = key(ALICE, \"s1\", \"wamid-malformed\");\n await store.claim(k);\n\n await expect(\n store.complete(k, completedTurn({\n reply: { role: \"assistant\", blocks: [{ type: \"text\", text: `bad \\ud83d end` }] },\n })),\n ).rejects.toThrow(/completed/);\n // The claim is untouched: a refused write leaves the turn re-runnable\n // rather than half-recorded.\n await expect(store.claim(k)).resolves.toEqual({ status: \"fresh\" });\n });\n\n it(\"refuses a malformed reply even for a claim that no longer exists\", async () => {\n // The ordering that keeps the two adapters honest: Postgres parses\n // `$5::jsonb` whether or not the UPDATE matches a row, so the guard runs\n // before the update-only test in the in-memory reference too. Checking\n // after it would have closed one divergence by opening another.\n const k = key(ALICE, \"s-erased\", \"wamid-gone\");\n await store.claim(k);\n await store.erase(ALICE, \"s-erased\");\n\n await expect(\n store.complete(k, completedTurn({\n reply: { role: \"assistant\", blocks: [{ type: \"text\", text: `bad \\ud83d end` }] },\n })),\n ).rejects.toThrow(/completed/);\n });\n\n it(\"makes a claim runnable again after abandon\", async () => {\n const k = key(ALICE, \"s1\", \"wamid-2\");\n await store.claim(k);\n await store.complete(k, completedTurn());\n await store.abandon(k);\n\n await expect(store.claim(k)).resolves.toEqual({ status: \"fresh\" });\n });\n\n it(\"isolates claims by key, session, uid, and org\", async () => {\n const k = key(ALICE, \"s1\", \"shared-key\");\n await store.claim(k);\n await store.complete(k, completedTurn());\n\n // The same idempotency key is only unique within the transport that\n // issued it; a global key space would let one tenant's retry collide\n // with another's.\n for (const other of [\n key(ALICE, \"s1\", \"different-key\"),\n key(ALICE, \"s2\", \"shared-key\"),\n key(BOB, \"s1\", \"shared-key\"),\n key(OTHER_ORG, \"s1\", \"shared-key\"),\n ]) {\n await expect(store.claim(other)).resolves.toEqual({ status: \"fresh\" });\n }\n });\n\n it(\"round-trips a reply with astral characters intact\", async () => {\n // The reply is stored verbatim and read back into a model request; a\n // backend that mangles surrogate pairs would corrupt it (spec 025).\n const k = key(ALICE, \"s1\", \"wamid-emoji\");\n await store.claim(k);\n const completed = completedTurn({\n reply: { role: \"assistant\", blocks: [{ type: \"text\", text: \"até logo 👋🏽 家\" }] },\n });\n await store.complete(k, completed);\n\n const claim = await store.claim(k);\n expect(claim.status === \"replay\" && claim.completed.reply).toEqual(completed.reply);\n });\n\n it(\"does not resurrect a claim erased while its turn was still running\", async () => {\n // Erasure wins over work that started before it — the rule the memory\n // tier spells out as the `stale` observe outcome (spec 011). A\n // `complete` that re-created the row would put the erased reply back.\n const k = key(ALICE, \"s1\", \"wamid-erased\");\n await store.claim(k);\n await store.erase(ALICE, \"s1\");\n\n await store.complete(k, completedTurn());\n\n await expect(store.claim(k)).resolves.toEqual({ status: \"fresh\" });\n });\n\n // ---- Erasure (§10) ---------------------------------------------------\n\n it(\"erases one session's claims and leaves its lease to the holder, so a turn in flight is not interleaved\", async () => {\n // Spec: close-review-part-two. The lease is the one-turn-per-session\n // guard, not content: removed under a live turn, a waiter would win\n // `acquire` mid-turn and the holder's release would match nothing.\n const target = key(ALICE, \"s1\", \"wamid-3\");\n const sibling = key(ALICE, \"s2\", \"wamid-3\");\n for (const k of [target, sibling]) {\n await store.claim(k);\n await store.complete(k, completedTurn());\n }\n const held = (await store.acquire(ALICE, \"s1\", NEVER_EXPIRES))!;\n\n await store.erase(ALICE, \"s1\");\n\n // The stored reply is gone — the record holds content, so §10 must reach it.\n await expect(store.claim(target)).resolves.toEqual({ status: \"fresh\" });\n // The session is still the holder's, and the holder can still free it.\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.toBeNull();\n await store.release(ALICE, \"s1\", held);\n await expect(store.acquire(ALICE, \"s1\", NEVER_EXPIRES)).resolves.not.toBeNull();\n const siblingClaim = await store.claim(sibling);\n expect(siblingClaim.status).toBe(\"replay\");\n });\n\n it(\"erases ONLY the named session, even when a sibling's id extends it\", async () => {\n // `sessionId` is not validated and never should be — a product using a\n // composite id (`\"platform/thread\"`, a migration's `\"s1/legacy\"`) is\n // making a reasonable choice. The reference store keyed claims as one\n // flat `scope/session/key` string and erased by prefix, so erasing `\"s1\"`\n // deleted `\"s1/legacy\"`'s stored reply; Postgres compares `session_id` by\n // SQL equality and was immune. The two adapters DIVERGED on erasure,\n // which is the one thing this suite exists to prevent — and the\n // sibling-session case above missed it because neither `\"s1\"` nor `\"s2\"`\n // is a prefix of the other (spec 033).\n const target = key(ALICE, \"s1\", \"wamid-5\");\n const extended = key(ALICE, \"s1/legacy\", \"wamid-5\");\n for (const k of [target, extended]) {\n await store.claim(k);\n await store.complete(k, completedTurn());\n }\n\n await store.erase(ALICE, \"s1\");\n\n await expect(store.claim(target)).resolves.toEqual({ status: \"fresh\" });\n const survivor = await store.claim(extended);\n expect(survivor.status).toBe(\"replay\");\n });\n\n it(\"erases every session in a scope without a sessionId, and stops at the scope boundary\", async () => {\n for (const [scope, sessionId] of [\n [ALICE, \"s1\"],\n [ALICE, \"s2\"],\n [BOB, \"s1\"],\n [OTHER_ORG, \"s1\"],\n ] as const) {\n const k = key(scope, sessionId, \"wamid-4\");\n await store.claim(k);\n await store.complete(k, completedTurn());\n }\n\n await store.erase(ALICE);\n\n await expect(store.claim(key(ALICE, \"s1\", \"wamid-4\"))).resolves.toEqual({ status: \"fresh\" });\n await expect(store.claim(key(ALICE, \"s2\", \"wamid-4\"))).resolves.toEqual({ status: \"fresh\" });\n for (const scope of [BOB, OTHER_ORG]) {\n const claim = await store.claim(key(scope, \"s1\", \"wamid-4\"));\n expect(claim.status).toBe(\"replay\");\n }\n });\n\n // ---- Scope validation ------------------------------------------------\n\n it(\"rejects an invalid scope on every surface\", async () => {\n // Backend neutrality (§6): no adapter may skip central scope validation.\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.acquire(bad, \"s1\", NEVER_EXPIRES)).rejects.toThrow();\n await expect(store.claim(key(bad, \"s1\", \"k\"))).rejects.toThrow();\n await expect(store.complete(key(bad, \"s1\", \"k\"), completedTurn())).rejects.toThrow();\n await expect(store.abandon(key(bad, \"s1\", \"k\"))).rejects.toThrow();\n await expect(store.erase(bad)).rejects.toThrow();\n });\n\n it(\"rejects a non-finite or negative lease duration instead of holding forever\", async () => {\n // A NaN ttl makes every expiry comparison false, so the lease reads as\n // live forever and the session is blocked until the process restarts.\n for (const opts of [\n { ttlMs: Number.NaN, waitMs: 0 },\n { ttlMs: -1, waitMs: 0 },\n { ttlMs: 1_000, waitMs: Number.NaN },\n ]) {\n await expect(store.acquire(ALICE, \"s1\", opts)).rejects.toThrow();\n }\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type { RoutineRun, RoutineRunStore, Scope } from \"@alma-harness/core\";\n\n/**\n * Shared `RoutineRunStore` contract suite — spec: postgres-routine-runs. Pins\n * the three reads the routine runner relies on (spec: routine-runner): the\n * same fire again, today's runs for the ceiling, the last run of an outcome\n * for the dedupe — and that a record is metadata that round-trips whole.\n *\n * ```ts\n * describeRoutineRunStoreContract(\"PostgresRoutineRunStore\", { create: () => … });\n * ```\n */\nexport interface RoutineRunStoreFactory {\n /** Must return a store holding NO runs for the scopes below. */\n create(): Promise<RoutineRunStore> | RoutineRunStore;\n destroy?(store: RoutineRunStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\nconst OTHER_ORG: Scope = { org: \"org-b\", uid: \"user-alice\" };\n\nconst T = {\n early: \"2026-08-24T08:00:00.000Z\",\n late: \"2026-08-24T20:00:00.000Z\",\n nextDay: \"2026-08-25T09:00:00.000Z\",\n /** 01:00+02:00 on the 25th IS 23:00Z on the 24th. */\n lateByOffset: \"2026-08-25T01:00:00+02:00\",\n} as const;\n\nfunction run(over: Partial<RoutineRun> & Pick<RoutineRun, \"id\" | \"startedAt\">): RoutineRun {\n return { routineId: \"briefing\", scope: ALICE, outcome: \"delivered\", costUsd: 0.01, ...over };\n}\n\nexport function describeRoutineRunStoreContract(name: string, factory: RoutineRunStoreFactory): void {\n describe(`RoutineRunStore contract: ${name}`, () => {\n let store: RoutineRunStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n it(\"round-trips a run whole, optional fields present when set and absent when not\", async () => {\n const full = run({\n id: \"r1\",\n startedAt: T.early,\n finishedAt: T.late,\n outcome: \"submitted\",\n reason: \"why\",\n costUsd: 0.000002,\n sessionId: \"s1\",\n turnId: \"t1\",\n handle: { provider: \"openai\", id: \"batch_1\", model: { provider: \"openai\", id: \"m\" } },\n deliveryHash: \"abc\",\n });\n const bare = run({ id: \"r2\", startedAt: T.late });\n await store.record(full);\n await store.record(bare);\n\n expect(await store.get(ALICE, \"briefing\", \"r1\")).toEqual(full);\n // Absent stays ABSENT: a `null` on one backend and nothing on another is a divergence.\n expect(await store.get(ALICE, \"briefing\", \"r2\")).toEqual(bare);\n });\n\n it(\"upserts by (scope, routine, run): a second record replaces the first\", async () => {\n await store.record(run({ id: \"r1\", startedAt: T.early, outcome: \"submitted\" }));\n await store.record(run({ id: \"r1\", startedAt: T.early, outcome: \"delivered\", finishedAt: T.late, deliveryHash: \"h\" }));\n\n expect(await store.get(ALICE, \"briefing\", \"r1\")).toMatchObject({ outcome: \"delivered\", deliveryHash: \"h\" });\n expect(await store.list(ALICE, \"briefing\")).toHaveLength(1);\n });\n\n it(\"resolves an unknown run to null\", async () => {\n await expect(store.get(ALICE, \"briefing\", \"never\")).resolves.toBeNull();\n });\n\n it(\"lists newest first; since is inclusive and compares instants; outcome filters; limit caps\", async () => {\n await store.record(run({ id: \"early\", startedAt: T.early }));\n await store.record(run({ id: \"late\", startedAt: T.late, outcome: \"duplicate\" }));\n await store.record(run({ id: \"offset\", startedAt: T.lateByOffset }));\n await store.record(run({ id: \"next\", startedAt: T.nextDay, outcome: \"refused\" }));\n\n expect((await store.list(ALICE, \"briefing\")).map((r) => r.id)).toEqual([\"next\", \"offset\", \"late\", \"early\"]);\n // Inclusive at the bound, and the offset stamp is the 24th in UTC — the day the ceiling counts.\n expect((await store.list(ALICE, \"briefing\", { since: T.late })).map((r) => r.id)).toEqual([\"next\", \"offset\", \"late\"]);\n expect((await store.list(ALICE, \"briefing\", { since: \"2026-08-24T00:00:00.000Z\" })).map((r) => r.id)).toEqual([\"next\", \"offset\", \"late\", \"early\"]);\n expect((await store.list(ALICE, \"briefing\", { since: \"2026-08-25T00:00:00.000Z\" })).map((r) => r.id)).toEqual([\"next\"]);\n expect((await store.list(ALICE, \"briefing\", { outcome: \"delivered\", limit: 1 })).map((r) => r.id)).toEqual([\"offset\"]);\n expect((await store.list(ALICE, \"briefing\", { outcome: \"refused\" })).map((r) => r.id)).toEqual([\"next\"]);\n expect(await store.list(ALICE, \"briefing\", { limit: 0 })).toEqual([]);\n });\n\n it(\"orders two runs at the same instant by id, on every backend\", async () => {\n // Spec: close-060-064-findings. The contract said \"newest first\" and the\n // two references filled the tie differently; `limit: 1` reads then\n // disagreed on which run was last.\n await store.record(run({ id: \"b\", startedAt: T.late }));\n await store.record(run({ id: \"a\", startedAt: T.late }));\n await store.record(run({ id: \"c\", startedAt: T.early }));\n\n expect((await store.list(ALICE, \"briefing\")).map((r) => r.id)).toEqual([\"a\", \"b\", \"c\"]);\n expect((await store.list(ALICE, \"briefing\", { limit: 1 })).map((r) => r.id)).toEqual([\"a\"]);\n });\n\n it(\"isolates runs by routine, uid and org\", async () => {\n await store.record(run({ id: \"r1\", startedAt: T.early }));\n await store.record(run({ id: \"r1\", startedAt: T.early, routineId: \"closing\" }));\n await store.record(run({ id: \"r1\", startedAt: T.early, scope: BOB }));\n await store.record(run({ id: \"r1\", startedAt: T.early, scope: OTHER_ORG }));\n\n expect(await store.list(ALICE, \"briefing\")).toHaveLength(1);\n expect(await store.list(ALICE, \"closing\")).toHaveLength(1);\n expect(await store.list(BOB, \"briefing\")).toHaveLength(1);\n expect(await store.list(OTHER_ORG, \"briefing\")).toHaveLength(1);\n await expect(store.get(ALICE, \"nothing\", \"r1\")).resolves.toBeNull();\n });\n\n it(\"rejects an invalid scope on every surface\", async () => {\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.record(run({ id: \"r1\", startedAt: T.early, scope: bad }))).rejects.toThrow();\n await expect(store.get(bad, \"briefing\", \"r1\")).rejects.toThrow();\n await expect(store.list(bad, \"briefing\")).rejects.toThrow();\n });\n\n it(\"rejects an unparseable since or startedAt rather than sorting it to the epoch\", async () => {\n await expect(store.record(run({ id: \"r1\", startedAt: \"not a date\" }))).rejects.toThrow();\n await store.record(run({ id: \"r2\", startedAt: T.early }));\n await expect(store.list(ALICE, \"briefing\", { since: \"not a date\" })).rejects.toThrow();\n });\n });\n}\n","import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\n\nimport type { Routine, RoutineStore, Scope } from \"@alma-harness/core\";\n\n/**\n * Shared `RoutineStore` contract suite — spec: clock-tick. What the tick\n * relies on: a routine round-trips whole with its registration stamp, the\n * stamp survives re-registration, cancel removes, and `list` sees every\n * scope while `get`/`cancel` are exact.\n */\nexport interface RoutineStoreFactory {\n /** Must return a store holding NO routines. */\n create(): Promise<RoutineStore> | RoutineStore;\n destroy?(store: RoutineStore): Promise<void> | void;\n}\n\nconst ALICE: Scope = { org: \"org-a\", uid: \"user-alice\" };\nconst BOB: Scope = { org: \"org-a\", uid: \"user-bob\" };\nconst OTHER_ORG: Scope = { org: \"org-b\", uid: \"user-alice\" };\n\nfunction routine(over: Partial<Routine> & Pick<Routine, \"id\">): Routine {\n return {\n scope: ALICE,\n schedule: { cron: \"0 8 * * 1-5\", tz: \"America/Sao_Paulo\" },\n goal: \"prepare the briefing\",\n intent: { tier: \"mechanical\", sensitivity: \"internal\" },\n toolProfile: \"briefing\",\n budget: { perTurnUsd: 0.2 },\n outputSink: \"inbox\",\n maxRunsPerDay: 2,\n ...over,\n };\n}\n\nexport function describeRoutineStoreContract(name: string, factory: RoutineStoreFactory): void {\n describe(`RoutineStore contract: ${name}`, () => {\n let store: RoutineStore;\n\n beforeEach(async () => {\n store = await factory.create();\n });\n\n afterEach(async () => {\n await factory.destroy?.(store);\n });\n\n it(\"registers a routine stamped with the time, round-trips it whole, and keeps the anchor on re-registration\", async () => {\n const before = Date.now();\n await store.register(routine({ id: \"briefing\" }));\n\n const stored = await store.get(ALICE, \"briefing\");\n expect(stored).toMatchObject(routine({ id: \"briefing\" }));\n const at = Date.parse(stored!.registeredAt);\n expect(Number.isNaN(at)).toBe(false);\n expect(at).toBeGreaterThanOrEqual(before - 1000);\n\n await store.register(routine({ id: \"briefing\", goal: \"prepare the briefing, shorter\" }));\n const edited = await store.get(ALICE, \"briefing\");\n expect(edited).toMatchObject({ goal: \"prepare the briefing, shorter\", registeredAt: stored!.registeredAt });\n });\n\n it(\"keeps a supplied registration stamp on first registration — a migration keeps its anchors — and ignores it on re-registration\", async () => {\n await store.register({ ...routine({ id: \"moved\" }), registeredAt: \"2026-01-01T00:00:00.000Z\" });\n expect((await store.get(ALICE, \"moved\"))?.registeredAt).toBe(\"2026-01-01T00:00:00.000Z\");\n\n await store.register({ ...routine({ id: \"moved\" }), registeredAt: \"2026-06-01T00:00:00.000Z\" });\n expect((await store.get(ALICE, \"moved\"))?.registeredAt).toBe(\"2026-01-01T00:00:00.000Z\");\n await expect(store.register({ ...routine({ id: \"bad\" }), registeredAt: \"not a date\" })).rejects.toThrow();\n });\n\n it(\"cancels a routine, after which get is null and list omits it\", async () => {\n await store.register(routine({ id: \"briefing\" }));\n await store.register(routine({ id: \"closing\", execution: \"job\", toolProfile: undefined as never }));\n\n await store.cancel(ALICE, \"briefing\");\n\n await expect(store.get(ALICE, \"briefing\")).resolves.toBeNull();\n expect((await store.list()).map((r) => r.id)).toEqual([\"closing\"]);\n // Cancelling what is not there is a no-op.\n await expect(store.cancel(ALICE, \"briefing\")).resolves.toBeUndefined();\n });\n\n it(\"lists every routine of every scope — the tick is a deployment read\", async () => {\n await store.register(routine({ id: \"briefing\" }));\n await store.register(routine({ id: \"briefing\", scope: BOB }));\n await store.register(routine({ id: \"briefing\", scope: OTHER_ORG }));\n\n const all = await store.list();\n expect(all).toHaveLength(3);\n expect(all.map((r) => `${r.scope.org}/${r.scope.uid}`).sort()).toEqual([\"org-a/user-alice\", \"org-a/user-bob\", \"org-b/user-alice\"]);\n });\n\n it(\"isolates get and cancel by scope and id\", async () => {\n await store.register(routine({ id: \"briefing\" }));\n await store.register(routine({ id: \"briefing\", scope: BOB, goal: \"bob's\" }));\n\n await store.cancel(OTHER_ORG, \"briefing\");\n await store.cancel(ALICE, \"closing\");\n\n expect((await store.get(ALICE, \"briefing\"))?.goal).toBe(\"prepare the briefing\");\n expect((await store.get(BOB, \"briefing\"))?.goal).toBe(\"bob's\");\n await expect(store.get(OTHER_ORG, \"briefing\")).resolves.toBeNull();\n });\n\n it(\"rejects an invalid scope on every surface\", async () => {\n const bad: Scope = { org: \"../evil\", uid: \"user-1\" };\n await expect(store.register(routine({ id: \"r\", scope: bad }))).rejects.toThrow();\n await expect(store.get(bad, \"r\")).rejects.toThrow();\n await expect(store.cancel(bad, \"r\")).rejects.toThrow();\n });\n });\n}\n"],"mappings":"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","names":["afterEach","beforeEach","describe","expect","it","ALICE","BOB","OTHER_ORG","afterEach","beforeEach","describe","expect","it","ALICE","BOB","T","key","afterEach","beforeEach","describe","expect","it","ALICE","BOB","afterEach","beforeEach","describe","expect","it","ALICE","BOB","OTHER_ORG","T","afterEach","beforeEach","describe","expect","it","ALICE","BOB","OTHER_ORG","afterEach","beforeEach","describe","expect","it","ALICE","BOB","OTHER_ORG","T","afterEach","beforeEach","describe","expect","it","ALICE","BOB","OTHER_ORG"]}