diff --git a/packages/core/src/__tests__/store-settings.test.ts b/packages/core/src/__tests__/store-settings.test.ts index d66b42911..f94338533 100644 --- a/packages/core/src/__tests__/store-settings.test.ts +++ b/packages/core/src/__tests__/store-settings.test.ts @@ -37,6 +37,18 @@ describe("TaskStore", () => { }); }); + describe("worktreesDir setting", () => { + it("round-trips worktreesDir via updateSettings and project serialization", async () => { + await harness.store().updateSettings({ worktreesDir: "~/.fn-worktrees/{repo}" }); + const settings = await harness.store().getSettings(); + expect(settings.worktreesDir).toBe("~/.fn-worktrees/{repo}"); + + const configRaw = await readFile(join(harness.rootDir(), ".fusion", "config.json"), "utf-8"); + const config = JSON.parse(configRaw); + expect(config.settings.worktreesDir).toBe("~/.fn-worktrees/{repo}"); + }); + }); + describe("autoResolveConflicts setting", () => { it("persists autoResolveConflicts and returns it via getSettings", async () => { await harness.store().updateSettings({ autoResolveConflicts: false }); diff --git a/packages/core/src/settings-schema.ts b/packages/core/src/settings-schema.ts index 728856a2a..3ddc4b2bc 100644 --- a/packages/core/src/settings-schema.ts +++ b/packages/core/src/settings-schema.ts @@ -192,6 +192,7 @@ export const DEFAULT_PROJECT_SETTINGS = { recycleWorktrees: false, executorAllowSiblingBranchRename: false, worktreeNaming: "random", + worktreesDir: undefined, taskPrefix: "FN", includeTaskIdInCommit: true, commitAuthorEnabled: true, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index cd07ef3b2..20878b921 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -2394,6 +2394,13 @@ export interface ProjectSettings { * - "task-title": Use a slugified version of the task title (e.g., fix-login-bug) * Default: "random". */ worktreeNaming?: "random" | "task-id" | "task-title"; + /** Optional container directory for task worktrees. + * When unset, worktrees default to `/.worktrees`. + * Supports leading `~` expansion and the `{repo}` token (basename of the project root). + * Accepts absolute paths or paths relative to the project root. + * Affects newly-created worktrees and pool/self-healing directory scans only; + * existing `task.worktree` absolute paths are honored as-is. */ + worktreesDir?: string; /** Prefix for generated task IDs (e.g. `"KB"` produces `KB-001`). * Defaults to `"KB"`. Only affects new tasks — existing tasks retain * their original IDs. */