SPB Git

spb/khaelor Public

KHAELOR — a terminal-native autonomous engineering agent powered by Anthropic.

TypeScript 82.9% HTML 14.9% CSS 1.1% JavaScript 0.7%
3.6 KB · 93 lines typescript
Raw Blame History
1/**2 * KHAELOR3 * File: tests/context/checkpoint.test.ts4 * Description: Checkpoint tests — deterministic serialization and byte-faithful round-trips.5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910import { describe, expect, it } from "vitest";11import { emptyCheckpoint, parseCheckpoint, serializeCheckpoint } from "../../src/context/index.js";12import type { Checkpoint } from "../../src/context/index.js";1314const RICH: Checkpoint = {15  objective: "Implement persistent session recovery for the store",16  completed: ["Journaled events atomically", "Startup restores interrupted sessions"],17  currentState: "Recovery works.\nRemaining: torn-write edge cases\nand resume tests.",18  importantFiles: [19    { path: "src/session/store.ts", reason: "owns the JSONL append path: critical" },20    { path: "src/session/events.ts", reason: "event catalog" },21  ],22  changes: ["src/session/store.ts: added fsync at loop boundaries"],23  failedAttempts: ["- tried rename-based journaling first; too slow on APFS"],24  decisions: ['kept "write-ahead" ordering: append before publish'],25  runningProcesses: [{ id: "proc_1", command: "npm run dev", status: "running" }],26  nextSteps: ["add torn-write tests", "measure resume at 10K events"],27  rawEvidence: [28    {29      label: "failing test output",30      content: "FAIL tests/store.test.ts\n\n  expected 3 events\n  received 2",31    },32  ],33};3435describe("serializeCheckpoint", () => {36  it("is deterministic — same checkpoint, byte-identical text", () => {37    expect(serializeCheckpoint(RICH)).toBe(serializeCheckpoint(RICH));38  });3940  it("omits raw_evidence when absent and renders empty lists as []", () => {41    const text = serializeCheckpoint(emptyCheckpoint());42    expect(text).toContain("completed: []");43    expect(text).toContain("running_processes: []");44    expect(text).not.toContain("raw_evidence");45  });46});4748describe("parseCheckpoint round-trip", () => {49  it("round-trips a rich checkpoint exactly", () => {50    const parsed = parseCheckpoint(serializeCheckpoint(RICH));51    expect(parsed.ok).toBe(true);52    if (parsed.ok) expect(parsed.value).toEqual(RICH);53  });5455  it("round-trips an empty checkpoint", () => {56    const parsed = parseCheckpoint(serializeCheckpoint(emptyCheckpoint()));57    expect(parsed.ok).toBe(true);58    if (parsed.ok) expect(parsed.value).toEqual(emptyCheckpoint());59  });6061  it("round-trips awkward strings (leading dash, colons, quotes, trailing newline, empty)", () => {62    const awkward: Checkpoint = {63      ...emptyCheckpoint(),64      objective: "",65      currentState: "ends with newline\n",66      completed: ["- looks like a list item", 'has "quotes" and: a colon', "  padded  "],67      decisions: ["multi\nline\ndecision", "line with\n\nan empty line inside"],68    };69    const parsed = parseCheckpoint(serializeCheckpoint(awkward));70    expect(parsed.ok).toBe(true);71    if (parsed.ok) expect(parsed.value).toEqual(awkward);72  });7374  it("re-serializing a parsed checkpoint is byte-identical (canonical form)", () => {75    const text = serializeCheckpoint(RICH);76    const parsed = parseCheckpoint(text);77    expect(parsed.ok).toBe(true);78    if (parsed.ok) expect(serializeCheckpoint(parsed.value)).toBe(text);79  });8081  it("tolerates unknown top-level keys", () => {82    const text = serializeCheckpoint(RICH) + "future_field: something\n  - nested thing\n";83    const parsed = parseCheckpoint(text);84    expect(parsed.ok).toBe(true);85    if (parsed.ok) expect(parsed.value).toEqual(RICH);86  });8788  it("rejects text with no checkpoint keys", () => {89    const parsed = parseCheckpoint("this is just prose, not a checkpoint");90    expect(parsed.ok).toBe(false);91  });92});93