/**
 * Save + propagation pipeline.
 *
 *  1. Validate every pending field via its `FieldDef.validate?.()`.
 *     Any failure aborts the whole save (no partial writes); pending stays
 *     intact for the user to fix.
 *  2. Persist secrets (`secret: true` fields) to the injected `SecretStore`.
 *     Only the `keyLocation` reference is then written to config.json — the
 *     raw value never lands there.
 *  3. Atomic-write ~/.wigolo/config.json (tmp file + rename) with 0o600.
 *  4. Fan out propagateable keys to every detected agent's `env:` block:
 *       a. Back the agent file up to `<dataDir>/backups/<agent>-<iso>.json`.
 *       b. Merge the propagation set into env, preserving every other key.
 *       c. Atomic-write the agent config.
 *  5. On full success → `store.commit()`. Partial failures surface in
 *     `SaveResult.failed` and pending is still committed (config.json is
 *     durable; failed agent fan-out is fixable on retry without re-staging).
 *  6. Prune per-agent backups to the most recent 5.
 *
 * All filesystem access flows through the `WritableFs` interface so tests
 * can inject EACCES / rename-failure shapes without touching real permissions.
 */
import type { CategoryDef } from '../schema/types.js';
import type { SettingsStore } from './settings-store.js';
import type { AgentTarget } from './agent-targets.js';
export interface SaveOpts {
    store: SettingsStore;
    catalog: ReadonlyArray<CategoryDef>;
    /** ~/.wigolo/config.json (or test-tmp path). */
    configPath: string;
    agents: ReadonlyArray<AgentTarget>;
    secretStore: SecretStore;
    /** Optional injection point for tests. Defaults to `defaultWritableFs()`. */
    fs?: WritableFs;
}
export interface SaveResult {
    /** settings keys persisted to config.json + secretStore (excludes failures). */
    saved: string[];
    /** Agent IDs whose env block was successfully updated. */
    propagated: string[];
    /** Per-agent failures, with reason for display. */
    failed: Array<{
        agentId: string;
        reason: string;
    }>;
    /** Validation errors, if any. Save is aborted when present. */
    errors?: Array<{
        key: string;
        reason: string;
    }>;
}
export interface SecretStore {
    /** Persist a secret. Returns where it landed (keychain or encrypted file). */
    set(key: string, value: string): Promise<{
        location: 'keychain' | 'file';
    }>;
    /** Read a secret. Returns null when not stored. */
    get(key: string): Promise<string | null>;
    /** Remove a stored secret. No-op when absent. */
    remove(key: string): Promise<void>;
}
export interface FsStat {
    isFile(): boolean;
    isDirectory(): boolean;
    isSymbolicLink(): boolean;
}
export interface WritableFs {
    readFile(path: string): Promise<string>;
    writeFile(path: string, data: string): Promise<void>;
    rename(from: string, to: string): Promise<void>;
    mkdir(path: string, opts?: {
        recursive?: boolean;
        mode?: number;
    }): Promise<void>;
    readdir(path: string): Promise<string[]>;
    unlink(path: string): Promise<void>;
    stat(path: string): Promise<FsStat>;
    /** Like stat, but does not follow symlinks. Used to refuse symlinked configs. */
    lstat(path: string): Promise<FsStat>;
}
export declare function defaultWritableFs(): WritableFs;
export declare function save(opts: SaveOpts): Promise<SaveResult>;
export interface InstallAgentOpts {
    target: AgentTarget;
    /** Env block to seed under target.envPath. Existing keys are preserved. */
    env: Readonly<Record<string, string>>;
    fs?: WritableFs;
}
export interface InstallAgentResult {
    ok: boolean;
    reason?: string;
}
export declare function installAgent(opts: InstallAgentOpts): Promise<InstallAgentResult>;
export interface UninstallOpts {
    target: AgentTarget;
    secretStore: SecretStore;
    fs?: WritableFs;
}
export interface UninstallResult {
    ok: boolean;
    reason?: string;
}
export declare function uninstallAgent(opts: UninstallOpts): Promise<UninstallResult>;
//# sourceMappingURL=propagation.d.ts.map