/** * daemon-config-migration.ts, move daemon-owned keys out of the per-surface * silos and into the daemon's own store, once, idempotently, with disclosure. * * Values MOVE. Nothing is copied (a copy is drift waiting to happen) and * nothing is abandoned. * * WHICH VALUE WINS, when two stores disagree about the same daemon-owned key: * * 1. A value already in the daemon store wins. This is what makes a re-run * safe: after a partial run the daemon store is authoritative and a second * pass cannot undo it. * 2. Otherwise the PRIMARY surface wins, the surface whose settings file the * daemon has actually been reading (`tui`, because the daemon binary is * the TUI binary). Choosing it preserves the behavior the machine has * right now: whatever the daemon was doing before the migration, it keeps * doing after it. * 3. Otherwise the first remaining surface in alphabetical order wins, so the * result does not depend on directory-listing order. * * Every value that does NOT win is disclosed in the marker with the store it * came from and the store that superseded it, redacted when the key names a * credential. Losing a value silently is the failure this whole change exists * to remove. * * CRASH SAFETY. The order is: write an `in-progress` marker carrying the full * plan, write the daemon store, strip the surfaces, then rewrite the marker as * `complete`. A marker is only believed when it PARSES and says `complete`, so * a torn or truncated marker re-runs the migration rather than stranding the * data. Every file write is temp-file + rename, so no reader sees a half file. */ import { type DaemonConfigMovedMarker, type DiscardedConfigKey, type MovedConfigKey } from './daemon-config-migration-io.js'; /** The surface store the daemon has historically read; wins on conflict. */ export declare const DEFAULT_PRIMARY_DAEMON_SURFACE = "tui"; export interface DaemonConfigMigrationOptions { /** User home directory whose `.goodvibes/` tree is migrated. */ readonly homeDir: string; /** Override the daemon store path (honors GOODVIBES_DAEMON_HOME callers). */ readonly daemonStorePath?: string | undefined; /** Surface whose value wins a conflict. Defaults to `tui`. */ readonly primarySurface?: string | undefined; /** Explicit surface list (tests); defaults to on-disk discovery. */ readonly surfaces?: readonly { surface: string; path: string; }[] | undefined; /** Clock injection for deterministic markers. */ readonly now?: (() => Date) | undefined; } export interface DaemonConfigMigrationResult { /** True when this call performed the move (false when already migrated). */ readonly migrated: boolean; /** The disclosure marker as written (or the pre-existing complete one). */ readonly marker: DaemonConfigMovedMarker; /** Absolute path of the marker file. */ readonly markerPath: string; } /** * Run the migration if it has not completed. Safe to call on every startup: the * fast path is one file read and one JSON parse. */ export declare function migrateDaemonOwnedConfig(options: DaemonConfigMigrationOptions): DaemonConfigMigrationResult; /** Human-readable disclosure of a completed migration, for a startup notice. */ export declare function describeDaemonConfigMigration(marker: DaemonConfigMovedMarker): string; export type { DaemonConfigMovedMarker, DiscardedConfigKey, MovedConfigKey }; //# sourceMappingURL=daemon-config-migration.d.ts.map