feat(FN-2123): merge fusion/fn-2123
This commit is contained in:
@@ -72,7 +72,9 @@ describe("FirstRunExperience", () => {
|
||||
|
||||
it("should return true when central core is not initialized", async () => {
|
||||
const uninitializedCore = new CentralCore(tempDir);
|
||||
const uninitializedFirstRun = new FirstRunExperience(uninitializedCore);
|
||||
const { GlobalSettingsStore } = await import("../global-settings.js");
|
||||
const globalSettingsStore = new GlobalSettingsStore(tempDir);
|
||||
const uninitializedFirstRun = new FirstRunExperience(uninitializedCore, globalSettingsStore);
|
||||
|
||||
const result = await uninitializedFirstRun.isFirstRun();
|
||||
expect(result).toBe(true);
|
||||
@@ -298,8 +300,10 @@ describe("FirstRunExperience", () => {
|
||||
});
|
||||
|
||||
describe("createFirstRunExperience", () => {
|
||||
it("should create a FirstRunExperience instance", () => {
|
||||
const instance = createFirstRunExperience(centralCore);
|
||||
it("should create a FirstRunExperience instance", async () => {
|
||||
const { GlobalSettingsStore } = await import("../global-settings.js");
|
||||
const globalSettingsStore = new GlobalSettingsStore(tempDir);
|
||||
const instance = createFirstRunExperience(centralCore, globalSettingsStore);
|
||||
expect(instance).toBeInstanceOf(FirstRunExperience);
|
||||
});
|
||||
});
|
||||
|
||||
70
packages/core/src/__tests__/global-settings-guard.test.ts
Normal file
70
packages/core/src/__tests__/global-settings-guard.test.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { mkdtempSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { resolveGlobalDir } from "../global-settings.js";
|
||||
|
||||
function withTempHome<T>(fn: (homeDir: string) => T): T {
|
||||
const originalHome = process.env.HOME;
|
||||
const homeDir = mkdtempSync(join(tmpdir(), "kb-global-dir-guard-"));
|
||||
process.env.HOME = homeDir;
|
||||
|
||||
try {
|
||||
return fn(homeDir);
|
||||
} finally {
|
||||
if (originalHome === undefined) {
|
||||
delete process.env.HOME;
|
||||
} else {
|
||||
process.env.HOME = originalHome;
|
||||
}
|
||||
rmSync(homeDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
function withVitestEnv<T>(value: string | undefined, fn: () => T): T {
|
||||
const originalVitest = process.env.VITEST;
|
||||
|
||||
if (value === undefined) {
|
||||
delete process.env.VITEST;
|
||||
} else {
|
||||
process.env.VITEST = value;
|
||||
}
|
||||
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
if (originalVitest === undefined) {
|
||||
delete process.env.VITEST;
|
||||
} else {
|
||||
process.env.VITEST = originalVitest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe("resolveGlobalDir() VITEST guard", () => {
|
||||
it("throws without explicit dir during test execution", () => {
|
||||
withVitestEnv("true", () => {
|
||||
withTempHome(() => {
|
||||
expect(() => resolveGlobalDir()).toThrow(
|
||||
"resolveGlobalDir() called without explicit dir during test execution. Pass a temp directory to avoid writing to real ~/.fusion/",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("allows explicit dir during test execution", () => {
|
||||
withVitestEnv("true", () => {
|
||||
const explicitPath = "/some/explicit/path";
|
||||
|
||||
expect(resolveGlobalDir(explicitPath)).toBe(explicitPath);
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves production behavior when VITEST is not set", () => {
|
||||
withVitestEnv(undefined, () => {
|
||||
withTempHome((homeDir) => {
|
||||
expect(resolveGlobalDir()).toBe(join(homeDir, ".fusion"));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -177,7 +177,7 @@ describe("TaskStore Backward Compatibility", () => {
|
||||
mkdirSync(projectDir, { recursive: true });
|
||||
|
||||
// Direct construction should still work
|
||||
const store = new TaskStore(projectDir);
|
||||
const store = new TaskStore(projectDir, join(projectDir, ".fusion-global-settings"));
|
||||
await store.init();
|
||||
|
||||
expect(store).toBeInstanceOf(TaskStore);
|
||||
@@ -198,7 +198,7 @@ describe("TaskStore Backward Compatibility", () => {
|
||||
const projectDir = join(tempDir, "event-test");
|
||||
mkdirSync(projectDir, { recursive: true });
|
||||
|
||||
const store = new TaskStore(projectDir);
|
||||
const store = new TaskStore(projectDir, join(projectDir, ".fusion-global-settings"));
|
||||
await store.init();
|
||||
|
||||
const taskCreatedListener = vi.fn();
|
||||
|
||||
@@ -15,7 +15,7 @@ describe("TaskStore.listTasks() sort order", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
rootDir = makeTmpDir();
|
||||
store = new TaskStore(rootDir);
|
||||
store = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await store.init();
|
||||
});
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ describe("TaskStore task documents", () => {
|
||||
kbDir = join(rootDir, ".fusion");
|
||||
db = new Database(kbDir);
|
||||
db.init();
|
||||
store = new TaskStore(rootDir);
|
||||
store = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await store.init();
|
||||
});
|
||||
|
||||
|
||||
@@ -60,6 +60,9 @@ function splitSettings(settings?: Partial<Settings>): {
|
||||
* This file provides per-fixture isolation on top of that safety net.
|
||||
*
|
||||
* Create an isolated temporary test project with a real TaskStore + SQLite DB.
|
||||
*
|
||||
* Note: we always pass an explicit `globalDir` into TaskStore so tests never
|
||||
* hit `resolveGlobalDir()`'s VITEST guard or write to a real ~/.fusion path.
|
||||
*/
|
||||
export async function createTestProject(
|
||||
options: CreateTestProjectOptions = {},
|
||||
|
||||
@@ -1492,7 +1492,7 @@ describe("AgentStore", () => {
|
||||
let taskId: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
taskStore = new TaskStore(rootDir);
|
||||
taskStore = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore.init();
|
||||
|
||||
store = new AgentStore({ rootDir, taskStore });
|
||||
|
||||
@@ -10,6 +10,25 @@ function makeTmpDir(): string {
|
||||
return mkdtempSync(join(tmpdir(), "kb-global-settings-test-"));
|
||||
}
|
||||
|
||||
/** Temporarily clear VITEST to test default GlobalSettingsStore resolution. */
|
||||
async function withDefaultGlobalSettingsStore<T>(
|
||||
fn: (store: GlobalSettingsStore) => Promise<T>,
|
||||
): Promise<T> {
|
||||
const savedVitest = process.env.VITEST;
|
||||
delete process.env.VITEST;
|
||||
|
||||
try {
|
||||
const store = new GlobalSettingsStore();
|
||||
return await fn(store);
|
||||
} finally {
|
||||
if (savedVitest === undefined) {
|
||||
delete process.env.VITEST;
|
||||
} else {
|
||||
process.env.VITEST = savedVitest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe("GlobalSettingsStore", () => {
|
||||
let dir: string;
|
||||
let store: GlobalSettingsStore;
|
||||
@@ -78,17 +97,20 @@ describe("GlobalSettingsStore", () => {
|
||||
JSON.stringify({ themeMode: "light" }),
|
||||
);
|
||||
|
||||
const defaultStore = new GlobalSettingsStore();
|
||||
await defaultStore.init();
|
||||
try {
|
||||
await withDefaultGlobalSettingsStore(async (defaultStore) => {
|
||||
await defaultStore.init();
|
||||
|
||||
expect(defaultStore.getSettingsPath()).toBe(join(defaultGlobalDir(), "settings.json"));
|
||||
expect(existsSync(join(homeDir, ".fusion", "settings.json"))).toBe(true);
|
||||
expect(existsSync(join(homeDir, ".pi", "kb"))).toBe(false);
|
||||
expect(defaultStore.getSettingsPath()).toBe(join(defaultGlobalDir(), "settings.json"));
|
||||
expect(existsSync(join(homeDir, ".fusion", "settings.json"))).toBe(true);
|
||||
expect(existsSync(join(homeDir, ".pi", "kb"))).toBe(false);
|
||||
|
||||
const settings = await defaultStore.getSettings();
|
||||
expect(settings.themeMode).toBe("light");
|
||||
|
||||
await rm(homeDir, { recursive: true, force: true });
|
||||
const settings = await defaultStore.getSettings();
|
||||
expect(settings.themeMode).toBe("light");
|
||||
});
|
||||
} finally {
|
||||
await rm(homeDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("adopts the legacy ~/.pi/fusion directory when ~/.fusion does not exist", async () => {
|
||||
@@ -107,20 +129,22 @@ describe("GlobalSettingsStore", () => {
|
||||
expect(existsSync(join(homeDir, ".pi", "fusion", "settings.json"))).toBe(true);
|
||||
expect(existsSync(join(homeDir, ".fusion"))).toBe(false);
|
||||
|
||||
// Instantiate GlobalSettingsStore with no argument (uses default resolution)
|
||||
const defaultStore = new GlobalSettingsStore();
|
||||
await defaultStore.init();
|
||||
try {
|
||||
await withDefaultGlobalSettingsStore(async (defaultStore) => {
|
||||
await defaultStore.init();
|
||||
|
||||
// Verify migration happened
|
||||
expect(defaultStore.getSettingsPath()).toBe(join(defaultGlobalDir(), "settings.json"));
|
||||
expect(existsSync(join(homeDir, ".fusion", "settings.json"))).toBe(true);
|
||||
expect(existsSync(join(homeDir, ".pi", "fusion"))).toBe(false);
|
||||
// Verify migration happened
|
||||
expect(defaultStore.getSettingsPath()).toBe(join(defaultGlobalDir(), "settings.json"));
|
||||
expect(existsSync(join(homeDir, ".fusion", "settings.json"))).toBe(true);
|
||||
expect(existsSync(join(homeDir, ".pi", "fusion"))).toBe(false);
|
||||
|
||||
// Verify settings were preserved
|
||||
const settings = await defaultStore.getSettings();
|
||||
expect(settings.themeMode).toBe("light");
|
||||
|
||||
await rm(homeDir, { recursive: true, force: true });
|
||||
// Verify settings were preserved
|
||||
const settings = await defaultStore.getSettings();
|
||||
expect(settings.themeMode).toBe("light");
|
||||
});
|
||||
} finally {
|
||||
await rm(homeDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -45,7 +45,15 @@ export function defaultGlobalDir(): string {
|
||||
* 4. Else → return `~/.fusion` (will be created on first use)
|
||||
*/
|
||||
export function resolveGlobalDir(dir?: string): string {
|
||||
if (dir) return dir;
|
||||
const hasExplicitDir = typeof dir === "string" && dir.length > 0;
|
||||
|
||||
if (!hasExplicitDir && process.env.VITEST === "true") {
|
||||
throw new Error(
|
||||
"resolveGlobalDir() called without explicit dir during test execution. Pass a temp directory to avoid writing to real ~/.fusion/",
|
||||
);
|
||||
}
|
||||
|
||||
if (hasExplicitDir) return dir;
|
||||
|
||||
const preferredDir = defaultGlobalDir();
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ describe("MissionFactory Parity: Core MissionStore", () => {
|
||||
vi.setSystemTime(new Date("2026-04-11T00:00:00.000Z"));
|
||||
|
||||
rootDir = makeTmpDir();
|
||||
taskStore = new TaskStore(rootDir);
|
||||
taskStore = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore.init();
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ describe("MissionFactory Parity: Core MissionStore", () => {
|
||||
|
||||
// Simulate restart by creating new store instance
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -99,7 +99,7 @@ describe("MissionFactory Parity: Core MissionStore", () => {
|
||||
|
||||
// Restart
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -122,7 +122,7 @@ describe("MissionFactory Parity: Core MissionStore", () => {
|
||||
|
||||
// Restart
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -145,7 +145,7 @@ describe("MissionFactory Parity: Core MissionStore", () => {
|
||||
|
||||
// Restart
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -239,7 +239,7 @@ describe("MissionFactory Parity: Core MissionStore", () => {
|
||||
|
||||
// Restart and verify link persists
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -391,7 +391,7 @@ describe("MissionFactory Parity: Core MissionStore", () => {
|
||||
|
||||
// Restart
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -434,7 +434,7 @@ describe("MissionFactory Parity: Core MissionStore", () => {
|
||||
|
||||
// Restart
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -456,7 +456,7 @@ describe("MissionFactory Parity: Core MissionStore", () => {
|
||||
|
||||
// Restart
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -533,7 +533,7 @@ describe("MissionFactory Parity: Core MissionStore", () => {
|
||||
|
||||
// Restart
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ describe("MissionStore integration with TaskStore", () => {
|
||||
vi.setSystemTime(new Date("2026-04-01T00:00:00.000Z"));
|
||||
|
||||
rootDir = makeTmpDir();
|
||||
taskStore = new TaskStore(rootDir);
|
||||
taskStore = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore.init();
|
||||
});
|
||||
|
||||
@@ -410,7 +410,7 @@ describe("MissionStore integration with TaskStore", () => {
|
||||
|
||||
// Restart store
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -436,7 +436,7 @@ describe("MissionStore integration with TaskStore", () => {
|
||||
|
||||
// Restart store
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -461,7 +461,7 @@ describe("MissionStore integration with TaskStore", () => {
|
||||
|
||||
// Restart store
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -484,7 +484,7 @@ describe("MissionStore integration with TaskStore", () => {
|
||||
|
||||
// Restart store
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -506,7 +506,7 @@ describe("MissionStore integration with TaskStore", () => {
|
||||
|
||||
// Restart store
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -530,7 +530,7 @@ describe("MissionStore integration with TaskStore", () => {
|
||||
|
||||
// Restart store
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
@@ -556,7 +556,7 @@ describe("MissionStore integration with TaskStore", () => {
|
||||
|
||||
// Restart store
|
||||
taskStore.close();
|
||||
const taskStore2 = new TaskStore(rootDir);
|
||||
const taskStore2 = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore2.init();
|
||||
const missionStore2 = taskStore2.getMissionStore();
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ describe("MissionStore planning context integration", () => {
|
||||
vi.setSystemTime(new Date("2026-04-01T00:00:00.000Z"));
|
||||
|
||||
rootDir = makeTmpDir();
|
||||
taskStore = new TaskStore(rootDir);
|
||||
taskStore = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore.init();
|
||||
});
|
||||
|
||||
|
||||
@@ -1663,7 +1663,7 @@ describe("MissionStore", () => {
|
||||
it("throws if feature not found", async () => {
|
||||
// Need a TaskStore reference for this test
|
||||
const { TaskStore } = await import("./store.js");
|
||||
const ts = new TaskStore(kbDir);
|
||||
const ts = new TaskStore(kbDir, join(kbDir, ".fusion-global-settings"));
|
||||
const msWithTs = ts.getMissionStore();
|
||||
|
||||
await expect(msWithTs.triageFeature("F-NONEXISTENT")).rejects.toThrow(
|
||||
@@ -1673,7 +1673,7 @@ describe("MissionStore", () => {
|
||||
|
||||
it("throws if feature is already triaged", async () => {
|
||||
const { TaskStore } = await import("./store.js");
|
||||
const ts = new TaskStore(kbDir);
|
||||
const ts = new TaskStore(kbDir, join(kbDir, ".fusion-global-settings"));
|
||||
const msWithTs = ts.getMissionStore();
|
||||
|
||||
const mission = msWithTs.createMission({ title: "Mission" });
|
||||
@@ -1693,7 +1693,7 @@ describe("MissionStore", () => {
|
||||
|
||||
it("creates a task and links it to the feature", async () => {
|
||||
const { TaskStore } = await import("./store.js");
|
||||
const ts = new TaskStore(kbDir);
|
||||
const ts = new TaskStore(kbDir, join(kbDir, ".fusion-global-settings"));
|
||||
const msWithTs = ts.getMissionStore();
|
||||
|
||||
const mission = msWithTs.createMission({ title: "Mission" });
|
||||
@@ -1725,7 +1725,7 @@ describe("MissionStore", () => {
|
||||
|
||||
it("uses provided title and description overrides", async () => {
|
||||
const { TaskStore } = await import("./store.js");
|
||||
const ts = new TaskStore(kbDir);
|
||||
const ts = new TaskStore(kbDir, join(kbDir, ".fusion-global-settings"));
|
||||
const msWithTs = ts.getMissionStore();
|
||||
|
||||
const mission = msWithTs.createMission({ title: "Mission" });
|
||||
@@ -1746,7 +1746,7 @@ describe("MissionStore", () => {
|
||||
|
||||
it("emits feature:linked event", async () => {
|
||||
const { TaskStore } = await import("./store.js");
|
||||
const ts = new TaskStore(kbDir);
|
||||
const ts = new TaskStore(kbDir, join(kbDir, ".fusion-global-settings"));
|
||||
const msWithTs = ts.getMissionStore();
|
||||
|
||||
const linkedHandler = vi.fn();
|
||||
@@ -1781,7 +1781,7 @@ describe("MissionStore", () => {
|
||||
|
||||
it("throws if slice not found", async () => {
|
||||
const { TaskStore } = await import("./store.js");
|
||||
const ts = new TaskStore(kbDir);
|
||||
const ts = new TaskStore(kbDir, join(kbDir, ".fusion-global-settings"));
|
||||
const msWithTs = ts.getMissionStore();
|
||||
|
||||
await expect(msWithTs.triageSlice("SL-NONEXISTENT")).rejects.toThrow(
|
||||
@@ -1791,7 +1791,7 @@ describe("MissionStore", () => {
|
||||
|
||||
it("triages all defined features in a slice", async () => {
|
||||
const { TaskStore } = await import("./store.js");
|
||||
const ts = new TaskStore(kbDir);
|
||||
const ts = new TaskStore(kbDir, join(kbDir, ".fusion-global-settings"));
|
||||
const msWithTs = ts.getMissionStore();
|
||||
|
||||
const mission = msWithTs.createMission({ title: "Mission" });
|
||||
@@ -1818,7 +1818,7 @@ describe("MissionStore", () => {
|
||||
|
||||
it("skips already triaged features", async () => {
|
||||
const { TaskStore } = await import("./store.js");
|
||||
const ts = new TaskStore(kbDir);
|
||||
const ts = new TaskStore(kbDir, join(kbDir, ".fusion-global-settings"));
|
||||
const msWithTs = ts.getMissionStore();
|
||||
|
||||
const mission = msWithTs.createMission({ title: "Mission" });
|
||||
@@ -1840,7 +1840,7 @@ describe("MissionStore", () => {
|
||||
|
||||
it("returns empty array if no defined features", async () => {
|
||||
const { TaskStore } = await import("./store.js");
|
||||
const ts = new TaskStore(kbDir);
|
||||
const ts = new TaskStore(kbDir, join(kbDir, ".fusion-global-settings"));
|
||||
const msWithTs = ts.getMissionStore();
|
||||
|
||||
const mission = msWithTs.createMission({ title: "Mission" });
|
||||
@@ -1861,7 +1861,7 @@ describe("MissionStore", () => {
|
||||
ms: MissionStore;
|
||||
}> {
|
||||
const { TaskStore } = await import("./store.js");
|
||||
const ts = new TaskStore(kbDir);
|
||||
const ts = new TaskStore(kbDir, join(kbDir, ".fusion-global-settings"));
|
||||
const ms = ts.getMissionStore();
|
||||
return { ts, ms };
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ describe("Run Audit Integration", () => {
|
||||
kbDir = join(rootDir, ".fusion");
|
||||
db = new Database(kbDir);
|
||||
db.init();
|
||||
store = new TaskStore(rootDir);
|
||||
store = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await store.init();
|
||||
});
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ describe("Run Audit", () => {
|
||||
kbDir = join(rootDir, ".fusion");
|
||||
db = new Database(kbDir);
|
||||
db.init();
|
||||
store = new TaskStore(rootDir);
|
||||
store = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await store.init();
|
||||
});
|
||||
|
||||
|
||||
@@ -86,7 +86,11 @@ export interface TaskStoreEvents {
|
||||
}
|
||||
|
||||
export class TaskStore extends EventEmitter<TaskStoreEvents> {
|
||||
static async getOrCreateForProject(projectId?: string, centralCore?: CentralCore): Promise<TaskStore> {
|
||||
static async getOrCreateForProject(
|
||||
projectId?: string,
|
||||
centralCore?: CentralCore,
|
||||
globalSettingsDir?: string,
|
||||
): Promise<TaskStore> {
|
||||
const central = centralCore ?? new CentralCore();
|
||||
let initializedHere = false;
|
||||
|
||||
@@ -98,7 +102,11 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
|
||||
try {
|
||||
const compat = new BackwardCompat(central);
|
||||
const context = await compat.resolveProjectContext(process.cwd(), projectId);
|
||||
const store = new TaskStore(context.workingDirectory);
|
||||
const resolvedGlobalSettingsDir = globalSettingsDir
|
||||
?? (process.env.VITEST === "true"
|
||||
? join(context.workingDirectory, ".fusion-global-settings")
|
||||
: undefined);
|
||||
const store = new TaskStore(context.workingDirectory, resolvedGlobalSettingsDir);
|
||||
await store.init();
|
||||
return store;
|
||||
} catch (error) {
|
||||
@@ -176,7 +184,9 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
|
||||
this.kbDir = join(rootDir, ".fusion");
|
||||
this.tasksDir = join(this.kbDir, "tasks");
|
||||
this.configPath = join(this.kbDir, "config.json");
|
||||
this.globalSettingsStore = new GlobalSettingsStore(globalSettingsDir);
|
||||
const resolvedGlobalSettingsDir = globalSettingsDir
|
||||
?? (process.env.VITEST === "true" ? join(rootDir, ".fusion-global-settings") : undefined);
|
||||
this.globalSettingsStore = new GlobalSettingsStore(resolvedGlobalSettingsDir);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user