import { z } from "zod"; import { type PerFieldStatuses, type RecipeMergeStatus } from "./pull-merge.js"; /** * Per-field winner pick for a recipe — operator's manual reconciliation * of a `tenant-edited` / `conflict` field. The `rawKey` is the internal * baselineLookupKey (`itemref|name:foo|lang|version`); `field` is the * human label rendered for display. `winner` is what the merge * synthesiser will pick for this field. * * `status` is the classification at plan-generation time; on apply the * pull re-classifies and verifies the status hasn't moved (a moved * classification means the tenant or disk changed between plan + apply, * and applying the stale plan could clobber a fresh edit — pull * refuses with a hint to regenerate). */ export declare const MergePlanFieldSchema: z.ZodObject<{ field: z.ZodString; rawKey: z.ZodString; status: z.ZodEnum<{ conflict: "conflict"; "in-sync": "in-sync"; "disk-ahead": "disk-ahead"; "tenant-edited": "tenant-edited"; }>; winner: z.ZodEnum<{ tenant: "tenant"; disk: "disk"; }>; }, z.core.$strip>; export declare const MergePlanRecipeSchema: z.ZodObject<{ handle: z.ZodString; kind: z.ZodString; rollupStatus: z.ZodEnum<{ conflict: "conflict"; "in-sync": "in-sync"; "disk-ahead": "disk-ahead"; "tenant-edited": "tenant-edited"; "disk-only": "disk-only"; "tenant-only": "tenant-only"; }>; fields: z.ZodArray; winner: z.ZodEnum<{ tenant: "tenant"; disk: "disk"; }>; }, z.core.$strip>>; }, z.core.$strip>; /** * On-disk plan file emitted by `--write-plan` and consumed by * `--apply-plan`. Hand-editable JSON: operator opens the file, edits * per-(recipe, field) `winner` to `"disk"` or `"tenant"`, re-runs pull * with `--apply-plan `. Pull rebuilds classifications + verifies * each entry's `status` still matches before applying — a drifted * classification means the world moved and applying the stale plan * could clobber a fresh edit. */ export declare const MergePlanSchema: z.ZodObject<{ schemaVersion: z.ZodLiteral<"1">; environment: z.ZodString; generatedAt: z.ZodString; policy: z.ZodOptional>; recipes: z.ZodArray; fields: z.ZodArray; winner: z.ZodEnum<{ tenant: "tenant"; disk: "disk"; }>; }, z.core.$strip>>; }, z.core.$strip>>; }, z.core.$strip>; export type MergePlan = z.infer; export type MergePlanRecipe = z.infer; export type MergePlanField = z.infer; /** * Load + validate a merge plan from disk. Used by `--apply-plan`. Throws * `INPUT_INVALID` on missing file (the operator named a plan that * doesn't exist), malformed JSON, or schema violation. */ export declare const loadMergePlan: (filePath: string) => Promise; /** * Compose a `MergePlan` from per-recipe per-field statuses + the * current `--conflict-policy`. The plan pre-fills `winner` per the * policy: `disk` for `disk-ahead`, `tenant` for everything else under * `tenant-wins` and `error`; `disk` for `disk-ahead` AND `tenant-edited` * (preserve disk's view) and `tenant` for the rest under `disk-wins`. * * The plan is hand-editable; operator opens the file and flips * `winner` to override the policy for individual fields, then re-runs * `recipe pull --apply-plan ` to commit. */ export declare const composeMergePlan: (envName: string, policy: "error" | "disk-wins" | "tenant-wins", generatedAt: string, perRecipe: ReadonlyArray<{ handle: string; kind: string; rollupStatus: RecipeMergeStatus; fieldStatuses: PerFieldStatuses; /** * Optional override for the humanised field label rendered into * the plan file. Used for template-style recipes where the rawKey * is a bare fieldRefKey (no `|name:...` segment) and * `humanizeFieldKey` would return an unrecognisable string. * Maps `rawKey.toLowerCase()` → human label (e.g., "Title (param)"). */ labels?: Map; }>) => MergePlan;