6b7636b088
CI / check (pull_request) Failing after 3m6s
Breaking changes: - UWF_STORAGE_ROOT → UWF_HOME - WORKFLOW_STORAGE_ROOT removed (no fallback) - OCAS_DIR → OCAS_HOME (aligned with ocas CLI) Library functions no longer read process.env: - util-agent/storage.ts: resolveStorageRoot(override), getGlobalCasDir(override) - agent-hermes: isResumeDisabled(flag) pure function, CLI reads env - agent-claude-code: CLI reads CLAUDE_MODEL and passes to agent Fixes #37
115 lines
4.1 KiB
TypeScript
115 lines
4.1 KiB
TypeScript
import { mkdir, mkdtemp, rm } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { type CasRef, createThreadIndexEntry, type ThreadId } from "@united-workforce/protocol";
|
|
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
import { resolveHeadHash } from "../commands/shared.js";
|
|
import { addHistoryEntry, createUwfStore, setThread } from "../store.js";
|
|
|
|
let tmpDir: string;
|
|
|
|
beforeEach(async () => {
|
|
tmpDir = await mkdtemp(join(tmpdir(), "cli-uwf-resolve-head-"));
|
|
const casDir = join(tmpDir, "cas");
|
|
await mkdir(casDir, { recursive: true });
|
|
process.env.OCAS_HOME = casDir;
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await rm(tmpDir, { recursive: true, force: true });
|
|
});
|
|
|
|
describe("resolveHeadHash", () => {
|
|
test("returns head hash from variable store for active thread", async () => {
|
|
const threadId = "01JTEST0000000000000000001" as ThreadId;
|
|
const uwf = await createUwfStore(tmpDir);
|
|
const headHash = (await uwf.store.cas.put(uwf.schemas.text, "active")) as CasRef;
|
|
setThread(uwf.varStore, threadId, createThreadIndexEntry(headHash as CasRef));
|
|
|
|
const result = await resolveHeadHash(tmpDir, threadId);
|
|
|
|
expect(result).toBe(headHash);
|
|
});
|
|
|
|
test("falls back to history variable when thread not in active index", async () => {
|
|
const threadId = "01JTEST0000000000000000002" as ThreadId;
|
|
const workflowHash = "workflow_hash_789" as CasRef;
|
|
|
|
const uwf = await createUwfStore(tmpDir);
|
|
const headHash = (await uwf.store.cas.put(uwf.schemas.text, "completed-head")) as CasRef;
|
|
addHistoryEntry(uwf.varStore, {
|
|
thread: threadId,
|
|
workflow: workflowHash,
|
|
head: headHash,
|
|
completedAt: Date.now(),
|
|
reason: null,
|
|
});
|
|
|
|
const result = await resolveHeadHash(tmpDir, threadId);
|
|
|
|
expect(result).toBe(headHash);
|
|
});
|
|
|
|
// Note: Testing the error case requires CLI-level testing because resolveHeadHash
|
|
// calls fail() which does process.exit(1), terminating the test runner.
|
|
// The error behavior is tested in integration tests below via CLI invocation.
|
|
|
|
test("prioritizes active thread over history when thread exists in both", async () => {
|
|
const threadId = "01JTEST0000000000000000004" as ThreadId;
|
|
const workflowHash = "workflow_hash_xyz" as CasRef;
|
|
|
|
const uwf = await createUwfStore(tmpDir);
|
|
const activeHead = (await uwf.store.cas.put(uwf.schemas.text, "active-v2")) as CasRef;
|
|
const historicalHash = (await uwf.store.cas.put(uwf.schemas.text, "historical-v1")) as CasRef;
|
|
setThread(uwf.varStore, threadId, createThreadIndexEntry(activeHead));
|
|
addHistoryEntry(uwf.varStore, {
|
|
thread: threadId,
|
|
workflow: workflowHash,
|
|
head: historicalHash,
|
|
completedAt: Date.now(),
|
|
reason: null,
|
|
});
|
|
|
|
const result = await resolveHeadHash(tmpDir, threadId);
|
|
|
|
// Should return the active head, not the historical one
|
|
expect(result).toBe(activeHead);
|
|
});
|
|
|
|
test("finds thread from multiple history entries", async () => {
|
|
const threadId1 = "01JTEST0000000000000000005" as ThreadId;
|
|
const threadId2 = "01JTEST0000000000000000006" as ThreadId;
|
|
const threadId3 = "01JTEST0000000000000000007" as ThreadId;
|
|
const workflowHash = "workflow_hash_abc" as CasRef;
|
|
const uwf = await createUwfStore(tmpDir);
|
|
const hash1 = (await uwf.store.cas.put(uwf.schemas.text, "hash-thread1")) as CasRef;
|
|
const hash2 = (await uwf.store.cas.put(uwf.schemas.text, "hash-thread2")) as CasRef;
|
|
const hash3 = (await uwf.store.cas.put(uwf.schemas.text, "hash-thread3")) as CasRef;
|
|
addHistoryEntry(uwf.varStore, {
|
|
thread: threadId1,
|
|
workflow: workflowHash,
|
|
head: hash1,
|
|
completedAt: Date.now() - 2000,
|
|
reason: null,
|
|
});
|
|
addHistoryEntry(uwf.varStore, {
|
|
thread: threadId2,
|
|
workflow: workflowHash,
|
|
head: hash2,
|
|
completedAt: Date.now() - 1000,
|
|
reason: null,
|
|
});
|
|
addHistoryEntry(uwf.varStore, {
|
|
thread: threadId3,
|
|
workflow: workflowHash,
|
|
head: hash3,
|
|
completedAt: Date.now(),
|
|
reason: null,
|
|
});
|
|
|
|
const result = await resolveHeadHash(tmpDir, threadId2);
|
|
|
|
expect(result).toBe(hash2);
|
|
});
|
|
});
|