feat(FN-1644): rename default global data directory from ~/.pi/fusion to ~/.fusion
- Change default global directory from ~/.pi/fusion to ~/.fusion - Add migration logic to copy existing data from old directory to new location - Update all core packages (store, settings, central-core, central-db) to use new default path - Update all documentation references from ~/.pi/fusion to ~/.fusion - Add test for ~/.pi/fusion migration path with updated mock paths - Include changeset for @gsxdsm/fusion minor version bump
This commit is contained in:
@@ -2,4 +2,4 @@
|
||||
"@gsxdsm/fusion": minor
|
||||
---
|
||||
|
||||
Rename project storage to `.fusion/fusion.db` and global storage to `~/.pi/fusion`.
|
||||
Rename project storage to `.fusion/fusion.db` and global storage to `~/.fusion`.
|
||||
|
||||
@@ -40,7 +40,7 @@ See [docs/storage.md](./docs/storage.md) for the full storage architecture docum
|
||||
|
||||
## Multi-Project Support
|
||||
|
||||
Fusion supports multiple projects with a central registry at `~/.pi/fusion/fusion-central.db`. Each project has its own SQLite database at `.fusion/fusion.db`. See [docs/multi-project.md](./docs/multi-project.md) for details on:
|
||||
Fusion supports multiple projects with a central registry at `~/.fusion/fusion-central.db`. Each project has its own SQLite database at `.fusion/fusion.db`. See [docs/multi-project.md](./docs/multi-project.md) for details on:
|
||||
- CentralCore API and project registration
|
||||
- Isolation modes (in-process, child-process)
|
||||
- Global concurrency management
|
||||
@@ -220,7 +220,7 @@ See [docs/architecture.md](./docs/architecture.md) for the full reference includ
|
||||
## Settings
|
||||
|
||||
fn uses a two-tier settings hierarchy:
|
||||
- **Global settings** — User preferences in `~/.pi/fusion/settings.json` (theme, models, notifications)
|
||||
- **Global settings** — User preferences in `~/.fusion/settings.json` (theme, models, notifications)
|
||||
- **Project settings** — Project-specific settings in `.fusion/config.json` (concurrency, worktrees, commands)
|
||||
|
||||
Project settings override global settings. Configure via the dashboard **Settings** modal or `fn settings` CLI.
|
||||
|
||||
@@ -49,7 +49,7 @@ At a high level, Fusion is split into:
|
||||
│ Persistence │
|
||||
│ - .fusion/fusion.db (SQLite/WAL)
|
||||
│ - .fusion/tasks/* (PROMPT/logs)
|
||||
│ - ~/.pi/fusion/fusion-central.db │
|
||||
│ - ~/.fusion/fusion-central.db │
|
||||
└──────────────────────────────────┘
|
||||
```
|
||||
|
||||
@@ -134,7 +134,7 @@ Concrete references:
|
||||
- Exported from `@fusion/core` for downstream persistence/API/UI work
|
||||
- **CentralCore**: `packages/core/src/central-core.ts`
|
||||
- Global project registry, health, central activity feed, global concurrency
|
||||
- Backed by `packages/core/src/central-db.ts` (`~/.pi/fusion/fusion-central.db`)
|
||||
- Backed by `packages/core/src/central-db.ts` (`~/.fusion/fusion-central.db`)
|
||||
- **Specialized stores**:
|
||||
- `AgentStore` (`agent-store.ts`) — filesystem-based agent metadata + heartbeat run history
|
||||
- `MissionStore` (`mission-store.ts`) — mission/milestone/slice/feature hierarchy
|
||||
@@ -383,7 +383,7 @@ SQLite schema is initialized in `packages/core/src/db.ts` and uses:
|
||||
- `__meta.lastModified` for change detection/polling
|
||||
|
||||
### Central storage (multi-project)
|
||||
- **Central DB**: `~/.pi/fusion/fusion-central.db`
|
||||
- **Central DB**: `~/.fusion/fusion-central.db`
|
||||
- Schema in `packages/core/src/central-db.ts`
|
||||
- `projects`, `projectHealth`, `centralActivityLog`, `globalConcurrency`, `nodes`, `__meta`
|
||||
|
||||
@@ -542,7 +542,7 @@ In `packages/engine/src/ipc/ipc-protocol.ts`:
|
||||
Settings are split by scope.
|
||||
|
||||
### Global scope
|
||||
- File: `~/.pi/fusion/settings.json`
|
||||
- File: `~/.fusion/settings.json`
|
||||
- Managed by `GlobalSettingsStore` (`packages/core/src/global-settings.ts`)
|
||||
- Examples: `themeMode`, `colorTheme`, default model/provider, notification preferences
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ Method used:
|
||||
- **High**
|
||||
- `packages/dashboard/src/subtask-breakdown.ts` — AI/session orchestration and persistence interactions; only route-level behavior is exercised.
|
||||
- `packages/dashboard/src/terminal.ts` — command validation + process spawning module has no tests and currently appears unused (no imports found), increasing drift risk.
|
||||
- `packages/dashboard/src/script-store.ts` — file persistence logic under `~/.pi/fusion/scripts.json` has no direct tests.
|
||||
- `packages/dashboard/src/script-store.ts` — file persistence logic under `~/.fusion/scripts.json` has no direct tests.
|
||||
- **Medium**
|
||||
- `packages/dashboard/src/mission-routes.ts` — no dedicated unit test file, but substantial endpoint coverage exists via `mission-e2e.test.ts`.
|
||||
- `packages/engine/src/github.ts` — git remote parsing helper has no direct test despite influencing scheduler GitHub linking behavior.
|
||||
|
||||
@@ -16,7 +16,7 @@ Use multi-project mode when you need to:
|
||||
|
||||
Multi-project metadata is stored in:
|
||||
|
||||
`~/.pi/fusion/fusion-central.db`
|
||||
`~/.fusion/fusion-central.db`
|
||||
|
||||
Core tables:
|
||||
|
||||
@@ -86,7 +86,7 @@ Migration is idempotent and designed to avoid repeated re-registration.
|
||||
|
||||
If central registry behavior needs to be reverted:
|
||||
|
||||
1. Delete `~/.pi/fusion/fusion-central.db`
|
||||
1. Delete `~/.fusion/fusion-central.db`
|
||||
2. Keep using per-project `.fusion/fusion.db` data
|
||||
3. Fusion falls back to legacy/single-project behavior
|
||||
4. Re-register projects later with `fn init` / `fn project add`
|
||||
|
||||
@@ -8,7 +8,7 @@ This guide documents Fusion settings from `packages/core/src/types.ts`.
|
||||
|
||||
Fusion uses a two-tier settings system:
|
||||
|
||||
- **Global settings** (`~/.pi/fusion/settings.json`): user preferences shared across projects
|
||||
- **Global settings** (`~/.fusion/settings.json`): user preferences shared across projects
|
||||
- **Project settings** (`.fusion/config.json`): execution/runtime behavior for one project
|
||||
|
||||
At runtime, settings are merged. **Project settings override global settings** when keys overlap.
|
||||
|
||||
@@ -56,7 +56,7 @@ API endpoints reviewed:
|
||||
- `PUT /api/settings/global`
|
||||
- `GET /api/settings/scopes`
|
||||
|
||||
### 3.1 Global settings (`~/.pi/fusion/settings.json`)
|
||||
### 3.1 Global settings (`~/.fusion/settings.json`)
|
||||
|
||||
| Setting Key | Scope | API Endpoint | Description |
|
||||
|---|---|---|---|
|
||||
|
||||
@@ -138,7 +138,7 @@ What the task should accomplish.
|
||||
|
||||
## Global Settings
|
||||
|
||||
User-level settings at `~/.pi/fusion/settings.json`:
|
||||
User-level settings at `~/.fusion/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -152,7 +152,7 @@ User-level settings at `~/.pi/fusion/settings.json`:
|
||||
|
||||
## Central Database (Multi-Project)
|
||||
|
||||
For multi-project setups: `~/.pi/fusion/fusion-central.db`
|
||||
For multi-project setups: `~/.fusion/fusion-central.db`
|
||||
- Project registry
|
||||
- Unified activity feed
|
||||
- Global concurrency management
|
||||
|
||||
@@ -458,7 +458,7 @@ vi.mock("@fusion/core", () => ({
|
||||
PluginStore: mocks.pluginStoreCtor,
|
||||
PluginLoader: mocks.pluginLoaderCtor,
|
||||
GlobalSettingsStore: vi.fn().mockImplementation(() => mocks.globalSettingsStoreInstance),
|
||||
resolveGlobalDir: vi.fn().mockReturnValue("/home/user/.pi/fusion"),
|
||||
resolveGlobalDir: vi.fn().mockReturnValue("/home/user/.fusion"),
|
||||
DaemonTokenManager: vi.fn().mockImplementation(() => ({
|
||||
getToken: vi.fn().mockImplementation(() => Promise.resolve(mocks.globalSettingsData.daemonToken as string | undefined)),
|
||||
generateToken: vi.fn().mockImplementation(() => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Provides project registry, health tracking, unified activity feed,
|
||||
* and global concurrency management across all registered projects.
|
||||
*
|
||||
* The central database is located at `~/.pi/fusion/fusion-central.db`.
|
||||
* The central database is located at `~/.fusion/fusion-central.db`.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
@@ -149,7 +149,7 @@ export class CentralCore extends EventEmitter<CentralCoreEvents> {
|
||||
|
||||
/**
|
||||
* Create a CentralCore instance.
|
||||
* @param globalDir — Directory for central database. Defaults to `~/.pi/fusion/`.
|
||||
* @param globalDir — Directory for central database. Defaults to `~/.fusion/`.
|
||||
* Accepts a custom path for testing.
|
||||
*/
|
||||
constructor(globalDir?: string) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* synchronous transaction handling. The database runs in WAL mode
|
||||
* for concurrent reader/writer access.
|
||||
*
|
||||
* This database is stored at `~/.pi/fusion/fusion-central.db` and serves as the
|
||||
* This database is stored at `~/.fusion/fusion-central.db` and serves as the
|
||||
* coordination hub for all projects, storing the project registry,
|
||||
* unified activity feed, global concurrency limits, and project health.
|
||||
*/
|
||||
@@ -412,7 +412,7 @@ export class CentralDatabase {
|
||||
/**
|
||||
* Create a new CentralDatabase instance (does NOT initialize schema).
|
||||
* Callers must call `db.init()` separately.
|
||||
* @param globalDir - Path to the global fusion directory (e.g., `~/.pi/fusion/`)
|
||||
* @param globalDir - Path to the global fusion directory (e.g., `~/.fusion/`)
|
||||
* @returns CentralDatabase instance (not yet initialized)
|
||||
*/
|
||||
export function createCentralDatabase(globalDir?: string): CentralDatabase {
|
||||
|
||||
@@ -600,7 +600,7 @@ async function createBackups(kbDir: string): Promise<void> {
|
||||
* - cwd has `.fusion/fusion.db` or `.fusion/fusion.db` (existing single-project)
|
||||
*
|
||||
* @param cwd — Current working directory to check
|
||||
* @param globalDir — Directory for central database. Defaults to `~/.pi/fusion/`.
|
||||
* @param globalDir — Directory for central database. Defaults to `~/.fusion/`.
|
||||
*/
|
||||
export function needsCentralMigration(cwd: string, globalDir?: string): boolean {
|
||||
const centralDbPath = join(resolveGlobalDir(globalDir), "fusion-central.db");
|
||||
@@ -646,7 +646,7 @@ export function needsCentralMigration(cwd: string, globalDir?: string): boolean
|
||||
* Detect existing projects by walking up from cwd.
|
||||
*
|
||||
* @param cwd — Starting directory (default: process.cwd())
|
||||
* @param globalDir — Directory for central database. Defaults to `~/.pi/fusion/`.
|
||||
* @param globalDir — Directory for central database. Defaults to `~/.fusion/`.
|
||||
* @returns Array of detected projects
|
||||
*/
|
||||
export async function detectExistingProjects(
|
||||
|
||||
@@ -67,7 +67,7 @@ describe("GlobalSettingsStore", () => {
|
||||
expect(settings.themeMode).toBe("light");
|
||||
});
|
||||
|
||||
it("adopts the legacy ~/.pi/kb directory when ~/.pi/fusion does not exist", async () => {
|
||||
it("adopts the legacy ~/.pi/kb directory when ~/.fusion does not exist", async () => {
|
||||
const homeDir = makeTmpDir();
|
||||
process.env.HOME = homeDir;
|
||||
|
||||
@@ -82,7 +82,7 @@ describe("GlobalSettingsStore", () => {
|
||||
await defaultStore.init();
|
||||
|
||||
expect(defaultStore.getSettingsPath()).toBe(join(defaultGlobalDir(), "settings.json"));
|
||||
expect(existsSync(join(homeDir, ".pi", "fusion", "settings.json"))).toBe(true);
|
||||
expect(existsSync(join(homeDir, ".fusion", "settings.json"))).toBe(true);
|
||||
expect(existsSync(join(homeDir, ".pi", "kb"))).toBe(false);
|
||||
|
||||
const settings = await defaultStore.getSettings();
|
||||
@@ -90,6 +90,38 @@ describe("GlobalSettingsStore", () => {
|
||||
|
||||
await rm(homeDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("adopts the legacy ~/.pi/fusion directory when ~/.fusion does not exist", async () => {
|
||||
const homeDir = makeTmpDir();
|
||||
process.env.HOME = homeDir;
|
||||
|
||||
// Create the legacy ~/.pi/fusion directory with settings
|
||||
const legacyDir = join(homeDir, ".pi", "fusion");
|
||||
await mkdir(legacyDir, { recursive: true });
|
||||
await writeFile(
|
||||
join(legacyDir, "settings.json"),
|
||||
JSON.stringify({ themeMode: "light" }),
|
||||
);
|
||||
|
||||
// Verify legacy exists and new does not
|
||||
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();
|
||||
|
||||
// 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 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("getSettings()", () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Global settings store — manages user-level settings in `~/.pi/fusion/settings.json`.
|
||||
* Global settings store — manages user-level settings in `~/.fusion/settings.json`.
|
||||
*
|
||||
* Global settings persist across all fn projects for the current user.
|
||||
* They include UI theme preferences, default AI model selection, and
|
||||
@@ -20,38 +20,65 @@ import { existsSync, mkdirSync, renameSync } from "node:fs";
|
||||
import type { GlobalSettings } from "./types.js";
|
||||
import { DEFAULT_GLOBAL_SETTINGS } from "./types.js";
|
||||
|
||||
/** Legacy directory for global settings before the rename to fusion. */
|
||||
/** Legacy directory for global settings (original name before rename to `.fusion`). */
|
||||
export function legacyGlobalDir(): string {
|
||||
return join(homedir(), ".pi", "fusion");
|
||||
}
|
||||
|
||||
/** Legacy directory for global settings from the earliest fn version (`.pi/kb`). */
|
||||
export function legacyGlobalDirOriginal(): string {
|
||||
return join(homedir(), ".pi", "kb");
|
||||
}
|
||||
|
||||
/** Default directory for global fusion settings: `~/.pi/fusion/` */
|
||||
/** Default directory for global fusion settings: `~/.fusion/` */
|
||||
export function defaultGlobalDir(): string {
|
||||
return join(homedir(), ".pi", "fusion");
|
||||
return join(homedir(), ".fusion");
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the active global directory.
|
||||
*
|
||||
* If the new `~/.pi/fusion` directory does not exist but the legacy
|
||||
* `~/.pi/fusion` directory does, move the legacy directory into place so
|
||||
* existing settings and central metadata continue to work after upgrade.
|
||||
* Migration chain:
|
||||
* 1. If `~/.fusion` exists → use it
|
||||
* 2. Else if `~/.pi/fusion` exists → rename to `~/.fusion` and use it
|
||||
* 3. Else if `~/.pi/kb` exists → rename to `~/.fusion` and use it
|
||||
* 4. Else → return `~/.fusion` (will be created on first use)
|
||||
*/
|
||||
export function resolveGlobalDir(dir?: string): string {
|
||||
if (dir) return dir;
|
||||
|
||||
const preferredDir = defaultGlobalDir();
|
||||
const legacyDir = legacyGlobalDir();
|
||||
|
||||
if (!existsSync(preferredDir) && existsSync(legacyDir)) {
|
||||
// Case 1: New directory already exists
|
||||
if (existsSync(preferredDir)) {
|
||||
return preferredDir;
|
||||
}
|
||||
|
||||
// Case 2: Check for legacy ~/.pi/fusion directory
|
||||
const legacyDir = legacyGlobalDir();
|
||||
if (existsSync(legacyDir)) {
|
||||
try {
|
||||
mkdirSync(dirname(preferredDir), { recursive: true });
|
||||
renameSync(legacyDir, preferredDir);
|
||||
return preferredDir;
|
||||
} catch {
|
||||
return legacyDir;
|
||||
}
|
||||
}
|
||||
|
||||
// Case 3: Check for original legacy ~/.pi/kb directory
|
||||
const legacyDirOriginal = legacyGlobalDirOriginal();
|
||||
if (existsSync(legacyDirOriginal)) {
|
||||
try {
|
||||
mkdirSync(dirname(preferredDir), { recursive: true });
|
||||
renameSync(legacyDirOriginal, preferredDir);
|
||||
return preferredDir;
|
||||
} catch {
|
||||
return legacyDirOriginal;
|
||||
}
|
||||
}
|
||||
|
||||
// Case 4: Return the preferred directory (will be created on first use)
|
||||
return preferredDir;
|
||||
}
|
||||
|
||||
@@ -67,7 +94,7 @@ export class GlobalSettingsStore {
|
||||
|
||||
/**
|
||||
* Create a GlobalSettingsStore.
|
||||
* @param dir — Directory to store settings.json. Defaults to `~/.pi/fusion/`.
|
||||
* @param dir — Directory to store settings.json. Defaults to `~/.fusion/`.
|
||||
* Accepts a custom path for testing.
|
||||
*/
|
||||
constructor(dir?: string) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Settings export and import functionality.
|
||||
*
|
||||
* This module provides utilities for exporting and importing fn settings,
|
||||
* supporting both global (~/.pi/fusion/settings.json) and project-level (.fusion/config.json)
|
||||
* supporting both global (~/.fusion/settings.json) and project-level (.fusion/config.json)
|
||||
* settings for backup, migration, and sharing.
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,7 @@ export interface SettingsExportData {
|
||||
exportedAt: string;
|
||||
/** Source identifier (e.g., hostname, project path) */
|
||||
source?: string;
|
||||
/** Global settings (user-level, ~/.pi/fusion/settings.json) */
|
||||
/** Global settings (user-level, ~/.fusion/settings.json) */
|
||||
global?: GlobalSettings;
|
||||
/** Project settings (project-level, .fusion/config.json) */
|
||||
project?: Partial<ProjectSettings>;
|
||||
|
||||
@@ -114,7 +114,7 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
|
||||
private configLock: Promise<void> = Promise.resolve();
|
||||
/** Cached workflow steps — invalidated on create/update/delete */
|
||||
private workflowStepsCache: import("./types.js").WorkflowStep[] | null = null;
|
||||
/** Global settings store (`~/.pi/fusion/settings.json`) */
|
||||
/** Global settings store (`~/.fusion/settings.json`) */
|
||||
private globalSettingsStore: GlobalSettingsStore;
|
||||
/** Polling interval for change detection */
|
||||
private pollInterval: ReturnType<typeof setInterval> | null = null;
|
||||
@@ -652,7 +652,7 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
|
||||
* Get merged settings: global defaults ← global user prefs ← project overrides.
|
||||
*
|
||||
* Returns the combined view that most consumers should use. Project-level
|
||||
* values in `.fusion/config.json` override global values from `~/.pi/fusion/settings.json`.
|
||||
* values in `.fusion/config.json` override global values from `~/.fusion/settings.json`.
|
||||
*
|
||||
* Settings are canonicalized to resolve legacy defaults (e.g., `.kb/backups` → `.fusion/backups`).
|
||||
*/
|
||||
@@ -842,7 +842,7 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update global (user-level) settings in `~/.pi/fusion/settings.json`.
|
||||
* Update global (user-level) settings in `~/.fusion/settings.json`.
|
||||
*
|
||||
* These settings persist across all fn projects for the current user.
|
||||
* Only fields defined in `GlobalSettings` are accepted.
|
||||
|
||||
@@ -807,7 +807,7 @@ export interface TaskCreateInput {
|
||||
//
|
||||
// Settings are split into two scopes:
|
||||
//
|
||||
// 1. **GlobalSettings** — User preferences stored in `~/.pi/fusion/settings.json`.
|
||||
// 1. **GlobalSettings** — User preferences stored in `~/.fusion/settings.json`.
|
||||
// These persist across all fn projects for the current user (theme, default
|
||||
// AI models, notification preferences).
|
||||
//
|
||||
@@ -840,7 +840,7 @@ export interface DaemonTokenSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Global (user-level) settings stored in `~/.pi/fusion/settings.json`.
|
||||
* Global (user-level) settings stored in `~/.fusion/settings.json`.
|
||||
*
|
||||
* These are user preferences that persist across all fn projects.
|
||||
* The dashboard UI shows these under a "Global" section.
|
||||
|
||||
@@ -743,7 +743,7 @@ The dashboard exposes run-audit retrieval and correlation endpoints for inspecti
|
||||
- `GET /api/config` - Server configuration
|
||||
- `GET /api/settings` - Merged settings (project overrides global)
|
||||
- `PUT /api/settings` - Update project-level settings (rejects global-only fields)
|
||||
- `GET /api/settings/global` - Global user settings (~/.pi/fusion/settings.json)
|
||||
- `GET /api/settings/global` - Global user settings (~/.fusion/settings.json)
|
||||
- `PUT /api/settings/global` - Update global user settings
|
||||
- `GET /api/settings/scopes` - Settings separated by scope: { global, project }
|
||||
- `GET /api/models` - Available AI models
|
||||
|
||||
@@ -344,7 +344,7 @@ export function fetchMemoryBackendStatus(projectId?: string): Promise<MemoryBack
|
||||
return api<MemoryBackendStatus>(withProjectId("/memory/backend", projectId));
|
||||
}
|
||||
|
||||
/** Fetch global (user-level) settings from ~/.pi/fusion/settings.json */
|
||||
/** Fetch global (user-level) settings from ~/.fusion/settings.json */
|
||||
export function fetchGlobalSettings(): Promise<GlobalSettings> {
|
||||
return api<GlobalSettings>("/settings/global");
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import { applyPresetToSelection, generateUniquePresetId } from "../utils/modelPr
|
||||
*
|
||||
* Each section groups related settings fields under a sidebar nav item.
|
||||
* Sections have a `scope` to indicate where their settings are stored:
|
||||
* - "global": User-level settings stored in ~/.pi/fusion/settings.json (shared across projects)
|
||||
* - "global": User-level settings stored in ~/.fusion/settings.json (shared across projects)
|
||||
* - "project": Project-specific settings stored in .fusion/config.json
|
||||
* - undefined: Section operates independently of settings storage (e.g. authentication)
|
||||
*
|
||||
|
||||
@@ -182,7 +182,7 @@ function unloadThemeDataStylesheet(): void {
|
||||
/**
|
||||
* Custom hook for theme management.
|
||||
*
|
||||
* Source of truth: backend global settings (`~/.pi/fusion/settings.json`).
|
||||
* Source of truth: backend global settings (`~/.fusion/settings.json`).
|
||||
*
|
||||
* Behavior:
|
||||
* - Initializes from localStorage cache to avoid pre-hydration theme flash
|
||||
|
||||
@@ -91,7 +91,7 @@ function createMockGlobalSettingsStore() {
|
||||
return {
|
||||
getSettings: vi.fn().mockResolvedValue({}),
|
||||
updateSettings: vi.fn().mockResolvedValue({}),
|
||||
getSettingsPath: vi.fn().mockReturnValue("/fake/home/.pi/fusion/settings.json"),
|
||||
getSettingsPath: vi.fn().mockReturnValue("/fake/home/.fusion/settings.json"),
|
||||
init: vi.fn().mockResolvedValue(false),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2147,7 +2147,7 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
||||
|
||||
/**
|
||||
* GET /api/settings/global
|
||||
* Returns the global (user-level) settings from ~/.pi/fusion/settings.json.
|
||||
* Returns the global (user-level) settings from ~/.fusion/settings.json.
|
||||
* Does NOT include computed/server-only fields like githubTokenConfigured.
|
||||
*/
|
||||
router.get("/settings/global", async (_req, res) => {
|
||||
@@ -2165,7 +2165,7 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
||||
|
||||
/**
|
||||
* PUT /api/settings/global
|
||||
* Update global (user-level) settings in ~/.pi/fusion/settings.json.
|
||||
* Update global (user-level) settings in ~/.fusion/settings.json.
|
||||
* These settings persist across all fn projects for the current user.
|
||||
*/
|
||||
router.put("/settings/global", async (req, res) => {
|
||||
|
||||
@@ -10,7 +10,7 @@ function createMockGlobalSettingsStore() {
|
||||
return {
|
||||
getSettings: vi.fn().mockResolvedValue({}),
|
||||
updateSettings: vi.fn().mockResolvedValue({}),
|
||||
getSettingsPath: vi.fn().mockReturnValue("/fake/home/.pi/fusion/settings.json"),
|
||||
getSettingsPath: vi.fn().mockReturnValue("/fake/home/.fusion/settings.json"),
|
||||
init: vi.fn().mockResolvedValue(false),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user