- Remove UNCAGED_CAS_DIR and UNCAGED_WORKFLOW_STORAGE_ROOT env var fallbacks - Tests updated to use OCAS_DIR / UWF_STORAGE_ROOT - All docs, READMEs, scripts, workflows, skills updated - Only symlink migration code retains .uncaged paths (functional requirement) Closes #12 (Phase 5 complete)
This commit is contained in:
@@ -67,7 +67,7 @@ describe("C1: adapter JSON round-trip integration", () => {
|
||||
prompt: "Test round-trip task",
|
||||
});
|
||||
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
|
||||
const threadId = "01ROUNDTRIPTEST0000000000" as ThreadId;
|
||||
await seedThreads(tmpDir, { [threadId]: startHash });
|
||||
@@ -134,7 +134,7 @@ describe("C1: adapter JSON round-trip integration", () => {
|
||||
env: {
|
||||
...process.env,
|
||||
WORKFLOW_STORAGE_ROOT: tmpDir,
|
||||
UNCAGED_CAS_DIR: casDir,
|
||||
OCAS_DIR: casDir,
|
||||
},
|
||||
cwd: tmpDir,
|
||||
timeout: 30000,
|
||||
|
||||
@@ -225,9 +225,9 @@ describe("currentRole field", () => {
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
await mkdir(casDir, { recursive: true });
|
||||
|
||||
// Set UNCAGED_CAS_DIR for this test
|
||||
originalEnv = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
// Set OCAS_DIR for this test
|
||||
originalEnv = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
}
|
||||
|
||||
async function teardown() {
|
||||
@@ -236,9 +236,9 @@ describe("currentRole field", () => {
|
||||
}
|
||||
// Restore original environment
|
||||
if (originalEnv === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalEnv;
|
||||
process.env.OCAS_DIR = originalEnv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ beforeEach(async () => {
|
||||
tmpDir = await mkdtemp(join(tmpdir(), "cli-uwf-resolve-head-"));
|
||||
const casDir = join(tmpDir, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
||||
@@ -70,16 +70,16 @@ let originalEnv: string | undefined;
|
||||
|
||||
beforeEach(async () => {
|
||||
tmpDir = await mkdtemp(join(tmpdir(), "cli-uwf-step-read-test-"));
|
||||
originalEnv = process.env.UNCAGED_CAS_DIR;
|
||||
originalEnv = process.env.OCAS_DIR;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await rm(tmpDir, { recursive: true, force: true });
|
||||
// Restore original environment
|
||||
if (originalEnv === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalEnv;
|
||||
process.env.OCAS_DIR = originalEnv;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -88,10 +88,10 @@ afterEach(async () => {
|
||||
describe("step read", () => {
|
||||
test("test 1: basic single-step read with 3 turns", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
const store = createFsStore(casDir);
|
||||
const schemas = await registerUwfSchemas(store);
|
||||
const detailSchemas = await registerDetailSchemas(store);
|
||||
@@ -177,9 +177,9 @@ describe("step read", () => {
|
||||
|
||||
test("test 2: quota enforcement - multiple turns", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
const store = createFsStore(casDir);
|
||||
const schemas = await registerUwfSchemas(store);
|
||||
const detailSchemas = await registerDetailSchemas(store);
|
||||
@@ -263,9 +263,9 @@ describe("step read", () => {
|
||||
|
||||
test("test 3: minimal quota edge case - always show at least one turn", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
const store = createFsStore(casDir);
|
||||
const schemas = await registerUwfSchemas(store);
|
||||
const detailSchemas = await registerDetailSchemas(store);
|
||||
@@ -340,9 +340,9 @@ describe("step read", () => {
|
||||
|
||||
test("test 4: step with no detail field", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
const store = createFsStore(casDir);
|
||||
const schemas = await registerUwfSchemas(store);
|
||||
|
||||
@@ -401,9 +401,9 @@ describe("step read", () => {
|
||||
|
||||
test("test 5: step with detail but no turns array", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
const store = createFsStore(casDir);
|
||||
const schemas = await registerUwfSchemas(store);
|
||||
await registerDetailSchemas(store);
|
||||
@@ -479,9 +479,9 @@ describe("step read", () => {
|
||||
|
||||
test("test 6: displays role and tool calls in turn body", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
const store = createFsStore(casDir);
|
||||
const schemas = await registerUwfSchemas(store);
|
||||
const detailSchemas = await registerDetailSchemas(store);
|
||||
@@ -553,9 +553,9 @@ describe("step read", () => {
|
||||
|
||||
test("test 7: turn content with special characters", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
const store = createFsStore(casDir);
|
||||
const schemas = await registerUwfSchemas(store);
|
||||
const detailSchemas = await registerDetailSchemas(store);
|
||||
|
||||
@@ -131,16 +131,16 @@ describe("cmdStepShow JSON serialization", () => {
|
||||
testDir = await mkdtemp(join(tmpdir(), "uwf-test-"));
|
||||
casDir = join(testDir, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
originalEnv = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
originalEnv = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await rm(testDir, { recursive: true, force: true });
|
||||
if (originalEnv === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalEnv;
|
||||
process.env.OCAS_DIR = originalEnv;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -67,17 +67,17 @@ let originalEnv: string | undefined;
|
||||
|
||||
beforeEach(async () => {
|
||||
tmpDir = await mkdtemp(join(tmpdir(), "cli-uwf-step-timing-test-"));
|
||||
originalEnv = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = join(tmpDir, "cas");
|
||||
await mkdir(process.env.UNCAGED_CAS_DIR, { recursive: true });
|
||||
originalEnv = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = join(tmpDir, "cas");
|
||||
await mkdir(process.env.OCAS_DIR, { recursive: true });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await rm(tmpDir, { recursive: true, force: true });
|
||||
if (originalEnv === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalEnv;
|
||||
process.env.OCAS_DIR = originalEnv;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -16,13 +16,11 @@ import {
|
||||
describe("Global CAS directory", () => {
|
||||
let tmpDir: string;
|
||||
let originalOcasDir: string | undefined;
|
||||
let originalLegacyCasDir: string | undefined;
|
||||
|
||||
beforeEach(async () => {
|
||||
tmpDir = join(tmpdir(), `uwf-test-global-cas-${Date.now()}`);
|
||||
await mkdir(tmpDir, { recursive: true });
|
||||
originalOcasDir = process.env.OCAS_DIR;
|
||||
originalLegacyCasDir = process.env.UNCAGED_CAS_DIR;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -34,16 +32,10 @@ describe("Global CAS directory", () => {
|
||||
} else {
|
||||
process.env.OCAS_DIR = originalOcasDir;
|
||||
}
|
||||
if (originalLegacyCasDir === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalLegacyCasDir;
|
||||
}
|
||||
});
|
||||
|
||||
test("getGlobalCasDir returns default path when no env var set", () => {
|
||||
delete process.env.OCAS_DIR;
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
const casDir = getGlobalCasDir();
|
||||
expect(casDir).toContain(".ocas");
|
||||
});
|
||||
@@ -55,22 +47,8 @@ describe("Global CAS directory", () => {
|
||||
expect(casDir).toBe(customPath);
|
||||
});
|
||||
|
||||
test("getGlobalCasDir respects UNCAGED_CAS_DIR environment variable", () => {
|
||||
const customPath = join(tmpDir, "legacy-cas");
|
||||
process.env.UNCAGED_CAS_DIR = customPath;
|
||||
const casDir = getGlobalCasDir();
|
||||
expect(casDir).toBe(customPath);
|
||||
});
|
||||
|
||||
test("getGlobalCasDir prefers OCAS_DIR over UNCAGED_CAS_DIR", () => {
|
||||
process.env.OCAS_DIR = join(tmpDir, "primary-cas");
|
||||
process.env.UNCAGED_CAS_DIR = join(tmpDir, "legacy-cas");
|
||||
expect(getGlobalCasDir()).toBe(join(tmpDir, "primary-cas"));
|
||||
});
|
||||
|
||||
test("getGlobalCasDir ignores empty OCAS_DIR", () => {
|
||||
process.env.OCAS_DIR = "";
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
const casDir = getGlobalCasDir();
|
||||
expect(casDir).toContain(".ocas");
|
||||
});
|
||||
@@ -83,7 +61,7 @@ describe("Global CAS directory", () => {
|
||||
|
||||
test("createUwfStore uses global CAS directory", async () => {
|
||||
const globalCasDir = join(tmpDir, "global-cas");
|
||||
process.env.UNCAGED_CAS_DIR = globalCasDir;
|
||||
process.env.OCAS_DIR = globalCasDir;
|
||||
|
||||
const storageRoot = join(tmpDir, "storage");
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
@@ -104,7 +82,7 @@ describe("Global CAS directory", () => {
|
||||
|
||||
test("createUwfStore creates global CAS directory if it does not exist", async () => {
|
||||
const globalCasDir = join(tmpDir, "new-global-cas");
|
||||
process.env.UNCAGED_CAS_DIR = globalCasDir;
|
||||
process.env.OCAS_DIR = globalCasDir;
|
||||
|
||||
const storageRoot = join(tmpDir, "storage");
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
@@ -119,7 +97,7 @@ describe("Global CAS directory", () => {
|
||||
|
||||
test("multiple uwfStore instances share the same global CAS filesystem", async () => {
|
||||
const globalCasDir = join(tmpDir, "shared-cas");
|
||||
process.env.UNCAGED_CAS_DIR = globalCasDir;
|
||||
process.env.OCAS_DIR = globalCasDir;
|
||||
|
||||
const storageRoot1 = join(tmpDir, "storage1");
|
||||
const storageRoot2 = join(tmpDir, "storage2");
|
||||
@@ -149,7 +127,7 @@ describe("Global CAS directory", () => {
|
||||
|
||||
test("workflow registry is stored in global CAS variable store", async () => {
|
||||
const globalCasDir = join(tmpDir, "global-cas");
|
||||
process.env.UNCAGED_CAS_DIR = globalCasDir;
|
||||
process.env.OCAS_DIR = globalCasDir;
|
||||
|
||||
const storageRoot = join(tmpDir, "storage");
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
@@ -170,7 +148,7 @@ describe("Global CAS directory", () => {
|
||||
|
||||
test("migrates workflows.yaml to variable store and renames file", async () => {
|
||||
const globalCasDir = join(tmpDir, "global-cas");
|
||||
process.env.UNCAGED_CAS_DIR = globalCasDir;
|
||||
process.env.OCAS_DIR = globalCasDir;
|
||||
|
||||
const storageRoot = join(tmpDir, "storage-migrate");
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
@@ -195,7 +173,7 @@ describe("Global CAS directory", () => {
|
||||
|
||||
test("migrates threads.yaml to variable store and renames file", async () => {
|
||||
const globalCasDir = join(tmpDir, "global-cas-threads");
|
||||
process.env.UNCAGED_CAS_DIR = globalCasDir;
|
||||
process.env.OCAS_DIR = globalCasDir;
|
||||
|
||||
const storageRoot = join(tmpDir, "storage-threads-migrate");
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
@@ -219,7 +197,7 @@ describe("Global CAS directory", () => {
|
||||
|
||||
test("thread metadata stored in ocas variable store", async () => {
|
||||
const globalCasDir = join(tmpDir, "global-cas");
|
||||
process.env.UNCAGED_CAS_DIR = globalCasDir;
|
||||
process.env.OCAS_DIR = globalCasDir;
|
||||
|
||||
const storageRoot = join(tmpDir, "storage");
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
@@ -240,7 +218,7 @@ describe("Global CAS directory", () => {
|
||||
|
||||
test("history is stored in global CAS variable store", async () => {
|
||||
const globalCasDir = join(tmpDir, "global-cas");
|
||||
process.env.UNCAGED_CAS_DIR = globalCasDir;
|
||||
process.env.OCAS_DIR = globalCasDir;
|
||||
|
||||
const storageRoot = join(tmpDir, "storage");
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
@@ -271,7 +249,7 @@ describe("Global CAS directory", () => {
|
||||
|
||||
test("migrates history.jsonl to variable store and renames file", async () => {
|
||||
const globalCasDir = join(tmpDir, "global-cas-history");
|
||||
process.env.UNCAGED_CAS_DIR = globalCasDir;
|
||||
process.env.OCAS_DIR = globalCasDir;
|
||||
|
||||
const storageRoot = join(tmpDir, "storage-history-migrate");
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
@@ -314,7 +292,7 @@ describe("Global CAS directory", () => {
|
||||
|
||||
test("CAS nodes are stored in global directory", async () => {
|
||||
const globalCasDir = join(tmpDir, "global-cas");
|
||||
process.env.UNCAGED_CAS_DIR = globalCasDir;
|
||||
process.env.OCAS_DIR = globalCasDir;
|
||||
|
||||
const storageRoot = join(tmpDir, "storage");
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
|
||||
@@ -10,13 +10,7 @@ import {
|
||||
} from "../store.js";
|
||||
|
||||
describe("Storage root resolution", () => {
|
||||
const envKeys = [
|
||||
"UWF_STORAGE_ROOT",
|
||||
"WORKFLOW_STORAGE_ROOT",
|
||||
"UNCAGED_WORKFLOW_STORAGE_ROOT",
|
||||
"OCAS_DIR",
|
||||
"UNCAGED_CAS_DIR",
|
||||
] as const;
|
||||
const envKeys = ["UWF_STORAGE_ROOT", "WORKFLOW_STORAGE_ROOT", "OCAS_DIR"] as const;
|
||||
const savedEnv: Partial<Record<(typeof envKeys)[number], string | undefined>> = {};
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -43,36 +37,23 @@ describe("Storage root resolution", () => {
|
||||
test("resolveStorageRoot prefers UWF_STORAGE_ROOT", () => {
|
||||
process.env.UWF_STORAGE_ROOT = "/tmp/uwf-primary";
|
||||
process.env.WORKFLOW_STORAGE_ROOT = "/tmp/uwf-fallback";
|
||||
process.env.UNCAGED_WORKFLOW_STORAGE_ROOT = "/tmp/uwf-legacy";
|
||||
expect(resolveStorageRoot()).toBe("/tmp/uwf-primary");
|
||||
});
|
||||
|
||||
test("resolveStorageRoot falls back to WORKFLOW_STORAGE_ROOT", () => {
|
||||
process.env.WORKFLOW_STORAGE_ROOT = "/tmp/uwf-fallback";
|
||||
process.env.UNCAGED_WORKFLOW_STORAGE_ROOT = "/tmp/uwf-legacy";
|
||||
expect(resolveStorageRoot()).toBe("/tmp/uwf-fallback");
|
||||
});
|
||||
|
||||
test("resolveStorageRoot falls back to UNCAGED_WORKFLOW_STORAGE_ROOT", () => {
|
||||
process.env.UNCAGED_WORKFLOW_STORAGE_ROOT = "/tmp/uwf-legacy";
|
||||
expect(resolveStorageRoot()).toBe("/tmp/uwf-legacy");
|
||||
});
|
||||
|
||||
test("getGlobalCasDir returns ~/.ocas by default", () => {
|
||||
const casDir = getGlobalCasDir();
|
||||
expect(casDir).toBe(join(homedir(), ".ocas"));
|
||||
});
|
||||
|
||||
test("getGlobalCasDir prefers OCAS_DIR over UNCAGED_CAS_DIR", () => {
|
||||
test("getGlobalCasDir respects OCAS_DIR", () => {
|
||||
process.env.OCAS_DIR = "/tmp/ocas-primary";
|
||||
process.env.UNCAGED_CAS_DIR = "/tmp/ocas-legacy";
|
||||
expect(getGlobalCasDir()).toBe("/tmp/ocas-primary");
|
||||
});
|
||||
|
||||
test("getGlobalCasDir falls back to UNCAGED_CAS_DIR", () => {
|
||||
process.env.UNCAGED_CAS_DIR = "/tmp/ocas-legacy";
|
||||
expect(getGlobalCasDir()).toBe("/tmp/ocas-legacy");
|
||||
});
|
||||
});
|
||||
|
||||
describe("migrateStorageIfNeeded", () => {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { addHistoryEntry, createUwfStore, loadAllHistory } from "../store.js";
|
||||
async function makeUwfStore(storageRoot: string) {
|
||||
const casDir = join(storageRoot, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
return createUwfStore(storageRoot);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ import {
|
||||
async function makeUwfStore(storageRoot: string): Promise<UwfStore> {
|
||||
const casDir = join(storageRoot, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
// Set UNCAGED_CAS_DIR to use the test's CAS directory
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
// Set OCAS_DIR to use the test's CAS directory
|
||||
process.env.OCAS_DIR = casDir;
|
||||
return createUwfStore(storageRoot);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ describe("Thread and edge location integration", () => {
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
await mkdir(casDir, { recursive: true });
|
||||
|
||||
// Set UNCAGED_CAS_DIR for this test
|
||||
originalEnv = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
// Set OCAS_DIR for this test
|
||||
originalEnv = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
}
|
||||
|
||||
async function teardown() {
|
||||
@@ -30,9 +30,9 @@ describe("Thread and edge location integration", () => {
|
||||
}
|
||||
// Restore original environment
|
||||
if (originalEnv === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalEnv;
|
||||
process.env.OCAS_DIR = originalEnv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,17 +71,17 @@ let originalEnv: string | undefined;
|
||||
|
||||
beforeEach(async () => {
|
||||
tmpDir = await mkdtemp(join(tmpdir(), "cli-uwf-quota-test-"));
|
||||
originalEnv = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = join(tmpDir, "cas");
|
||||
await mkdir(process.env.UNCAGED_CAS_DIR, { recursive: true });
|
||||
originalEnv = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = join(tmpDir, "cas");
|
||||
await mkdir(process.env.OCAS_DIR, { recursive: true });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await rm(tmpDir, { recursive: true, force: true });
|
||||
if (originalEnv === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalEnv;
|
||||
process.env.OCAS_DIR = originalEnv;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ const DETAIL_SCHEMA = {
|
||||
async function makeUwfStore(storageRoot: string): Promise<UwfStore> {
|
||||
const casDir = join(storageRoot, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
return createUwfStore(storageRoot);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ async function setupSuspendedThread(mode: MockAgentMode): Promise<{
|
||||
cwd: tmpDir,
|
||||
});
|
||||
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
await seedThreads(tmpDir, { [THREAD_ID]: startHash });
|
||||
|
||||
const outputHash = await store.put(outputSchemaHash, {
|
||||
@@ -189,7 +189,7 @@ function runUwf(
|
||||
env: {
|
||||
...process.env,
|
||||
WORKFLOW_STORAGE_ROOT: tmpDir,
|
||||
UNCAGED_CAS_DIR: casDir,
|
||||
OCAS_DIR: casDir,
|
||||
},
|
||||
cwd: tmpDir,
|
||||
timeout: 30000,
|
||||
@@ -241,7 +241,7 @@ describe("uwf thread resume", () => {
|
||||
cwd: tmpDir,
|
||||
});
|
||||
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
await seedThreads(tmpDir, { [THREAD_ID]: startHash });
|
||||
|
||||
const result = runUwf(["thread", "resume", THREAD_ID], casDir);
|
||||
@@ -250,9 +250,9 @@ describe("uwf thread resume", () => {
|
||||
});
|
||||
|
||||
test("resume suspended thread executes step and becomes idle", async () => {
|
||||
const originalCasDir = process.env.UNCAGED_CAS_DIR;
|
||||
const originalCasDir = process.env.OCAS_DIR;
|
||||
const { casDir, mockAgentPath } = await setupSuspendedThread("ok");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
|
||||
try {
|
||||
const result = runUwf(["thread", "resume", THREAD_ID, "--agent", mockAgentPath], casDir);
|
||||
@@ -278,17 +278,17 @@ describe("uwf thread resume", () => {
|
||||
expect(showResult.suspendMessage).toBeNull();
|
||||
} finally {
|
||||
if (originalCasDir === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalCasDir;
|
||||
process.env.OCAS_DIR = originalCasDir;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("resume without -p uses suspend message as agent prompt", async () => {
|
||||
const originalCasDir = process.env.UNCAGED_CAS_DIR;
|
||||
const originalCasDir = process.env.OCAS_DIR;
|
||||
const { casDir, mockAgentPath, promptCapturePath } = await setupSuspendedThread("ok");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
|
||||
try {
|
||||
const result = runUwf(["thread", "resume", THREAD_ID, "--agent", mockAgentPath], casDir);
|
||||
@@ -298,17 +298,17 @@ describe("uwf thread resume", () => {
|
||||
expect(capturedPrompt).toBe(SUSPEND_MESSAGE);
|
||||
} finally {
|
||||
if (originalCasDir === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalCasDir;
|
||||
process.env.OCAS_DIR = originalCasDir;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("resume with -p appends supplementary info to agent prompt", async () => {
|
||||
const originalCasDir = process.env.UNCAGED_CAS_DIR;
|
||||
const originalCasDir = process.env.OCAS_DIR;
|
||||
const { casDir, mockAgentPath, promptCapturePath } = await setupSuspendedThread("ok");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
|
||||
try {
|
||||
const supplement = "Use the REST API.";
|
||||
@@ -322,17 +322,17 @@ describe("uwf thread resume", () => {
|
||||
expect(capturedPrompt).toBe(`${SUSPEND_MESSAGE}\n\n${supplement}`);
|
||||
} finally {
|
||||
if (originalCasDir === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalCasDir;
|
||||
process.env.OCAS_DIR = originalCasDir;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("multiple suspend/resume cycles", async () => {
|
||||
const originalCasDir = process.env.UNCAGED_CAS_DIR;
|
||||
const originalCasDir = process.env.OCAS_DIR;
|
||||
const { casDir, mockAgentPath, promptCapturePath } = await setupSuspendedThread("suspend");
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
|
||||
try {
|
||||
const firstResult = runUwf(["thread", "resume", THREAD_ID, "--agent", mockAgentPath], casDir);
|
||||
@@ -370,9 +370,9 @@ describe("uwf thread resume", () => {
|
||||
expect(capturedPrompt).toBe(SUSPEND_MESSAGE);
|
||||
} finally {
|
||||
if (originalCasDir === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalCasDir;
|
||||
process.env.OCAS_DIR = originalCasDir;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -305,8 +305,8 @@ describe("thread show status field", () => {
|
||||
await setupTestEnv();
|
||||
const casDir = join(tmpDir, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
const originalCasDir = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
const originalCasDir = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
|
||||
try {
|
||||
const workflowPath = join(tmpDir, "test-suspend-status.yaml");
|
||||
@@ -331,9 +331,9 @@ describe("thread show status field", () => {
|
||||
expect(result.thread).toBe(threadId);
|
||||
} finally {
|
||||
if (originalCasDir === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalCasDir;
|
||||
process.env.OCAS_DIR = originalCasDir;
|
||||
}
|
||||
await teardown();
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ describe("thread start --cwd CLI option", () => {
|
||||
await mkdir(storageRoot, { recursive: true });
|
||||
await mkdir(casDir, { recursive: true });
|
||||
|
||||
// Set UNCAGED_CAS_DIR for this test
|
||||
originalEnv = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
// Set OCAS_DIR for this test
|
||||
originalEnv = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
}
|
||||
|
||||
async function teardown() {
|
||||
@@ -31,9 +31,9 @@ describe("thread start --cwd CLI option", () => {
|
||||
}
|
||||
// Restore original environment
|
||||
if (originalEnv === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalEnv;
|
||||
process.env.OCAS_DIR = originalEnv;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ graph:
|
||||
|
||||
// Register the workflow
|
||||
execFileSync("bun", [uwfBin, "workflow", "add", workflowPath], {
|
||||
env: { ...process.env, UWF_STORAGE_ROOT: storageRoot, UNCAGED_CAS_DIR: casDir },
|
||||
env: { ...process.env, UWF_STORAGE_ROOT: storageRoot, OCAS_DIR: casDir },
|
||||
encoding: "utf8",
|
||||
});
|
||||
|
||||
@@ -146,7 +146,7 @@ graph:
|
||||
"bun",
|
||||
[uwfBin, "thread", "start", "test-cwd-cli", "-p", "test prompt", "--cwd", testCwd],
|
||||
{
|
||||
env: { ...process.env, UWF_STORAGE_ROOT: storageRoot, UNCAGED_CAS_DIR: casDir },
|
||||
env: { ...process.env, UWF_STORAGE_ROOT: storageRoot, OCAS_DIR: casDir },
|
||||
encoding: "utf8",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -34,8 +34,8 @@ describe("suspend step CAS chain and threads.yaml metadata", () => {
|
||||
test("thread exec records suspend step in CAS and suspend metadata in threads.yaml", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
const originalCasDir = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
const originalCasDir = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
|
||||
try {
|
||||
const store = createFsStore(casDir);
|
||||
@@ -128,7 +128,7 @@ describe("suspend step CAS chain and threads.yaml metadata", () => {
|
||||
env: {
|
||||
...process.env,
|
||||
WORKFLOW_STORAGE_ROOT: tmpDir,
|
||||
UNCAGED_CAS_DIR: casDir,
|
||||
OCAS_DIR: casDir,
|
||||
},
|
||||
cwd: tmpDir,
|
||||
timeout: 30000,
|
||||
@@ -169,9 +169,9 @@ describe("suspend step CAS chain and threads.yaml metadata", () => {
|
||||
expect(showResult.suspendedRole).toBe("worker");
|
||||
} finally {
|
||||
if (originalCasDir === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalCasDir;
|
||||
process.env.OCAS_DIR = originalCasDir;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -33,8 +33,8 @@ describe("suspended thread display", () => {
|
||||
test("thread list shows [suspended] marker for suspended threads", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
const originalCasDir = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
const originalCasDir = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
|
||||
try {
|
||||
const uwf = await createUwfStore(tmpDir);
|
||||
@@ -131,9 +131,9 @@ describe("suspended thread display", () => {
|
||||
expect(idleItem!.statusDisplay).toBe("idle");
|
||||
} finally {
|
||||
if (originalCasDir === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalCasDir;
|
||||
process.env.OCAS_DIR = originalCasDir;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -141,8 +141,8 @@ describe("suspended thread display", () => {
|
||||
test("thread show displays suspend info and resume hint", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
const originalCasDir = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
const originalCasDir = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
|
||||
try {
|
||||
const uwf = await createUwfStore(tmpDir);
|
||||
@@ -219,9 +219,9 @@ describe("suspended thread display", () => {
|
||||
);
|
||||
} finally {
|
||||
if (originalCasDir === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalCasDir;
|
||||
process.env.OCAS_DIR = originalCasDir;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -229,8 +229,8 @@ describe("suspended thread display", () => {
|
||||
test("non-suspended threads do not show suspend markers or hints", async () => {
|
||||
const casDir = join(tmpDir, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
const originalCasDir = process.env.UNCAGED_CAS_DIR;
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
const originalCasDir = process.env.OCAS_DIR;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
|
||||
try {
|
||||
const uwf = await createUwfStore(tmpDir);
|
||||
@@ -278,9 +278,9 @@ describe("suspended thread display", () => {
|
||||
expect(threadItem!.statusDisplay).toBe("idle");
|
||||
} finally {
|
||||
if (originalCasDir === undefined) {
|
||||
delete process.env.UNCAGED_CAS_DIR;
|
||||
delete process.env.OCAS_DIR;
|
||||
} else {
|
||||
process.env.UNCAGED_CAS_DIR = originalCasDir;
|
||||
process.env.OCAS_DIR = originalCasDir;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -58,7 +58,7 @@ const DETAIL_SCHEMA = {
|
||||
async function makeUwfStore(storageRoot: string): Promise<UwfStore> {
|
||||
const casDir = join(storageRoot, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
return createUwfStore(storageRoot);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { createUwfStore, saveWorkflowRegistry } from "../store.js";
|
||||
async function makeUwfStore(storageRoot: string): Promise<UwfStore> {
|
||||
const casDir = join(storageRoot, "cas");
|
||||
await mkdir(casDir, { recursive: true });
|
||||
process.env.UNCAGED_CAS_DIR = casDir;
|
||||
process.env.OCAS_DIR = casDir;
|
||||
return createUwfStore(storageRoot);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ export function getDefaultStorageRoot(): string {
|
||||
|
||||
/**
|
||||
* Resolve storage root.
|
||||
* Priority: `UWF_STORAGE_ROOT` → `WORKFLOW_STORAGE_ROOT` → `UNCAGED_WORKFLOW_STORAGE_ROOT` (legacy) → default.
|
||||
* Priority: `UWF_STORAGE_ROOT` → `WORKFLOW_STORAGE_ROOT` → default.
|
||||
*/
|
||||
export function resolveStorageRoot(): string {
|
||||
const primary = process.env.UWF_STORAGE_ROOT;
|
||||
@@ -130,10 +130,6 @@ export function resolveStorageRoot(): string {
|
||||
if (userOverride !== undefined && userOverride !== "") {
|
||||
return userOverride;
|
||||
}
|
||||
const legacy = process.env.UNCAGED_WORKFLOW_STORAGE_ROOT;
|
||||
if (legacy !== undefined && legacy !== "") {
|
||||
return legacy;
|
||||
}
|
||||
return getDefaultStorageRoot();
|
||||
}
|
||||
|
||||
@@ -145,7 +141,7 @@ export function migrateStorageIfNeeded(home: string = homedir()): void {
|
||||
if (!existsSync(newPath) && existsSync(oldPath)) {
|
||||
symlinkSync(oldPath, newPath);
|
||||
// biome-ignore lint/suspicious/noConsole: migration notice
|
||||
console.log("⚠️ Storage migrated: ~/.uwf → ~/.uncaged/workflow (symlink)");
|
||||
console.log("⚠️ Storage linked: ~/.uwf → legacy workflow directory (symlink)");
|
||||
// biome-ignore lint/suspicious/noConsole: migration notice
|
||||
console.log(
|
||||
" This symlink is temporary. Copy your data to ~/.uwf/ and remove the symlink in a future version.",
|
||||
@@ -157,7 +153,7 @@ export function migrateStorageIfNeeded(home: string = homedir()): void {
|
||||
if (!existsSync(newCas) && existsSync(oldCas)) {
|
||||
symlinkSync(oldCas, newCas);
|
||||
// biome-ignore lint/suspicious/noConsole: migration notice
|
||||
console.log("⚠️ CAS storage migrated: ~/.ocas → ~/.uncaged/json-cas (symlink)");
|
||||
console.log("⚠️ CAS storage linked: ~/.ocas → legacy CAS directory (symlink)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,17 +167,13 @@ export function getCasDir(storageRoot: string): string {
|
||||
|
||||
/**
|
||||
* Returns the global CAS directory shared by all uwf and ocas tools.
|
||||
* Priority: `OCAS_DIR` → `UNCAGED_CAS_DIR` (legacy) → default ~/.ocas
|
||||
* Priority: `OCAS_DIR` → default ~/.ocas
|
||||
*/
|
||||
export function getGlobalCasDir(): string {
|
||||
const primary = process.env.OCAS_DIR;
|
||||
if (primary !== undefined && primary !== "") {
|
||||
return primary;
|
||||
}
|
||||
const legacy = process.env.UNCAGED_CAS_DIR;
|
||||
if (legacy !== undefined && legacy !== "") {
|
||||
return legacy;
|
||||
}
|
||||
return join(homedir(), ".ocas");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user