@koda-sl/baker-cli 0.517.0 → 0.518.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/canvas/scaffold-static-ad.ts","../src/commands/canvas/scaffold-viewer.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n AD_DESCRIBE_FOCUS,\n AD_DESCRIBE_MODEL,\n AD_PLATFORM_LEAD,\n AD_SELECT_PROMPT,\n AD_SELECT_SYSTEM,\n BLUEPRINT_ANALYSIS_MODEL,\n} from \"@baker/canvas-contract\";\nimport { referenceReadResponseSchema } from \"@baker/api/ad-library\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { enforceNewCreativeLimit } from \"./creative-limit.ts\";\nimport type { BackendClient } from \"../../engine/client/backend-client.ts\";\nimport type { ValidationIssue } from \"../../engine/engine/errors.ts\";\nimport { createEngineFromEnv, defaultRegistry, ValidationError, validateCanvasDeep } from \"../../engine/index.ts\";\nimport { toModelSafeImage } from \"../../engine/nodes/ingest.ts\";\nimport { sha256Hex } from \"../../engine/storage/sha256.ts\";\nimport { fetchExternalBytes, MAX_REMOTE_IMAGE_BYTES } from \"../../lib/externalFetch.ts\";\nimport { brandBlock, readNamedTypefaces, readStaticBrandKit } from \"../../engine/scaffold/static-brand.ts\";\nimport { withClientLogo } from \"./clientLogo.ts\";\nimport { brandHeadlineFont, type ResolvedFont, webFontUrl } from \"../../engine/scaffold/static-fonts.ts\";\nimport { pickImageModel } from \"../../engine/lib/image-model-router.ts\";\nimport { recordedShape } from \"../../engine/scaffold/static-shape-route.ts\";\nimport type { MasterShape } from \"../../engine/scaffold/static-sizes.ts\";\nimport { conceptClassOf, conceptProblems, readAdSpec } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport {\n castAvatarsOnStaticElements,\n castOnIdeaSpec,\n type StaticAdOpts,\n scaffoldStaticAd,\n staticAdReport,\n staticAdSpec,\n staticAvatarsNotCast,\n} from \"../../engine/scaffold/staticAd.ts\";\nimport {\n fail,\n fileExists,\n loadAssetText,\n parseElements,\n resolveModel,\n} from \"./scaffold-common.ts\";\nimport { fetchJson, lookupGoogleCss } from \"../brand/fonts.ts\";\nimport { findBrandRoot } from \"./static-copy-projection.ts\";\nimport {\n buildCreativeDefinition,\n type DefinitionSourceFields,\n describeBlueprintIntent,\n resolveFormatList,\n setDefinitionDelivery,\n setDefinitionViewer,\n rebasedDefinition,\n titleFromSlug,\n} from \"./creative-definition.ts\";\nimport { type DeliveryFlags, deliveryDefinitionFields, deliveryNote, namesDelivery, scaffoldDelivery } from \"./scaffold-delivery.ts\";\nimport type { ResolvedDelivery } from \"../../engine/scaffold/static-delivery.ts\";\nimport { buildBackendClient } from \"./run.ts\";\nimport { isValidScaffoldSlug, resolveScaffoldStaticAdPaths } from \"./scaffold-static-ad-paths.ts\";\nimport { resolveRelativeCanvasPaths } from \"./resolve-paths.ts\";\nimport { computeSourceSha } from \"./source-version.ts\";\nimport { readDefinitionPlatforms, syncCreativeDefinitionBestEffort } from \"./sync-definition.ts\";\nimport { type ScaffoldViewer, scaffoldViewer } from \"./scaffold-viewer.ts\";\nimport { describeViewer, liveViewerLookups } from \"./viewer-check.ts\";\nimport { resolveCastAvatars } from \"../avatars/resolveCast.ts\";\nimport {\n type DesignRefusal,\n fetchLibraryReference,\n LIBRARY_PLATFORMS,\n type LibraryReference,\n libraryReferenceBlock,\n mergeReferenceIntoBlueprint,\n notADesignReference,\n referenceDescribeContext,\n resolveSourcePlatform,\n} from \"./library-reference.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { conceptFromFit, fitHints, NO_FIT_HINT, readCachedFit } from \"../winning-ads/fit.ts\";\nimport { readLogoFile } from \"./logo-file.ts\";\nimport { findWorkspaceRoot } from \"./normalize-paths.ts\";\nimport { marketFromCompanyDoc, VIEWER_TEMPERATURE_VALUES } from \"../../viewer-profile.ts\";\n\n/** A workspace file as the canvas refers to it: relative to the canvas, never absolute. */\nfunction toCanvasRelative(canvasDir: string, file: string): string {\n const rel = path.relative(canvasDir, file).split(path.sep).join(\"/\");\n return rel.startsWith(\".\") ? rel : `./${rel}`;\n}\n\n/**\n * Localize the source image to the durable content-addressed R2 store — downloading a URL first,\n * since winning-ad references are presigned and expire within the hour — so both the vision passes\n * and the emitted canvas ingest a stable URL that re-runs in any future sandbox. Raster source\n * images NEVER enter git (they bloated every client repo when this wrote a committed\n * `references/` copy); the R2 URL is content-addressed, so it survives forever and re-scaffolds\n * of the same source upload nothing new.\n *\n * The bytes are normalized through `toModelSafeImage` up front (rasterizing SVG/AVIF/HEIC/… to\n * PNG), so the first `baker canvas run` ingests a model-safe reference.\n */\nexport async function uploadSourceAsReference(\n source: string,\n isUrl: boolean,\n client: BackendClient,\n): Promise<string> {\n let bytes: Buffer;\n if (isUrl) {\n // Somebody else's server, so it climbs on a refusal. The R2 PUT below is\n // ours and deliberately stays a bare `fetch` — routing our own storage\n // through a metered exit would bill us for our own bytes.\n try {\n ({ buffer: bytes } = await fetchExternalBytes(source, { maxBytes: MAX_REMOTE_IMAGE_BYTES }));\n } catch (e) {\n throw new Error(`failed to download source image (${e instanceof Error ? e.message : String(e)})`);\n }\n } else {\n bytes = await readFile(source);\n }\n const safe = await toModelSafeImage(bytes);\n const sha256 = sha256Hex(safe.bytes);\n // \"source\": wired into the COMMITTED canvas.json — the GC registry pins it forever.\n const { putUrl, publicUrl } = await client.presignAssetUpload(sha256, safe.mime, undefined, \"source\");\n const putRes = await fetch(putUrl, {\n method: \"PUT\",\n body: new Uint8Array(safe.bytes),\n headers: { \"Content-Type\": safe.mime },\n });\n if (!putRes.ok) throw new Error(`source upload failed (${putRes.status})`);\n return publicUrl;\n}\n\n/**\n * The typeface the model is shown: the brand's font file, else the family tokens.json or\n * BRAND.md names (fetched as a web font file). Null when the brand names none: the model\n * then follows the blueprint's `fonts`, and no neutral default is put in front of it.\n */\nasync function brandFace(\n root: string,\n kit: { headlineFont?: string },\n toCanvas: (file: string) => string,\n): Promise<ResolvedFont | null> {\n const font = await brandHeadlineFont({\n file: kit.headlineFont,\n named: await readNamedTypefaces(root),\n resolveUrl: (family, weight) => webFontUrl(family, weight, { lookupGoogleCss, fetchJson }),\n });\n if (!font) return null;\n return \"path\" in font.slot ? { ...font, slot: { path: toCanvas(font.slot.path) } } : font;\n}\n\ntype Report = ReturnType<typeof staticAdReport>;\n\n/** What the checklist says about the copy. */\nfunction staticTextNote(report: Report): string {\n if (report.text_forward) {\n return \"The reference pictures nothing but copy, so this ad is its words on the brand's colours: keep prompt.json's \\`references\\` empty unless the concept wants a picture.\";\n }\n const face = report.font ? `in ${report.font}, shown to it as a specimen` : \"in the face `brand.typeface` names (the brand has no font file)\";\n return `The copy is set by the image model: every line of \\`copy\\` in prompt.json, exactly as written, once. A line marked \\`\"lettering\": \"designed\"\\` is set ${face}; a line marked \\`\"in_scene\"\\` is lettered on the object it names (\\`on\\`), the way \\`look\\` says. Edit the copy in prompt.json; every run compiles the render prompts from it again and the review reads every word back against it.`;\n}\n\n/** How each delivered format is made. */\nfunction staticFormatsNote(report: Report, genModel: string, delivery?: ResolvedDelivery): string {\n const set = delivery ? ` ${deliveryNote(delivery, report.format_plan.master.renderRatio)}` : \"\";\n const banners =\n report.banners.length > 0\n ? ` The fixed banners ${report.banners.join(\", \")} are not made from the picture: make them apart, from the delivered sizes, before staging a display campaign.`\n : \"\";\n const plan = report.format_plan;\n const made: Record<string, (format: string) => string> = {\n master: (format) => `${format} is the chosen picture (rendered at ${plan.master.renderRatio})`,\n relayout: (format) =>\n `${format} is the chosen ad re-laid out for that frame by the image model (one billed request): the same words, people, product and logo, re-scaled for the frame, inside its safe area`,\n crop: (format) => `${format} is cut from it, every word kept inside its safe area (free)`,\n adapt: (format) => `${format} is adapted from it by the reframe model (one billed request)`,\n };\n const how = plan.sizes.map((f) => made[f.from]?.(f.format) ?? f.format).join(\"; \");\n const again = plan.sizes.some((s) => s.from === \"relayout\") ? \"\" : \" No size is rendered again.\";\n return `Delivers ${report.output_formats.join(\", \")}, each at its exact size, all from one picture (${genModel}): ${how}.${again}${set}${banners}`;\n}\n\n/** Who the ad is for, in the output: the ad set and the viewer it reaches, when known. */\nfunction viewerOutput(who: ScaffoldViewer): Record<string, unknown> {\n return {\n ...(who.targetAdSet ? { target_adset: who.targetAdSet } : {}),\n ...(who.viewer\n ? {\n viewer: {\n temperature: who.viewer.temperature,\n knows: who.viewer.knows,\n placements: who.viewer.placements,\n source: who.viewer.source,\n },\n }\n : {}),\n };\n}\n\n/** What the checklist says about the viewer. */\nfunction viewerNote(who: ScaffoldViewer): string {\n if (!who.viewer) {\n return \"Nobody said who sees this ad: pass --target-adset <id> (or, with no ad account, --viewer-temperature from the Knowledge) so the sizes keep clear of its placements and every run checks the ad against that viewer. Until then it is checked against a cold stranger.\";\n }\n const sizes = who.adPlacements ? `the sizes keep clear of ${who.adPlacements.join(\", \")}` : \"the sizes keep clear of every placement (Advantage+)\";\n return `Made for ${describeViewer(who.viewer)}: write prompt.json's \\`viewer\\` for them, ${sizes}, and every run checks the ad against this viewer before it spends.`;\n}\n\n/** Resolve every model id, honoring overrides; an unknown override throws (see `resolveModel`). */\nfunction resolveModels(args: Record<string, unknown>) {\n return {\n describeModel: resolveModel(\"image_describe\", args[\"describe-model\"], AD_DESCRIBE_MODEL),\n selectModel: resolveModel(\"text_generate\", args[\"select-model\"], BLUEPRINT_ANALYSIS_MODEL),\n // The render model: `--gen-model`, else the router's model for the concept (decided once\n // the blueprint is read, `renderModelFor`). Resolved here only so a bad override fails for free.\n genModel: args[\"gen-model\"] ? resolveModel(\"image_generate\", args[\"gen-model\"], String(args[\"gen-model\"])) : undefined,\n };\n}\n\n/**\n * Where the ad runs, decided before anything is billed, or the refusal printed: a creative (a\n * slug) always needs one, an ad-hoc canvas only when a flag names one (else its single size).\n */\nasync function deliveryOrFail(\n args: DeliveryFlags,\n definitionText: string | null,\n isCreative: boolean,\n): Promise<ResolvedDelivery | undefined> {\n if (!isCreative && !namesDelivery(args)) return undefined;\n const resolved = await scaffoldDelivery(args, definitionText);\n if (!resolved.ok) return fail(resolved.error.code, resolved.error.message, resolved.error.fix);\n return resolved.delivery;\n}\n\n/** Where the ad runs, in the output: the platforms, the size designed first, where they were read from. */\nfunction deliveryOutput(delivery: ResolvedDelivery | undefined): Record<string, unknown> {\n return delivery ? { platforms: delivery.platforms, lead: delivery.lead, platform_source: delivery.source } : {};\n}\n\n/**\n * Validate the scaffolded canvas as `canvas validate` will read it: canvas-relative paths\n * (`./prompt.json`) resolved against the canvas's own folder. A prompt over the model's cap\n * is the blueprint the describe pass wrote — already paid for, and fixed by editing\n * prompt.json — so it is reported as a hint on a written canvas, never an exit that\n * discards it. Every other issue still blocks.\n */\nexport async function validateScaffoldedStaticAd(\n canvas: unknown,\n canvasDir: string,\n): Promise<{ blocking: ValidationIssue[]; hints: string[]; estimatedCredits?: number }> {\n const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(canvas, canvasDir), defaultRegistry());\n if (validation.ok) return { blocking: [], hints: [], estimatedCredits: validation.estimatedCredits };\n const overCap = validation.issues.filter((i) => i.code === \"PROMPT_OVER_MODEL_LIMIT\");\n return {\n blocking: validation.issues.filter((i) => i.code !== \"PROMPT_OVER_MODEL_LIMIT\"),\n hints: overCap.map((i) => `${i.code}: ${i.message} Trim prompt.json, then \\`baker canvas validate\\`.`),\n };\n}\n\n/** The describe + element-selection canvas, run once up front; we read both node outputs after. */\nexport function buildDescribeCanvas(\n imageSource: string,\n imageIsUrl: boolean,\n describeModel: string,\n selectModel: string,\n context?: string,\n) {\n const originalParams = imageIsUrl\n ? { source: \"url\" as const, url: imageSource, expect: \"image\" as const }\n : { source: \"path\" as const, path: imageSource, expect: \"image\" as const };\n return {\n schema: \"baker-canvas/1\" as const,\n metadata: { name: \"static-ad describe pass\" },\n nodes: [\n { id: \"original\", type: \"ingest\", params: originalParams },\n {\n id: \"describe\",\n type: \"image_describe\",\n inputs: { image: \"$ref:original.asset\" },\n params: { model: describeModel, max_tokens: 9000, ...(context ? { context } : {}), focus: AD_DESCRIBE_FOCUS },\n },\n {\n id: \"select\",\n type: \"text_generate\",\n inputs: { blueprint: \"$ref:describe.description\" },\n params: {\n model: selectModel,\n max_tokens: 4000,\n temperature: 0,\n response_format: \"json_object\",\n system: AD_SELECT_SYSTEM,\n prompt: AD_SELECT_PROMPT,\n },\n },\n ],\n // No declared output: runVisionPasses reads both node outputs after the run.\n };\n}\n\n/** Run the vision passes and read back the blueprint and the selected elements. */\nasync function runVisionPasses(canvas: ReturnType<typeof buildDescribeCanvas>): Promise<{\n blueprint: unknown;\n elements: unknown[];\n creditsSpent: number | undefined;\n}> {\n const engine = createEngineFromEnv({ log: (line) => process.stderr.write(`${line}\\n`) });\n let outputsByNode: Record<string, Record<string, unknown>>;\n let creditsSpent: number | undefined;\n try {\n const result = await engine.run(canvas, {});\n outputsByNode = result.outputs_by_node;\n creditsSpent = (result.stats as { total_credits?: number })?.total_credits;\n } catch (e) {\n if (e instanceof ValidationError) return fail(\"validation\", JSON.stringify(e.issues));\n return fail(\"describe\", e instanceof Error ? e.message : String(e));\n }\n try {\n const blueprint = JSON.parse(await loadAssetText(outputsByNode.describe?.description, \"describe output\"));\n const elements = parseElements(await loadAssetText(outputsByNode.select?.text, \"selection output\"));\n return { blueprint, elements, creditsSpent };\n } catch (e) {\n return fail(\"read_outputs\", e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Whether the picture's read is the library's shared one: a library ad's own picture read with nothing of the\n * company's own (its context, another model) depends only on the ad, so it is read once for every\n * company (`/api/ad-library/reference-read`; dev, Oct 2026: each company paid ~40 s for the same read).\n */\n/** The note for a reference not fitted yet. `fit` defaults to Meta, so it names the reference's platform. */\nexport function noFitNote(reference: { ad_id: string; platform: string }): string {\n return `${NO_FIT_HINT}: \\`baker winning-ads fit ${reference.ad_id} --platform ${reference.platform}\\` says what it wins on and what we have for it, and re-scaffolding seeds prompt.json's \\`concept\\` from it.`;\n}\n\nexport function sharesLibraryRead(args: Record<string, unknown>, fromLibrary: boolean): boolean {\n return fromLibrary && !args.file && !args.context && !args[\"describe-model\"] && !args[\"select-model\"];\n}\n\n/**\n * The library's shared read of the ad, null when it cannot be had (the run then reads the\n * picture itself). A first read takes as long as a local one; a reused one is instant and free.\n */\nasync function sharedLibraryRead(reference: LibraryReference): Promise<Awaited<ReturnType<typeof runVisionPasses>> | null> {\n try {\n const read = referenceReadResponseSchema.parse(\n await apiPost<unknown>(\n \"/api/ad-library/reference-read\",\n { ad_id: reference.ad_id, platform: reference.platform },\n { timeoutMs: 240_000 },\n ),\n );\n process.stderr.write(`[read ] ${read.reused ? \"the library's read of this ad, already made\" : \"read this ad for the library\"}\\n`);\n return {\n blueprint: read.blueprint,\n elements: parseElements(JSON.stringify({ elements: read.elements })),\n creditsSpent: read.credits_charged,\n };\n } catch (e) {\n process.stderr.write(`[read ] the library's read is unavailable (${e instanceof Error ? e.message : String(e)}); reading the picture here\\n`);\n return null;\n }\n}\n\nconst SOURCE_AD_ID_DESCRIPTION =\n \"The winners-library ad this creative adapts (the `ad_id` from `baker winning-ads search`). The library's read of \" +\n \"that ad (container, layout, colours, text blocks with their roles, persuasion mechanism, offer) is fetched and \" +\n \"written into prompt.json as `reference`, the describe pass is told it so the two reads agree, and the source is \" +\n \"recorded on the creative from this scaffold on. With it, the image is optional: the library's picture is used \" +\n \"when none is given. Pass it whenever the reference came from the library.\";\nconst PLATFORMS_DESCRIPTION =\n \"Where the ad runs, the main platform first. Start here: --platforms meta (4:5 + 9:16), --platforms linkedin (1:1), \" +\n \"--platforms linkedin,meta (1:1 first, then 4:5 + 9:16). Take it from the person's request, the idea or the ad set; \" +\n \"required for a creative, never defaulted. Every size the platforms need is delivered, the platform's own size designed \" +\n \"first, each kept clear of its placement's interface; a placement id names one placement alone (meta_stories: 9:16 only). \" +\n `Platforms: ${Object.entries(AD_PLATFORM_LEAD).map(([p, lead]) => `${p} (${lead})`).join(\", \")}. Fixed banner sizes (728x90…) are listed, not made.`;\nconst FORMATS_DESCRIPTION =\n \"Exactly the sizes to deliver, when the person asks for others than the platform's (e.g. `--platforms linkedin --formats 1:1,4:5`). \" +\n \"A size the platform never shows is refused; leaving out one it needs is honoured with a warning naming the placements that get a cropped picture.\";\nconst RETIRED_PLATFORM_DESCRIPTION = \"Retired: use --platforms. Still read (meta|google|linkedin|tiktok|youtube|x) and mapped onto --platforms.\";\nconst RETIRED_PLACEMENTS_DESCRIPTION =\n \"Retired: use --platforms (meta_feed_stories → meta, meta_all → meta,meta_right_column). `none` is refused: name the placement instead (--platforms meta_stories).\";\n\nconst SOURCE_PLATFORM_DESCRIPTION = `Which platform the library ad is on: ${LIBRARY_PLATFORMS.join(\"|\")} (default meta).`;\nconst TARGET_ADSET_DESCRIPTION =\n \"The Meta ad set this ad will run in (an id from `baker ads meta adsets`). Who it reaches is read off its targeting, \" +\n \"as `baker ads meta adsets --audience` reads it, and recorded in _definition.md as `targetAdSet` and `viewer`; the \" +\n \"sizes and the render brief keep clear of its placements, and every run checks the ad against that viewer. Free, \" +\n \"read before anything is billed. Start here whenever the ad is for a known ad set.\";\nconst VIEWER_TEMPERATURE_DESCRIPTION =\n \"With no ad set to read (no ad account, or not decided yet): how warm the viewer is, from the Knowledge (personas, \" +\n \"funnel): cold (never heard of the brand), warm (knows the brand), hot (a customer). Recorded as `viewer` with \" +\n \"`source: knowledge`. With --target-adset it corrects the temperature read off the ad set.\";\nconst VIEWER_KNOWS_DESCRIPTION =\n \"What the viewer already knows, comma-separated from brand,offer,product (e.g. `brand,offer`). Needs \" +\n \"--viewer-temperature or --target-adset.\";\nconst VIEWER_PLACEMENTS_DESCRIPTION =\n \"Where the viewer meets the ad, comma-separated Meta placements (e.g. `instagram_feed,facebook_feed`, \" +\n \"`instagram_stories`); default automatic (Advantage+, Reels included). The sizes keep clear of these placements' \" +\n \"interface. Needs --viewer-temperature or --target-adset.\";\n// Operator-only flags: citty cannot hide an argument from `--help`, so the description says so and\n// the agent-facing docs leave them out.\nconst OPERATOR = \"Operator only, agents never need it.\";\n\n/** The master shapes an operator may scaffold with (`--master-shape`): the default (ADR 0014) and the one it replaced. */\nconst SCAFFOLD_SHAPES = [\"plate\", \"relayout\"] as const satisfies readonly MasterShape[];\n\n/** `--master-shape`, read: undefined (the default) when absent, null when it names no shape an operator may pick. */\nfunction masterShapeArg(value: unknown): MasterShape | undefined | null {\n if (value === undefined) return undefined;\n const shape = SCAFFOLD_SHAPES.find((s) => s === String(value));\n return shape ?? null;\n}\n\nconst SOURCE_ADVERTISER_ID_DESCRIPTION =\n \"The library advertiser id of the reference (the `advertiser_id` beside the ad in search results). Defaults to the one the library returns for the ad.\";\n\nregisterSchema({\n command: \"canvas.scaffold-static-ad\",\n description:\n \"Turn a reference image into a runnable static-ad canvas: billed image_describe + element-selection passes, then a canvas on which the image model renders the finished ad from prompt.json. Start here for a static ad adapted from a winning ad: pass `--source-ad-id <ad_id> --source-platform <platform>` from the search result, so the library's structured read grounds the describe pass (and so prompt.json) and the source is recorded on the creative; the image may then be omitted. Use `--avatar <handle>` by default whenever the ad needs a person: inspect `baker avatars list`, choose a ready actor who fits the buyer, or create one with explicit identity and setting. Description-only casting remains available when explicitly requested.\",\n args: {\n file: {\n type: \"positional\",\n required: false,\n description: \"Path or http(s) URL to the reference image. Optional with --source-ad-id: the library's picture is used.\",\n },\n \"source-ad-id\": { type: \"string\", required: false, description: SOURCE_AD_ID_DESCRIPTION },\n spec: {\n type: \"string\",\n required: false,\n description:\n \"Start from an ad spec (a prompt.json) instead of a reference picture: no describe pass, no source. `baker creatives make` writes one from an idea when no proven ad fits. Needs --slug.\",\n },\n \"source-platform\": {\n type: \"string\",\n required: false,\n description: SOURCE_PLATFORM_DESCRIPTION,\n enum: [...LIBRARY_PLATFORMS],\n },\n \"source-advertiser-id\": { type: \"string\", required: false, description: SOURCE_ADVERTISER_ID_DESCRIPTION },\n context: {\n type: \"string\",\n required: false,\n description: \"Known provenance (advertiser, category, market, their brand palette) to ground the describe pass\",\n },\n slug: {\n type: \"string\",\n required: false,\n description: \"Creative slug: writes src/creatives/<slug>/<slug>.canvas.json, prompt.json and _definition.md\",\n },\n title: { type: \"string\", required: false, description: \"Creative title for _definition.md (default: title-cased slug)\" },\n platform: { type: \"string\", required: false, description: RETIRED_PLATFORM_DESCRIPTION },\n advertiser: {\n type: \"string\",\n required: false,\n description: \"Source advertiser name for _definition.md (default: the library ad's advertiser when --source-ad-id is given)\",\n },\n placements: { type: \"string\", required: false, description: RETIRED_PLACEMENTS_DESCRIPTION },\n platforms: { type: \"string\", required: false, description: PLATFORMS_DESCRIPTION },\n formats: { type: \"string\", required: false, description: FORMATS_DESCRIPTION },\n aspect: {\n type: \"string\",\n required: false,\n description: \"Retired: adds this size when the platforms show it (never narrows). For an ad-hoc canvas with no platform, its one size.\",\n },\n \"target-adset\": { type: \"string\", required: false, description: TARGET_ADSET_DESCRIPTION },\n \"viewer-temperature\": {\n type: \"string\",\n required: false,\n description: VIEWER_TEMPERATURE_DESCRIPTION,\n enum: [...VIEWER_TEMPERATURE_VALUES],\n },\n \"viewer-knows\": { type: \"string\", required: false, description: VIEWER_KNOWS_DESCRIPTION },\n \"viewer-placements\": { type: \"string\", required: false, description: VIEWER_PLACEMENTS_DESCRIPTION },\n takes: {\n type: \"string\",\n required: false,\n description: \"Variants of the finished ad rendered (one request each) and judged, 1-3 (default 3). 1 skips the judge.\",\n },\n avatar: {\n type: \"string\",\n required: false,\n description: \"Cast company avatars as the ad's people, comma-separated in detection order (`marta` or `marta,joan`)\",\n },\n out: { type: \"string\", required: false, description: \"Output canvas path (default <image-dir>/static-ad.canvas.json)\" },\n \"describe-model\": { type: \"string\", required: false, description: \"Override the image_describe model id\" },\n \"select-model\": { type: \"string\", required: false, description: \"Override the element-selection text_generate model id\" },\n \"gen-model\": { type: \"string\", required: false, description: \"Override the image_generate model id\" },\n },\n});\n\n/** What the library said about the reference, or why nothing was fetched. Never fails the scaffold. */\nexport type ReferenceLookup =\n | { status: \"none\" }\n | { status: \"refused\"; refusal: DesignRefusal }\n | { status: \"grounded\"; reference: LibraryReference; mediaUrl: string | undefined }\n | { status: \"unavailable\"; adId: string; platform: string; message: string };\n\nexport async function lookupReference(args: Record<string, unknown>): Promise<ReferenceLookup> {\n const adId = args[\"source-ad-id\"] ? String(args[\"source-ad-id\"]).trim() : \"\";\n if (!adId) return { status: \"none\" };\n const platformResult = resolveSourcePlatform(args[\"source-platform\"] ? String(args[\"source-platform\"]) : undefined);\n if (!platformResult.ok) return fail(\"invalid_source_platform\", platformResult.message);\n const platform = platformResult.platform;\n const advertiserId = args[\"source-advertiser-id\"] ? String(args[\"source-advertiser-id\"]).trim() : undefined;\n try {\n const ad = await fetchLibraryReference(adId, platform);\n const refusal = notADesignReference(platform, adId, ad);\n if (refusal) return { status: \"refused\", refusal };\n return {\n status: \"grounded\",\n reference: libraryReferenceBlock(ad, { adId, platform, advertiserId }),\n mediaUrl: ad.media_url ?? undefined,\n };\n } catch (e) {\n return { status: \"unavailable\", adId, platform, message: e instanceof Error ? e.message : String(e) };\n }\n}\n\n/**\n * A static ad started from an ad spec rather than a reference picture: the spec is the ad (its\n * message, viewer and whatever the agent still has to write), the brand and formats are ours,\n * and the canvas has no source picture. Free: nothing is described or billed.\n */\nasync function scaffoldFromSpec(args: Record<string, unknown>, slug: string | undefined): Promise<void> {\n if (!slug) return fail(\"missing_slug\", \"--spec needs --slug: an ad started from a spec is a creative.\");\n const specPath = path.resolve(process.cwd(), String(args.spec));\n let started: ReturnType<typeof readAdSpec>;\n try {\n started = readAdSpec(JSON.parse(await readFile(specPath, \"utf8\")));\n } catch (e) {\n return fail(\"invalid_spec\", `${specPath} is not an ad spec: ${e instanceof Error ? e.message : String(e)}`);\n }\n const outPath = path.join(process.cwd(), \"src\", \"creatives\", slug, `${slug}.canvas.json`);\n const dir = path.dirname(outPath);\n const blueprintPath = path.join(dir, \"prompt.json\");\n const definitionPath = path.join(dir, \"_definition.md\");\n const existingDefinition = (await fileExists(definitionPath)) ? await readFile(definitionPath, \"utf8\") : null;\n // Where the ad runs decides its sizes: settled first, before anything is written or claimed.\n const delivery = await deliveryOrFail(args, existingDefinition, true);\n await enforceNewCreativeLimit(slug, outPath);\n const who = await scaffoldViewer(args, existingDefinition, liveViewerLookups(process.cwd()).adSetViewer);\n if (!who.ok) return fail(\"invalid_viewer\", who.message);\n // An idea has no people to find: each Avatar asked for is one, cast before anything is written.\n const avatars = await resolveCastAvatars(args.avatar);\n if (\"error\" in avatars) return fail(\"avatar\", avatars.error);\n const persona = existingDefinition?.match(/^persona:\\s*\"?([^\"\\n]+)\"?\\s*$/m)?.[1] ?? started.viewer?.who;\n const cast = castOnIdeaSpec(started, avatars.avatars, persona);\n await mkdir(dir, { recursive: true });\n\n const workspaceRoot = (await findBrandRoot(dir)) ?? process.cwd();\n const found = await withClientLogo(workspaceRoot, await readStaticBrandKit(workspaceRoot), () => readStaticBrandKit(workspaceRoot));\n const kit = found.kit;\n const market =\n who.viewer?.market ?? marketFromCompanyDoc(await readFile(path.join(workspaceRoot, \"COMPANY.md\"), \"utf8\").catch(() => null));\n const brand = brandBlock(kit);\n const font = await brandFace(workspaceRoot, kit, (file) => toCanvasRelative(dir, file));\n const genModel = pickImageModel(conceptClassOf(cast.spec), \"generate\");\n const masterShape = masterShapeArg(args[\"master-shape\"]);\n if (masterShape === null) return fail(\"invalid_master_shape\", `--master-shape is ${SCAFFOLD_SHAPES.join(\" or \")}`);\n const logo = await placedLogo(kit.logo, (file) => toCanvasRelative(dir, file));\n const opts: StaticAdOpts = {\n genModel,\n blueprintPath: \"./prompt.json\",\n ...(masterShape ? { masterShape } : {}),\n ...(delivery ? { delivery } : {}),\n ...(who.adPlacements ? { adPlacements: who.adPlacements } : {}),\n brand: { logoPath: kit.logo ? toCanvasRelative(dir, kit.logo) : undefined, ...logo.brand, ...(font ? { font } : {}) },\n ...logo.opts,\n };\n const report = staticAdReport({}, cast.elements, { ...opts, spec: cast.spec });\n const spec = {\n ...cast.spec,\n ...(brand ? { brand: { ...brand, ...cast.spec.brand } } : {}),\n formats: report.output_formats,\n logo: Boolean(kit.logo),\n ...(market ? { viewer: { ...(cast.spec.viewer ?? { who: \"the people this ad is for\" }), market } } : {}),\n };\n await writeFile(blueprintPath, `${JSON.stringify(spec, null, 2)}\\n`, \"utf8\");\n const canvas = scaffoldStaticAd({}, cast.elements, { ...opts, spec });\n const validation = await validateScaffoldedStaticAd(canvas, dir);\n if (validation.blocking.length > 0) return fail(\"validation\", validation.blocking.map((i) => i.message).join(\"; \"));\n await writeFile(outPath, `${JSON.stringify(canvas, null, 2)}\\n`, \"utf8\");\n\n const title = args.title ? String(args.title) : titleFromSlug(slug);\n const recorded = who.record ? { targetAdSet: who.targetAdSet, viewer: who.viewer } : {};\n const where = delivery ? deliveryDefinitionFields(delivery) : undefined;\n if (existingDefinition === null) {\n const formats = resolveFormatList(report.output_formats);\n await writeFile(definitionPath, buildCreativeDefinition({ title, kind: \"static\", ...where, formats, ...recorded }), \"utf8\");\n } else if (where) {\n await writeFile(definitionPath, setDefinitionDelivery(existingDefinition, where), \"utf8\");\n }\n await syncCreativeDefinitionBestEffort({\n slug,\n title,\n ...(where ? { platform: where.platform } : {}),\n ...(await readDefinitionPlatforms(outPath)),\n formats: resolveFormatList(report.output_formats),\n canvas,\n sourceSha: await computeSourceSha(outPath),\n });\n process.stdout.write(\n `${JSON.stringify(\n {\n ok: true,\n canvas_path: outPath,\n prompt_path: blueprintPath,\n definition_path: definitionPath,\n output: canvas.output,\n hints: [...who.notes, ...(delivery?.notes ?? []), ...(found.hint ? [found.hint] : []), ...validation.hints],\n ...viewerOutput(who),\n ...deliveryOutput(delivery),\n output_formats: report.output_formats,\n master_shape: report.master_shape,\n stats: { total_nodes: canvas.nodes.length, describe_credits_spent: 0, run_estimated_credits: validation.estimatedCredits },\n },\n null,\n 2,\n )}\\n`,\n );\n}\n\nexport const scaffoldStaticAdCommand = defineCommand({\n meta: {\n name: \"scaffold-static-ad\",\n description:\n \"Turn a source/inspiration image into a runnable static-ad canvas. Runs billed passes — image_describe (read \" +\n \"into prompt.json, the ad spec you rewrite) and an AI selection of the image's MAIN identity elements — then \" +\n \"scaffolds a canvas on which the image model renders the FINISHED ad: up to three variants, one request each, \" +\n \"from a brief compiled from prompt.json, the copy quoted verbatim, the brand's typeface shown as a specimen and \" +\n 'the logo from src/brand/logos/ as a reference (only when prompt.json has \"logo\": true). A prefilter drops ' +\n \"variants whose words or placement fail the checks, and a judge compares the rest pairwise against the brief; \" +\n \"the chosen picture is delivered at the platform's lead size (4:5 on Meta, 1:1 on LinkedIn) and every other placement format is that \" +\n \"ad re-laid out for its own frame by one image request, with the chosen picture as the reference: the same \" +\n \"words, people, product and logo, re-scaled for the frame, never cut or shrunk onto a background. The run reads every word back and refuses to call the ad ready when one is off. No copy means the picture is the ad. \" +\n \"Where the ad runs decides its sizes: pass --platforms (meta → 4:5 + 9:16, linkedin → 1:1, tiktok → 9:16), from the person's request; a creative with none is refused. Edit prompt.json and drop the real assets, then `baker canvas run` it. A person \" +\n \"is cast from a suitable company Avatar by default: pass `--avatar <handle>` (`baker avatars list`), \" +\n \"or create one with explicit identity and buyer setting. A description-only one-off remains available when \" +\n \"explicitly requested. Never cast a stranger from a searched photo. A reference from the library: pass \" +\n \"`--source-ad-id <ad_id> --source-platform <platform>` so its structured read grounds the describe pass and the \" +\n \"source is recorded on the creative.\",\n },\n args: {\n file: {\n type: \"positional\",\n required: false,\n description: \"Path or http(s) URL to the source/inspiration image (optional with --source-ad-id)\",\n },\n \"source-ad-id\": { type: \"string\", description: SOURCE_AD_ID_DESCRIPTION },\n spec: {\n type: \"string\",\n description:\n \"Start from an ad spec (a prompt.json) instead of a reference picture: no describe pass, no source. `baker creatives make` writes one from an idea when no proven ad fits. Needs --slug.\",\n },\n \"source-platform\": { type: \"string\", description: SOURCE_PLATFORM_DESCRIPTION },\n \"source-advertiser-id\": { type: \"string\", description: SOURCE_ADVERTISER_ID_DESCRIPTION },\n context: { type: \"string\", description: \"Known provenance (advertiser, category, market) to ground the describe\" },\n out: { type: \"string\", description: \"Output canvas path (default <image-dir>/static-ad.canvas.json)\" },\n slug: {\n type: \"string\",\n description: \"Creative slug — writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)\",\n },\n title: { type: \"string\", description: \"Creative title for _definition.md (default: title-cased slug)\" },\n platform: { type: \"string\", description: RETIRED_PLATFORM_DESCRIPTION },\n advertiser: {\n type: \"string\",\n description: \"Source advertiser recorded in _definition.md (default: the library ad's advertiser)\",\n },\n \"describe-model\": { type: \"string\", description: \"Override the image_describe model id\" },\n \"select-model\": { type: \"string\", description: \"Override the text_generate model id for element selection\" },\n \"gen-model\": { type: \"string\", description: \"Override the image_generate model id\" },\n aspect: {\n type: \"string\",\n description:\n \"Retired: adds this size when the platforms show it (never narrows). For an ad-hoc canvas with no platform, its one size.\",\n },\n \"target-adset\": { type: \"string\", description: TARGET_ADSET_DESCRIPTION },\n \"viewer-temperature\": { type: \"string\", description: VIEWER_TEMPERATURE_DESCRIPTION },\n \"viewer-knows\": { type: \"string\", description: VIEWER_KNOWS_DESCRIPTION },\n \"viewer-placements\": { type: \"string\", description: VIEWER_PLACEMENTS_DESCRIPTION },\n placements: { type: \"string\", description: RETIRED_PLACEMENTS_DESCRIPTION },\n platforms: { type: \"string\", description: PLATFORMS_DESCRIPTION },\n formats: { type: \"string\", description: FORMATS_DESCRIPTION },\n takes: {\n type: \"string\",\n description: \"Variants of the finished ad to render (one request each) and judge, 1-3 (default 3). 1 skips the judge.\",\n },\n \"master-shape\": {\n type: \"string\",\n description: `${OPERATOR} How the sizes are made: plate (each variant's picture drawn without the ad's words, every size cut from the chosen one and its words set for it) or relayout (each size re-laid out from the chosen ad). Default: routed by the ad's kind, plate for a photo-led ad and relayout for a designed, chat, screenshot or interface one (the output's master_shape says why). On an existing creative, plate moves it onto one picture, keeping its approved size.`,\n },\n avatar: {\n type: \"string\",\n description:\n \"Cast company avatars as the ad's people — preferred whenever an ad needs an actor, including a single ad. \" +\n \"Choose a ready avatar who fits the buyer, or create one with explicit identity and setting. One handle, or \" +\n \"several comma-separated in the order the people were detected (`--avatar marta` / `--avatar marta,joan`). \" +\n \"Each person slot grounds on that avatar's identity sheet and prompt.json describes them in the avatar's own \" +\n \"words, so the ad shows the company's cast instead of the source ad's. `baker avatars list` shows who there is; \" +\n \"checked before anything is billed.\",\n },\n },\n async run({ args }) {\n const slug = args.slug ? String(args.slug) : undefined;\n if (slug && !isValidScaffoldSlug(slug)) {\n process.stderr.write(\n `${JSON.stringify({ ok: false, error: { code: \"invalid_slug\", message: \"--slug must be lowercase kebab (a-z, 0-9, hyphens), max 100 chars\" } }, null, 2)}\\n`,\n );\n process.exit(2);\n }\n // The library's read of the reference, fetched before anything bills. A failed fetch\n // with an image given degrades to a scaffold without the DNA (warned, and said in hints);\n // with no image there is nothing to describe, so it stops here.\n if (args.spec) return scaffoldFromSpec(args, slug);\n const lookup = await lookupReference(args);\n if (lookup.status === \"refused\") return fail(\"not_a_design_reference\", lookup.refusal.message, lookup.refusal.fix);\n if (lookup.status === \"unavailable\") {\n process.stderr.write(\n `[warn] winners-library ad ${lookup.adId} (${lookup.platform}) could not be read (${lookup.message}); scaffolding without its structured read\\n`,\n );\n }\n const reference = lookup.status === \"grounded\" ? lookup.reference : undefined;\n const fileArg = args.file ? String(args.file) : undefined;\n const sourceFile = fileArg ?? (lookup.status === \"grounded\" ? lookup.mediaUrl : undefined);\n if (!sourceFile) {\n if (lookup.status === \"none\") return fail(\"missing_source\", \"Pass the reference image, or --source-ad-id <ad_id> to use a library ad.\");\n if (lookup.status === \"unavailable\") return fail(\"source_unavailable\", `No image given and the library ad could not be read (${lookup.message}).`);\n return fail(\"source_unavailable\", `The library holds no picture for ad ${reference?.ad_id}; pass the image.`);\n }\n\n const { imageIsUrl, imageSource, outPath, blueprintPath, definitionPath, referencesDir } =\n resolveScaffoldStaticAdPaths(sourceFile, args.out ? String(args.out) : undefined, process.cwd(), slug);\n\n if (slug) await enforceNewCreativeLimit(slug, outPath);\n\n // Who the ad is for, read before anything is billed: a bad flag fails for free, and an ad\n // set that cannot be read only costs the ad its narrower placements.\n const existingDefinition =\n definitionPath && (await fileExists(definitionPath)) ? await readFile(definitionPath, \"utf8\") : null;\n // Where the ad runs decides its sizes: settled before the billed read, never defaulted.\n const delivery = await deliveryOrFail(args, existingDefinition, definitionPath !== null);\n const who = await scaffoldViewer(args, existingDefinition, liveViewerLookups(process.cwd()).adSetViewer);\n if (!who.ok) return fail(\"invalid_viewer\", who.message);\n\n // The fit made of this reference (`baker winning-ads fit`), read before anything bills: a\n // reference judged not to fit is refused here, and one that fits seeds prompt.json's concept.\n const fitRoot = findWorkspaceRoot(process.cwd()) ?? process.cwd();\n const fit =\n reference || lookup.status === \"unavailable\"\n ? await readCachedFit(fitRoot, reference?.platform ?? (lookup.status === \"unavailable\" ? lookup.platform : \"meta\"), reference?.ad_id ?? (lookup.status === \"unavailable\" ? lookup.adId : \"\"))\n : null;\n const fitProblems = fit ? fitHints(fit, reference?.ad_id ?? \"\").filter((h) => h.startsWith(\"Pick another reference\")) : [];\n if (fitProblems.length > 0) return fail(\"concept_does_not_fit\", fitProblems.join(\" \"));\n\n // Create the creative folder up front (was missing — the agent had to `mkdir -p` and re-run,\n // double-billing the vision passes) and fail before any billed work if the path is unwritable.\n await mkdir(path.dirname(outPath), { recursive: true });\n\n let models: ReturnType<typeof resolveModels>;\n try {\n models = resolveModels(args);\n } catch (e) {\n return fail(\"unknown_model\", e instanceof Error ? e.message : String(e));\n }\n const { describeModel, selectModel } = models;\n\n // Resolved before the billed passes: a handle that cannot be cast fails for free.\n const cast = await resolveCastAvatars(args.avatar);\n if (\"error\" in cast) return fail(\"avatar\", cast.error);\n\n // Localize the source to durable storage BEFORE any billed pass: presigned\n // winning-ad URLs expire within the hour, the raster bytes must never land\n // in git, and the vision passes + emitted canvas then read one stable URL\n // (a dead source aborts here, before any credits are spent).\n let durableSourceUrl: string | undefined;\n if (referencesDir) {\n const client = buildBackendClient();\n if (client) {\n try {\n durableSourceUrl = await uploadSourceAsReference(imageSource, imageIsUrl, client);\n } catch (e) {\n return fail(\"source_unavailable\", e instanceof Error ? e.message : String(e));\n }\n }\n }\n\n // One run: ingest → describe → select. We read both node outputs after.\n const describeCanvas = buildDescribeCanvas(\n durableSourceUrl ?? imageSource,\n durableSourceUrl !== undefined || imageIsUrl,\n describeModel,\n selectModel,\n referenceDescribeContext(reference, args.context ? String(args.context) : undefined),\n );\n const shared =\n reference && sharesLibraryRead(args, lookup.status === \"grounded\") ? await sharedLibraryRead(reference) : null;\n const vision = shared ?? (await runVisionPasses(describeCanvas));\n const { creditsSpent } = vision;\n // The library's read joins the blueprint as `reference` (bookkeeping, never a mechanism).\n const blueprint = mergeReferenceIntoBlueprint(vision.blueprint, reference);\n // Cast by who the ad is for (D2): the definition's persona, else the viewer the ad set reaches.\n const persona = existingDefinition?.match(/^persona:\\s*\"?([^\"\\n]+)\"?\\s*$/m)?.[1];\n const elements = castAvatarsOnStaticElements(vision.elements, cast.avatars, persona);\n const uncast = staticAvatarsNotCast(elements, cast.handles);\n\n // The brand's colours ride in prompt.json as `brand`: the brief ties each to an object and\n // never borrows a colour from the reference ad.\n const canvasDir = path.dirname(outPath);\n const workspaceRoot = (await findBrandRoot(canvasDir)) ?? process.cwd();\n const found = await withClientLogo(workspaceRoot, await readStaticBrandKit(workspaceRoot), () => readStaticBrandKit(workspaceRoot));\n const kit = found.kit;\n // Where the ad runs: the ad set's countries, else the market COMPANY.md names (D1).\n const market =\n who.viewer?.market ?? marketFromCompanyDoc(await readFile(path.join(workspaceRoot, \"COMPANY.md\"), \"utf8\").catch(() => null));\n const brand = brandBlock(kit);\n\n // Creative convention: point the canvas at the durable source URL (content-addressed,\n // never expires, re-runs in any fresh sandbox with zero git bloat) and at a canvas-relative\n // blueprint path. Ad-hoc canvases (no slug) keep their verbatim source + absolute blueprint path.\n let canvasImagePath = imageSource;\n let canvasImageIsUrl = imageIsUrl;\n let canvasBlueprintPath = blueprintPath;\n if (referencesDir) {\n canvasBlueprintPath = \"./prompt.json\";\n if (durableSourceUrl) {\n canvasImagePath = durableSourceUrl;\n canvasImageIsUrl = true;\n }\n }\n\n const where = delivery ? deliveryDefinitionFields(delivery) : undefined;\n\n // The brand's typeface and logo: the canvas points at them by canvas-relative path, so\n // the render reads the real files.\n const relative = (file: string | undefined) => (file ? toCanvasRelative(canvasDir, file) : undefined);\n const takes = args.takes !== undefined ? Number.parseInt(String(args.takes), 10) : undefined;\n if (takes !== undefined && !(takes >= 1 && takes <= 3)) return fail(\"invalid_takes\", \"--takes must be 1, 2 or 3\");\n const masterShape = masterShapeArg(args[\"master-shape\"]);\n if (masterShape === null) return fail(\"invalid_master_shape\", `--master-shape is ${SCAFFOLD_SHAPES.join(\" or \")}`);\n const font = await brandFace(workspaceRoot, kit, (file) => toCanvasRelative(canvasDir, file));\n const logo = await placedLogo(kit.logo, (file) => toCanvasRelative(canvasDir, file));\n\n // The render model the router picks for this kind of concept, unless `--gen-model` pinned one.\n const genModel = models.genModel ?? pickImageModel(conceptClassOf(staticAdSpec(blueprint, elements)), \"generate\");\n const opts: StaticAdOpts = {\n genModel,\n imagePath: canvasImagePath,\n imageIsUrl: canvasImageIsUrl,\n blueprintPath: canvasBlueprintPath,\n aspectRatio: args.aspect ? String(args.aspect) : undefined,\n ...(delivery ? { delivery } : {}),\n ...(who.adPlacements ? { adPlacements: who.adPlacements } : {}),\n brand: { logoPath: relative(kit.logo), ...logo.brand, ...(font ? { font } : {}) },\n ...logo.opts,\n takes,\n ...(masterShape ? { masterShape } : {}),\n };\n\n // prompt.json is the ad spec the agent rewrites into our ad; every render prompt is\n // compiled from it (static-brief.ts), here and again on every run.\n let canvas: ReturnType<typeof scaffoldStaticAd>;\n let report: ReturnType<typeof staticAdReport>;\n let conceptNotes: string[] = [];\n try {\n report = staticAdReport(blueprint, elements, { ...opts, spec: staticAdSpec(blueprint, elements, { logo: Boolean(kit.logo) }) });\n const spec = staticAdSpec(blueprint, elements, {\n brand,\n formats: report.output_formats,\n logo: Boolean(kit.logo),\n ...(fit ? { fit: conceptFromFit(fit, reference?.ad_id ?? \"\") } : {}),\n ...(market ? { market } : {}),\n });\n await writeFile(blueprintPath, `${JSON.stringify(spec, null, 2)}\\n`, \"utf8\");\n conceptNotes = conceptProblems(spec).map(\n (p) => `CONCEPT: ${p} Then \\`baker canvas run\\`; until then it refuses to render.`,\n );\n if (!fit && reference) {\n conceptNotes.push(noFitNote(reference));\n }\n canvas = scaffoldStaticAd(blueprint, elements, { ...opts, spec });\n } catch (e) {\n return fail(\"scaffold\", e instanceof Error ? e.message : String(e));\n }\n\n const validation = await validateScaffoldedStaticAd(canvas, path.dirname(outPath));\n if (validation.blocking.length > 0) {\n process.stderr.write(\n `${JSON.stringify({ ok: false, error: { code: \"validation\", issues: validation.blocking } }, null, 2)}\\n`,\n );\n process.exit(2);\n }\n\n await writeFile(outPath, `${JSON.stringify(canvas, null, 2)}\\n`, \"utf8\");\n\n // The library ids, recorded on the creative from this scaffold on (the definition and the\n // sync alike), so `baker_uses` in reference search counts this adaptation before Publish.\n const sourceFields: DefinitionSourceFields = reference\n ? {\n sourceAdId: reference.ad_id,\n sourcePlatform: reference.platform,\n ...(reference.advertiser_id ? { sourceAdvertiserId: reference.advertiser_id } : {}),\n }\n : lookup.status === \"unavailable\"\n ? {\n sourceAdId: lookup.adId,\n sourcePlatform: lookup.platform,\n ...(args[\"source-advertiser-id\"] ? { sourceAdvertiserId: String(args[\"source-advertiser-id\"]).trim() } : {}),\n }\n : {};\n\n // Auto-write _definition.md so the creative joins the content collection immediately (title,\n // platform, source metadata) — the agent no longer hand-writes it. Preserve one on re-scaffold.\n const recorded = who.record ? { targetAdSet: who.targetAdSet, viewer: who.viewer } : {};\n const sourceAdvertiser = args.advertiser ? String(args.advertiser) : reference?.advertiser;\n const sourceReferenceUrl = durableSourceUrl ?? (imageIsUrl ? imageSource : undefined);\n const rebased =\n existingDefinition !== null && sourceFields.sourceAdId && sourceFields.sourcePlatform\n ? rebasedDefinition(existingDefinition, {\n ...sourceFields,\n sourceAdId: sourceFields.sourceAdId,\n sourcePlatform: sourceFields.sourcePlatform,\n ...(sourceAdvertiser ? { sourceAdvertiser } : {}),\n ...(sourceReferenceUrl ? { sourceReferenceUrl } : {}),\n })\n : existingDefinition;\n if (definitionPath && rebased !== null && (who.record || where || rebased !== existingDefinition)) {\n const viewed = who.record ? setDefinitionViewer(rebased, recorded) : rebased;\n await writeFile(definitionPath, where ? setDefinitionDelivery(viewed, where) : viewed, \"utf8\");\n }\n if (definitionPath && existingDefinition === null) {\n await writeFile(\n definitionPath,\n buildCreativeDefinition({\n title: args.title ? String(args.title) : titleFromSlug(slug ?? \"\"),\n kind: \"static\",\n ...where,\n formats: resolveFormatList(report.output_formats),\n sourceReferenceUrl: durableSourceUrl ?? (imageIsUrl ? imageSource : undefined),\n sourceAdvertiser: args.advertiser\n ? String(args.advertiser)\n : (reference?.advertiser ?? (args.context ? String(args.context) : undefined)),\n ...sourceFields,\n sourceKind: \"image\",\n ...recorded,\n description: describeBlueprintIntent(blueprint),\n }),\n \"utf8\",\n );\n }\n\n // Push the parsed node-graph so the dashboard can draw this creative's\n // workflow immediately — before the first (billed) run. Best-effort.\n if (slug) {\n await syncCreativeDefinitionBestEffort({\n slug,\n title: args.title ? String(args.title) : titleFromSlug(slug),\n ...(where ? { platform: where.platform } : {}),\n ...(await readDefinitionPlatforms(outPath)),\n formats: resolveFormatList(report.output_formats),\n sourceReferenceUrl: durableSourceUrl ?? (imageIsUrl ? imageSource : undefined),\n ...sourceFields,\n canvas,\n sourceSha: await computeSourceSha(outPath),\n });\n }\n\n const hints = [\n ...who.notes,\n ...(delivery?.notes ?? []),\n ...(lookup.status === \"unavailable\"\n ? [\n `REFERENCE NOT READ: the winners library could not return ad ${lookup.adId} (${lookup.message}). prompt.json is read from the picture alone and has no \\`reference\\` block; the source ids are still recorded. Check the ad id and platform, or continue from the picture.`,\n ]\n : []),\n ...(uncast.length\n ? [\n `NOT CAST: ${uncast.map((h) => `\\`${h}\\``).join(\", \")} — the element selection found fewer people than avatars passed, so ${uncast.length === 1 ? \"this avatar plays\" : \"these avatars play\"} nobody in this ad. Tell the user who is cast and who is not.`,\n ]\n : []),\n ...(found.hint ? [found.hint] : []),\n ...validation.hints,\n ...conceptNotes,\n ...report.describe_gaps.map((gap) =>\n gap === \"winning_mechanisms\"\n ? \"The describe pass named no winning mechanism. Look at the source ad, add a `mechanism` entry to prompt.json ({ device, why_it_works }) and rebuild that device for our brand; a rewrite without it keeps the look and loses what made the ad work.\"\n : \"The describe pass recorded no typefaces. The designed lines are set in the brand's font when one loads (src/brand/fonts/, tokens.json or BRAND.md); with none, name our face in prompt.json's `brand.typeface` (for example \\\"a heavy geometric sans\\\"), or they are set in a plain sans.\",\n ),\n ];\n process.stdout.write(\n `${JSON.stringify(\n {\n ok: true,\n canvas_path: outPath,\n prompt_path: blueprintPath,\n definition_path: definitionPath ?? undefined,\n source_reference: durableSourceUrl ?? undefined,\n ...(reference\n ? {\n reference: {\n ad_id: reference.ad_id,\n platform: reference.platform,\n advertiser_id: reference.advertiser_id,\n format_pattern: reference.format_pattern,\n mechanism: reference.message.mechanism,\n },\n }\n : {}),\n output: canvas.output,\n ...(hints.length ? { hints } : {}),\n models: { describe: describeModel, select: selectModel, gen: opts.genModel },\n aspect_ratio: report.aspect_ratio,\n ...deliveryOutput(delivery),\n ...viewerOutput(who),\n output_formats: report.output_formats,\n // As the canvas records it: its spec carries the fit's concept, which the report's does not.\n master_shape: recordedShape(canvas) ?? report.master_shape,\n stats: {\n total_nodes: canvas.nodes.length,\n describe_credits_spent: creditsSpent,\n run_estimated_credits: validation.estimatedCredits,\n },\n checklist: {\n edit_prompt: `Edit ${path.basename(blueprintPath)}: it is the ad spec, read from your image, to rewrite into the ad you want. \\`viewer\\` (who sees it and what they already know), \\`message\\` (the one thing it tells them), \\`copy\\` (each line, \\`in_scene\\` or \\`designed\\`), \\`scene\\`, \\`references\\` (one picture each, by role), \\`colors\\` (each tied to an object, from the brand) and an optional \\`direction\\`. You never write a model prompt: every render prompt is compiled from this file and shown on its node.${reference ? \" Its `reference` block is the library's read of the source ad (container, layout, mechanism, offer, text blocks): keep it as the account of why the ad won, and rebuild it for our brand.\" : \"\"}`,\n mechanism: report.winning_mechanisms,\n rebuild_the_mechanism:\n \"`mechanism` is WHY the source ad works. Rebuild each device for our brand in prompt.json's copy and scene (a rhyme stays a rhyme in our words, a before/after stays a before/after of our product); never copy the source's literal copy.\",\n assets_to_supply: report.elements,\n summary: report.summary,\n text: staticTextNote(report),\n font: report.font,\n in_scene_text: report.in_scene_text,\n logo: report.logo.why,\n takes:\n report.takes === 1\n ? \"1 finished ad is rendered and used as it is (no judge).\"\n : `${report.takes} variants of the finished ad are rendered, one request each on its own direction. A prefilter drops any whose words or placement fail the checks, and the judge compares the rest pairwise against the brief (words, picture, space, one idea, the brief itself, brand); the winner becomes the ad and the others stay in the run as options the person can switch to (\\`baker canvas run --use-variant\\`).`,\n pictures:\n \"The reference's own people, products, animals and badges are not slots to fill: they are the source's world. Cast a person from a suitable ready company Avatar by default (--avatar <handle>); create one from the buyer context if none fits. A description-only one-off is available when explicitly requested; never use a stranger's found photo. To show our own product or another picture, add it to prompt.json's `references` with its `image` (a path from this folder, or a URL): every run wires it.\",\n formats: staticFormatsNote(report, opts.genModel, delivery),\n viewer: viewerNote(who),\n note: `Populate as you go: for each [TODO] ingest slot, source its real asset and wire it into the slot right away, one at a time. The logo is optional and never a slot to fill: it is given to the model only when prompt.json has \\`\"logo\": true\\` and src/brand/logos/ has the real file; never fetch or draw a stand-in. When every slot is filled, \\`baker canvas validate\\` then \\`baker canvas run\\`. Running generates billed images: it is not free.`,\n },\n },\n null,\n 2,\n )}\\n`,\n );\n },\n});\n\n/**\n * The brand's logo file as every size places it: its shape and its other colourways, paths as the\n * canvas reads them. A file that does not open as a picture is drawn by the model from the file\n * (`logoComposite: false`); the first run says so.\n */\nasync function placedLogo(\n file: string | undefined,\n relative: (file: string) => string,\n): Promise<{ brand: { logoAspect?: number; logoColourways?: string[] }; opts: { logoComposite?: false } }> {\n if (!file) return { brand: {}, opts: {} };\n const read = await readLogoFile(file);\n if (!read) return { brand: {}, opts: { logoComposite: false } };\n return {\n brand: {\n logoAspect: read.aspect,\n ...(read.colourways.length > 0 ? { logoColourways: read.colourways.map(relative) } : {}),\n },\n opts: {},\n };\n}\n","import {\n VIEWER_KNOWS_VALUES,\n VIEWER_TEMPERATURE_VALUES,\n type ViewerKnows,\n type ViewerProfile,\n type ViewerTemperature,\n} from \"../../viewer-profile.ts\";\nimport { parseDefinitionViewerFields } from \"./creative-definition.ts\";\nimport { resolveViewer } from \"./viewer-check.ts\";\n\n/**\n * Who a scaffolded static ad is for, decided before anything is billed: the viewer the\n * ad set it will run in reaches (`--target-adset`, read as `baker ads meta adsets\n * --audience` reads it). The viewer's placements are what the sizes, the brief and the\n * prefilter keep clear of; the viewer itself is recorded in `_definition.md`, where the\n * viewer check reads it before every render.\n */\n\n/** The scaffold flags that say who the ad is for, as citty hands them over. */\nexport type ScaffoldViewerFlags = {\n \"target-adset\"?: unknown;\n \"viewer-temperature\"?: unknown;\n \"viewer-knows\"?: unknown;\n \"viewer-placements\"?: unknown;\n};\n\nexport type ScaffoldViewer = {\n ok: true;\n targetAdSet?: string;\n viewer?: ViewerProfile;\n /** Write `targetAdSet` / `viewer` into `_definition.md`: they came from this scaffold's flags. */\n record: boolean;\n /** The placements the sizes are planned around; absent = Advantage+ (Reels included). */\n adPlacements?: string[];\n /** What could not be read, for the hints. */\n notes: string[];\n};\n\n/** The viewer one ad set reaches, or null when no connected account holds it. */\nexport type AdSetViewerLookup = (adSetId: string) => Promise<ViewerProfile | null>;\n\nfunction flagText(value: unknown): string | undefined {\n const text = typeof value === \"string\" || typeof value === \"number\" ? String(value).trim() : \"\";\n return text || undefined;\n}\n\n/** Placements that narrow what Advantage+ runs; `automatic` alone is Advantage+ itself. */\nfunction narrows(placements: readonly string[]): boolean {\n return placements.some((placement) => placement !== \"automatic\");\n}\n\nfunction flagList(value: unknown): string[] | undefined {\n const list = (flagText(value) ?? \"\")\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n return list.length > 0 ? list : undefined;\n}\n\n/** What the `--viewer-*` flags say, checked. */\ntype ViewerFields = { temperature?: ViewerTemperature; knows?: ViewerKnows[]; placements?: string[] };\n\nconst isTemperature = (value: string): value is ViewerTemperature =>\n (VIEWER_TEMPERATURE_VALUES as readonly string[]).includes(value);\nconst isKnows = (value: string): value is ViewerKnows => (VIEWER_KNOWS_VALUES as readonly string[]).includes(value);\n\nfunction viewerFields(flags: ScaffoldViewerFlags): { ok: true; fields: ViewerFields } | { ok: false; message: string } {\n const temperature = flagText(flags[\"viewer-temperature\"]);\n if (temperature !== undefined && !isTemperature(temperature)) {\n return { ok: false, message: `--viewer-temperature must be one of ${VIEWER_TEMPERATURE_VALUES.join(\", \")}` };\n }\n const knows = flagList(flags[\"viewer-knows\"]);\n if (knows && !knows.every(isKnows)) {\n return { ok: false, message: `--viewer-knows takes ${VIEWER_KNOWS_VALUES.join(\", \")}` };\n }\n const placements = flagList(flags[\"viewer-placements\"]);\n return {\n ok: true,\n fields: {\n ...(temperature ? { temperature } : {}),\n ...(knows ? { knows: knows.filter(isKnows) } : {}),\n ...(placements ? { placements } : {}),\n },\n };\n}\n\n/** The viewer the agent read from the Knowledge, with no ad set to read it from. */\nfunction givenViewer(fields: ViewerFields): ViewerProfile | undefined {\n if (!fields.temperature) return undefined;\n return {\n temperature: fields.temperature,\n knows: fields.knows ?? [],\n placements: fields.placements ?? [\"automatic\"],\n source: \"knowledge\",\n reasons: [\"No ad set was read: this viewer was given when the ad was scaffolded, from the Knowledge.\"],\n };\n}\n\nconst FIELD_WORDS: Record<keyof ViewerFields, string> = {\n temperature: \"Temperature\",\n knows: \"What they know\",\n placements: \"Placements\",\n};\n\n/** The viewer read off the ad set, with whatever the agent stated in its place. */\nfunction correctedViewer(read: ViewerProfile, fields: ViewerFields): ViewerProfile {\n const stated = (Object.keys(FIELD_WORDS) as (keyof ViewerFields)[]).filter((key) => fields[key] !== undefined);\n if (stated.length === 0) return read;\n return {\n ...read,\n ...fields,\n reasons: [...read.reasons, ...stated.map((key) => `${FIELD_WORDS[key]} given when the ad was scaffolded.`)],\n };\n}\n\nconst EVERY_PLACEMENT = \"so the sizes keep clear of every placement\";\n\nasync function readAdSet(\n adSetId: string,\n adSetViewer: AdSetViewerLookup,\n notes: string[],\n): Promise<ViewerProfile | undefined> {\n try {\n const viewer = await adSetViewer(adSetId);\n if (viewer) return viewer;\n notes.push(`Ad set ${adSetId} is not in any connected Meta ad account, ${EVERY_PLACEMENT}.`);\n } catch (e) {\n notes.push(`Could not read ad set ${adSetId} (${e instanceof Error ? e.message : String(e)}), ${EVERY_PLACEMENT}.`);\n }\n return undefined;\n}\n\n/**\n * The viewer a creative's `_definition.md` already names, resolved as the viewer check\n * resolves it (the recorded viewer, else its ad set's); nothing is written back.\n */\nasync function recordedViewer(definition: string, adSetViewer: AdSetViewerLookup): Promise<ScaffoldViewer> {\n const { targetAdSet, viewer: recorded } = parseDefinitionViewerFields(definition);\n if (!targetAdSet && recorded === undefined) return { ok: true, record: false, notes: [] };\n const resolved = await resolveViewer({ recorded, targetAdSet }, { adSetViewer, personas: async () => [] });\n const viewer = resolved.from === \"recorded\" || resolved.from === \"ad_set\" ? resolved.viewer : undefined;\n return outcome(targetAdSet, viewer, false, resolved.notes);\n}\n\nfunction outcome(\n targetAdSet: string | undefined,\n viewer: ViewerProfile | undefined,\n record: boolean,\n notes: string[],\n): ScaffoldViewer {\n return {\n ok: true,\n ...(targetAdSet ? { targetAdSet } : {}),\n ...(viewer ? { viewer } : {}),\n record,\n ...(viewer && narrows(viewer.placements) ? { adPlacements: viewer.placements } : {}),\n notes,\n };\n}\n\n/**\n * Who the ad is for, from the scaffold's flags: `--target-adset` read off the ad set (any\n * `--viewer-*` flag correcting that read), else the `--viewer-*` flags alone (a viewer from\n * the Knowledge); with neither, whatever the creative's `_definition.md` already records.\n * A bad flag is refused before anything is billed; an ad set that cannot be read is not.\n */\nexport async function scaffoldViewer(\n flags: ScaffoldViewerFlags,\n existingDefinition: string | null,\n adSetViewer: AdSetViewerLookup,\n): Promise<ScaffoldViewer | { ok: false; message: string }> {\n const targetAdSet = flagText(flags[\"target-adset\"]);\n const given = viewerFields(flags);\n if (!given.ok) return given;\n const { fields } = given;\n if (!targetAdSet && !fields.temperature && (fields.knows || fields.placements)) {\n return {\n ok: false,\n message: \"--viewer-knows and --viewer-placements describe a viewer: pass --viewer-temperature too\",\n };\n }\n if (!targetAdSet && !fields.temperature && existingDefinition !== null) {\n return await recordedViewer(existingDefinition, adSetViewer);\n }\n const notes: string[] = [];\n const read = targetAdSet ? await readAdSet(targetAdSet, adSetViewer, notes) : undefined;\n const viewer = read ? correctedViewer(read, fields) : givenViewer(fields);\n return outcome(targetAdSet, viewer, targetAdSet !== undefined || viewer !== undefined, notes);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,OAAO,UAAU,iBAAiB;AAC3C,OAAO,UAAU;AAUjB,SAAS,qBAAqB;;;AC8B9B,SAAS,SAAS,OAAoC;AACpD,QAAM,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW,OAAO,KAAK,EAAE,KAAK,IAAI;AAC7F,SAAO,QAAQ;AACjB;AAGA,SAAS,QAAQ,YAAwC;AACvD,SAAO,WAAW,KAAK,CAAC,cAAc,cAAc,WAAW;AACjE;AAEA,SAAS,SAAS,OAAsC;AACtD,QAAM,QAAQ,SAAS,KAAK,KAAK,IAC9B,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,OAAO;AACjB,SAAO,KAAK,SAAS,IAAI,OAAO;AAClC;AAKA,IAAM,gBAAgB,CAAC,UACpB,0BAAgD,SAAS,KAAK;AACjE,IAAM,UAAU,CAAC,UAAyC,oBAA0C,SAAS,KAAK;AAElH,SAAS,aAAa,OAAiG;AACrH,QAAM,cAAc,SAAS,MAAM,oBAAoB,CAAC;AACxD,MAAI,gBAAgB,UAAa,CAAC,cAAc,WAAW,GAAG;AAC5D,WAAO,EAAE,IAAI,OAAO,SAAS,uCAAuC,0BAA0B,KAAK,IAAI,CAAC,GAAG;AAAA,EAC7G;AACA,QAAM,QAAQ,SAAS,MAAM,cAAc,CAAC;AAC5C,MAAI,SAAS,CAAC,MAAM,MAAM,OAAO,GAAG;AAClC,WAAO,EAAE,IAAI,OAAO,SAAS,wBAAwB,oBAAoB,KAAK,IAAI,CAAC,GAAG;AAAA,EACxF;AACA,QAAM,aAAa,SAAS,MAAM,mBAAmB,CAAC;AACtD,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,QAAQ;AAAA,MACN,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,MACrC,GAAI,QAAQ,EAAE,OAAO,MAAM,OAAO,OAAO,EAAE,IAAI,CAAC;AAAA,MAChD,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,IACrC;AAAA,EACF;AACF;AAGA,SAAS,YAAY,QAAiD;AACpE,MAAI,CAAC,OAAO,YAAa,QAAO;AAChC,SAAO;AAAA,IACL,aAAa,OAAO;AAAA,IACpB,OAAO,OAAO,SAAS,CAAC;AAAA,IACxB,YAAY,OAAO,cAAc,CAAC,WAAW;AAAA,IAC7C,QAAQ;AAAA,IACR,SAAS,CAAC,2FAA2F;AAAA,EACvG;AACF;AAEA,IAAM,cAAkD;AAAA,EACtD,aAAa;AAAA,EACb,OAAO;AAAA,EACP,YAAY;AACd;AAGA,SAAS,gBAAgB,MAAqB,QAAqC;AACjF,QAAM,SAAU,OAAO,KAAK,WAAW,EAA6B,OAAO,CAAC,QAAQ,OAAO,GAAG,MAAM,MAAS;AAC7G,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,SAAS,CAAC,GAAG,KAAK,SAAS,GAAG,OAAO,IAAI,CAAC,QAAQ,GAAG,YAAY,GAAG,CAAC,oCAAoC,CAAC;AAAA,EAC5G;AACF;AAEA,IAAM,kBAAkB;AAExB,eAAe,UACb,SACA,aACA,OACoC;AACpC,MAAI;AACF,UAAM,SAAS,MAAM,YAAY,OAAO;AACxC,QAAI,OAAQ,QAAO;AACnB,UAAM,KAAK,UAAU,OAAO,6CAA6C,eAAe,GAAG;AAAA,EAC7F,SAAS,GAAG;AACV,UAAM,KAAK,yBAAyB,OAAO,KAAK,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC,MAAM,eAAe,GAAG;AAAA,EACpH;AACA,SAAO;AACT;AAMA,eAAe,eAAe,YAAoB,aAAyD;AACzG,QAAM,EAAE,aAAa,QAAQ,SAAS,IAAI,4BAA4B,UAAU;AAChF,MAAI,CAAC,eAAe,aAAa,OAAW,QAAO,EAAE,IAAI,MAAM,QAAQ,OAAO,OAAO,CAAC,EAAE;AACxF,QAAM,WAAW,MAAM,cAAc,EAAE,UAAU,YAAY,GAAG,EAAE,aAAa,UAAU,YAAY,CAAC,EAAE,CAAC;AACzG,QAAM,SAAS,SAAS,SAAS,cAAc,SAAS,SAAS,WAAW,SAAS,SAAS;AAC9F,SAAO,QAAQ,aAAa,QAAQ,OAAO,SAAS,KAAK;AAC3D;AAEA,SAAS,QACP,aACA,QACA,QACA,OACgB;AAChB,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,IACrC,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B;AAAA,IACA,GAAI,UAAU,QAAQ,OAAO,UAAU,IAAI,EAAE,cAAc,OAAO,WAAW,IAAI,CAAC;AAAA,IAClF;AAAA,EACF;AACF;AAQA,eAAsB,eACpB,OACA,oBACA,aAC0D;AAC1D,QAAM,cAAc,SAAS,MAAM,cAAc,CAAC;AAClD,QAAM,QAAQ,aAAa,KAAK;AAChC,MAAI,CAAC,MAAM,GAAI,QAAO;AACtB,QAAM,EAAE,OAAO,IAAI;AACnB,MAAI,CAAC,eAAe,CAAC,OAAO,gBAAgB,OAAO,SAAS,OAAO,aAAa;AAC9E,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS;AAAA,IACX;AAAA,EACF;AACA,MAAI,CAAC,eAAe,CAAC,OAAO,eAAe,uBAAuB,MAAM;AACtE,WAAO,MAAM,eAAe,oBAAoB,WAAW;AAAA,EAC7D;AACA,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,cAAc,MAAM,UAAU,aAAa,aAAa,KAAK,IAAI;AAC9E,QAAM,SAAS,OAAO,gBAAgB,MAAM,MAAM,IAAI,YAAY,MAAM;AACxE,SAAO,QAAQ,aAAa,QAAQ,gBAAgB,UAAa,WAAW,QAAW,KAAK;AAC9F;;;ADzGA,SAAS,iBAAiB,WAAmB,MAAsB;AACjE,QAAM,MAAM,KAAK,SAAS,WAAW,IAAI,EAAE,MAAM,KAAK,GAAG,EAAE,KAAK,GAAG;AACnE,SAAO,IAAI,WAAW,GAAG,IAAI,MAAM,KAAK,GAAG;AAC7C;AAaA,eAAsB,wBACpB,QACA,OACA,QACiB;AACjB,MAAI;AACJ,MAAI,OAAO;AAIT,QAAI;AACF,OAAC,EAAE,QAAQ,MAAM,IAAI,MAAM,mBAAmB,QAAQ,EAAE,UAAU,uBAAuB,CAAC;AAAA,IAC5F,SAAS,GAAG;AACV,YAAM,IAAI,MAAM,oCAAoC,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC,GAAG;AAAA,IACnG;AAAA,EACF,OAAO;AACL,YAAQ,MAAM,SAAS,MAAM;AAAA,EAC/B;AACA,QAAM,OAAO,MAAM,iBAAiB,KAAK;AACzC,QAAM,SAAS,UAAU,KAAK,KAAK;AAEnC,QAAM,EAAE,QAAQ,UAAU,IAAI,MAAM,OAAO,mBAAmB,QAAQ,KAAK,MAAM,QAAW,QAAQ;AACpG,QAAM,SAAS,MAAM,MAAM,QAAQ;AAAA,IACjC,QAAQ;AAAA,IACR,MAAM,IAAI,WAAW,KAAK,KAAK;AAAA,IAC/B,SAAS,EAAE,gBAAgB,KAAK,KAAK;AAAA,EACvC,CAAC;AACD,MAAI,CAAC,OAAO,GAAI,OAAM,IAAI,MAAM,yBAAyB,OAAO,MAAM,GAAG;AACzE,SAAO;AACT;AAOA,eAAe,UACb,MACA,KACA,UAC8B;AAC9B,QAAM,OAAO,MAAM,kBAAkB;AAAA,IACnC,MAAM,IAAI;AAAA,IACV,OAAO,MAAM,mBAAmB,IAAI;AAAA,IACpC,YAAY,CAAC,QAAQ,WAAW,WAAW,QAAQ,QAAQ,EAAE,iBAAiB,UAAU,CAAC;AAAA,EAC3F,CAAC;AACD,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,UAAU,KAAK,OAAO,EAAE,GAAG,MAAM,MAAM,EAAE,MAAM,SAAS,KAAK,KAAK,IAAI,EAAE,EAAE,IAAI;AACvF;AAKA,SAAS,eAAe,QAAwB;AAC9C,MAAI,OAAO,cAAc;AACvB,WAAO;AAAA,EACT;AACA,QAAM,OAAO,OAAO,OAAO,MAAM,OAAO,IAAI,gCAAgC;AAC5E,SAAO,yJAAyJ,IAAI;AACtK;AAGA,SAAS,kBAAkB,QAAgB,UAAkB,UAAqC;AAChG,QAAM,MAAM,WAAW,IAAI,aAAa,UAAU,OAAO,YAAY,OAAO,WAAW,CAAC,KAAK;AAC7F,QAAM,UACJ,OAAO,QAAQ,SAAS,IACpB,sBAAsB,OAAO,QAAQ,KAAK,IAAI,CAAC,kHAC/C;AACN,QAAM,OAAO,OAAO;AACpB,QAAM,OAAmD;AAAA,IACvD,QAAQ,CAAC,WAAW,GAAG,MAAM,uCAAuC,KAAK,OAAO,WAAW;AAAA,IAC3F,UAAU,CAAC,WACT,GAAG,MAAM;AAAA,IACX,MAAM,CAAC,WAAW,GAAG,MAAM;AAAA,IAC3B,OAAO,CAAC,WAAW,GAAG,MAAM;AAAA,EAC9B;AACA,QAAM,MAAM,KAAK,MAAM,IAAI,CAAC,MAAM,KAAK,EAAE,IAAI,IAAI,EAAE,MAAM,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI;AACjF,QAAM,QAAQ,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU,IAAI,KAAK;AACnE,SAAO,YAAY,OAAO,eAAe,KAAK,IAAI,CAAC,mDAAmD,QAAQ,MAAM,GAAG,IAAI,KAAK,GAAG,GAAG,GAAG,OAAO;AAClJ;AAGA,SAAS,aAAa,KAA8C;AAClE,SAAO;AAAA,IACL,GAAI,IAAI,cAAc,EAAE,cAAc,IAAI,YAAY,IAAI,CAAC;AAAA,IAC3D,GAAI,IAAI,SACJ;AAAA,MACE,QAAQ;AAAA,QACN,aAAa,IAAI,OAAO;AAAA,QACxB,OAAO,IAAI,OAAO;AAAA,QAClB,YAAY,IAAI,OAAO;AAAA,QACvB,QAAQ,IAAI,OAAO;AAAA,MACrB;AAAA,IACF,IACA,CAAC;AAAA,EACP;AACF;AAGA,SAAS,WAAW,KAA6B;AAC/C,MAAI,CAAC,IAAI,QAAQ;AACf,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,IAAI,eAAe,2BAA2B,IAAI,aAAa,KAAK,IAAI,CAAC,KAAK;AAC5F,SAAO,YAAY,eAAe,IAAI,MAAM,CAAC,8CAA8C,KAAK;AAClG;AAGA,SAAS,cAAc,MAA+B;AACpD,SAAO;AAAA,IACL,eAAe,aAAa,kBAAkB,KAAK,gBAAgB,GAAG,iBAAiB;AAAA,IACvF,aAAa,aAAa,iBAAiB,KAAK,cAAc,GAAG,wBAAwB;AAAA;AAAA;AAAA,IAGzF,UAAU,KAAK,WAAW,IAAI,aAAa,kBAAkB,KAAK,WAAW,GAAG,OAAO,KAAK,WAAW,CAAC,CAAC,IAAI;AAAA,EAC/G;AACF;AAMA,eAAe,eACb,MACA,gBACA,YACuC;AACvC,MAAI,CAAC,cAAc,CAAC,cAAc,IAAI,EAAG,QAAO;AAChD,QAAM,WAAW,MAAM,iBAAiB,MAAM,cAAc;AAC5D,MAAI,CAAC,SAAS,GAAI,QAAO,KAAK,SAAS,MAAM,MAAM,SAAS,MAAM,SAAS,SAAS,MAAM,GAAG;AAC7F,SAAO,SAAS;AAClB;AAGA,SAAS,eAAe,UAAiE;AACvF,SAAO,WAAW,EAAE,WAAW,SAAS,WAAW,MAAM,SAAS,MAAM,iBAAiB,SAAS,OAAO,IAAI,CAAC;AAChH;AASA,eAAsB,2BACpB,QACA,WACsF;AACtF,QAAM,aAAa,MAAM,mBAAmB,2BAA2B,QAAQ,SAAS,GAAG,gBAAgB,CAAC;AAC5G,MAAI,WAAW,GAAI,QAAO,EAAE,UAAU,CAAC,GAAG,OAAO,CAAC,GAAG,kBAAkB,WAAW,iBAAiB;AACnG,QAAM,UAAU,WAAW,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,yBAAyB;AACpF,SAAO;AAAA,IACL,UAAU,WAAW,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,yBAAyB;AAAA,IAC9E,OAAO,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,OAAO,oDAAoD;AAAA,EACvG;AACF;AAGO,SAAS,oBACd,aACA,YACA,eACA,aACA,SACA;AACA,QAAM,iBAAiB,aACnB,EAAE,QAAQ,OAAgB,KAAK,aAAa,QAAQ,QAAiB,IACrE,EAAE,QAAQ,QAAiB,MAAM,aAAa,QAAQ,QAAiB;AAC3E,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,UAAU,EAAE,MAAM,0BAA0B;AAAA,IAC5C,OAAO;AAAA,MACL,EAAE,IAAI,YAAY,MAAM,UAAU,QAAQ,eAAe;AAAA,MACzD;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,QAAQ,EAAE,OAAO,sBAAsB;AAAA,QACvC,QAAQ,EAAE,OAAO,eAAe,YAAY,KAAM,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,GAAI,OAAO,kBAAkB;AAAA,MAC9G;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,QAAQ,EAAE,WAAW,4BAA4B;AAAA,QACjD,QAAQ;AAAA,UACN,OAAO;AAAA,UACP,YAAY;AAAA,UACZ,aAAa;AAAA,UACb,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA;AAAA,EAEF;AACF;AAGA,eAAe,gBAAgB,QAI5B;AACD,QAAM,SAAS,oBAAoB,EAAE,KAAK,CAAC,SAAS,QAAQ,OAAO,MAAM,GAAG,IAAI;AAAA,CAAI,EAAE,CAAC;AACvF,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,IAAI,QAAQ,CAAC,CAAC;AAC1C,oBAAgB,OAAO;AACvB,mBAAgB,OAAO,OAAsC;AAAA,EAC/D,SAAS,GAAG;AACV,QAAI,aAAa,gBAAiB,QAAO,KAAK,cAAc,KAAK,UAAU,EAAE,MAAM,CAAC;AACpF,WAAO,KAAK,YAAY,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,EACpE;AACA,MAAI;AACF,UAAM,YAAY,KAAK,MAAM,MAAM,cAAc,cAAc,UAAU,aAAa,iBAAiB,CAAC;AACxG,UAAM,WAAW,cAAc,MAAM,cAAc,cAAc,QAAQ,MAAM,kBAAkB,CAAC;AAClG,WAAO,EAAE,WAAW,UAAU,aAAa;AAAA,EAC7C,SAAS,GAAG;AACV,WAAO,KAAK,gBAAgB,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,EACxE;AACF;AAQO,SAAS,UAAU,WAAwD;AAChF,SAAO,GAAG,WAAW,6BAA6B,UAAU,KAAK,eAAe,UAAU,QAAQ;AACpG;AAEO,SAAS,kBAAkB,MAA+B,aAA+B;AAC9F,SAAO,eAAe,CAAC,KAAK,QAAQ,CAAC,KAAK,WAAW,CAAC,KAAK,gBAAgB,KAAK,CAAC,KAAK,cAAc;AACtG;AAMA,eAAe,kBAAkB,WAA0F;AACzH,MAAI;AACF,UAAM,OAAO,4BAA4B;AAAA,MACvC,MAAM;AAAA,QACJ;AAAA,QACA,EAAE,OAAO,UAAU,OAAO,UAAU,UAAU,SAAS;AAAA,QACvD,EAAE,WAAW,KAAQ;AAAA,MACvB;AAAA,IACF;AACA,YAAQ,OAAO,MAAM,cAAc,KAAK,SAAS,gDAAgD,8BAA8B;AAAA,CAAI;AACnI,WAAO;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,UAAU,cAAc,KAAK,UAAU,EAAE,UAAU,KAAK,SAAS,CAAC,CAAC;AAAA,MACnE,cAAc,KAAK;AAAA,IACrB;AAAA,EACF,SAAS,GAAG;AACV,YAAQ,OAAO,MAAM,iDAAiD,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,CAA+B;AAC/I,WAAO;AAAA,EACT;AACF;AAEA,IAAM,2BACJ;AAKF,IAAM,wBACJ,oeAIc,OAAO,QAAQ,gBAAgB,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,MAAM,GAAG,CAAC,KAAK,IAAI,GAAG,EAAE,KAAK,IAAI,CAAC;AAChG,IAAM,sBACJ;AAEF,IAAM,+BAA+B;AACrC,IAAM,iCACJ;AAEF,IAAM,8BAA8B,wCAAwC,kBAAkB,KAAK,GAAG,CAAC;AACvG,IAAM,2BACJ;AAIF,IAAM,iCACJ;AAGF,IAAM,2BACJ;AAEF,IAAM,gCACJ;AAKF,IAAM,WAAW;AAGjB,IAAM,kBAAkB,CAAC,SAAS,UAAU;AAG5C,SAAS,eAAe,OAAgD;AACtE,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,QAAQ,gBAAgB,KAAK,CAAC,MAAM,MAAM,OAAO,KAAK,CAAC;AAC7D,SAAO,SAAS;AAClB;AAEA,IAAM,mCACJ;AAEF,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,gBAAgB,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,yBAAyB;AAAA,IACzF,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aACE;AAAA,IACJ;AAAA,IACA,mBAAmB;AAAA,MACjB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,MACb,MAAM,CAAC,GAAG,iBAAiB;AAAA,IAC7B;AAAA,IACA,wBAAwB,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,iCAAiC;AAAA,IACzG,SAAS;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,OAAO,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,gEAAgE;AAAA,IACvH,UAAU,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,6BAA6B;AAAA,IACvF,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,YAAY,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,+BAA+B;AAAA,IAC3F,WAAW,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,sBAAsB;AAAA,IACjF,SAAS,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,oBAAoB;AAAA,IAC7E,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,gBAAgB,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,yBAAyB;AAAA,IACzF,sBAAsB;AAAA,MACpB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,MACb,MAAM,CAAC,GAAG,yBAAyB;AAAA,IACrC;AAAA,IACA,gBAAgB,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,yBAAyB;AAAA,IACzF,qBAAqB,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,8BAA8B;AAAA,IACnG,OAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,KAAK,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,iEAAiE;AAAA,IACtH,kBAAkB,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,uCAAuC;AAAA,IACzG,gBAAgB,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,wDAAwD;AAAA,IACxH,aAAa,EAAE,MAAM,UAAU,UAAU,OAAO,aAAa,uCAAuC;AAAA,EACtG;AACF,CAAC;AASD,eAAsB,gBAAgB,MAAyD;AAC7F,QAAM,OAAO,KAAK,cAAc,IAAI,OAAO,KAAK,cAAc,CAAC,EAAE,KAAK,IAAI;AAC1E,MAAI,CAAC,KAAM,QAAO,EAAE,QAAQ,OAAO;AACnC,QAAM,iBAAiB,sBAAsB,KAAK,iBAAiB,IAAI,OAAO,KAAK,iBAAiB,CAAC,IAAI,MAAS;AAClH,MAAI,CAAC,eAAe,GAAI,QAAO,KAAK,2BAA2B,eAAe,OAAO;AACrF,QAAM,WAAW,eAAe;AAChC,QAAM,eAAe,KAAK,sBAAsB,IAAI,OAAO,KAAK,sBAAsB,CAAC,EAAE,KAAK,IAAI;AAClG,MAAI;AACF,UAAM,KAAK,MAAM,sBAAsB,MAAM,QAAQ;AACrD,UAAM,UAAU,oBAAoB,UAAU,MAAM,EAAE;AACtD,QAAI,QAAS,QAAO,EAAE,QAAQ,WAAW,QAAQ;AACjD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,WAAW,sBAAsB,IAAI,EAAE,MAAM,UAAU,aAAa,CAAC;AAAA,MACrE,UAAU,GAAG,aAAa;AAAA,IAC5B;AAAA,EACF,SAAS,GAAG;AACV,WAAO,EAAE,QAAQ,eAAe,MAAM,UAAU,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,EAAE;AAAA,EACtG;AACF;AAOA,eAAe,iBAAiB,MAA+B,MAAyC;AACtG,MAAI,CAAC,KAAM,QAAO,KAAK,gBAAgB,+DAA+D;AACtG,QAAM,WAAW,KAAK,QAAQ,QAAQ,IAAI,GAAG,OAAO,KAAK,IAAI,CAAC;AAC9D,MAAI;AACJ,MAAI;AACF,cAAU,WAAW,KAAK,MAAM,MAAM,SAAS,UAAU,MAAM,CAAC,CAAC;AAAA,EACnE,SAAS,GAAG;AACV,WAAO,KAAK,gBAAgB,GAAG,QAAQ,uBAAuB,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC,EAAE;AAAA,EAC5G;AACA,QAAM,UAAU,KAAK,KAAK,QAAQ,IAAI,GAAG,OAAO,aAAa,MAAM,GAAG,IAAI,cAAc;AACxF,QAAM,MAAM,KAAK,QAAQ,OAAO;AAChC,QAAM,gBAAgB,KAAK,KAAK,KAAK,aAAa;AAClD,QAAM,iBAAiB,KAAK,KAAK,KAAK,gBAAgB;AACtD,QAAM,qBAAsB,MAAM,WAAW,cAAc,IAAK,MAAM,SAAS,gBAAgB,MAAM,IAAI;AAEzG,QAAM,WAAW,MAAM,eAAe,MAAM,oBAAoB,IAAI;AACpE,QAAM,wBAAwB,MAAM,OAAO;AAC3C,QAAM,MAAM,MAAM,eAAe,MAAM,oBAAoB,kBAAkB,QAAQ,IAAI,CAAC,EAAE,WAAW;AACvG,MAAI,CAAC,IAAI,GAAI,QAAO,KAAK,kBAAkB,IAAI,OAAO;AAEtD,QAAM,UAAU,MAAM,mBAAmB,KAAK,MAAM;AACpD,MAAI,WAAW,QAAS,QAAO,KAAK,UAAU,QAAQ,KAAK;AAC3D,QAAM,UAAU,oBAAoB,MAAM,gCAAgC,IAAI,CAAC,KAAK,QAAQ,QAAQ;AACpG,QAAM,OAAO,eAAe,SAAS,QAAQ,SAAS,OAAO;AAC7D,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AAEpC,QAAM,gBAAiB,MAAM,cAAc,GAAG,KAAM,QAAQ,IAAI;AAChE,QAAM,QAAQ,MAAM,eAAe,eAAe,MAAM,mBAAmB,aAAa,GAAG,MAAM,mBAAmB,aAAa,CAAC;AAClI,QAAM,MAAM,MAAM;AAClB,QAAM,SACJ,IAAI,QAAQ,UAAU,qBAAqB,MAAM,SAAS,KAAK,KAAK,eAAe,YAAY,GAAG,MAAM,EAAE,MAAM,MAAM,IAAI,CAAC;AAC7H,QAAM,QAAQ,WAAW,GAAG;AAC5B,QAAM,OAAO,MAAM,UAAU,eAAe,KAAK,CAAC,SAAS,iBAAiB,KAAK,IAAI,CAAC;AACtF,QAAM,WAAW,eAAe,eAAe,KAAK,IAAI,GAAG,UAAU;AACrE,QAAM,cAAc,eAAe,KAAK,cAAc,CAAC;AACvD,MAAI,gBAAgB,KAAM,QAAO,KAAK,wBAAwB,qBAAqB,gBAAgB,KAAK,MAAM,CAAC,EAAE;AACjH,QAAM,OAAO,MAAM,WAAW,IAAI,MAAM,CAAC,SAAS,iBAAiB,KAAK,IAAI,CAAC;AAC7E,QAAM,OAAqB;AAAA,IACzB;AAAA,IACA,eAAe;AAAA,IACf,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,IACrC,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/B,GAAI,IAAI,eAAe,EAAE,cAAc,IAAI,aAAa,IAAI,CAAC;AAAA,IAC7D,OAAO,EAAE,UAAU,IAAI,OAAO,iBAAiB,KAAK,IAAI,IAAI,IAAI,QAAW,GAAG,KAAK,OAAO,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG;AAAA,IACpH,GAAG,KAAK;AAAA,EACV;AACA,QAAM,SAAS,eAAe,CAAC,GAAG,KAAK,UAAU,EAAE,GAAG,MAAM,MAAM,KAAK,KAAK,CAAC;AAC7E,QAAM,OAAO;AAAA,IACX,GAAG,KAAK;AAAA,IACR,GAAI,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,GAAG,KAAK,KAAK,MAAM,EAAE,IAAI,CAAC;AAAA,IAC3D,SAAS,OAAO;AAAA,IAChB,MAAM,QAAQ,IAAI,IAAI;AAAA,IACtB,GAAI,SAAS,EAAE,QAAQ,EAAE,GAAI,KAAK,KAAK,UAAU,EAAE,KAAK,4BAA4B,GAAI,OAAO,EAAE,IAAI,CAAC;AAAA,EACxG;AACA,QAAM,UAAU,eAAe,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAC3E,QAAM,SAAS,iBAAiB,CAAC,GAAG,KAAK,UAAU,EAAE,GAAG,MAAM,KAAK,CAAC;AACpE,QAAM,aAAa,MAAM,2BAA2B,QAAQ,GAAG;AAC/D,MAAI,WAAW,SAAS,SAAS,EAAG,QAAO,KAAK,cAAc,WAAW,SAAS,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;AAClH,QAAM,UAAU,SAAS,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAEvE,QAAM,QAAQ,KAAK,QAAQ,OAAO,KAAK,KAAK,IAAI,cAAc,IAAI;AAClE,QAAM,WAAW,IAAI,SAAS,EAAE,aAAa,IAAI,aAAa,QAAQ,IAAI,OAAO,IAAI,CAAC;AACtF,QAAM,QAAQ,WAAW,yBAAyB,QAAQ,IAAI;AAC9D,MAAI,uBAAuB,MAAM;AAC/B,UAAM,UAAU,kBAAkB,OAAO,cAAc;AACvD,UAAM,UAAU,gBAAgB,wBAAwB,EAAE,OAAO,MAAM,UAAU,GAAG,OAAO,SAAS,GAAG,SAAS,CAAC,GAAG,MAAM;AAAA,EAC5H,WAAW,OAAO;AAChB,UAAM,UAAU,gBAAgB,sBAAsB,oBAAoB,KAAK,GAAG,MAAM;AAAA,EAC1F;AACA,QAAM,iCAAiC;AAAA,IACrC;AAAA,IACA;AAAA,IACA,GAAI,QAAQ,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,IAC5C,GAAI,MAAM,wBAAwB,OAAO;AAAA,IACzC,SAAS,kBAAkB,OAAO,cAAc;AAAA,IAChD;AAAA,IACA,WAAW,MAAM,iBAAiB,OAAO;AAAA,EAC3C,CAAC;AACD,UAAQ,OAAO;AAAA,IACb,GAAG,KAAK;AAAA,MACN;AAAA,QACE,IAAI;AAAA,QACJ,aAAa;AAAA,QACb,aAAa;AAAA,QACb,iBAAiB;AAAA,QACjB,QAAQ,OAAO;AAAA,QACf,OAAO,CAAC,GAAG,IAAI,OAAO,GAAI,UAAU,SAAS,CAAC,GAAI,GAAI,MAAM,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,GAAI,GAAG,WAAW,KAAK;AAAA,QAC1G,GAAG,aAAa,GAAG;AAAA,QACnB,GAAG,eAAe,QAAQ;AAAA,QAC1B,gBAAgB,OAAO;AAAA,QACvB,cAAc,OAAO;AAAA,QACrB,OAAO,EAAE,aAAa,OAAO,MAAM,QAAQ,wBAAwB,GAAG,uBAAuB,WAAW,iBAAiB;AAAA,MAC3H;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA;AAAA,EACH;AACF;AAEO,IAAM,0BAA0B,cAAc;AAAA,EACnD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EAeJ;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,gBAAgB,EAAE,MAAM,UAAU,aAAa,yBAAyB;AAAA,IACxE,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aACE;AAAA,IACJ;AAAA,IACA,mBAAmB,EAAE,MAAM,UAAU,aAAa,4BAA4B;AAAA,IAC9E,wBAAwB,EAAE,MAAM,UAAU,aAAa,iCAAiC;AAAA,IACxF,SAAS,EAAE,MAAM,UAAU,aAAa,yEAAyE;AAAA,IACjH,KAAK,EAAE,MAAM,UAAU,aAAa,iEAAiE;AAAA,IACrG,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,OAAO,EAAE,MAAM,UAAU,aAAa,gEAAgE;AAAA,IACtG,UAAU,EAAE,MAAM,UAAU,aAAa,6BAA6B;AAAA,IACtE,YAAY;AAAA,MACV,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,kBAAkB,EAAE,MAAM,UAAU,aAAa,uCAAuC;AAAA,IACxF,gBAAgB,EAAE,MAAM,UAAU,aAAa,4DAA4D;AAAA,IAC3G,aAAa,EAAE,MAAM,UAAU,aAAa,uCAAuC;AAAA,IACnF,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,aACE;AAAA,IACJ;AAAA,IACA,gBAAgB,EAAE,MAAM,UAAU,aAAa,yBAAyB;AAAA,IACxE,sBAAsB,EAAE,MAAM,UAAU,aAAa,+BAA+B;AAAA,IACpF,gBAAgB,EAAE,MAAM,UAAU,aAAa,yBAAyB;AAAA,IACxE,qBAAqB,EAAE,MAAM,UAAU,aAAa,8BAA8B;AAAA,IAClF,YAAY,EAAE,MAAM,UAAU,aAAa,+BAA+B;AAAA,IAC1E,WAAW,EAAE,MAAM,UAAU,aAAa,sBAAsB;AAAA,IAChE,SAAS,EAAE,MAAM,UAAU,aAAa,oBAAoB;AAAA,IAC5D,OAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,gBAAgB;AAAA,MACd,MAAM;AAAA,MACN,aAAa,GAAG,QAAQ;AAAA,IAC1B;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,aACE;AAAA,IAMJ;AAAA,EACF;AAAA,EACA,MAAM,IAAI,EAAE,KAAK,GAAG;AAClB,UAAM,OAAO,KAAK,OAAO,OAAO,KAAK,IAAI,IAAI;AAC7C,QAAI,QAAQ,CAAC,oBAAoB,IAAI,GAAG;AACtC,cAAQ,OAAO;AAAA,QACb,GAAG,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,gBAAgB,SAAS,oEAAoE,EAAE,GAAG,MAAM,CAAC,CAAC;AAAA;AAAA,MAC1J;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAIA,QAAI,KAAK,KAAM,QAAO,iBAAiB,MAAM,IAAI;AACjD,UAAM,SAAS,MAAM,gBAAgB,IAAI;AACzC,QAAI,OAAO,WAAW,UAAW,QAAO,KAAK,0BAA0B,OAAO,QAAQ,SAAS,OAAO,QAAQ,GAAG;AACjH,QAAI,OAAO,WAAW,eAAe;AACnC,cAAQ,OAAO;AAAA,QACb,6BAA6B,OAAO,IAAI,KAAK,OAAO,QAAQ,wBAAwB,OAAO,OAAO;AAAA;AAAA,MACpG;AAAA,IACF;AACA,UAAM,YAAY,OAAO,WAAW,aAAa,OAAO,YAAY;AACpE,UAAM,UAAU,KAAK,OAAO,OAAO,KAAK,IAAI,IAAI;AAChD,UAAM,aAAa,YAAY,OAAO,WAAW,aAAa,OAAO,WAAW;AAChF,QAAI,CAAC,YAAY;AACf,UAAI,OAAO,WAAW,OAAQ,QAAO,KAAK,kBAAkB,0EAA0E;AACtI,UAAI,OAAO,WAAW,cAAe,QAAO,KAAK,sBAAsB,wDAAwD,OAAO,OAAO,IAAI;AACjJ,aAAO,KAAK,sBAAsB,uCAAuC,WAAW,KAAK,mBAAmB;AAAA,IAC9G;AAEA,UAAM,EAAE,YAAY,aAAa,SAAS,eAAe,gBAAgB,cAAc,IACrF,6BAA6B,YAAY,KAAK,MAAM,OAAO,KAAK,GAAG,IAAI,QAAW,QAAQ,IAAI,GAAG,IAAI;AAEvG,QAAI,KAAM,OAAM,wBAAwB,MAAM,OAAO;AAIrD,UAAM,qBACJ,kBAAmB,MAAM,WAAW,cAAc,IAAK,MAAM,SAAS,gBAAgB,MAAM,IAAI;AAElG,UAAM,WAAW,MAAM,eAAe,MAAM,oBAAoB,mBAAmB,IAAI;AACvF,UAAM,MAAM,MAAM,eAAe,MAAM,oBAAoB,kBAAkB,QAAQ,IAAI,CAAC,EAAE,WAAW;AACvG,QAAI,CAAC,IAAI,GAAI,QAAO,KAAK,kBAAkB,IAAI,OAAO;AAItD,UAAM,UAAU,kBAAkB,QAAQ,IAAI,CAAC,KAAK,QAAQ,IAAI;AAChE,UAAM,MACJ,aAAa,OAAO,WAAW,gBAC3B,MAAM,cAAc,SAAS,WAAW,aAAa,OAAO,WAAW,gBAAgB,OAAO,WAAW,SAAS,WAAW,UAAU,OAAO,WAAW,gBAAgB,OAAO,OAAO,GAAG,IAC1L;AACN,UAAM,cAAc,MAAM,SAAS,KAAK,WAAW,SAAS,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,wBAAwB,CAAC,IAAI,CAAC;AACzH,QAAI,YAAY,SAAS,EAAG,QAAO,KAAK,wBAAwB,YAAY,KAAK,GAAG,CAAC;AAIrF,UAAM,MAAM,KAAK,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AAEtD,QAAI;AACJ,QAAI;AACF,eAAS,cAAc,IAAI;AAAA,IAC7B,SAAS,GAAG;AACV,aAAO,KAAK,iBAAiB,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IACzE;AACA,UAAM,EAAE,eAAe,YAAY,IAAI;AAGvC,UAAM,OAAO,MAAM,mBAAmB,KAAK,MAAM;AACjD,QAAI,WAAW,KAAM,QAAO,KAAK,UAAU,KAAK,KAAK;AAMrD,QAAI;AACJ,QAAI,eAAe;AACjB,YAAM,SAAS,mBAAmB;AAClC,UAAI,QAAQ;AACV,YAAI;AACF,6BAAmB,MAAM,wBAAwB,aAAa,YAAY,MAAM;AAAA,QAClF,SAAS,GAAG;AACV,iBAAO,KAAK,sBAAsB,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,QAC9E;AAAA,MACF;AAAA,IACF;AAGA,UAAM,iBAAiB;AAAA,MACrB,oBAAoB;AAAA,MACpB,qBAAqB,UAAa;AAAA,MAClC;AAAA,MACA;AAAA,MACA,yBAAyB,WAAW,KAAK,UAAU,OAAO,KAAK,OAAO,IAAI,MAAS;AAAA,IACrF;AACA,UAAM,SACJ,aAAa,kBAAkB,MAAM,OAAO,WAAW,UAAU,IAAI,MAAM,kBAAkB,SAAS,IAAI;AAC5G,UAAM,SAAS,UAAW,MAAM,gBAAgB,cAAc;AAC9D,UAAM,EAAE,aAAa,IAAI;AAEzB,UAAM,YAAY,4BAA4B,OAAO,WAAW,SAAS;AAEzE,UAAM,UAAU,oBAAoB,MAAM,gCAAgC,IAAI,CAAC;AAC/E,UAAM,WAAW,4BAA4B,OAAO,UAAU,KAAK,SAAS,OAAO;AACnF,UAAM,SAAS,qBAAqB,UAAU,KAAK,OAAO;AAI1D,UAAM,YAAY,KAAK,QAAQ,OAAO;AACtC,UAAM,gBAAiB,MAAM,cAAc,SAAS,KAAM,QAAQ,IAAI;AACtE,UAAM,QAAQ,MAAM,eAAe,eAAe,MAAM,mBAAmB,aAAa,GAAG,MAAM,mBAAmB,aAAa,CAAC;AAClI,UAAM,MAAM,MAAM;AAElB,UAAM,SACJ,IAAI,QAAQ,UAAU,qBAAqB,MAAM,SAAS,KAAK,KAAK,eAAe,YAAY,GAAG,MAAM,EAAE,MAAM,MAAM,IAAI,CAAC;AAC7H,UAAM,QAAQ,WAAW,GAAG;AAK5B,QAAI,kBAAkB;AACtB,QAAI,mBAAmB;AACvB,QAAI,sBAAsB;AAC1B,QAAI,eAAe;AACjB,4BAAsB;AACtB,UAAI,kBAAkB;AACpB,0BAAkB;AAClB,2BAAmB;AAAA,MACrB;AAAA,IACF;AAEA,UAAM,QAAQ,WAAW,yBAAyB,QAAQ,IAAI;AAI9D,UAAM,WAAW,CAAC,SAA8B,OAAO,iBAAiB,WAAW,IAAI,IAAI;AAC3F,UAAM,QAAQ,KAAK,UAAU,SAAY,OAAO,SAAS,OAAO,KAAK,KAAK,GAAG,EAAE,IAAI;AACnF,QAAI,UAAU,UAAa,EAAE,SAAS,KAAK,SAAS,GAAI,QAAO,KAAK,iBAAiB,2BAA2B;AAChH,UAAM,cAAc,eAAe,KAAK,cAAc,CAAC;AACvD,QAAI,gBAAgB,KAAM,QAAO,KAAK,wBAAwB,qBAAqB,gBAAgB,KAAK,MAAM,CAAC,EAAE;AACjH,UAAM,OAAO,MAAM,UAAU,eAAe,KAAK,CAAC,SAAS,iBAAiB,WAAW,IAAI,CAAC;AAC5F,UAAM,OAAO,MAAM,WAAW,IAAI,MAAM,CAAC,SAAS,iBAAiB,WAAW,IAAI,CAAC;AAGnF,UAAM,WAAW,OAAO,YAAY,eAAe,eAAe,aAAa,WAAW,QAAQ,CAAC,GAAG,UAAU;AAChH,UAAM,OAAqB;AAAA,MACzB;AAAA,MACA,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,aAAa,KAAK,SAAS,OAAO,KAAK,MAAM,IAAI;AAAA,MACjD,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,MAC/B,GAAI,IAAI,eAAe,EAAE,cAAc,IAAI,aAAa,IAAI,CAAC;AAAA,MAC7D,OAAO,EAAE,UAAU,SAAS,IAAI,IAAI,GAAG,GAAG,KAAK,OAAO,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG;AAAA,MAChF,GAAG,KAAK;AAAA,MACR;AAAA,MACA,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,IACvC;AAIA,QAAI;AACJ,QAAI;AACJ,QAAI,eAAyB,CAAC;AAC9B,QAAI;AACF,eAAS,eAAe,WAAW,UAAU,EAAE,GAAG,MAAM,MAAM,aAAa,WAAW,UAAU,EAAE,MAAM,QAAQ,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;AAC9H,YAAM,OAAO,aAAa,WAAW,UAAU;AAAA,QAC7C;AAAA,QACA,SAAS,OAAO;AAAA,QAChB,MAAM,QAAQ,IAAI,IAAI;AAAA,QACtB,GAAI,MAAM,EAAE,KAAK,eAAe,KAAK,WAAW,SAAS,EAAE,EAAE,IAAI,CAAC;AAAA,QAClE,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC7B,CAAC;AACD,YAAM,UAAU,eAAe,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAC3E,qBAAe,gBAAgB,IAAI,EAAE;AAAA,QACnC,CAAC,MAAM,YAAY,CAAC;AAAA,MACtB;AACA,UAAI,CAAC,OAAO,WAAW;AACrB,qBAAa,KAAK,UAAU,SAAS,CAAC;AAAA,MACxC;AACA,eAAS,iBAAiB,WAAW,UAAU,EAAE,GAAG,MAAM,KAAK,CAAC;AAAA,IAClE,SAAS,GAAG;AACV,aAAO,KAAK,YAAY,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IACpE;AAEA,UAAM,aAAa,MAAM,2BAA2B,QAAQ,KAAK,QAAQ,OAAO,CAAC;AACjF,QAAI,WAAW,SAAS,SAAS,GAAG;AAClC,cAAQ,OAAO;AAAA,QACb,GAAG,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,cAAc,QAAQ,WAAW,SAAS,EAAE,GAAG,MAAM,CAAC,CAAC;AAAA;AAAA,MACvG;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,UAAU,SAAS,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAIvE,UAAM,eAAuC,YACzC;AAAA,MACE,YAAY,UAAU;AAAA,MACtB,gBAAgB,UAAU;AAAA,MAC1B,GAAI,UAAU,gBAAgB,EAAE,oBAAoB,UAAU,cAAc,IAAI,CAAC;AAAA,IACnF,IACA,OAAO,WAAW,gBAChB;AAAA,MACE,YAAY,OAAO;AAAA,MACnB,gBAAgB,OAAO;AAAA,MACvB,GAAI,KAAK,sBAAsB,IAAI,EAAE,oBAAoB,OAAO,KAAK,sBAAsB,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC;AAAA,IAC5G,IACA,CAAC;AAIP,UAAM,WAAW,IAAI,SAAS,EAAE,aAAa,IAAI,aAAa,QAAQ,IAAI,OAAO,IAAI,CAAC;AACtF,UAAM,mBAAmB,KAAK,aAAa,OAAO,KAAK,UAAU,IAAI,WAAW;AAChF,UAAM,qBAAqB,qBAAqB,aAAa,cAAc;AAC3E,UAAM,UACJ,uBAAuB,QAAQ,aAAa,cAAc,aAAa,iBACnE,kBAAkB,oBAAoB;AAAA,MACpC,GAAG;AAAA,MACH,YAAY,aAAa;AAAA,MACzB,gBAAgB,aAAa;AAAA,MAC7B,GAAI,mBAAmB,EAAE,iBAAiB,IAAI,CAAC;AAAA,MAC/C,GAAI,qBAAqB,EAAE,mBAAmB,IAAI,CAAC;AAAA,IACrD,CAAC,IACD;AACN,QAAI,kBAAkB,YAAY,SAAS,IAAI,UAAU,SAAS,YAAY,qBAAqB;AACjG,YAAM,SAAS,IAAI,SAAS,oBAAoB,SAAS,QAAQ,IAAI;AACrE,YAAM,UAAU,gBAAgB,QAAQ,sBAAsB,QAAQ,KAAK,IAAI,QAAQ,MAAM;AAAA,IAC/F;AACA,QAAI,kBAAkB,uBAAuB,MAAM;AACjD,YAAM;AAAA,QACJ;AAAA,QACA,wBAAwB;AAAA,UACtB,OAAO,KAAK,QAAQ,OAAO,KAAK,KAAK,IAAI,cAAc,QAAQ,EAAE;AAAA,UACjE,MAAM;AAAA,UACN,GAAG;AAAA,UACH,SAAS,kBAAkB,OAAO,cAAc;AAAA,UAChD,oBAAoB,qBAAqB,aAAa,cAAc;AAAA,UACpE,kBAAkB,KAAK,aACnB,OAAO,KAAK,UAAU,IACrB,WAAW,eAAe,KAAK,UAAU,OAAO,KAAK,OAAO,IAAI;AAAA,UACrE,GAAG;AAAA,UACH,YAAY;AAAA,UACZ,GAAG;AAAA,UACH,aAAa,wBAAwB,SAAS;AAAA,QAChD,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF;AAIA,QAAI,MAAM;AACR,YAAM,iCAAiC;AAAA,QACrC;AAAA,QACA,OAAO,KAAK,QAAQ,OAAO,KAAK,KAAK,IAAI,cAAc,IAAI;AAAA,QAC3D,GAAI,QAAQ,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,QAC5C,GAAI,MAAM,wBAAwB,OAAO;AAAA,QACzC,SAAS,kBAAkB,OAAO,cAAc;AAAA,QAChD,oBAAoB,qBAAqB,aAAa,cAAc;AAAA,QACpE,GAAG;AAAA,QACH;AAAA,QACA,WAAW,MAAM,iBAAiB,OAAO;AAAA,MAC3C,CAAC;AAAA,IACH;AAEA,UAAM,QAAQ;AAAA,MACZ,GAAG,IAAI;AAAA,MACP,GAAI,UAAU,SAAS,CAAC;AAAA,MACxB,GAAI,OAAO,WAAW,gBAClB;AAAA,QACE,+DAA+D,OAAO,IAAI,KAAK,OAAO,OAAO;AAAA,MAC/F,IACA,CAAC;AAAA,MACL,GAAI,OAAO,SACP;AAAA,QACE,aAAa,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,4EAAuE,OAAO,WAAW,IAAI,sBAAsB,oBAAoB;AAAA,MAC9L,IACA,CAAC;AAAA,MACL,GAAI,MAAM,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC;AAAA,MACjC,GAAG,WAAW;AAAA,MACd,GAAG;AAAA,MACH,GAAG,OAAO,cAAc;AAAA,QAAI,CAAC,QAC3B,QAAQ,uBACJ,uPACA;AAAA,MACN;AAAA,IACF;AACA,YAAQ,OAAO;AAAA,MACb,GAAG,KAAK;AAAA,QACN;AAAA,UACE,IAAI;AAAA,UACJ,aAAa;AAAA,UACb,aAAa;AAAA,UACb,iBAAiB,kBAAkB;AAAA,UACnC,kBAAkB,oBAAoB;AAAA,UACtC,GAAI,YACA;AAAA,YACE,WAAW;AAAA,cACT,OAAO,UAAU;AAAA,cACjB,UAAU,UAAU;AAAA,cACpB,eAAe,UAAU;AAAA,cACzB,gBAAgB,UAAU;AAAA,cAC1B,WAAW,UAAU,QAAQ;AAAA,YAC/B;AAAA,UACF,IACA,CAAC;AAAA,UACL,QAAQ,OAAO;AAAA,UACf,GAAI,MAAM,SAAS,EAAE,MAAM,IAAI,CAAC;AAAA,UAChC,QAAQ,EAAE,UAAU,eAAe,QAAQ,aAAa,KAAK,KAAK,SAAS;AAAA,UAC3E,cAAc,OAAO;AAAA,UACrB,GAAG,eAAe,QAAQ;AAAA,UAC1B,GAAG,aAAa,GAAG;AAAA,UACnB,gBAAgB,OAAO;AAAA;AAAA,UAEvB,cAAc,cAAc,MAAM,KAAK,OAAO;AAAA,UAC9C,OAAO;AAAA,YACL,aAAa,OAAO,MAAM;AAAA,YAC1B,wBAAwB;AAAA,YACxB,uBAAuB,WAAW;AAAA,UACpC;AAAA,UACA,WAAW;AAAA,YACT,aAAa,QAAQ,KAAK,SAAS,aAAa,CAAC,kdAAkd,YAAY,8LAA8L,EAAE;AAAA,YAC/sB,WAAW,OAAO;AAAA,YAClB,uBACE;AAAA,YACF,kBAAkB,OAAO;AAAA,YACzB,SAAS,OAAO;AAAA,YAChB,MAAM,eAAe,MAAM;AAAA,YAC3B,MAAM,OAAO;AAAA,YACb,eAAe,OAAO;AAAA,YACtB,MAAM,OAAO,KAAK;AAAA,YAClB,OACE,OAAO,UAAU,IACb,4DACA,GAAG,OAAO,KAAK;AAAA,YACrB,UACE;AAAA,YACF,SAAS,kBAAkB,QAAQ,KAAK,UAAU,QAAQ;AAAA,YAC1D,QAAQ,WAAW,GAAG;AAAA,YACtB,MAAM;AAAA,UACR;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA;AAAA,IACH;AAAA,EACF;AACF,CAAC;AAOD,eAAe,WACb,MACA,UACyG;AACzG,MAAI,CAAC,KAAM,QAAO,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,EAAE;AACxC,QAAM,OAAO,MAAM,aAAa,IAAI;AACpC,MAAI,CAAC,KAAM,QAAO,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,eAAe,MAAM,EAAE;AAC9D,SAAO;AAAA,IACL,OAAO;AAAA,MACL,YAAY,KAAK;AAAA,MACjB,GAAI,KAAK,WAAW,SAAS,IAAI,EAAE,gBAAgB,KAAK,WAAW,IAAI,QAAQ,EAAE,IAAI,CAAC;AAAA,IACxF;AAAA,IACA,MAAM,CAAC;AAAA,EACT;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/canvas/scaffold-video.ts","../src/engine/scaffold/lib/model-router.ts","../src/engine/nodes/local/lib/sceneDetect.ts","../src/commands/canvas/gitignore.ts"],"sourcesContent":["import { cp, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport {\n AD_IMAGE_MODEL,\n BLUEPRINT_ANALYSIS_MODEL,\n DEFAULT_VIDEO_GENERATE_MODEL,\n SEEDANCE_DURATIONS,\n VIDEO_DECONSTRUCT_MODEL,\n} from \"@baker/canvas-contract\";\nimport { defineCommand } from \"citty\";\nimport { enforceNewCreativeLimit } from \"./creative-limit.ts\";\nimport { fetchExternalBytes } from \"../../lib/externalFetch.ts\";\nimport { MAX_ASSET_BYTES } from \"../../engine/storage/asset-store.ts\";\nimport { routeVideoModel, type VideoBudget } from \"../../engine/scaffold/lib/model-router.ts\";\nimport { sha256Hex } from \"../../engine/storage/sha256.ts\";\nimport { createEngineFromEnv, defaultRegistry, ValidationError, validateCanvasDeep } from \"../../engine/index.ts\";\nimport { detectSceneCutsPySceneDetect } from \"../../engine/nodes/local/lib/sceneDetect.ts\";\nimport {\n annotateBlueprintWithElements,\n avatarsNotCast,\n buildOverlayHtml,\n canvasDims,\n castAvatarsOnElements,\n genAspectsFor,\n resolveAspect,\n type ScaffoldVideoOpts,\n scaffoldVideoCanvas,\n slimBlueprintForSelection,\n videoReport,\n} from \"../../engine/scaffold/video.ts\";\nimport { stampCompositionDims } from \"./composition-dims.ts\";\nimport {\n fail,\n fileExists,\n loadAssetText,\n parseElements,\n resolveModel,\n SHIPPED_CAPTIONS_DIR,\n SHIPPED_OVERLAY_COMPOSITION_DIR,\n} from \"./scaffold-common.ts\";\nimport { REBUILD_FILE, writeSceneFiles } from \"./scene-files.ts\";\nimport { renderStyleProjectionFromValue } from \"./style-projection.ts\";\nimport { buildCreativeDefinition, definitionPlatformsOf, resolveFormats, titleFromSlug } from \"./creative-definition.ts\";\nimport { ensureGitignore } from \"./gitignore.ts\";\nimport { computeSourceSha } from \"./source-version.ts\";\nimport { readDefinitionPlatforms, syncCreativeDefinitionBestEffort } from \"./sync-definition.ts\";\nimport { resolveRelativeCanvasPaths } from \"./resolve-paths.ts\";\nimport { isValidScaffoldSlug } from \"./scaffold-static-ad-paths.ts\";\nimport { resolveCastAvatars } from \"../avatars/resolveCast.ts\";\nimport { askJevQuestions } from \"../../engine/nodes/local/lib/jev.ts\";\nimport { cachedJev } from \"../../engine/nodes/local/lib/jev-cache.ts\";\nimport { voiceGenderModel } from \"../../engine/scaffold/video/dialogue/voice-gender.ts\";\nimport type { ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport { languageCodeNamed, spokenLanguage } from \"../../engine/scaffold/lib/language.ts\";\nimport { readBlueprintSpeech } from \"../../engine/scaffold/video/speech-reading.ts\";\nimport { findWorkspaceRoot } from \"./normalize-paths.ts\";\nimport { holdUnbilledSpend } from \"./unbilled-spend.ts\";\n\nconst SELECT_SYSTEM =\n \"You identify the RECURRING, identity-critical visual elements of a video ad from its deconstruction blueprint — \" +\n \"the people, animals, products, and logos that must stay consistent every time they appear, so a faithful \" +\n \"reproduction grounds each in ONE real reference image reused across every frame it appears in. Output ONLY a JSON \" +\n 'object of the form { \"elements\": [ ... ] }, no prose.';\n\nconst SELECT_PROMPT =\n \"VIDEO DECONSTRUCTION BLUEPRINT (video-deconstruct/1):\\n{{blueprint}}\\n\\n\" +\n \"List ONLY the elements worth keeping consistent across frames — the ones a reproduction must ground in a real asset:\\n\" +\n '- each recurring person from global.cast (a presenter/actor/persona) -> type \"person\"\\n' +\n '- a recurring animal/pet/character with a stable identity -> type \"animal\"\\n' +\n '- a showcased product, package, card, or device the ad sells or demonstrates -> type \"product\"\\n' +\n '- the advertiser brand logo/wordmark (from global.branding) -> type \"logo\"\\n' +\n '- a recurring trust/rating/certification badge -> type \"badge\"\\n' +\n '- the dominant recording set/location the scenes share (e.g. the same living room, car interior, kitchen) -> type \"location\"\\n\\n' +\n \"DROP one-off background extras and incidental props — but the shared set/location is NOT generic scenery: pin it as ONE \" +\n '\"location\" element so the room stays identical across scenes. A person in global.cast is almost always recurring. Keep at most ~8.\\n\\n' +\n \"ONE PERSON, MULTIPLE LOOKS: if a single individual plays MULTIPLE personas or wardrobes (e.g. a creator as a skeptic in \" +\n \"one outfit and a believer in another, or a before/after), emit ONE element PER look (so each outfit gets its own real \" +\n 'reference image) and link the extra looks to the first via \"same_as\" — they are the SAME person, only the wardrobe/state ' +\n \"differs, so the face must stay identical.\\n\\n\" +\n 'For each kept element return: { \"type\": one of person|animal|product|logo|badge|location, \"label\": a short ' +\n 'UPPER_SNAKE_CASE name (e.g. HERO, CREATOR_SKEPTIC, INSURANCE_CARD, LOGO), \"description\": a concrete reusable ' +\n \"description to source/shoot the real asset — for a person/animal give a NEUTRAL castable role (e.g. \" +\n '\"hero pet-owner, woman in her 30s\" or \"a small beagle\"), NOT the original individual\\'s literal face/identity: ' +\n \"we RECAST with a FRESH person/animal, so never tell the agent to reuse the original. \" +\n '\"expression\": a living subject\\'s typical expression or null, \"cast_id\": the global.cast id if it maps to one else ' +\n 'null, \"same_as\": the label of another element this is the SAME individual as (different wardrobe/persona) else null, ' +\n '\"scenes\": the 0-based indices of ONLY the scenes where the element is ACTUALLY VISIBLE ON SCREEN — judged from ' +\n \"that scene's start_frame_prompt / end_frame_prompt subjects and its action_detail, NOT from who is merely \" +\n \"speaking. A narrator heard over b-roll is NOT present in that b-roll scene; a dog-running cutaway does NOT \" +\n \"contain the couch creator just because she talks across it. Do NOT pad the list — an element wrongly listed in a \" +\n \"scene makes the reproduction render the wrong subject there (e.g. the creator appearing in a pure-dog b-roll). \" +\n \"When in doubt, leave a scene OUT. Output ONLY the JSON object.\";\n\n/** Load the deconstruct's word-level transcript as text; a missing/unreadable one just\n * means no caption track is wired (best-effort — never fails the scaffold). */\nasync function loadTranscriptBestEffort(ref: unknown): Promise<string | undefined> {\n if (!ref) return undefined;\n try {\n return await loadAssetText(ref, \"deconstruct transcript\");\n } catch {\n return undefined;\n }\n}\n\n/**\n * Stage the burned-in caption track next to the canvas: copy the TikTok caption\n * composition. The caption TEXT is transcribed from the rendered audio at run time\n * (`video_transcribe`, wired by the scaffolder) — not the source transcript — so we don't\n * persist the deconstruct transcript here; we only use its presence to decide whether the\n * ad has speech worth captioning. Returns `compositionPath` (undefined ⇒ no caption track).\n */\nasync function stageCaptions(outDir: string, transcript: string | undefined): Promise<{ compositionPath?: string }> {\n const text = transcript?.trim();\n if (!text || text === \"[]\") return {};\n const compositionPath = path.join(outDir, \"tiktok-captions-composition\");\n await cp(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });\n return { compositionPath };\n}\n\n/**\n * Detect hard shot cuts in the local video with PySceneDetect (`scenedetect`, installed\n * in the canvas sandbox). Best-effort: a detection failure just falls back to LLM-only\n * scene boundaries, so a transient `scenedetect` error never blocks the scaffold.\n */\nasync function detectShotCutsBestEffort(videoPath: string, threshold?: number): Promise<number[] | undefined> {\n try {\n const cuts = await detectSceneCutsPySceneDetect(videoPath, threshold ? { threshold } : {});\n if (cuts.length > 0) {\n process.stderr.write(`Detected ${cuts.length} shot cut(s) via PySceneDetect: ${cuts.join(\", \")}s\\n`);\n } else {\n process.stderr.write(\"PySceneDetect ran but found no hard cuts; using LLM scene boundaries.\\n\");\n }\n return cuts;\n } catch (e) {\n // Stay non-fatal (the deconstruct can still segment with LLM-only boundaries),\n // but a MISSING `scenedetect` binary is an actionable setup gap, not a transient\n // blip — without cuts the segmentation tends to be too coarse, so shout LOUDLY\n // and tell the operator how to fix it instead of degrading silently.\n const msg = e instanceof Error ? e.message : String(e);\n const code = (e as { code?: unknown })?.code;\n const missing = code === \"ENOENT\" || /ENOENT|not found|command not found/i.test(msg);\n if (missing) {\n process.stderr.write(\n \"WARNING: `scenedetect` (PySceneDetect) is NOT installed — falling back to LLM-only scene boundaries, \" +\n \"which under-segments (coarse 9-15s scenes instead of the real 1-4s cuts). \" +\n \"Install it (`pipx install scenedetect[opencv]` or `pip install scenedetect[opencv]`) for accurate shot-cut detection.\\n\",\n );\n } else {\n process.stderr.write(`Shot-cut detection skipped (${msg}); using LLM boundaries.\\n`);\n }\n // Detection FAILED (vs \"ran and found none\") — undefined tells the deconstruct\n // it cannot treat the video as verified cut-less.\n return undefined;\n }\n}\n\nconst VIDEO_EXT_BY_MIME: Record<string, string> = {\n \"video/mp4\": \".mp4\",\n \"video/quicktime\": \".mov\",\n \"video/webm\": \".webm\",\n \"video/x-matroska\": \".mkv\",\n};\n\n/** Extension for a downloaded reference: URL pathname first, then content-type, else .mp4. */\nexport function referenceVideoExt(url: string, contentType: string | null): string {\n const fromPath = path.extname(new URL(url).pathname).toLowerCase();\n if (fromPath && fromPath.length <= 5) return fromPath;\n const mime = (contentType ?? \"\").split(\";\")[0]?.trim().toLowerCase();\n return (mime && VIDEO_EXT_BY_MIME[mime]) || \".mp4\";\n}\n\n/**\n * The reference the scaffold reproduces. Accept a URL (e.g. a `baker winning-ads`\n * presigned link) directly and download it once to a temp file — the local bytes\n * are needed anyway for PySceneDetect shot-cut detection before the billed\n * deconstruct — so the caller never has to `curl` it first. A local path passes\n * straight through.\n */\n/**\n * The INSPIRATION video's provenance for the creative's `_definition.md` + dashboard: the\n * durable, content-addressed R2 URL the deconstruct already uploaded the source to\n * (`blueprint.source.url` — survives even after a presigned winning-ads URL expires),\n * falling back to the original URL argument; plus the advertiser the deconstruct identified.\n * We record the URL rather than committing the file: a reference video can be up to 2 GiB\n * and the video canvas never re-ingests the source at run time (it uses the extracted frame\n * URLs), so a git copy would be pure bloat with no re-run benefit.\n */\nfunction videoSourceReference(blueprint: unknown, fileArg: string): { url?: string; advertiser?: string } {\n const bp = (blueprint ?? {}) as { source?: { url?: unknown }; global?: { branding?: { brand_name?: unknown } } };\n const durable = typeof bp.source?.url === \"string\" ? bp.source.url : undefined;\n const original = /^https?:\\/\\//i.test(fileArg) ? fileArg : undefined;\n const brand = bp.global?.branding?.brand_name;\n return { url: durable ?? original, advertiser: typeof brand === \"string\" && brand.trim() ? brand.trim() : undefined };\n}\n\n/** A short human summary for the video creative's `_definition.md` body (deconstruct-derived). */\nfunction videoDefinitionDescription(blueprint: unknown): string | undefined {\n const g = ((blueprint ?? {}) as { global?: Record<string, unknown> }).global ?? {};\n const notes = g.reproduction_notes;\n if (typeof notes === \"string\" && notes.trim()) return notes.trim();\n const product = (g.branding as { product?: unknown } | undefined)?.product;\n return typeof product === \"string\" && product.trim() ? product.trim() : undefined;\n}\n\n/**\n * The frames mode the canvas actually uses. `--frames reuse` on a video with people in it\n * is refused by the scaffold (their faces would reach our ad), so report that and why\n * rather than echo the flag back.\n */\nfunction framesModeReport(\n canvas: { metadata?: unknown },\n requested: \"generate\" | \"reuse\",\n): { frames_mode: string; frames_reuse_refused?: string } {\n const todo = (canvas.metadata as { todo?: { frames_mode?: unknown; frames_reuse_refused?: unknown } } | undefined)\n ?.todo;\n const mode = typeof todo?.frames_mode === \"string\" ? todo.frames_mode : requested;\n const refused = typeof todo?.frames_reuse_refused === \"string\" ? todo.frames_reuse_refused : undefined;\n return { frames_mode: mode, ...(refused ? { frames_reuse_refused: refused } : {}) };\n}\n\nasync function materializeReferenceVideo(fileArg: string): Promise<string> {\n if (!/^https?:\\/\\//i.test(fileArg)) return path.resolve(fileArg);\n let bytes: Buffer;\n let contentType: string | null;\n try {\n // No challenge sniff: this is definitionally a video file, and decoding the\n // first 64 KB of one as text to look for a bot wall is waste, not caution.\n // The canvas asset ceiling, not the image one: this is a reference video,\n // and it is the surface most likely to meet a limit at all.\n ({ buffer: bytes, contentType } = await fetchExternalBytes(fileArg, {\n sniffChallenge: false,\n maxBytes: MAX_ASSET_BYTES,\n }));\n } catch (e) {\n throw new Error(`failed to download reference video: ${e instanceof Error ? e.message : String(e)}`);\n }\n if (bytes.length === 0) throw new Error(\"reference video download was empty\");\n const dest = path.join(\n tmpdir(),\n `baker-ref-${sha256Hex(bytes).slice(0, 16)}${referenceVideoExt(fileArg, contentType)}`,\n );\n await writeFile(dest, bytes);\n return dest;\n}\n\n/** Parse the `--seam-dedup` flag; defaults to \"head\". Rejects any other value so a typo fails loud. */\nfunction resolveSeamDedup(raw: unknown): ScaffoldVideoOpts[\"seamDedup\"] {\n if (raw === undefined) return \"head\";\n const v = String(raw);\n if (v === \"head\" || v === \"tail\" || v === \"off\") return v;\n throw new Error(`--seam-dedup must be \"head\", \"tail\", or \"off\" (got \"${v}\")`);\n}\n\nconst VIDEO_BUDGETS: readonly VideoBudget[] = [\"economy\", \"standard\", \"premium\"];\nfunction parseBudget(raw: unknown): VideoBudget {\n const v = raw === undefined ? \"standard\" : String(raw);\n if ((VIDEO_BUDGETS as readonly string[]).includes(v)) return v as VideoBudget;\n throw new Error(`--budget must be one of ${VIDEO_BUDGETS.join(\", \")} (got \"${v}\")`);\n}\n\n/** Resolve the model ids that DON'T depend on the deconstruct output. The video\n * model is resolved separately (`resolveVideoModel`) once the cast is known. */\nfunction resolveModels(args: Record<string, unknown>): {\n deconstructModel: string;\n selectModel: string;\n imageModel: string;\n} {\n return {\n // Flash by default (the `videoDeconstruct` role). Override with --deconstruct-model\n // ~google/gemini-pro-latest for the densest extraction when speed matters less.\n deconstructModel: resolveModel(\"video_deconstruct\", args[\"deconstruct-model\"], VIDEO_DECONSTRUCT_MODEL),\n selectModel: resolveModel(\"text_generate\", args[\"select-model\"], BLUEPRINT_ANALYSIS_MODEL),\n // The ad-frame model (matches the static-ad scaffold); the frame generators need the\n // most faithful text/identity reproduction. Override with --image-model for a\n // cheaper/faster pass.\n imageModel: resolveModel(\"image_generate\", args[\"image-model\"], AD_IMAGE_MODEL),\n };\n}\n\n/** True when the deconstruct surfaced a photoreal on-camera person/animal cast —\n * exactly the frames ByteDance's real-person filter blocks on Seedance. */\nexport function hasPhotorealCast(elements: unknown): boolean {\n return (\n Array.isArray(elements) &&\n elements.some((e) => {\n const type = typeof e === \"object\" && e !== null ? (e as { type?: unknown }).type : undefined;\n return type === \"person\" || type === \"animal\";\n })\n );\n}\n\n/** Resolve the video model once the cast is known. An explicit --video-model\n * always wins. Otherwise the scored router picks from the curated roster — and a\n * detected photoreal on-camera cast counts as a real-face brief, so it routes to\n * Veo up front. That cast WOULD be blocked on Seedance by ByteDance's real-person\n * filter, and a blocked frame-started clip is not moved to another model at run\n * time, so picking Seedance burns an attempt and dead-ends. Mirrors Higgsfield's models_explore\n * and explains its pick via the returned reason. */\nexport function resolveVideoModel(\n args: Record<string, unknown>,\n elements: unknown,\n): { videoModel: string; videoRouteReason?: string } {\n if (args[\"video-model\"]) {\n return { videoModel: resolveModel(\"video_generate\", args[\"video-model\"], DEFAULT_VIDEO_GENERATE_MODEL) };\n }\n const photorealCast = hasPhotorealCast(elements);\n const route = routeVideoModel({\n hasRealFace: Boolean(args[\"real-face\"]) || photorealCast,\n needsIdentity: Boolean(args.identity),\n needsMotionTransfer: Boolean(args[\"motion-transfer\"]),\n budget: parseBudget(args.budget),\n });\n // Make the auto-detection legible when it (not an explicit flag) drove the pick.\n const reason =\n photorealCast && !args[\"real-face\"]\n ? `${route.reason} — detected a photoreal on-camera cast, which Seedance's real-person filter would block`\n : route.reason;\n return {\n videoModel: resolveModel(\"video_generate\", route.model, DEFAULT_VIDEO_GENERATE_MODEL),\n videoRouteReason: reason,\n };\n}\n\n/** The deconstruct canvas: ingest → full scene-by-scene blueprint. Run first, on its own. */\nfunction buildDeconstructCanvas(\n videoPath: string,\n deconstructModel: string,\n opts: { maxScenes?: number; language?: string; focus?: string; shotCuts?: number[] },\n) {\n const deconstructParams: Record<string, unknown> = { model: deconstructModel, mode: \"full\" };\n if (typeof opts.maxScenes === \"number\") deconstructParams.max_scenes = opts.maxScenes;\n if (opts.language) deconstructParams.language = opts.language;\n if (opts.focus) deconstructParams.focus = opts.focus;\n // Real visual shot cuts (detected locally with PySceneDetect) so the deconstruct\n // snaps scene boundaries onto them and never lets a scene span a hard cut. An\n // EMPTY list is meaningful (detection ran, the video is verified cut-less — every\n // LLM boundary is a same-take beat); only a failed detection omits the param.\n if (opts.shotCuts) deconstructParams.shot_cuts = opts.shotCuts;\n // The Seedance per-clip ceiling: a shot longer than this is split into seamless\n // continuation sub-scenes (shared splice frame) instead of being truncated.\n deconstructParams.max_clip_s = SEEDANCE_DURATIONS[SEEDANCE_DURATIONS.length - 1];\n return {\n schema: \"baker-canvas/1\" as const,\n metadata: { name: \"video deconstruct pass\" },\n nodes: [\n { id: \"src\", type: \"ingest\", params: { source: \"path\", path: videoPath, expect: \"video\" } },\n { id: \"deconstruct\", type: \"video_deconstruct\", inputs: { video: \"$ref:src.asset\" }, params: deconstructParams },\n ],\n output: { node: \"deconstruct\", output: \"analysis\" },\n };\n}\n\n/**\n * The element-selection canvas: a single text_generate over a SLIMMED blueprint. The slim\n * is inlined into the prompt as a literal STRING (no `$ref` slot), so it never trips the\n * engine's 256KB inline-slot limit no matter how long the ad — a full 42-scene blueprint\n * inlined as a slot blew past it. A function replacer keeps `$`/`{{` in the JSON literal.\n */\nfunction buildSelectCanvas(selectModel: string, slimmedBlueprintJson: string) {\n return {\n schema: \"baker-canvas/1\" as const,\n metadata: { name: \"element selection pass\" },\n nodes: [\n {\n id: \"select\",\n type: \"text_generate\",\n params: {\n model: selectModel,\n max_tokens: 6000,\n temperature: 0,\n response_format: \"json_object\",\n system: SELECT_SYSTEM,\n prompt: SELECT_PROMPT.replace(\"{{blueprint}}\", () => slimmedBlueprintJson),\n },\n },\n ],\n output: { node: \"select\", output: \"text\" },\n };\n}\n\n/**\n * Run the deconstruct pass, then the element-selection pass over a SLIMMED blueprint.\n * Two passes (not one chained canvas) so the CLI can slim the blueprint between them —\n * the selector only reads cast/branding + a few per-scene prompt fields, and inlining the\n * full blueprint busts the engine's inline-prompt limit on long ads. The FULL blueprint is\n * still returned (the source of truth for prompt.json + scaffolding). Credits sum both runs.\n */\nasync function runAnalysisPasses(\n deconstructCanvas: ReturnType<typeof buildDeconstructCanvas>,\n selectModel: string,\n): Promise<{\n blueprint: unknown;\n elements: unknown[];\n transcript: string | undefined;\n /** The language the deconstruct's transcriber heard, as it named it (\"es\", or \"spanish\"). */\n detectedLanguage: string | undefined;\n creditsSpent: number | undefined;\n}> {\n const engine = createEngineFromEnv({ log: (line) => process.stderr.write(`${line}\\n`) });\n let credits = 0;\n let sawCredits = false;\n const addCredits = (stats: unknown) => {\n const c = (stats as { total_credits?: number })?.total_credits;\n if (typeof c === \"number\") {\n credits += c;\n sawCredits = true;\n }\n };\n\n // Pass 1: the full deconstruct blueprint (+ its word-level transcript, used to drive\n // the burned-in caption track).\n let blueprint: unknown;\n let transcript: string | undefined;\n let detectedLanguage: string | undefined;\n try {\n const r1 = await engine.run(deconstructCanvas, {});\n addCredits(r1.stats);\n blueprint = JSON.parse(await loadAssetText(r1.outputs_by_node.deconstruct?.analysis, \"deconstruct output\"));\n transcript = await loadTranscriptBestEffort(r1.outputs_by_node.deconstruct?.transcript);\n const heard = (r1.outputs_by_node.deconstruct?.transcript as { metadata?: { detected_language?: unknown } } | undefined)\n ?.metadata?.detected_language;\n detectedLanguage = typeof heard === \"string\" && heard.trim() ? heard.trim() : undefined;\n } catch (e) {\n if (e instanceof ValidationError) return fail(\"validation\", JSON.stringify(e.issues));\n if (e instanceof SyntaxError) return fail(\"read_outputs\", e.message);\n return fail(\"deconstruct\", e instanceof Error ? e.message : String(e));\n }\n\n // Pass 2: element selection over the slimmed blueprint (inlined as a literal prompt).\n const slimJson = JSON.stringify(slimBlueprintForSelection(blueprint));\n try {\n const r2 = await engine.run(buildSelectCanvas(selectModel, slimJson), {});\n addCredits(r2.stats);\n const elements = parseElements(await loadAssetText(r2.outputs_by_node.select?.text, \"selection output\"));\n return { blueprint, elements, transcript, detectedLanguage, creditsSpent: sawCredits ? credits : undefined };\n } catch (e) {\n if (e instanceof ValidationError) return fail(\"validation\", JSON.stringify(e.issues));\n if (e instanceof SyntaxError) return fail(\"read_outputs\", e.message);\n return fail(\"deconstruct\", e instanceof Error ? e.message : String(e));\n }\n}\n\nexport const scaffoldVideoCommand = defineCommand({\n meta: {\n name: \"scaffold-video\",\n description:\n \"Turn a reference video into a runnable reproduction canvas in one command. Runs billed passes — video_deconstruct \" +\n \"(the full scene-by-scene blueprint + transcript, baked to a split, editable blueprint: a global prompt.json plus one \" +\n \"small scenes/sNN.json per scene) and an AI selection \" +\n \"of the video's RECURRING identity elements (person/animal/product/logo) — then scaffolds a pipeline where every \" +\n \"scene boundary is a static-ad-grade frame (the blueprint as target_blueprint, a reference legend, the real frame as \" +\n \"anchor) and each recurring element gets ONE shared [TODO] ingest slot wired into every frame it appears in. The \" +\n \"clips feed Seedance an ultra-detailed motion brief (action, camera, dialogue, transcript). Edit a scene's \" +\n \"scenes/sNN.json (or prompt.json for global cast/palette/brand), fill the remaining [TODO] images, then `baker canvas run`. \" +\n \"A person in the reference is played by an invented, realistic person generated from their description — never the \" +\n \"source actor and never a photo of anyone real; pass `--avatar <handle>` (`baker avatars list`) when the same actor \" +\n \"has to recur across the company's ads.\",\n },\n args: {\n file: {\n type: \"positional\",\n required: true,\n description:\n \"Reference video — a local path OR an http(s) URL (e.g. a winning-ads link). A URL is downloaded for you; pass --slug or --out with it.\",\n },\n out: { type: \"string\", description: \"Output canvas path (default <video-dir>/<name>.video.canvas.json)\" },\n slug: {\n type: \"string\",\n description: \"Creative slug — writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)\",\n },\n frames: {\n type: \"string\",\n description:\n '\"generate\" (default, every frame regenerated for our ad) or \"reuse\" (wire the source\\'s real frames in). Reuse applies only to a video with nobody in it — on a video showing people it is refused and every frame is generated, so the source\\'s actors never reach our ad.',\n },\n ambient: {\n type: \"boolean\",\n description: \"Give silent b-roll scenes native diegetic ambient mixed deep under the music bed (off by default)\",\n },\n \"seam-dedup\": {\n type: \"string\",\n description:\n 'How to dedup the frame two clips SHARE when a long shot is split for length: \"head\" (default, drop the second clip\\'s first frame), \"tail\" (drop the first clip\\'s last frame), or \"off\" (keep both).',\n },\n \"max-scenes\": { type: \"string\", description: \"Cap the number of scenes the deconstruct emits\" },\n \"shot-threshold\": {\n type: \"string\",\n description:\n \"PySceneDetect content threshold. Default is adaptive (18, auto re-checked at 27 when a continuous shot looks over-segmented); pinning a value disables the re-check. Lower = more/softer cuts, higher = fewer.\",\n },\n language: { type: \"string\", description: \"Transcript/dialogue language hint (e.g. fr, en)\" },\n focus: { type: \"string\", description: \"Known provenance/emphasis to ground the deconstruct\" },\n advertiser: {\n type: \"string\",\n description: \"Source advertiser recorded in _definition.md (default: the brand the deconstruct identified)\",\n },\n platforms: {\n type: \"string\",\n description:\n \"Where the ad runs, the main platform first (meta, linkedin, tiktok, …): recorded in _definition.md. Take it from the person's request or the idea.\",\n },\n platform: { type: \"string\", description: \"Retired: use --platforms. Still recorded in _definition.md.\" },\n \"deconstruct-model\": { type: \"string\", description: \"Override the video_deconstruct model id\" },\n \"select-model\": { type: \"string\", description: \"Override the text_generate model id for element selection\" },\n \"image-model\": { type: \"string\", description: \"Override the image_generate model id for frames\" },\n \"video-model\": { type: \"string\", description: \"Override the video_generate model id for clips (skips the scored router)\" },\n \"real-face\": {\n type: \"boolean\",\n description:\n \"The ad has a photoreal human face on camera → the router picks Veo (dodges the ByteDance real-person filter). Set this for ANY photoreal presenter/creator/testimonial cast — the filter blocks AI-GENERATED photoreal faces too, not just real ones.\",\n },\n \"motion-transfer\": {\n type: \"boolean\",\n description: \"Motion driven from a reference video / deliberately hyper-dynamic → the router picks Kling.\",\n },\n identity: {\n type: \"boolean\",\n description: \"The same character/product must stay consistent across clips → the router picks the Seedance workhorse.\",\n },\n budget: {\n type: \"string\",\n description: 'Cost posture for the router: \"economy\" | \"standard\" | \"premium\" (default standard).',\n },\n aspect: {\n type: \"string\",\n description:\n 'Output aspect ratio (e.g. \"4:5\"). Default: the source video\\'s detected ratio. When the video model ' +\n \"can't generate the ratio (Seedance has no 4:5) clips generate at the nearest supported ratio and are \" +\n \"center-cropped onto the output canvas.\",\n },\n resolution: {\n type: \"string\",\n description:\n 'Output resolution for generated clips (e.g. \"1080p\"). Default 1080p — the highest the video model supports — so clips keep the keyframe sharpness instead of the model\\'s low default.',\n },\n avatar: {\n type: \"string\",\n description:\n \"Cast company avatars as the reference's people — pass this when the same actor has to recur across ads (without it, \" +\n \"each person is invented from their description). \" +\n 'One handle, or several comma-separated in the order the people appear (`--avatar marta` / `--avatar marta,joan`). ' +\n \"Each recurring person grounds on that avatar's identity sheet, so the ad shows the company's own cast instead of \" +\n \"the source ad's actors. `baker avatars list` shows who there is; checked before anything is billed.\",\n },\n },\n async run({ args }) {\n const fileArg = String(args.file);\n const slug = args.slug ? String(args.slug) : undefined;\n if (slug && !isValidScaffoldSlug(slug)) {\n process.stderr.write(\n `${JSON.stringify({ ok: false, error: { code: \"invalid_slug\", message: \"--slug must be lowercase kebab (a-z, 0-9, hyphens), max 100 chars\" } }, null, 2)}\\n`,\n );\n process.exit(2);\n }\n // A URL is downloaded to a temp file, which is no sensible home for the output\n // canvas — require an explicit target so the reproduction lands in the repo.\n const isUrl = /^https?:\\/\\//i.test(fileArg);\n if (isUrl && !slug && !args.out) {\n return fail(\n \"missing_output_target\",\n \"When the reference is a URL, pass --slug (writes src/creatives/<slug>/) or --out <path> so the scaffolded canvas has a home in the repo.\",\n );\n }\n let videoPath: string;\n try {\n videoPath = await materializeReferenceVideo(fileArg);\n } catch (e) {\n return fail(\"download\", e instanceof Error ? e.message : String(e));\n }\n const base = path.basename(videoPath, path.extname(videoPath));\n const outPath = args.out\n ? path.resolve(String(args.out))\n : slug\n ? path.join(process.cwd(), \"src\", \"creatives\", slug, `${slug}.canvas.json`)\n : path.join(path.dirname(videoPath), `${base}.video.canvas.json`);\n if (slug) await enforceNewCreativeLimit(slug, outPath);\n const outDir = path.dirname(outPath);\n const blueprintPath = path.join(outDir, \"prompt.json\");\n // The slim style projection every frame's target_blueprint reads (global cast/palette/\n // brand only). Written alongside prompt.json so the full blueprint stays hand-editable.\n const blueprintStylePath = path.join(outDir, \"prompt.style.json\");\n const frames = args.frames === \"reuse\" ? \"reuse\" : \"generate\";\n const maxScenes = args[\"max-scenes\"] ? Number(args[\"max-scenes\"]) : undefined;\n\n // A faithful reproduction defaults to ALL source scenes. Capping is a cost\n // lever that silently DROPS scenes (the deconstruct merges everything past the\n // cap into the last kept scene), so make it a loud, explicit operator choice.\n if (Number.isFinite(maxScenes)) {\n process.stderr.write(\n `⚠️ --max-scenes ${maxScenes} caps the deconstruct: any scenes beyond ${maxScenes} are MERGED away, ` +\n `reducing fidelity (fewer cuts, lost beats). Omit it to reproduce every scene.\\n`,\n );\n }\n\n let models: ReturnType<typeof resolveModels>;\n try {\n models = resolveModels(args);\n // Checked now, before the billed passes, although the video model is only\n // routed once the cast is known.\n if (args[\"video-model\"]) resolveModel(\"video_generate\", args[\"video-model\"], DEFAULT_VIDEO_GENERATE_MODEL);\n } catch (e) {\n return fail(\"unknown_model\", e instanceof Error ? e.message : String(e));\n }\n const { deconstructModel, selectModel, imageModel } = models;\n\n // Resolved before the billed passes: a handle that cannot be cast fails for free.\n const cast = await resolveCastAvatars(args.avatar);\n if (\"error\" in cast) return fail(\"avatar\", cast.error);\n const { handles: avatarHandles, avatars } = cast;\n\n // Detect real visual shot cuts locally with PySceneDetect so the deconstruct can\n // snap scene boundaries onto them (a scene must never span a hard cut). Lower\n // `--shot-threshold` to catch more (softer) cuts on a fast-cut ad; higher to catch\n // fewer.\n const shotThreshold = args[\"shot-threshold\"] ? Number(args[\"shot-threshold\"]) : undefined;\n const shotCuts = await detectShotCutsBestEffort(videoPath, shotThreshold);\n\n // Two passes: ingest → video_deconstruct, then element selection over a SLIMMED\n // blueprint (so a long ad's blueprint never busts the inline-prompt limit).\n const deconstructCanvas = buildDeconstructCanvas(videoPath, deconstructModel, {\n maxScenes: Number.isFinite(maxScenes) ? maxScenes : undefined,\n language: args.language ? String(args.language) : undefined,\n focus: args.focus ? String(args.focus) : undefined,\n shotCuts,\n });\n const analysis = await runAnalysisPasses(deconstructCanvas, selectModel);\n const { blueprint, transcript, creditsSpent } = analysis;\n // The language the lines are spoken in: `--language` when given, else what the transcriber\n // heard, else Jev's reading of the lines. Read with each voice's gender and the words a\n // caption card may not end on, in one request, kept in the workspace's cache.\n const heard = analysis.detectedLanguage;\n const declaredLanguage =\n (args.language ? spokenLanguage(String(args.language))?.tag : undefined) ??\n (heard ? (spokenLanguage(heard)?.tag ?? languageCodeNamed(heard)) : undefined);\n const speechCache = path.join(findWorkspaceRoot(outDir) ?? process.cwd(), \"canvas\", \".cache\");\n const speechSpent: ReviewUsage[] = [];\n const speech = await readBlueprintSpeech(\n blueprint,\n declaredLanguage ? { declaredLanguage } : {},\n {\n ask: cachedJev(speechCache, (questions) => askJevQuestions(questions, (u) => speechSpent.push(u))),\n genders: voiceGenderModel(speechCache, (u) => speechSpent.push(u)),\n },\n );\n await holdUnbilledSpend(speechCache, speechSpent).catch(() => {});\n const elements = castAvatarsOnElements(analysis.elements, avatars);\n const uncast = avatarsNotCast(analysis.elements, avatarHandles);\n const uncastHint = uncast.length\n ? {\n hints: [\n `NOT CAST: ${uncast.map((h) => `\\`${h}\\``).join(\", \")} — the element selection found no more recurring people than it cast, so ${uncast.length === 1 ? \"this avatar plays\" : \"these avatars play\"} nobody in this canvas. A person shown in only one scene is not a recurring element, so those frames render whoever their scene file describes — tell the user who is cast and who is not.`,\n ],\n }\n : {};\n\n // Route the video model now that the cast is known: a photoreal on-camera\n // person/animal is auto-routed to Veo (Seedance's real-person filter would\n // block it — no point burning a wasted attempt before the runtime fallback).\n let routed: ReturnType<typeof resolveVideoModel>;\n try {\n routed = resolveVideoModel(args, elements);\n } catch (e) {\n return fail(\"unknown_model\", e instanceof Error ? e.message : String(e));\n }\n const { videoModel, videoRouteReason } = routed;\n if (videoRouteReason && !args[\"video-model\"] && !args[\"real-face\"] && hasPhotorealCast(elements)) {\n process.stderr.write(`🎬 Photoreal on-camera cast detected → generating clips on ${videoModel} (dodges Seedance's real-person filter).\\n`);\n }\n\n // Bake the deconstruct blueprint as the editable prompt, annotated so the human\n // editing it sees which wired slot grounds which recurring element.\n await mkdir(outDir, { recursive: true });\n const annotated = annotateBlueprintWithElements(blueprint, elements);\n // Split the blueprint into the global slice (`prompt.json`) + one `scenes/sNN.json`\n // per scene. An agent edits ONE small scene file at a time instead of a 2000-line\n // monolith; `run`/`validate` re-assemble and re-flow each scene into the graph\n // (see scene-projection.ts). blueprintPath still names prompt.json — now scene-less.\n await writeSceneFiles(outDir, annotated);\n // The slim style projection frames actually read via target_blueprint (no per-scene\n // array), derived from the SAME annotated blueprint so brand/cast/palette stay in\n // sync. Written through the ONE renderer `validate`/`run` also use to re-derive it\n // from an edited prompt.json — byte-identical formatting is what makes their\n // \"already up to date\" comparison (and the ingest cache) work.\n await writeFile(blueprintStylePath, renderStyleProjectionFromValue(annotated), \"utf8\");\n\n // Copy the overlay composition next to the canvas, then BAKE the reference's\n // overlays into its index.html as real, editable HTML at the <!--OVERLAYS-->\n // marker. The operator edits that HTML to paint the broadcast look — overlays\n // are authored markup, never props fed to a styling engine.\n // Resolve the output vs generation aspect up front: the overlay/caption composition\n // dims, the ffmpeg canvas, and the clip/frame generation params must all agree.\n let aspect: ReturnType<typeof resolveAspect>;\n try {\n aspect = resolveAspect(\n (blueprint as { source?: { aspect_ratio?: string } }).source?.aspect_ratio,\n args.aspect ? String(args.aspect) : undefined,\n genAspectsFor(videoModel),\n );\n } catch (e) {\n return fail(\"aspect\", e instanceof Error ? e.message : String(e));\n }\n const outDims = canvasDims(aspect.outAr);\n if (aspect.remapped) {\n process.stderr.write(\n `⚠️ ${aspect.outAr} output → clips generate at ${aspect.genAr} (the video model's nearest ratio) and are ` +\n `center-cropped to ${aspect.outAr} (${outDims.w}×${outDims.h}) — keep subjects centered in frame prompts.\\n`,\n );\n }\n\n const compositionDest = path.join(outDir, \"video-overlay-composition\");\n await cp(SHIPPED_OVERLAY_COMPOSITION_DIR, compositionDest, { recursive: true });\n await stampCompositionDims(compositionDest, outDims);\n const indexPath = path.join(compositionDest, \"index.html\");\n // With a transcript the scaffold wires a word-synced caption track (stageCaptions\n // below) — the reference's caption-role overlay fragments must then NOT also seed\n // as frozen static overlays (they'd double the same words on screen).\n const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript), videoModel });\n const indexHtml = await readFile(indexPath, \"utf8\");\n // Function replacer (not the string form) so `$`-sequences in overlay copy\n // (e.g. `save $$$!`, a literal `$&`) are inserted verbatim, not interpreted as\n // replacement patterns by String.prototype.replace.\n const injected = indexHtml.replace(\"<!--OVERLAYS-->\", () => overlayHtml);\n // replace() returns the string unchanged when the marker is absent — fail loud\n // rather than silently shipping a composition with no overlay layer.\n if (injected === indexHtml && overlayHtml.trim()) {\n fail(\n \"composition_marker_missing\",\n `video-overlay-composition/index.html is missing the <!--OVERLAYS--> marker — cannot inject the overlay layer`,\n );\n }\n await writeFile(indexPath, injected, \"utf8\");\n\n // Burned-in caption track: a sound-off feed needs the spoken words on screen, so the\n // scaffold wires a word-synced TikTok track by default whenever the deconstruct\n // returned a transcript (staged below). No transcript ⇒ no caption track.\n const captions = await stageCaptions(outDir, transcript);\n if (captions.compositionPath) await stampCompositionDims(captions.compositionPath, outDims);\n\n // Embed paths RELATIVE to the canvas file so the written canvas is portable —\n // `run`/`validate` resolve them against the canvas dir at load time. Baking\n // absolutes here is what made a moved/renamed workspace read a sibling's stale\n // composition + assets (the `memphis` cross-workspace bug).\n const opts: ScaffoldVideoOpts = {\n imageModel,\n videoModel,\n overlayCompositionPath: path.relative(outDir, compositionDest),\n captionsCompositionPath: captions.compositionPath\n ? path.relative(outDir, captions.compositionPath)\n : undefined,\n blueprintPath: path.relative(outDir, blueprintPath),\n blueprintStylePath: path.relative(outDir, blueprintStylePath),\n frames,\n ambient: Boolean(args.ambient),\n seamDedup: resolveSeamDedup(args[\"seam-dedup\"]),\n ...(speech.spokenLanguage ? { spokenLanguage: speech.spokenLanguage } : {}),\n voiceGenders: speech.voiceGenders,\n ...(speech.captionCarriesOn.length ? { captionCarriesOn: speech.captionCarriesOn } : {}),\n ...(args.aspect ? { aspect: String(args.aspect) } : {}),\n ...(args.resolution ? { resolution: String(args.resolution) } : {}),\n };\n\n let canvas: ReturnType<typeof scaffoldVideoCanvas>;\n let report: ReturnType<typeof videoReport>;\n try {\n canvas = scaffoldVideoCanvas(blueprint, elements, opts);\n report = videoReport(blueprint, elements, videoModel);\n } catch (e) {\n return fail(\"scaffold\", e instanceof Error ? e.message : String(e));\n }\n\n // MERGED overlay+captions pass: when the scaffold rendered the caption track\n // inside the overlay composition (no standalone `captions` node), the staged\n // TikTok caption dir is unused — remove it so the workspace holds no dead\n // composition an operator would edit to zero effect.\n if (captions.compositionPath && !canvas.nodes.some((n) => n.id === \"captions\")) {\n await rm(captions.compositionPath, { recursive: true, force: true });\n }\n\n // Validate against a copy whose relative paths are resolved to the output dir\n // (the on-disk canvas keeps the portable relatives).\n const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(canvas, outDir), defaultRegistry());\n\n // ALWAYS write the canvas — the deconstruct behind it is already paid for. A\n // blocking validation issue becomes part of the operator's checklist (fix, then\n // `baker canvas validate`), never a hard exit that discards the artifact.\n if (!validation.ok) {\n const meta = canvas.metadata as Record<string, unknown>;\n const todo = (meta.todo ?? {}) as Record<string, unknown>;\n todo.blocking_validation_issues = validation.issues;\n meta.todo = todo;\n }\n await writeFile(outPath, `${JSON.stringify(canvas, null, 2)}\\n`, \"utf8\");\n // The frozen rebuild context the scene sync feeds back into scaffoldVideoCanvas to\n // regenerate scene prompts deterministically (NO model call): the element-selection\n // artifact + the exact scaffold opts. Written once, never hand-edited. Its absence\n // (an old canvas) makes the sync degrade to legacy behavior, never fail.\n await writeFile(\n path.join(outDir, REBUILD_FILE),\n `${JSON.stringify({ elements, opts }, null, 2)}\\n`,\n \"utf8\",\n );\n if (!validation.ok) {\n process.stderr.write(\n `${JSON.stringify(\n {\n ok: false,\n error: { code: \"validation\", issues: validation.issues },\n canvas_path: outPath,\n prompt_path: blueprintPath,\n ...framesModeReport(canvas, frames),\n note: \"The canvas WAS written despite the blocking issue(s) — fix them in place, then `baker canvas validate` before running.\",\n ...uncastHint,\n },\n null,\n 2,\n )}\\n`,\n );\n process.exit(2);\n }\n\n // Keep the engine's run cache + the scaffold's working files out of git.\n await ensureGitignore(process.cwd(), [\"canvas/\", \".context/\"]);\n\n // Preserve the INSPIRATION video the same way the static flow preserves its reference\n // image — so the creative (and the dashboard) shows what it was built from. We record the\n // durable R2 URL the deconstruct already produced, not a committed copy (see helper).\n const sourceRef = videoSourceReference(blueprint, fileArg);\n if (slug) {\n // Auto-write _definition.md so the video creative joins the content collection with its\n // source provenance (the video command never wrote one before). Preserve on re-scaffold.\n const definitionPath = path.join(outDir, \"_definition.md\");\n if (!(await fileExists(definitionPath))) {\n await writeFile(\n definitionPath,\n buildCreativeDefinition({\n title: titleFromSlug(slug),\n kind: \"video\",\n ...definitionPlatformsOf(\n args.platforms ? String(args.platforms) : undefined,\n args.platform ? String(args.platform) : undefined,\n ),\n formats: resolveFormats(aspect.outAr),\n sourceReferenceUrl: sourceRef.url,\n sourceAdvertiser: args.advertiser ? String(args.advertiser) : sourceRef.advertiser,\n sourceKind: \"video\",\n description: videoDefinitionDescription(blueprint),\n }),\n \"utf8\",\n );\n }\n }\n\n // Push the parsed node-graph so the dashboard can draw this video's full\n // workflow immediately — before spending any of the ~200-credit render. Best-effort.\n if (slug) {\n await syncCreativeDefinitionBestEffort({\n slug,\n title: titleFromSlug(slug),\n ...(await readDefinitionPlatforms(outPath)),\n formats: [aspect.outAr],\n canvas,\n sourceReferenceUrl: sourceRef.url,\n sourceSha: await computeSourceSha(outPath),\n });\n }\n\n process.stdout.write(\n `${JSON.stringify(\n {\n ok: true,\n canvas_path: outPath,\n prompt_path: blueprintPath,\n source_reference: sourceRef.url,\n composition_dir: compositionDest,\n output: canvas.output,\n ...uncastHint,\n ...framesModeReport(canvas, frames),\n models: {\n deconstruct: deconstructModel,\n select: selectModel,\n image: imageModel,\n video: videoModel,\n ...(videoRouteReason ? { video_route_reason: videoRouteReason } : {}),\n },\n stats: {\n scene_count: report.scene_count,\n total_nodes: canvas.nodes.length,\n analysis_credits_spent: creditsSpent,\n run_estimated_credits: validation.estimatedCredits,\n // WHY the graph has its nodes: per-scene routes + the node-type histogram\n // (mirrors metadata.video.graph_stats in the canvas).\n graph: (canvas.metadata as { video?: { graph_stats?: unknown } })?.video?.graph_stats,\n },\n checklist: {\n edit_prompt: `The blueprint is split so you edit ONE small file at a time — never a giant one. Per-scene content (a scene's dialogue, action, frame prompts, overlays) lives in \\`scenes/sNN.json\\` — edit the single scene you want to change. Global cast/palette/brand/copy lives in \\`${path.basename(blueprintPath)}\\`. \\`baker canvas validate\\`/\\`run\\` re-assemble the blueprint and re-flow every edited scene back into the render (and regenerate ${path.basename(blueprintStylePath)}, the projection each frame's target_blueprint reads) — so your scene edits reach the render automatically. Never hand-edit the inlined node prompts in the canvas or the derived ${path.basename(blueprintStylePath)}; both are regenerated.`,\n recurring_elements_to_supply: report.elements,\n voices_to_confirm: report.dialogue.map((d) => ({\n scene: d.scene,\n speaker: d.speaker,\n voice_description: d.voice_description,\n line: d.line,\n })),\n sfx_count: report.sfx_count,\n overlay_count: report.overlay_count,\n has_music: report.has_music,\n scenes_clamped_to_clip_max: report.clamped_scenes,\n oversize_scenes: report.oversize_scenes,\n overstuffed_scenes: report.overstuffed_scenes,\n // Steer the edit toward disciplined prompting + on-brand MOTION, not just\n // on-brand color. The overlays inherit the reference's motion unless the\n // operator restyles easing/transition/accent from the brand's motion language.\n prompt_discipline:\n \"Rewrite each scene with the six-decision structure (Route / Spec / Beats / Copy / Technique / Negatives): quote exact copy, give every beat a timestamp, and name the moves. Pull easing, transition (cut vs fade), pacing, and the accent moment from BRAND.md § Brand in Motion so the overlays move like THIS brand — not the reference's. If BRAND.md has no Brand-in-Motion section, seed it with brand-build first. See the creative-canvas-ads skill: references/prompt-anatomy.md + references/hyperframes/.\",\n // Photoreal on-camera casts auto-route to Veo above, so this only fires\n // when `--video-model bytedance/seedance-2.0` was EXPLICITLY forced despite\n // a person/animal cast — overriding that safety route. Warn that every such\n // clip will hit ByteDance's real-person filter and burn a wasted attempt.\n ...(report.elements.some((e) => e.type === \"person\" || e.type === \"animal\") && /seedance/i.test(videoModel)\n ? {\n content_policy_risk:\n \"You FORCED Seedance (`--video-model bytedance/seedance-2.0`) on an ad with a photoreal on-camera cast. ByteDance's real-person filter will reject those clips (content_policy_blocked, E005) — no prompt change clears it. Each clip auto-recovers on Veo at render time so the run still completes, but you burn a wasted Seedance attempt per clip. Drop `--video-model` to let the scaffold route the cast to Veo up front, or make the frames less photorealistic.\",\n }\n : {}),\n note: \"Fill each el_* [TODO] — a person needs none (invented from their description, or cast with `--avatar <handle>`), never a photo of a real person; anything else with ONE real source image (reused across every frame that element appears in) — confirm each voice_select casting, then `baker canvas validate` and `baker canvas run`. Running generates many billed image/video/audio assets — it is not free.\",\n },\n },\n null,\n 2,\n )}\\n`,\n );\n },\n});\n","/**\n * A SCORED video-model router — the curated-and-explainable answer to\n * Higgsfield's `models_explore(recommend)`. Instead of a single hardcoded\n * default, a small weighted scorer picks between five curated video models (the\n * `videoRouter*` and `videoDefault` roles in the contract's `MODEL_ROLES`) and\n * returns a human-readable `reason` (mirroring Higgsfield's `match_reason`).\n *\n * The roster stays deliberately tiny (curation over breadth); this only makes the\n * pick correct and transparent:\n * - a real human likeness → Veo (the ONLY model that dodges ByteDance's\n * real-person filter), so a real-face brief never wastes a billed Seedance 422.\n * - motion-transfer / deliberately dynamic multi-shot beats → Kling.\n * - identity/product consistency → Seedance, the workhorse.\n * - anything else → the default video model (Gemini Omni 1.1).\n * - budget \"economy\" prefers the cheap Veo-fast tier over the 3.1 ceiling.\n *\n * Pure function, no I/O — tier-1 unit-testable per `.claude/rules/tdd.md`.\n */\n\nimport { MODEL_ROLES } from \"@baker/canvas-contract\";\n\nexport type VideoBudget = \"economy\" | \"standard\" | \"premium\";\n\nexport type VideoRouterInput = {\n /** The brief needs a real human likeness preserved (from a real reference face). */\n hasRealFace?: boolean;\n /** The same character/product must stay consistent across clips. */\n needsIdentity?: boolean;\n /** Motion is driven from a reference video, or the ad is deliberately hyper-dynamic. */\n needsMotionTransfer?: boolean;\n /** Cost posture. `economy` favors the cheap iteration tier. */\n budget?: VideoBudget;\n};\n\nexport type VideoRoute = {\n model: string;\n reason: string;\n /** Per-candidate score, exposed so the pick is fully auditable. */\n scores: Record<string, number>;\n};\n\nconst SEEDANCE = MODEL_ROLES.videoRouterWorkhorse.model;\nconst VEO = MODEL_ROLES.videoRouterRealFace.model;\nconst VEO_FAST = MODEL_ROLES.videoRouterRealFaceEconomy.model;\nconst KLING = MODEL_ROLES.videoRouterMotion.model;\n// The default video model (Omni 1.1, never the legacy preview): the router picks for\n// NEW work, and the preview exists only so stored canvases re-run verbatim.\nconst GEMINI_OMNI = MODEL_ROLES.videoDefault.model;\n\n/** A single weighted contribution to a candidate's score, with the reason it fired. */\ntype Signal = { model: string; weight: number; because: string };\n\n/**\n * Score every curated video model against the brief and return the winner plus\n * the dominant reason. Weights are intentionally coarse and readable — the goal\n * is a correct, explainable pick, not a tuned ML score.\n */\nexport function routeVideoModel(input: VideoRouterInput): VideoRoute {\n const budget = input.budget ?? \"standard\";\n const signals: Signal[] = [];\n\n // Hard rule: a real face MUST route to Veo — Seedance/Kling hit ByteDance-style\n // real-person filters. This dominates everything else.\n if (input.hasRealFace) {\n signals.push({ model: VEO, weight: 1200, because: \"real human likeness → Veo (dodges the real-person filter)\" });\n }\n\n // Motion transfer / hyper-dynamic multi-shot beats are Kling's lane.\n if (input.needsMotionTransfer) {\n signals.push({ model: KLING, weight: 800, because: \"motion-transfer / dynamic multi-shot → Kling\" });\n }\n\n // Identity/product consistency is the Seedance workhorse's strength (cheap, strong i2v).\n if (input.needsIdentity && !input.hasRealFace) {\n signals.push({ model: SEEDANCE, weight: 300, because: \"identity/product consistency → Seedance workhorse\" });\n }\n\n // Baseline preference so a signal-free brief still has a sensible default.\n // Omni wins the default because it renders picture + synchronized audio in one\n // call. It is deliberately a WEAK signal: it loses to every specific need above,\n // and it should: it stops at 10s and takes only 16:9 or 9:16, so any brief with a\n // real requirement is better served elsewhere.\n signals.push({ model: GEMINI_OMNI, weight: 100, because: \"default — native audio in one call\" });\n\n // Budget nudges: economy shifts a Veo pick to the cheap iteration tier; premium\n // keeps the 3.1 ceiling. Applied as a swap, not a competing candidate.\n const scores: Record<string, number> = { [SEEDANCE]: 0, [VEO]: 0, [VEO_FAST]: 0, [KLING]: 0, [GEMINI_OMNI]: 0 };\n let top: Signal = signals[0] as Signal;\n for (const s of signals) {\n scores[s.model] = (scores[s.model] ?? 0) + s.weight;\n if ((scores[s.model] ?? 0) >= (scores[top.model] ?? 0)) top = s;\n }\n\n let model = top.model;\n let reason = top.because;\n if (model === VEO && budget === \"economy\") {\n model = VEO_FAST;\n reason = `${reason}, on the economy fast tier`;\n scores[VEO_FAST] = scores[VEO] ?? 0;\n }\n\n return { model, reason, scores };\n}\n","import { execFile } from \"node:child_process\";\nimport { mkdtemp, readdir, readFile, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * PySceneDetect `detect-content` threshold (HSV per-frame content difference, 0–255\n * scale; NOT comparable to ffmpeg's `scene` luma score). PySceneDetect's own default is\n * 27, but social ads cut fast and often on SOFT reframes (same set, slight angle change)\n * that 27 misses — leaving the deconstruct under-segmented. 18 recovers those soft cuts\n * while staying clear of motion-driven false positives; tune per video with\n * `--shot-threshold` (lower = more cuts).\n */\nconst PYSCENEDETECT_THRESHOLD = 18;\n/**\n * Minimum scene length (seconds) for PySceneDetect. Its own default is ~0.6s, which\n * merges away rapid montage flashes; 0.25 matches the backend's `snapAndSplitToCuts`\n * minimum scene duration so fast cuts survive end-to-end (and sub-2s silent beats become\n * cheap still-holds). Below ~0.2s is single-frame flicker, not a real cut.\n */\nconst PYSCENEDETECT_MIN_SCENE_LEN_S = 0.25;\n/**\n * Adaptive re-check threshold. The low default (18) recovers soft reframes on montage\n * ads, but on a CONTINUOUS talking-head selfie (no real cuts) the creator's motion and\n * the held subject trip it dozens of times — shredding one shot into 20+ micro-scenes.\n * PySceneDetect's own default (27) is the discriminator: a real montage's cuts are\n * genuine HSV jumps that SURVIVE 27, while a continuous shot's motion artifacts VANISH.\n * So when the first pass looks over-segmented we re-run at 27 and trust that result —\n * it keeps real cuts and drops false ones. Paired with a longer min-scene-len.\n */\nconst PYSCENEDETECT_RECHECK_THRESHOLD = 27;\nconst PYSCENEDETECT_RECHECK_MIN_SCENE_LEN_S = 0.6;\n\n/**\n * Does a cut list look like a continuous shot shredded by motion rather than a real\n * montage? True when there are many cuts packed close together — the MEDIAN gap between\n * consecutive boundaries (counting 0 → first cut) is short. This is only a TRIGGER to\n * re-check at a higher threshold; the re-check itself is what decides montage vs\n * continuous, so a false trigger on a genuinely fast montage is harmless (its real cuts\n * survive the re-check). Pure + deterministic.\n */\nexport function isLikelyOverSegmented(cuts: number[], opts: { minCuts?: number; medianGapS?: number } = {}): boolean {\n const minCuts = opts.minCuts ?? 6;\n const maxMedianGap = opts.medianGapS ?? 2.0;\n const sorted = [...cuts].filter((c) => Number.isFinite(c) && c > 0).sort((a, b) => a - b);\n if (sorted.length < minCuts) return false;\n const gaps: number[] = [];\n let prev = 0;\n for (const c of sorted) {\n gaps.push(c - prev);\n prev = c;\n }\n gaps.sort((a, b) => a - b);\n const mid = Math.floor(gaps.length / 2);\n const median = gaps.length % 2 ? (gaps[mid] as number) : ((gaps[mid - 1] as number) + (gaps[mid] as number)) / 2;\n return median < maxMedianGap;\n}\n\n/**\n * Merge the over-segmentation re-check with the first pass instead of discarding it\n * wholesale. The high-threshold set is the base (it dropped the motion shred), but the\n * low pass ALSO found real SOFT transitions (blur-morphs, gradual reframes) that vanish\n * at 27 — losing them chains scenes across real shot changes. An extra is added back\n * only when it is ISOLATED: ≥ `isolationS` from every kept cut and from every other\n * extra. Motion shred clusters (sub-second neighbors); genuine soft cuts stand alone.\n * Pure + deterministic.\n */\nexport function mergeRecheckCuts(firstPass: number[], recheck: number[], isolationS = 0.75): number[] {\n const kept = [...new Set(recheck)].sort((a, b) => a - b);\n const extras = [...new Set(firstPass)]\n .filter((c) => kept.every((k) => Math.abs(k - c) >= isolationS))\n .sort((a, b) => a - b);\n const isolated = extras.filter((c, i) => {\n const prev = extras[i - 1];\n const next = extras[i + 1];\n return (prev === undefined || c - prev >= isolationS) && (next === undefined || next - c >= isolationS);\n });\n return [...new Set([...kept, ...isolated])].sort((a, b) => a - b);\n}\n\n/** Parse an `HH:MM:SS.mmm` PySceneDetect timecode into seconds, or null if malformed. */\nexport function timecodeToSeconds(tc: string): number | null {\n const m = tc.trim().match(/^(\\d+):(\\d{1,2}):(\\d{1,2}(?:\\.\\d+)?)$/);\n if (!m) return null;\n const h = Number.parseInt(m[1] ?? \"\", 10);\n const min = Number.parseInt(m[2] ?? \"\", 10);\n const s = Number.parseFloat(m[3] ?? \"\");\n if (!Number.isFinite(h) || !Number.isFinite(min) || !Number.isFinite(s)) return null;\n return h * 3600 + min * 60 + s;\n}\n\n/**\n * Parse hard-cut timestamps (seconds) out of a PySceneDetect `*-Scenes.csv`. The\n * first CSV row is the cutting list: `Timecode List:,00:00:08.900,00:00:11.333,…`\n * — each entry is a scene boundary (internal hard cut). Sorted, deduped, positive. Pure.\n */\nexport function parsePySceneDetectCsvCuts(csv: string): number[] {\n const firstLine = csv.split(/\\r?\\n/, 1)[0] ?? \"\";\n if (!/^\\s*Timecode List:/i.test(firstLine)) return [];\n const cuts: number[] = [];\n for (const cell of firstLine.split(\",\").slice(1)) {\n const t = timecodeToSeconds(cell);\n if (t !== null && t > 0) cuts.push(Math.round(t * 1000) / 1000);\n }\n return [...new Set(cuts)].sort((a, b) => a - b);\n}\n\n/**\n * Detect hard visual shot cuts with PySceneDetect's `scenedetect` CLI (battle-tested\n * ContentDetector: RGB→HSV per-frame average difference, default threshold 27). Writes\n * the scene CSV to a temp dir, parses the cutting list, then cleans up. Returns the cut\n * timestamps in seconds. Throws if `scenedetect` is missing or fails (caller falls back).\n */\n/** One `scenedetect detect-content` invocation at a fixed threshold; returns the cuts. */\nasync function runSceneDetectOnce(\n filePath: string,\n threshold: number,\n minSceneLenS: number,\n timeoutMs: number,\n): Promise<number[]> {\n const outDir = await mkdtemp(join(tmpdir(), \"baker-scenedetect-\"));\n try {\n await execFileAsync(\n \"scenedetect\",\n [\n \"--input\",\n filePath,\n \"--output\",\n outDir,\n \"detect-content\",\n \"--threshold\",\n String(threshold),\n \"--min-scene-len\",\n String(minSceneLenS),\n \"list-scenes\",\n \"--quiet\",\n ],\n { encoding: \"utf-8\", maxBuffer: 32 * 1024 * 1024, timeout: timeoutMs },\n );\n const csvName = (await readdir(outDir)).find((f) => f.toLowerCase().endsWith(\".csv\"));\n if (!csvName) return [];\n return parsePySceneDetectCsvCuts(await readFile(join(outDir, csvName), \"utf-8\"));\n } finally {\n await rm(outDir, { recursive: true, force: true });\n }\n}\n\nexport async function detectSceneCutsPySceneDetect(\n filePath: string,\n opts: { threshold?: number; minSceneLenS?: number; timeout_ms?: number } = {},\n): Promise<number[]> {\n // An operator-pinned threshold disables the adaptive re-check (they know best).\n const pinned = opts.threshold !== undefined;\n const threshold = opts.threshold ?? PYSCENEDETECT_THRESHOLD;\n // Minimum scene length (seconds). PySceneDetect's default (~0.6s) MERGES cuts closer\n // than that, silently dropping super-fast montage flashes. We floor it at the backend's\n // own minimum scene duration so genuine sub-second flashes survive as their own scenes\n // (then become cheap still-holds downstream). A float string is parsed as seconds.\n const minSceneLenS = opts.minSceneLenS ?? PYSCENEDETECT_MIN_SCENE_LEN_S;\n const timeoutMs = opts.timeout_ms ?? 120_000;\n const cuts = await runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs);\n // Adaptive guard: if the first pass shredded a continuous shot into many micro-cuts,\n // re-run at PySceneDetect's own (higher) default and trust THAT — real montage cuts\n // survive it, motion artifacts don't. Only when the operator didn't pin a threshold.\n if (!pinned && isLikelyOverSegmented(cuts)) {\n const rechecked = await runSceneDetectOnce(\n filePath,\n PYSCENEDETECT_RECHECK_THRESHOLD,\n PYSCENEDETECT_RECHECK_MIN_SCENE_LEN_S,\n timeoutMs,\n );\n // Merge instead of replace: the re-check drops the motion shred, but the low pass\n // also caught real SOFT transitions invisible at 27 — keep its isolated extras.\n return mergeRecheckCuts(cuts, rechecked);\n }\n return cuts;\n}\n","import { appendFile, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Which of `entries` are not already ignored by `existing` .gitignore content.\n * Matches a whole non-comment line (trimmed, optional trailing slash) so `canvas`\n * and `canvas/` both count as present. Pure — unit-tested without the filesystem.\n */\nexport function missingGitignoreEntries(existing: string, entries: string[]): string[] {\n const present = new Set(\n existing\n .split(\"\\n\")\n .map((l) => l.trim().replace(/\\/+$/, \"\"))\n .filter((l) => l.length > 0 && !l.startsWith(\"#\")),\n );\n return entries.filter((e) => !present.has(e.trim().replace(/\\/+$/, \"\")));\n}\n\n/**\n * Append any missing `entries` to `<dir>/.gitignore`. The canvas engine writes a\n * content-addressed cache + per-run dirs under `canvas/`, and the scaffold writes\n * working files under `.context/` — committing either would bloat the repo. Only\n * touches an EXISTING .gitignore (never creates surprise files); best-effort.\n */\nexport async function ensureGitignore(dir: string, entries: string[]): Promise<void> {\n const file = path.join(dir, \".gitignore\");\n let existing: string;\n try {\n existing = await readFile(file, \"utf8\");\n } catch {\n return; // no .gitignore here — don't conjure one\n }\n const missing = missingGitignoreEntries(existing, entries);\n if (missing.length === 0) return;\n const prefix = existing.endsWith(\"\\n\") || existing.length === 0 ? \"\" : \"\\n\";\n await appendFile(file, `${prefix}\\n# Baker canvas (engine cache + scaffold working files)\\n${missing.join(\"\\n\")}\\n`);\n}\n"],"mappings":"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","names":["readFile","rm","tmpdir","path","readFile","path","tmpdir","readFile","rm"]}