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 · 80 lines typescript
Raw Blame History
1/**2 * KHAELOR3 * File: tests/workspace/file-times.test.ts4 * Description: Unit tests for the FileTimeRegistry — read-before-write and external-modification detection.5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910import { mkdtempSync, rmSync, writeFileSync } from "node:fs";11import { tmpdir } from "node:os";12import * as path from "node:path";13import { afterEach, beforeEach, describe, expect, it } from "vitest";14import { InMemoryFileTimeRegistry } from "../../src/workspace/index.js";1516let dir: string;17let registry: InMemoryFileTimeRegistry;1819beforeEach(() => {20  dir = mkdtempSync(path.join(tmpdir(), "khaelor-ft-"));21  registry = new InMemoryFileTimeRegistry();22});2324afterEach(() => {25  rmSync(dir, { recursive: true, force: true });26});2728describe("FileTimeRegistry", () => {29  it("reports unread for files never stamped", () => {30    expect(registry.check(path.join(dir, "unknown.ts"), "anything")).toBe("unread");31    expect(registry.get(path.join(dir, "unknown.ts"))).toBeUndefined();32  });3334  it("reports clean when disk content matches the stamped content", () => {35    const file = path.join(dir, "a.ts");36    writeFileSync(file, "const a = 1;\n");37    registry.stamp(file, "const a = 1;\n");38    expect(registry.check(file, "const a = 1;\n")).toBe("clean");39  });4041  it("detects external modification when content changed since the stamp", () => {42    const file = path.join(dir, "b.ts");43    writeFileSync(file, "original\n");44    registry.stamp(file, "original\n");45    writeFileSync(file, "changed by the user\n");46    expect(registry.check(file, "changed by the user\n")).toBe("externally-modified");47  });4849  it("records path, size, sha256, mtime and timestamp", () => {50    const file = path.join(dir, "c.ts");51    writeFileSync(file, "abc");52    const before = Date.now();53    registry.stamp(file, "abc");54    const stamp = registry.get(file);55    expect(stamp).toBeDefined();56    expect(stamp?.path).toBe(file);57    expect(stamp?.size).toBe(3);58    expect(stamp?.sha256).toMatch(/^[0-9a-f]{64}$/);59    expect(stamp?.mtimeMs).toBeGreaterThan(0);60    expect(stamp?.at).toBeGreaterThanOrEqual(before);61  });6263  it("re-stamping after an agent write returns the file to clean", () => {64    const file = path.join(dir, "d.ts");65    writeFileSync(file, "v1");66    registry.stamp(file, "v1");67    writeFileSync(file, "v2");68    expect(registry.check(file, "v2")).toBe("externally-modified");69    registry.stamp(file, "v2");70    expect(registry.check(file, "v2")).toBe("clean");71  });7273  it("normalizes paths so relative and absolute forms agree", () => {74    const file = path.join(dir, "e.ts");75    writeFileSync(file, "x");76    registry.stamp(file, "x");77    expect(registry.get(path.join(dir, ".", "e.ts"))?.path).toBe(file);78  });79});80