/** * KHAELOR * File: tests/context/checkpoint.test.ts * Description: Checkpoint tests — deterministic serialization and byte-faithful round-trips. * * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai */ import { describe, expect, it } from "vitest"; import { emptyCheckpoint, parseCheckpoint, serializeCheckpoint } from "../../src/context/index.js"; import type { Checkpoint } from "../../src/context/index.js"; const RICH: Checkpoint = { objective: "Implement persistent session recovery for the store", completed: ["Journaled events atomically", "Startup restores interrupted sessions"], currentState: "Recovery works.\nRemaining: torn-write edge cases\nand resume tests.", importantFiles: [ { path: "src/session/store.ts", reason: "owns the JSONL append path: critical" }, { path: "src/session/events.ts", reason: "event catalog" }, ], changes: ["src/session/store.ts: added fsync at loop boundaries"], failedAttempts: ["- tried rename-based journaling first; too slow on APFS"], decisions: ['kept "write-ahead" ordering: append before publish'], runningProcesses: [{ id: "proc_1", command: "npm run dev", status: "running" }], nextSteps: ["add torn-write tests", "measure resume at 10K events"], rawEvidence: [ { label: "failing test output", content: "FAIL tests/store.test.ts\n\n expected 3 events\n received 2", }, ], }; describe("serializeCheckpoint", () => { it("is deterministic — same checkpoint, byte-identical text", () => { expect(serializeCheckpoint(RICH)).toBe(serializeCheckpoint(RICH)); }); it("omits raw_evidence when absent and renders empty lists as []", () => { const text = serializeCheckpoint(emptyCheckpoint()); expect(text).toContain("completed: []"); expect(text).toContain("running_processes: []"); expect(text).not.toContain("raw_evidence"); }); }); describe("parseCheckpoint round-trip", () => { it("round-trips a rich checkpoint exactly", () => { const parsed = parseCheckpoint(serializeCheckpoint(RICH)); expect(parsed.ok).toBe(true); if (parsed.ok) expect(parsed.value).toEqual(RICH); }); it("round-trips an empty checkpoint", () => { const parsed = parseCheckpoint(serializeCheckpoint(emptyCheckpoint())); expect(parsed.ok).toBe(true); if (parsed.ok) expect(parsed.value).toEqual(emptyCheckpoint()); }); it("round-trips awkward strings (leading dash, colons, quotes, trailing newline, empty)", () => { const awkward: Checkpoint = { ...emptyCheckpoint(), objective: "", currentState: "ends with newline\n", completed: ["- looks like a list item", 'has "quotes" and: a colon', " padded "], decisions: ["multi\nline\ndecision", "line with\n\nan empty line inside"], }; const parsed = parseCheckpoint(serializeCheckpoint(awkward)); expect(parsed.ok).toBe(true); if (parsed.ok) expect(parsed.value).toEqual(awkward); }); it("re-serializing a parsed checkpoint is byte-identical (canonical form)", () => { const text = serializeCheckpoint(RICH); const parsed = parseCheckpoint(text); expect(parsed.ok).toBe(true); if (parsed.ok) expect(serializeCheckpoint(parsed.value)).toBe(text); }); it("tolerates unknown top-level keys", () => { const text = serializeCheckpoint(RICH) + "future_field: something\n - nested thing\n"; const parsed = parseCheckpoint(text); expect(parsed.ok).toBe(true); if (parsed.ok) expect(parsed.value).toEqual(RICH); }); it("rejects text with no checkpoint keys", () => { const parsed = parseCheckpoint("this is just prose, not a checkpoint"); expect(parsed.ok).toBe(false); }); });