/** * Brand-kit baseline — per-cell SHA-256 hashes for three-way merge * across the kit's metadata and its sections × fields grid. * * Cell-path scheme (flat namespace): * - `kit.description` — kit-level scalar * - `kit.industry` — kit-level scalar * - `sections.
.` — per-field value * * The diff today emits writes only for fields (no kit-metadata update * endpoint is verified on the Brand Management API). Kit-level * classifications are informational; the meaningful three-way merge * surface is the per-field grid where `updateBrandKitField` writes * and the EnrichSections pipeline may concurrently author values. * * `documents[]` is input-only — it drives the ingestion pipeline at * apply time. It does not participate in compare and gets no baseline. */ import type { Baseline, FieldClassification } from "../../sync/index.js"; import type { BrandKitRecipe } from "./schema.js"; export interface BrandBaselinePayload { schemaVersion: "1"; cells: Record; /** * Server UUID of the brand kit this baseline was captured against. * When present, apply prefers id-match via `getBrandKit(id)` before * falling back to name-based resolution. Survives a kit name edit * between pushes without orphaning the existing tenant row. */ tenantId?: string; } export type BrandBaseline = Baseline; /** * Walk a brand-kit recipe and emit per-cell hashes. * * `documents` is deliberately omitted — it's input-only ingestion fuel, * not a write-back surface. * * `description` and `industry` are ALSO omitted. They are Sitecore-owned * kit metadata: written once at `createBrandKit` time and never again by * the converge loop (there is no field-write path for them). But * `readCurrent` always populates them from the live kit, while a pushed * recipe omits them (the registry renders them read-only). Hashing them * here made `desired` (undefined) perpetually diverge from `current` * (live value), so the three-way merge classified both as a `cms-edit` * on every push — and under `--conflict-policy error` the planner * refuses before any writes, breaking push entirely for content that is * otherwise unchanged. They have no business in a write-back diff, so * keep them out of the merge surface. */ export declare const hashBrandCells: (recipe: BrandKitRecipe) => Record; export declare const captureBrandBaselinePayload: (recipe: BrandKitRecipe, tenantId?: string) => BrandBaselinePayload; /** * Three-way classify every cell across desired / current / baseline. * Cells present in only one side classify against `hashJsonValue(undefined)` * on the other. */ export declare const classifyBrandCells: (desired: BrandKitRecipe, current: BrandKitRecipe, baselinePayload: BrandBaselinePayload | undefined) => Record; /** * Merge desired vs current per the policy and return a brand-kit * recipe whose `sections` carry policy-resolved values. Kit-level * metadata (description, industry) takes the policy-resolved choice * even though apply has no write path for it — keeps the in-memory * recipe coherent for downstream consumers (logs, registry persistence * after pull, etc.). */ export declare const mergeBrandByPolicy: (desired: BrandKitRecipe, current: BrandKitRecipe, classifications: Record, policy: "error" | "recipe-wins" | "cms-wins") => { merged: BrandKitRecipe; policyErrors: Array<{ path: string; classification: FieldClassification; }>; };