/** * Generic config-dir synthesis (layer C) — the SINGLE deep-merge / union / * symlink implementation for all harnesses (see the `harness-config-dir` * capability). A harness declares its shape via `HarnessConfigProfile` * (`src/harness/interface.ts`); this module does the filesystem work so the * merge algorithm lives in exactly one place. * * Two modes: * - `layer` (default): synth dir = deep-merge of base ⊕ overlay * (`mergeFiles` deep-merged, overlay keys win, arrays replaced wholesale; * `unionDirs` unioned, overlay wins on name clash; `authFiles` symlinked FROM * base). Synth dirs live under `/tmp/subagents//` * — the same location and lifecycle as pi's per-spawn config, so * `subagent-teardown.ts` already scopes there. * - `replace`: no synthesis — resolve straight to the user's dir; nothing is * copied and teardown skips it. * * Host-neutral: no pi package imports (enforced by * `test/host-import-boundary.test.ts`). */ import type { HarnessConfigProfile } from "#src/harness/interface"; export type ConfigDirMode = "layer" | "replace"; export interface SynthesizedConfigDir { /** The dir the harness's CLI is pointed at (the redirect target). */ dir: string; /** The env assignment that points the harness at `dir` (`redirectEnv`). */ env: Record; } /** Identity of the spawn, used to place the per-spawn synth dir. */ export interface SynthIds { parentId: string; agentId: string; } /** * Base dir under which every per-agent synth config dir lives. MUST match * `subagentsBaseDir()` in `src/subagent-teardown.ts` so layer synth dirs are * torn down, and pi's `createSubagentConfig` location so no-override pi output * is byte-for-byte unchanged. */ export declare function synthConfigDirRoot(ids: SynthIds): string; /** * Deep-merge two JSON objects: overlay keys win; nested plain objects are * merged recursively; arrays (and scalars) are replaced WHOLESALE (not * element-merged), matching the guard `turnThresholds` precedent. */ export declare function deepMergeJson(base: Record, overlay: Record): Record; /** * Union a directory base ⊕ overlay into the target: symlink each top-level * entry from base, then from overlay (overlay wins on name collision). Skips a * side that does not exist. Nothing written when neither side exists. */ export declare function unionDir(baseDir: string, overlayDir: string, targetDir: string): void; /** * Provide an auth file in the synth dir FROM the base (symlink by default). * No credential duplication; read-only. Skips a base file that does not exist. */ export declare function provideAuth(baseFile: string, targetFile: string): void; /** * Synthesize (layer) or resolve (replace) the config dir for a harness. * * @param profile The harness's declarative config-dir shape. * @param overlayDir The user-supplied config dir (layer overlay / replace target). * @param mode "layer" (deep-merge base ⊕ overlay) or "replace" (dir as-is). * @param ids Spawn identity, for the per-spawn synth dir location. */ export declare function synthesizeConfigDir(profile: HarnessConfigProfile, overlayDir: string, mode: ConfigDirMode, ids: SynthIds): SynthesizedConfigDir; //# sourceMappingURL=config-dir-synth.d.ts.map