/** * Install plan executors for the AIDLC install pipeline. * * The plan/execute split ensures `--dry-run` is provably equivalent to a real * install — same plan, different executor (Req 1.5). * * - `executePlan()`: applies a plan to the filesystem (creates dirs, writes files, * invokes `mergeBlock` for managed blocks). * - `dryRunPlan()`: returns an identical report shape without touching the filesystem. * * Requirements: 1.2, 1.5, 17.2 * * @module */ import type { InstallPlan } from '../core/types.js'; /** * What one write actually did to one file. * * `filesWritten` used to be the whole story, and a bare path cannot tell a new * file apart from one whose prose was replaced. Both executors already read the * existing content and computed the new content in order to decide whether to * write at all, then dropped both — so the information a reader needs to judge * the blast radius was being computed and discarded on every run * (update-overwrites-authored-context/AC-1). * * `addedLines`/`removedLines` are **whole-file counts, not a diff stat**. On an * overwrite both are the full line counts of the two sides, so a one-word edit to * a 400-line skill reports `+400/-400`. That is deliberate — a real diff is out of * scope — and it is why the caller prints a legend saying so * (update-overwrites-authored-context/R4). */ export interface FileChange { /** Path relative to the project root, as `op.path` gives it. */ path: string; /** `create` when nothing was on disk; `overwrite` when content was replaced. */ kind: 'create' | 'overwrite'; addedLines: number; removedLines: number; } /** Result of applying (or simulating) an install plan. */ export interface ExecutionReport { /** * One record per file this run changed, in plan order. * * Additive: `filesWritten` is still the same list of paths, so every existing * caller keeps working and only the callers that want detail read this * (update-overwrites-authored-context/NFR-1). */ changes: FileChange[]; /** Paths of files that were written or updated. */ filesWritten: string[]; /** Paths that would not change (content already identical). */ filesSkipped: string[]; /** Non-fatal warnings forwarded from the plan. */ warnings: string[]; } /** * Describe one write, given the two sides both executors already hold. * * The single source of the per-file record, called by `executePlan` and * `dryRunPlan` on the same two strings. That is what makes a dry run and a real * run structurally unable to disagree — the property this module's header already * claims for the path lists, extended to the counts * (update-overwrites-authored-context/AC-2). * * `existed` is passed in rather than re-stat'ed: an empty existing file and an * absent one both read as `''`, so presence cannot be recovered from the content. */ export declare function describeChange(path: string, existed: boolean, before: string, after: string): FileChange; /** * Apply an install plan to the filesystem. * * - `create`/`replace`: write file content, creating directories as needed. * - `merge-block`: read existing file (or empty), call `mergeBlock()`, write result. * * Skips files whose computed content is identical to what's already on disk. * * @param plan - The install plan to execute. * @param rootDir - Absolute path to the project root. All `op.path` entries are relative to this. * @returns Report of what was written, skipped, and warnings. */ export declare function executePlan(plan: InstallPlan, rootDir: string): ExecutionReport; /** * Simulate applying an install plan without writing to the filesystem. * * Computes the same content resolution as `executePlan()` to determine which * files would be written or skipped, but never creates directories or writes files. * * @param plan - The install plan to simulate. * @param rootDir - Absolute path to the project root. * @returns Report of what would be written, skipped, and warnings. */ export declare function dryRunPlan(plan: InstallPlan, rootDir: string): ExecutionReport; //# sourceMappingURL=install-plan.d.ts.map