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%
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