/** * Operational-skill emission: plan building and staged, all-or-nothing execution. * * Reuses `InstallPlan`/`FileOp` — the same types the framework adapters produce — * which buys skip-if-identical idempotence (NFR-7), dry-run equivalence, and * `mergeBlock` support for codex without touching `SkillMeta` (AC-33). * * `executePlan` writes op-by-op, so a mid-plan failure leaves a partial tree. That * is unacceptable under AC-45 and unrepairable under AC-10's collision refusal, so * emission uses `executePlanStaged` instead: resolve and validate everything, * stage every byte into one scratch directory, then commit by rename. * * Requirements: AC-15, AC-17, AC-45, AC-47, NFR-7 * * @module */ import type { InstallPlan, PlatformId } from '../core/types.js'; import { type FileChange } from '../compile/install-plan.js'; import { type OperationalSkill } from './schema.js'; /** Inputs for one emission. */ export interface EmitRequest { /** The skill being emitted (its canonical body is (re)written). */ skill: OperationalSkill; /** Platforms from `.aidlc/config.yaml`. */ platforms: PlatformId[]; /** Absolute project root. */ projectRoot: string; /** * Every operational skill in the project, including `skill`. Index platforms * need the full set; per-skill platforms ignore it. */ allSkills: OperationalSkill[]; } /** Result of applying (or simulating) an operational plan. */ export interface EmitReport { /** * One record per changed file, in plan order — the same shape and the same * producer (`describeChange`) as `ExecutionReport.changes`. * * This is the second of the two report types that carried nothing but paths. * The bug report named only `install-plan.ts`; the population was both, plus a * third local declaration in `init.ts` * (update-overwrites-authored-context/NFR-1). */ changes: FileChange[]; filesWritten: string[]; filesSkipped: string[]; warnings: string[]; } /** Thrown when staging or committing fails. */ export declare class EmitError extends Error { /** Ops whose rename already completed, when a commit fails part-way. */ readonly committed: string[]; constructor(reason: string, /** Ops whose rename already completed, when a commit fails part-way. */ committed?: string[]); } /** * Build the InstallPlan for one operational skill. * * Every packager is resolved **before** any op is produced, so a mixed * supported/unsupported `platforms:` list throws during planning with nothing * staged — AC-47's all-or-nothing guarantee. * * @param req - The emission request. * @returns A plan whose ops cover the canonical body plus every platform artifact. * @throws {UnsupportedPlatformError} When any configured platform lacks packaging. */ export declare function planEmit(req: EmitRequest): InstallPlan; /** * Apply a plan atomically-as-possible. * * Three phases: * 1. **Resolve and validate** — compute final content for every op. Pure. Every * predictable failure lands here, before a single byte is written. * 2. **Stage** — write each op into one scratch directory outside every path the * project enumerates. On failure, remove the scratch dir and abort; the tree is * exactly as it was. * 3. **Commit** — create parent directories, then rename each staged file onto its * target. * * Honest bound: phase 3 is a rename sequence, not one transaction. A failure there * reports which renames completed, and the residual state is repaired by * `--re-emit`, which is idempotent. Directories this run created are removed on a * phase-3 failure only when still empty. * * Skip-if-identical is preserved, so re-emitting unchanged input writes nothing * (NFR-7, AC-17). * * @param plan - The plan to apply. * @param rootDir - Absolute project root. * @returns What was written and skipped. */ export declare function executePlanStaged(plan: InstallPlan, rootDir: string): EmitReport; /** * Simulate `executePlanStaged` without touching the filesystem. * * Uses the same resolution, so `--dry-run` is provably equivalent to a real run. * * @param plan - The plan to simulate. * @param rootDir - Absolute project root. */ export declare function dryRunPlanStaged(plan: InstallPlan, rootDir: string): EmitReport; //# sourceMappingURL=emit.d.ts.map