/** Creates a directory (and all parents) if it does not already exist. */ export declare function ensureDir(dirPath: string): void; /** * Resolves a user-provided relative path ensuring it stays inside the workspace root. * Throws if the path is absolute, escapes via `../`, or resolves to the root itself. */ export declare function resolveWorkspacePath(root: string, relativePath: string): string; /** * Writes content to a file atomically by first writing to a temp file in the * same directory, then renaming. Prevents corruption if the process crashes mid-write. */ export declare function writeFileAtomic(filePath: string, content: string): void; /** * Executes `fn` while holding a directory-based file lock. * Uses mkdir for atomic acquisition; retries with backoff on contention. */ export declare function withFileLock(filePath: string, fn: () => T, timeoutMs?: number): T; /** Reads a JSONL file and returns parsed records. Returns [] if the file does not exist or is empty. */ export declare function readJsonlFile(filePath: string): T[]; /** Appends a record as a JSON line to a JSONL file, creating the file and its parent dirs if needed. */ export declare function appendJsonlFile(filePath: string, record: T): void; /** * Deduplicates an array of id-keyed records by keeping the last write for each id. * Mirrors the append-log pattern used throughout JSONL state files. */ export declare function dedupeById(records: T[]): T[]; /** Strips undefined values from a plain object (used before JSON serialisation). */ export declare function compact>(value: T): T; export type WriteResult = 'written' | 'skipped'; export type FileWriterOptions = { force: boolean; /** Enforce ownership checks for forceful whole-file replacement. */ protectUnownedPaths?: readonly string[]; /** Called with the file path after a successful write. */ log: (filePath: string) => void; /** Called with the file path when a write is skipped. */ warn: (filePath: string) => void; /** Called with the file path after a successful removal. Defaults to a no-op. */ onRemove?: (filePath: string) => void; /** Observes each requested artifact write without coupling generators to run finalization. */ onWrite?: (event: FileWriteEvent) => void; }; export type FileWriteEvent = { filePath: string; content: string; previousContent: string | null; finalContent: string; result: WriteResult; }; /** * Thin wrapper around node:fs write operations. * Centralises the force/skip decision so every setup module * shares the same behaviour without duplicating the guard. */ export declare class FileWriter { private readonly force; private readonly protectUnownedPaths; private readonly log; private readonly warn; private readonly onRemove; private readonly onWrite; constructor(opts: FileWriterOptions); /** * Writes `content` to `filePath`. * Skips the write (and calls `warn`) when the file already exists and * `force` is false. Returns whether the file was actually written. */ write(filePath: string, content: string): WriteResult; /** * Removes `filePath` if it exists and reports it via `onRemove`. Used to clean up orphaned * setup-agents-generated files that have been relocated (e.g. on-demand Claude profile rules * moved out of `.claude/rules/`). The caller is responsible for confirming the file is a * setup-agents artifact before calling — this method does not inspect content. */ remove(filePath: string): void; }