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%
2.7 KB · 68 lines typescript
Raw Blame History
1/**2 * KHAELOR3 * File: tests/memory/memory.test.ts4 * Description: Project-memory tests — parse/append round-trip, provenance anchors, purge candidates (v2 §5).5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910import { describe, expect, it } from "vitest";11import { appendMemoryEntry, parseMemory, purgeCandidates } from "../../src/memory/index.js";1213const PROVENANCE = {14  session: "01ABCDEF",15  tool: "toolu_1",16  confidence: "high" as const,17  date: "2026-08-10",18};1920describe("project memory", () => {21  it("creates the file with a header and section on first append", () => {22    const content = appendMemoryEntry(null, {23      section: "conventions",24      text: "Errors flow through Result<T, KError>, never throw in src/core.",25      provenance: PROVENANCE,26    });27    expect(content).toContain("# Project memory");28    expect(content).toContain("## Conventions");29    expect(content).toContain("- Errors flow through Result");30    expect(content).toContain("<!-- khaelor: session=01ABCDEF tool=toolu_1 confidence=high date=2026-08-10 -->");31  });3233  it("round-trips entries with provenance through parseMemory", () => {34    let content = appendMemoryEntry(null, { section: "commands", text: "Build: npm run check", provenance: PROVENANCE });35    content = appendMemoryEntry(content, {36      section: "pitfalls",37      text: "Never touch the render buffer outside the 16ms tick.",38      provenance: { ...PROVENANCE, confidence: "medium" },39    });40    const entries = parseMemory(content);41    expect(entries).toHaveLength(2);42    expect(entries[0]?.section).toBe("Commands");43    expect(entries[0]?.provenance?.confidence).toBe("high");44    expect(entries[1]?.section).toBe("Pitfalls");45    expect(entries[1]?.provenance?.tool).toBe("toolu_1");46  });4748  it("appends into an existing section, not a duplicate one", () => {49    let content = appendMemoryEntry(null, { section: "commands", text: "Build: npm run check", provenance: PROVENANCE });50    content = appendMemoryEntry(content, { section: "commands", text: "Test: npm test", provenance: PROVENANCE });51    expect(content.match(/## Commands/g)).toHaveLength(1);52    const entries = parseMemory(content);53    expect(entries.filter((entry) => entry.section === "Commands")).toHaveLength(2);54  });5556  it("flags low-confidence entries as purge candidates (v2 §5.4)", () => {57    let content = appendMemoryEntry(null, { section: "notes", text: "Solid fact.", provenance: PROVENANCE });58    content = appendMemoryEntry(content, {59      section: "notes",60      text: "Shaky guess.",61      provenance: { ...PROVENANCE, confidence: "low" },62    });63    const candidates = purgeCandidates(parseMemory(content));64    expect(candidates).toHaveLength(1);65    expect(candidates[0]?.text).toContain("Shaky guess");66  });67});68