@koda-sl/baker-cli 0.479.0 → 0.480.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.
@@ -10,7 +10,7 @@ import {
10
10
  definitionFieldsOf,
11
11
  setDefinitionFields,
12
12
  setSpecMessage
13
- } from "./chunk-WL6FWK2Q.js";
13
+ } from "./chunk-RDCYPWQZ.js";
14
14
  import {
15
15
  IDEAS_DIR
16
16
  } from "./chunk-BSEB55E6.js";
@@ -94,4 +94,4 @@ export {
94
94
  makeSeriesAd,
95
95
  seriesMadeEnvelope
96
96
  };
97
- //# sourceMappingURL=chunk-IDN4FOOP.js.map
97
+ //# sourceMappingURL=chunk-NBNLGJH5.js.map
@@ -104,6 +104,15 @@ function pooledCandidates(searches, limit) {
104
104
  const proven = (c) => proofStrength(c.winner_score) !== "little";
105
105
  return [...pooled.filter(proven), ...pooled.filter((c) => !proven(c))].slice(0, limit);
106
106
  }
107
+ function freshReferencesFirst(candidates, taken) {
108
+ return [
109
+ ...candidates.filter((c) => !isTakenReference(c, taken)),
110
+ ...candidates.filter((c) => isTakenReference(c, taken))
111
+ ];
112
+ }
113
+ function isTakenReference(c, taken) {
114
+ return c.ad_id != null && taken.adIds.has(c.ad_id) || c.advertiser_id != null && taken.advertiserIds.has(c.advertiser_id);
115
+ }
107
116
  function fitsIdea(fit) {
108
117
  return fit.verdict !== "reject" && missingElements(fit).length === 0 && fit.our_viewer?.stops !== "no";
109
118
  }
@@ -232,6 +241,8 @@ export {
232
241
  rankedForOf,
233
242
  isOwnBrand,
234
243
  pooledCandidates,
244
+ freshReferencesFirst,
245
+ isTakenReference,
235
246
  fitsIdea,
236
247
  missingElements,
237
248
  whyUnfit,
@@ -246,4 +257,4 @@ export {
246
257
  unsourcedCopyLines,
247
258
  ideaSpec
248
259
  };
249
- //# sourceMappingURL=chunk-WL6FWK2Q.js.map
260
+ //# sourceMappingURL=chunk-RDCYPWQZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/creatives/make-model.ts"],"sourcesContent":["/**\n * The rules `baker creatives make` applies to turn an idea into a creative: which reference to\n * look for, which one fits, and what the creative records about the idea it carries. Pure.\n */\nimport { proofStrength } from \"@baker/api/ad-library\";\nimport { parse, parseDocument, Scalar, visit } from \"yaml\";\nimport { AD_SPEC_SCHEMA, type AdSpec, unfitReasons } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport type { ViewerTemperature } from \"../../viewer-profile.ts\";\nimport type { PersonaEntry } from \"../canvas/viewer-check.ts\";\nimport type { FitAnswer, FitBet } from \"../winning-ads/fit.ts\";\nimport type { WinningAdsSearchArgs } from \"../winning-ads/search.ts\";\nimport { type EvidenceLevel, figuresIn, IDEA_VIDEO_FORMATS, type Idea, unsourcedClaims } from \"./ideas-model.ts\";\nimport type { ReferenceBrief } from \"./reference-brief.ts\";\nimport type { RankedFor } from \"./reference-rank.ts\";\n\nexport const REFERENCE_CANDIDATES = 6;\n\n/** Whether the idea is a video, built from beats, rather than a static from a reference. */\nexport function isVideoIdea(idea: Pick<Idea, \"format\">): boolean {\n return (IDEA_VIDEO_FORMATS as readonly string[]).includes(idea.format);\n}\n\n/** Who a reference was made for, by our viewer: a stranger's ad never leans on its own brand. */\nconst BY_TEMPERATURE: Record<ViewerTemperature, { audienceTemperature: string; excludeBrandReliant?: true }> = {\n cold: { audienceTemperature: \"0_cold\", excludeBrandReliant: true },\n warm: { audienceTemperature: \"1_warm_engaged,2_hot_visited\", excludeBrandReliant: true },\n hot: { audienceTemperature: \"3_customer\" },\n};\n\n/**\n * Where a reference is looked for: the company's market (`GB`), what it sells (\"rooftop solar\") and\n * who the ad is for (\"Bill-shocked homeowner\") and its broader industry (\"home energy\"), when known.\n */\nexport type ReferenceWhere = {\n country?: string;\n category?: string;\n audience?: string;\n /** Searches that widen from the ad, closest first: adjacent products, the same buyer, the same decision. */\n wider?: readonly string[];\n industry?: string;\n};\n\n/**\n * The library search for a static idea's reference: its container, made for our viewer, on what\n * the company sells (else the idea's message), in its market when given.\n */\nexport function referenceSearchFor(\n idea: Idea,\n temperature: ViewerTemperature,\n where: ReferenceWhere = {},\n): WinningAdsSearchArgs {\n return {\n query: where.category || idea.message,\n scope: \"followed-first\",\n platform: \"meta\",\n format: \"static\",\n formatPattern: idea.format,\n awareness: idea.awareness,\n ...BY_TEMPERATURE[temperature],\n ...(where.country ? { country: where.country } : {}),\n maxPerAdvertiser: 1,\n limit: REFERENCE_CANDIDATES,\n diverse: true,\n };\n}\n\n/**\n * The searches whose candidates are tried, best first. A proven ad of what the company sells comes\n * before the idea's container: its market, viewer and objections are ours, and its container is one\n * the thinking can keep or change. So: what the company sells, in its market (in the idea's\n * container for our viewer, loosened in turn, then any container), then anywhere; then ads made for\n * the same people, whatever they sell; then wider (an adjacent product, the same buyer buying\n * something else, the same kind of decision); then ads of the broader industry; then the message;\n * then the container's proven winners from any category, in the market and anywhere.\n * The library's judge scores an ad against the query: prod, Oct 2026, a customer's sentence about\n * one product matched no ad of another category and 13 of 15 ideas found nothing; dev, Oct 2026,\n * searched with the whole message, a UK solar installer's ads were checked against a crypto\n * exchange, a clinic and an English course, while the library held UK solar ads; and with the\n * container a filter, 7 of 10 companies found 0–2 ads of their own category.\n */\nexport function referenceSearchesFor(\n idea: Idea,\n temperature: ViewerTemperature,\n where: ReferenceWhere = {},\n): WinningAdsSearchArgs[] {\n const strict = referenceSearchFor(idea, temperature, where);\n const { awareness: _awareness, ...anyStage } = strict;\n const { audienceTemperature: _temperature, excludeBrandReliant: _reliant, ...viewerAny } = anyStage;\n const anyViewer = { ...viewerAny, scope: \"all\" as const };\n const { formatPattern: _pattern, ...anyContainer } = anyViewer;\n const { country: _country, ...anywhere } = anyViewer;\n const { country: _anyCountry, ...anyContainerAnywhere } = anyContainer;\n const { query: _query, ...winners } = anyStage;\n const { query: _anyQuery, country: _winnersCountry, ...winnersAnywhere } = anyViewer;\n const inMarket = (steps: WinningAdsSearchArgs[]) => (where.country ? steps : []);\n const anyAd = (query: string | undefined) =>\n query?.trim()\n ? [...inMarket([{ ...anyContainer, query: query.trim() }]), { ...anyContainerAnywhere, query: query.trim() }]\n : [];\n return [\n ...(where.country ? [strict, anyStage, anyContainer] : [strict, anyStage]),\n anywhere,\n anyContainerAnywhere,\n ...anyAd(where.audience),\n ...(where.wider ?? []).flatMap((q) => (q.trim() ? [{ ...anyContainerAnywhere, query: q.trim() }] : [])),\n ...anyAd(where.industry),\n ...(where.category ? [{ ...anyContainerAnywhere, query: idea.message }] : []),\n ...inMarket([{ ...winners, sort: \"winner\" }]),\n { ...winnersAnywhere, sort: \"winner\" },\n ];\n}\n\n/**\n * Where a reference is looked for, from the brief when the model read one (its market over the\n * notes' guess; every market when it says the ad runs in several), else from the notes. Pure.\n */\nexport function referenceWhereOf(brief: ReferenceBrief | null, fallback: ReferenceWhere): ReferenceWhere {\n if (!brief) return fallback;\n const country = brief.country === null ? undefined : (brief.country ?? fallback.country);\n const audience = brief.audience ?? fallback.audience;\n return {\n ...(country ? { country } : {}),\n category: brief.category,\n ...(brief.industry ? { industry: brief.industry } : {}),\n ...(audience ? { audience } : {}),\n ...(brief.wider.length ? { wider: brief.wider } : {}),\n };\n}\n\n/** The ad being made, as candidates are ranked and picked for it: the brief's read, else the search's words. Pure. */\nexport function rankedForOf(\n brief: ReferenceBrief | null,\n where: ReferenceWhere,\n bet: Pick<FitBet, \"who\" | \"message\">,\n): RankedFor {\n return {\n category: brief?.category ?? where.category ?? bet.message,\n ...(brief?.industry ? { industry: brief.industry } : {}),\n ...(brief?.buyer ? { buyer: brief.buyer } : {}),\n ...(brief?.humour ? { humour: brief.humour } : {}),\n ...(brief?.memes ? { memes: brief.memes } : {}),\n ...(brief?.memesWhy ? { memesWhy: brief.memesWhy } : {}),\n ...(brief?.avoid.length ? { avoid: brief.avoid } : {}),\n message: bet.message,\n who: bet.who,\n };\n}\n\n/** A name as the library and a person may both spell it: no accents, case or punctuation. Pure. */\nconst brandKey = (name: string) =>\n name\n .normalize(\"NFD\")\n .replace(/\\p{M}/gu, \"\")\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]/gu, \"\");\n\n/** Whether an ad's advertiser is the company itself, by its brand names (three letters or more). Pure. */\nexport function isOwnBrand(advertiser: string | null | undefined, brands: readonly string[]): boolean {\n const page = brandKey(advertiser ?? \"\");\n return page !== \"\" && brands.some((b) => brandKey(b).length >= 3 && page.includes(brandKey(b)));\n}\n\ntype PoolCandidate = { ad_id?: string | null; advertiser_id?: string | null; winner_score?: number | null };\n\n/**\n * Every search's candidates in one list, the better search's first, one ad per brand (each fit\n * tried is another brand's move), the ads whose run barely proves them (`proofStrength` \"little\")\n * after the proven ones, at most `limit`. Pure.\n */\nexport function pooledCandidates<T extends PoolCandidate>(searches: readonly T[][], limit: number): T[] {\n const seen = new Set<string>();\n const pooled: T[] = [];\n for (const candidate of searches.flat()) {\n const brand = candidate.advertiser_id ? `brand:${candidate.advertiser_id}` : null;\n if (!candidate.ad_id || seen.has(candidate.ad_id) || (brand && seen.has(brand))) continue;\n seen.add(candidate.ad_id);\n if (brand) seen.add(brand);\n pooled.push(candidate);\n }\n const proven = (c: T) => proofStrength(c.winner_score) !== \"little\";\n return [...pooled.filter(proven), ...pooled.filter((c) => !proven(c))].slice(0, limit);\n}\n\n/** The proven ads, and their brands, the workspace's other creatives are already built on. */\nexport type TakenReferences = { adIds: ReadonlySet<string>; advertiserIds: ReadonlySet<string> };\n\n/**\n * The candidates no other creative is built on first (neither the ad nor its brand), then the\n * rest, each in its order: a batch of ideas is no longer built on one winning ad over and over,\n * and one already used is still built on when nothing else fits. Pure.\n */\nexport function freshReferencesFirst<T extends PoolCandidate>(candidates: readonly T[], taken: TakenReferences): T[] {\n return [\n ...candidates.filter((c) => !isTakenReference(c, taken)),\n ...candidates.filter((c) => isTakenReference(c, taken)),\n ];\n}\n\n/** Whether another creative is built on this ad or on another ad of its brand. Pure. */\nexport function isTakenReference(c: PoolCandidate, taken: TakenReferences): boolean {\n return (\n (c.ad_id != null && taken.adIds.has(c.ad_id)) ||\n (c.advertiser_id != null && taken.advertiserIds.has(c.advertiser_id))\n );\n}\n\n/** A reference fits when what it wins on is something we can supply, and our viewer would stop for it. */\nexport function fitsIdea(fit: Pick<FitAnswer, \"verdict\" | \"load_bearing\" | \"our_viewer\">): boolean {\n return fit.verdict !== \"reject\" && missingElements(fit).length === 0 && fit.our_viewer?.stops !== \"no\";\n}\n\n/** The load-bearing elements a reference wins on that we have nothing for. Pure. */\nexport function missingElements(fit: Pick<FitAnswer, \"load_bearing\">): string[] {\n return fit.load_bearing.filter((l) => l.have === \"missing\" && !l.ours?.trim()).map((l) => l.element);\n}\n\n/**\n * Why a checked reference was not built on, in one line the person can hear: what stops the scroll\n * or the proof that cannot be ours first, with the rule that forbids it; else that our viewer would\n * not stop for it; else the check's own note. Pure.\n */\nexport function whyUnfit(fit: Pick<FitAnswer, \"load_bearing\" | \"our_viewer\" | \"transfer_note\">): string {\n const reasons = unfitReasons(fit);\n if (reasons.length > 0) return reasons.join(\"; \");\n if (fit.our_viewer?.stops === \"no\") {\n return `our viewer would not stop for it${fit.our_viewer.why ? `: ${fit.our_viewer.why}` : \"\"}`;\n }\n return fit.transfer_note?.trim() || \"the check found it does not carry this ad\";\n}\n\nexport type DefinitionStrategyFields = {\n idea: string;\n message: string;\n evidence?: EvidenceLevel;\n angle: string;\n persona: string;\n awareness: string;\n hypothesis: string;\n};\n\n/** What a creative records about the idea it executes. */\nexport function definitionFieldsOf(idea: Idea, evidence: EvidenceLevel | \"explore\"): DefinitionStrategyFields {\n return {\n idea: idea.id,\n message: idea.message,\n ...(evidence !== \"explore\" ? { evidence } : {}),\n angle: idea.angle,\n persona: idea.who,\n awareness: idea.awareness,\n hypothesis: idea.why,\n };\n}\n\nconst FRONTMATTER = /^---\\r?\\n([\\s\\S]*?\\r?\\n)?---/;\n\n/** Whether a bare string reads back as the same text under YAML 1.1. */\nfunction readsAsText11(text: string): boolean {\n try {\n return parse(text, { version: \"1.1\" }) === text;\n } catch {\n return false;\n }\n}\n\n/** Set fields in a markdown file's frontmatter, keeping every other field and the body. */\nexport function setDefinitionFields(raw: string, fields: Record<string, unknown>): string {\n const match = raw.match(FRONTMATTER);\n if (!match) return raw;\n const doc = parseDocument(match[1] ?? \"\");\n if (doc.errors.length > 0) return raw;\n for (const [key, value] of Object.entries(fields)) {\n if (value === undefined) continue;\n const node = doc.createNode(value);\n // The site reads frontmatter as YAML 1.1, where a bare 2026-10-04 is a date, not text.\n visit(node, {\n Scalar(_, scalar) {\n if (typeof scalar.value === \"string\" && !readsAsText11(scalar.value)) {\n scalar.type = Scalar.QUOTE_DOUBLE;\n }\n },\n });\n doc.set(key, node);\n }\n return `---\\n${doc.toString()}---${raw.slice(match[0].length)}`;\n}\n\n/** The ad spec with the idea's message as the one thing it tells the viewer. */\nexport function setSpecMessage(specJson: string, message: string): string {\n const spec = JSON.parse(specJson) as Record<string, unknown>;\n return `${JSON.stringify({ ...spec, message }, null, 2)}\\n`;\n}\n\n/**\n * The ad spec made for the idea's persona: its title and segment from the Knowledge (\"The owner on\n * the move (Owner, 30–55, 1–10 staff)\"), else the idea's own words. The image prompt, the casting\n * check and the viewer check all read `viewer.who`; a reference-built spec held only the\n * scaffold's placeholder. The market and what the viewer knows are kept. Pure.\n */\nexport function setSpecViewer(specJson: string, idea: Pick<Idea, \"who\">, personas: readonly PersonaEntry[]): string {\n const spec = JSON.parse(specJson) as Record<string, unknown>;\n const viewer = (spec.viewer ?? {}) as Record<string, unknown>;\n return `${JSON.stringify({ ...spec, viewer: { ...viewer, who: personaWho(idea, personas) } }, null, 2)}\\n`;\n}\n\n/** Who an idea is for, in its persona's words (\"The owner on the move (Owner, 30–55)\"), else its own. Pure. */\nexport function personaWho(idea: Pick<Idea, \"who\">, personas: readonly PersonaEntry[]): string {\n const persona = personas.find((p) => p.slug === idea.who);\n if (persona?.title) return `${persona.title}${persona.segment ? ` (${persona.segment})` : \"\"}`;\n return persona?.segment ?? idea.who.replace(/[-_]/g, \" \");\n}\n\n/** The most words the audience search keeps: the library's judge reads a long query slowly. */\nconst AUDIENCE_QUERY_WORDS = 9;\n\n/**\n * The people the idea is for, as a library search: its persona's own words, cut short. Dev, Oct\n * 2026: \"homeowners worried about rising energy bills\" found twelve proven energy ads where\n * \"rooftop solar\" in the idea's container found one. Pure.\n */\nexport function audienceQuery(idea: Pick<Idea, \"who\">, personas: readonly PersonaEntry[]): string {\n return personaWho(idea, personas)\n .replace(/\\(/g, \" \")\n .replace(/\\)/g, \"\")\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, AUDIENCE_QUERY_WORDS)\n .join(\" \")\n .replace(/[\\s,;:.–—-]+$/, \"\");\n}\n\n/** The ad being made, as the fit judges a reference for it: its persona, message and the customers' words it stands on. Pure. */\nexport function fitBetOf(\n idea: Pick<Idea, \"who\" | \"message\" | \"awareness\" | \"angle\" | \"evidence\">,\n personas: readonly PersonaEntry[],\n insights: readonly { id: string; quote: string }[],\n market?: string,\n): FitBet {\n const quotes = insights.filter((i) => idea.evidence.includes(i.id)).map((i) => i.quote);\n return {\n who: personaWho(idea, personas),\n message: idea.message,\n awareness: idea.awareness,\n angle: idea.angle,\n ...(quotes.length > 0 ? { quotes } : {}),\n ...(market ? { market } : {}),\n };\n}\n\n/**\n * The ad spec with the concept the reference's fit read (`conceptFromFit`): a build started before\n * the fit answered has none, or only the one the scaffold drafted from its describe, which names no\n * reference and nothing of what we have; without the fit's, the render never sees the reference at\n * the level that won. A concept a fit already seeded (it names its reference) stays. Pure.\n */\nexport function withFitConcept(specJson: string, seeded: Record<string, unknown>): string {\n const spec = JSON.parse(specJson) as Record<string, unknown>;\n const held = spec.concept as { reference_ad_id?: unknown } | undefined;\n if (held?.reference_ad_id) return specJson;\n return `${JSON.stringify({ ...spec, ...seeded }, null, 2)}\\n`;\n}\n\n/**\n * The copy lines the scaffold drafted that claim a figure the company never wrote: a draft written\n * beside a competitor's ad can carry the competitor's promise. `corpus` is what the company wrote.\n */\nexport function unsourcedCopyLines(specJson: string, corpus: string): string[] {\n const spec = JSON.parse(specJson) as { copy?: unknown };\n const figures = figuresIn(corpus);\n const lines = Array.isArray(spec.copy) ? spec.copy : [];\n return lines.flatMap((line) => {\n const text = typeof line === \"object\" && line !== null ? (line as { text?: unknown }).text : undefined;\n return typeof text === \"string\" && unsourcedClaims(text, figures).length > 0 ? [text] : [];\n });\n}\n\n/** Containers shown as a photograph; every other container is a designed graphic or a screen. */\nconst PHOTO_FORMATS = /photo|lifestyle|before_after|ugc|product|selfie|street/;\n\n/**\n * The ad spec an idea starts from when no proven ad fits it: the message and who it is for are\n * the idea's; the scene and the copy are placeholders the agent writes before anything renders\n * (`canvas run` refuses a placeholder). Pure.\n */\nexport function ideaSpec(idea: Idea, who: string): AdSpec {\n const container = idea.format.replace(/_/g, \" \");\n return {\n schema: AD_SPEC_SCHEMA,\n viewer: { who },\n message: idea.message,\n copy: [{ text: \"[TODO: the headline, in the customer's words]\", lettering: \"designed\", role: \"headline\" }],\n scene: {\n description: `[TODO: what the viewer sees, as a ${container}, that shows: ${idea.message}]`,\n look: PHOTO_FORMATS.test(idea.format) ? \"photo\" : \"designed\",\n },\n colors: [],\n references: [],\n logo: true,\n third_party_brands: [],\n scene_text: [],\n mechanism: [],\n };\n}\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -123,7 +123,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
123
123
  gsc: () => import("./gsc-UU3T2C6B.js").then((m) => m.gscCommand),
124
124
  research: () => import("./research-MBAPL35Y.js").then((m) => m.researchCommand),
125
125
  decide: () => import("./decide-TWKH5QQU.js").then((m) => m.decideCommand),
126
- creatives: () => import("./creatives-YOMFW2UP.js").then((m) => m.creativesCommand),
126
+ creatives: () => import("./creatives-F3TMRTIR.js").then((m) => m.creativesCommand),
127
127
  flows: () => import("./flows-274YPU6I.js").then((m) => m.flowsCommand),
128
128
  funnel: () => import("./funnel-LEUXICXU.js").then((m) => m.funnelCommand),
129
129
  images: () => import("./images-ZMZ4WLYH.js").then((m) => m.imagesCommand),
@@ -41,9 +41,9 @@ Full guide: __tooling__/docs/tools/baker/creatives.md`
41
41
  subCommands: {
42
42
  brief: () => import("./brief-WAQ2V6Q4.js").then((m) => m.briefCommand),
43
43
  ideas: () => import("./ideas-UTSCGCT6.js").then((m) => m.ideasCommand),
44
- make: () => import("./make-IZJ47YZY.js").then((m) => m.makeCommand),
45
- translate: () => import("./translate-AEOQJ5JN.js").then((m) => m.translateCommand),
46
- learn: () => import("./learn-NJOV2DHD.js").then((m) => m.learnCommand),
44
+ make: () => import("./make-X6IG6KAZ.js").then((m) => m.makeCommand),
45
+ translate: () => import("./translate-K4D7KDYV.js").then((m) => m.translateCommand),
46
+ learn: () => import("./learn-RGO5KDHS.js").then((m) => m.learnCommand),
47
47
  feedback: () => import("./feedback-CCU6ECMQ.js").then((m) => m.feedbackCommand),
48
48
  rules: () => import("./rules-SZIY67QF.js").then((m) => m.rulesCommand),
49
49
  check: () => import("./check-GCZ2ZBKH.js").then((m) => m.checkCommand),
@@ -55,4 +55,4 @@ Full guide: __tooling__/docs/tools/baker/creatives.md`
55
55
  export {
56
56
  creativesCommand
57
57
  };
58
- //# sourceMappingURL=creatives-YOMFW2UP.js.map
58
+ //# sourceMappingURL=creatives-F3TMRTIR.js.map
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-CXQRTLSQ.js";
5
5
  import {
6
6
  setDefinitionFields
7
- } from "./chunk-WL6FWK2Q.js";
7
+ } from "./chunk-RDCYPWQZ.js";
8
8
  import {
9
9
  IDEAS_DIR,
10
10
  readIdeas
@@ -201,4 +201,4 @@ export {
201
201
  learnCommand,
202
202
  learnEnvelope
203
203
  };
204
- //# sourceMappingURL=learn-NJOV2DHD.js.map
204
+ //# sourceMappingURL=learn-RGO5KDHS.js.map
@@ -17,7 +17,7 @@ import {
17
17
  import {
18
18
  makeSeriesAd,
19
19
  seriesMadeEnvelope
20
- } from "./chunk-IDN4FOOP.js";
20
+ } from "./chunk-NBNLGJH5.js";
21
21
  import "./chunk-XZ4YMCZK.js";
22
22
  import {
23
23
  runBaker
@@ -42,8 +42,10 @@ import {
42
42
  definitionFieldsOf,
43
43
  fitBetOf,
44
44
  fitsIdea,
45
+ freshReferencesFirst,
45
46
  ideaSpec,
46
47
  isOwnBrand,
48
+ isTakenReference,
47
49
  isVideoIdea,
48
50
  missingElements,
49
51
  personaWho,
@@ -57,7 +59,7 @@ import {
57
59
  unsourcedCopyLines,
58
60
  whyUnfit,
59
61
  withFitConcept
60
- } from "./chunk-WL6FWK2Q.js";
62
+ } from "./chunk-RDCYPWQZ.js";
61
63
  import {
62
64
  IDEAS_DIR,
63
65
  coverageOf,
@@ -145,7 +147,7 @@ import {
145
147
  import "./chunk-YQSBHWOI.js";
146
148
 
147
149
  // src/commands/creatives/make.ts
148
- import { mkdir as mkdir2, mkdtemp, readFile as readFile2, rm, stat, writeFile as writeFile2 } from "fs/promises";
150
+ import { mkdir as mkdir2, mkdtemp, readdir, readFile as readFile2, rm, stat, writeFile as writeFile2 } from "fs/promises";
149
151
  import { tmpdir } from "os";
150
152
  import path2 from "path";
151
153
  import { defineCommand } from "citty";
@@ -402,7 +404,7 @@ var FITS_AT_ONCE = 3;
402
404
  var RANKED_POOL = 24;
403
405
  var SEARCH_TIMEOUT_MS = 12e4;
404
406
  var REFERENCE_MS = 15e4;
405
- var DESCRIPTION = `Build one idea from src/creatives/_ideas/ into a creative. For a static it builds on a proven winning ad: it reads what this ad sells and for whom, searches ads of that in its market (the idea's container first, then any), then ads made for the idea's persona, its industry, the idea's message, then the container's strongest winners from any category; leaves out the company's own ads, ranks the rest for this ad's buyer, viewer and brand, checks which fit us (one whose scroll-stopper or proof cannot be ours is passed over, and the first hint says which and why) and, when several do, compares them side by side, scaffolds the creative on the best-ranked one, records the idea on it and sets the ad's message. The fit says what made that ad win, so what ours carries of it (\`reference.carry\`: whole_ad, layout, hook or angle); its first hint names the ad: tell the person. When no proven ad fits, it starts the ad from the idea itself and says why (never a dead end, never retry with another format). You then write the copy lines and the scene in prompt.json and run it. Takes up to about two and a half minutes: run it in the foreground, once per idea.
407
+ var DESCRIPTION = `Build one idea from src/creatives/_ideas/ into a creative. For a static it builds on a proven winning ad: it reads what this ad sells and for whom, searches ads of that in its market (the idea's container first, then any), then ads made for the idea's persona, its industry, the idea's message, then the container's strongest winners from any category; leaves out the company's own ads, ranks the rest for this ad's buyer, viewer and brand (a proven ad, or brand, another creative is already built on last, so a batch of ideas builds on different winners), checks which fit us (one whose scroll-stopper or proof cannot be ours is passed over, and the first hint says which and why) and, when several do, compares them side by side, scaffolds the creative on the best-ranked one, records the idea on it and sets the ad's message. The fit says what made that ad win, so what ours carries of it (\`reference.carry\`: whole_ad, layout, hook or angle); its first hint names the ad: tell the person. When no proven ad fits, it starts the ad from the idea itself and says why (never a dead end, never retry with another format). You then write the copy lines and the scene in prompt.json and run it. Takes up to about two and a half minutes: run it in the foreground, once per idea.
406
408
 
407
409
  Where the ad runs decides its sizes (Meta 4:5 + 9:16, LinkedIn 1:1, TikTok 9:16): it is the idea's \`platforms\`, or --platforms from the person's request; nothing saying so is refused, never defaulted to Meta.
408
410
 
@@ -566,9 +568,10 @@ async function findCandidates(searches, deps) {
566
568
  results.map((found) => (found ?? []).flatMap(buildable)),
567
569
  deps.rank ? RANKED_POOL : FITS_TRIED
568
570
  );
569
- if (!deps.rank) return pooled;
571
+ const fresh = (found) => deps.taken ? freshReferencesFirst(found, deps.taken) : found;
572
+ if (!deps.rank) return fresh(pooled);
570
573
  const ranked = await deps.rank(pooled).catch(() => pooled);
571
- return ranked.flatMap(buildable).slice(0, FITS_TRIED);
574
+ return fresh(ranked.flatMap(buildable)).slice(0, FITS_TRIED);
572
575
  }
573
576
  var candidateOf = (c) => ({
574
577
  adId: String(c.ad_id),
@@ -599,7 +602,7 @@ async function pickReference(root, searches, deps = liveReferenceDeps(root), pre
599
602
  );
600
603
  };
601
604
  for (let slot = 0; slot < FITS_AT_ONCE; slot++) askNext();
602
- const deciding = deps.choose ? chosenFitting(candidates, asked, deps.choose) : firstFitting(candidates, asked);
605
+ const deciding = deps.choose ? chosenFitting(candidates, asked, deps.choose, deps.taken) : firstFitting(candidates, asked);
603
606
  const kept = await Promise.race([deciding, out]);
604
607
  settled = true;
605
608
  if (kept === "out") {
@@ -652,12 +655,14 @@ async function allFits(fits) {
652
655
  }
653
656
  return await Promise.all(fits);
654
657
  }
655
- async function chosenFitting(candidates, fits, choose) {
658
+ async function chosenFitting(candidates, fits, choose, taken) {
656
659
  const answered = await allFits(fits);
657
- const fitting = answered.flatMap((fit, index) => {
660
+ const fitted = answered.flatMap((fit, index) => {
658
661
  const candidate = candidates[index];
659
662
  return candidate && fit.ok && fitsIdea(fit.fit) ? [{ index, candidate, fit: fit.fit }] : [];
660
663
  });
664
+ const fresh = taken ? fitted.filter((f) => !isTakenReference(f.candidate, taken)) : [];
665
+ const fitting = fresh.length > 0 ? fresh : fitted;
661
666
  if (fitting.length < 2) return await firstFitting(candidates, fits);
662
667
  const chosen = await choose(
663
668
  fitting.map((f) => ({ adId: String(f.candidate.ad_id), candidate: f.candidate, fit: f.fit }))
@@ -842,6 +847,22 @@ async function referenceTarget(root, idea) {
842
847
  });
843
848
  return { market, personas, brief, where };
844
849
  }
850
+ async function takenReferencesIn(root, slug) {
851
+ const creatives = path2.join(root, "src", "creatives");
852
+ const names = await readdir(creatives).catch(() => []);
853
+ const sources = await Promise.all(
854
+ names.filter((name) => name !== slug && !name.startsWith("_")).map(
855
+ (name) => readFile2(path2.join(creatives, name, "_definition.md"), "utf8").then(
856
+ parseDefinitionSourceFields,
857
+ () => ({})
858
+ )
859
+ )
860
+ );
861
+ return {
862
+ adIds: new Set(sources.flatMap((s) => s.sourceAdId ? [s.sourceAdId] : [])),
863
+ advertiserIds: new Set(sources.flatMap((s) => s.sourceAdvertiserId ? [s.sourceAdvertiserId] : []))
864
+ };
865
+ }
845
866
  async function scaffoldStatic(root, idea, args, slug, temperature, viewerFlags) {
846
867
  const onReference = (c, signal) => runBaker(
847
868
  [
@@ -870,7 +891,10 @@ async function scaffoldStatic(root, idea, args, slug, temperature, viewerFlags)
870
891
  await readInsights(root).catch(() => []),
871
892
  market ? describeMarket(market) : void 0
872
893
  );
873
- const deps = liveReferenceDeps(root, bet, rankedForOf(brief, where, bet), brief?.brands);
894
+ const deps = {
895
+ ...liveReferenceDeps(root, bet, rankedForOf(brief, where, bet), brief?.brands),
896
+ taken: await takenReferencesIn(root, slug)
897
+ };
874
898
  const definition = await readFile2(path2.join(dir, "_definition.md"), "utf8").catch(() => null);
875
899
  const recast = castRebuild(definition, args);
876
900
  const fromIdea = args.fromIdea || ideaRecast(definition, args);
@@ -1307,4 +1331,4 @@ export {
1307
1331
  seedConcept,
1308
1332
  unbuiltReference
1309
1333
  };
1310
- //# sourceMappingURL=make-IZJ47YZY.js.map
1334
+ //# sourceMappingURL=make-X6IG6KAZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/creatives/make.ts","../src/commands/creatives/reference-brief.ts","../src/commands/creatives/reference-rank.ts","../src/commands/creatives/reference-pick.ts"],"sourcesContent":["/**\n * `baker creatives make <idea>`: one idea becomes one creative. For a static it finds a reference\n * for the job itself (the idea's container, made for our viewer), keeps the first whose\n * load-bearing parts we can supply, scaffolds from it, and records the idea on the creative and\n * its message in the ad spec. The agent then writes only the copy lines and the scene, and runs it.\n */\n\nimport { mkdir, mkdtemp, readdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport type { ScopedWinnersSearchResponse } from \"@baker/api/ad-library\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { memeRegister, readCompanyReading } from \"../../engine/creative-context/company.ts\";\nimport { avoidOf, readCreativeContext } from \"../../engine/creative-context/index.ts\";\nimport type { ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport type { ConceptCarry } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport { readAdSpec, SPEC_SHAPES_HINT, unwrittenProblems } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport { projectAdaptBriefs } from \"../../engine/scaffold/static-adapt-briefs.ts\";\nimport {\n parseDefinitionDelivery,\n platformsNamedIn,\n type ResolvedDelivery,\n} from \"../../engine/scaffold/static-delivery.ts\";\nimport { projectFormatBriefs } from \"../../engine/scaffold/static-format-briefs.ts\";\nimport { projectStaticBriefs } from \"../../engine/scaffold/static-render-briefs.ts\";\nimport { recordedShape } from \"../../engine/scaffold/static-shape-route.ts\";\nimport { reroutedOnSpec } from \"../../engine/scaffold/static-upgrade.ts\";\nimport { optionalChatId } from \"../../env.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport {\n describeMarket,\n marketFromCompanyDoc,\n type ViewerTemperature,\n viewerFromKnowledge,\n} from \"../../viewer-profile.ts\";\nimport { runBaker as baker } from \"../baker-child.ts\";\nimport { type DefinitionSourceFields, parseDefinitionSourceFields } from \"../canvas/creative-definition.ts\";\nimport { type LibraryPlatform, notADesignReference, resolveSourcePlatform } from \"../canvas/library-reference.ts\";\nimport { findWorkspaceRoot } from \"../canvas/normalize-paths.ts\";\nimport { scaffoldDelivery } from \"../canvas/scaffold-delivery.ts\";\nimport { holdUnbilledSpend } from \"../canvas/unbilled-spend.ts\";\nimport { liveViewerLookups, readPersonas } from \"../canvas/viewer-check.ts\";\nimport {\n conceptFromFit,\n type FitAnswer,\n type FitBet,\n type FitFailure,\n fitReference,\n NO_FIT_HINT,\n pictureOf,\n} from \"../winning-ads/fit.ts\";\nimport { buildSearchBody } from \"../winning-ads/search.ts\";\nimport { castInventory, companyName } from \"./cast-inventory.ts\";\nimport { checkIdeas, type EvidenceLevel, type Idea, type IdeaCheck, sourcesClaims } from \"./ideas-model.ts\";\nimport {\n coverageOf,\n IDEAS_DIR,\n readCreativeRecords,\n readIdeas,\n readInsights,\n readKnowledgeCorpus,\n readPersonaIds,\n} from \"./ideas-workspace.ts\";\nimport {\n audienceQuery,\n definitionFieldsOf,\n fitBetOf,\n fitsIdea,\n freshReferencesFirst,\n ideaSpec,\n isOwnBrand,\n isTakenReference,\n isVideoIdea,\n missingElements,\n personaWho,\n pooledCandidates,\n rankedForOf,\n referenceSearchesFor,\n referenceWhereOf,\n setDefinitionFields,\n setSpecMessage,\n setSpecViewer,\n type TakenReferences,\n unsourcedCopyLines,\n whyUnfit,\n withFitConcept,\n} from \"./make-model.ts\";\nimport { makeSeriesAd, seriesMadeEnvelope } from \"./make-series.ts\";\nimport { referenceBriefFor } from \"./reference-brief.ts\";\nimport { type Avoid, askPickModel, pickAmong, type ReferencePick, type Take } from \"./reference-pick.ts\";\nimport { type RankedFor, rankForBet } from \"./reference-rank.ts\";\nimport { thinkingOutline, withThinking } from \"./thinking.ts\";\n\n/** Candidates whose fit may be asked (a few cents each, cached per workspace). */\nconst FITS_TRIED = 6;\n/**\n * Fits asked at a time: the best-ranked candidate is usually kept, so the rest wait for a slot that\n * one not fitting frees (six at once billed six fits where one was kept).\n */\nconst FITS_AT_ONCE = 3;\n/** How many found ads are ranked for the ad being made before the best FITS_TRIED are checked. */\nconst RANKED_POOL = 24;\nconst SEARCH_TIMEOUT_MS = 120_000;\n/**\n * How long make looks for, checks and describes a reference before it starts the ad from the idea.\n * Every ad starts from a proven one when it can: dev, Oct 2026, a search took 3-30 s, a fit 20-50 s\n * and the describe ~35 s beside them, so the 50 s this once was sent good references to the idea.\n */\nconst REFERENCE_MS = 150_000;\n\nconst DESCRIPTION = `Build one idea from src/creatives/_ideas/ into a creative. For a static it builds on a proven winning ad: it reads what this ad sells and for whom, searches ads of that in its market (the idea's container first, then any), then ads made for the idea's persona, its industry, the idea's message, then the container's strongest winners from any category; leaves out the company's own ads, ranks the rest for this ad's buyer, viewer and brand (a proven ad, or brand, another creative is already built on last, so a batch of ideas builds on different winners), checks which fit us (one whose scroll-stopper or proof cannot be ours is passed over, and the first hint says which and why) and, when several do, compares them side by side, scaffolds the creative on the best-ranked one, records the idea on it and sets the ad's message. The fit says what made that ad win, so what ours carries of it (\\`reference.carry\\`: whole_ad, layout, hook or angle); its first hint names the ad: tell the person. When no proven ad fits, it starts the ad from the idea itself and says why (never a dead end, never retry with another format). You then write the copy lines and the scene in prompt.json and run it. Takes up to about two and a half minutes: run it in the foreground, once per idea.\n\nWhere the ad runs decides its sizes (Meta 4:5 + 9:16, LinkedIn 1:1, TikTok 9:16): it is the idea's \\`platforms\\`, or --platforms from the person's request; nothing saying so is refused, never defaulted to Meta.\n\nStart here, with an idea from \\`baker creatives ideas\\` build_next:\n baker creatives make phone-payroll # static: reference found and checked for you\n baker creatives make phone-payroll --platforms linkedin # where it runs, when the idea does not say\n baker creatives make phone-payroll --adset 120210000000 # written for that ad set's viewer\n baker creatives make phone-payroll --reference 1310524137919413 # your own reference instead\n baker creatives make founder-story --spec beats.json # a video idea: from its beats spec\n baker creatives make phone-payroll --slug phone-payroll-h2 # another hook of the same idea\n baker creatives make tiktok-speed --series zernio-live # another message in the style of a ready ad\nThen: edit src/creatives/<slug>/prompt.json (copy + scene; the message is set), and \\`baker canvas run src/creatives/<slug>/<slug>.canvas.json\\`.`;\n\nconst ARGS = {\n idea: { type: \"positional\", required: true, description: \"The idea id (src/creatives/_ideas/<idea>.md)\" },\n slug: { type: \"string\", required: false, description: \"Creative slug (default: the idea id)\" },\n adset: { type: \"string\", required: false, description: \"Meta ad set the ad is for: its viewer and placements\" },\n reference: {\n type: \"string\",\n required: false,\n description: \"A library ad id to build on instead of searching (statics)\",\n },\n platforms: {\n type: \"string\",\n required: false,\n description:\n \"Where the ad runs, the main platform first: meta (4:5 + 9:16), linkedin (1:1), tiktok (9:16), google_demandgen, … Take it from the person's request; default the creative's definition (and the sizes it records), then the idea's `platforms`, then the ad set's (Meta). Nothing saying so is refused, never defaulted.\",\n },\n formats: {\n type: \"string\",\n required: false,\n description:\n \"Exactly the sizes to make, when the person asks for others than the platform's (`--platforms linkedin --formats 1:1,4:5`).\",\n },\n \"reference-platform\": {\n type: \"string\",\n required: false,\n description:\n \"Library platform of --reference: meta|linkedin|tiktok|google (default meta). On google only display ads are built on (a static needs a picture)\",\n },\n platform: {\n type: \"string\",\n required: false,\n description:\n \"Retired: --platforms says where the ad runs; --reference-platform says which library --reference is in.\",\n },\n spec: {\n type: \"string\",\n required: false,\n description: \"Video ideas: the beats spec for `baker canvas scaffold-ad --spec`\",\n },\n series: {\n type: \"string\",\n required: false,\n description:\n \"Statics: make this idea as another ad of the series led by this creative (its slug): the same design, only its words changed. No reference is searched; seconds. The lead must have a ready version. Then write its words and run the whole series: baker canvas run --series <lead>\",\n },\n avatar: {\n type: \"string\",\n required: false,\n description:\n \"Statics: the Avatar(s) the ad's people are cast as (`@eduard` or `eduard,lucia`; `baker avatars list`). Run make again with it once the definition decides the cast, before prompt.json is written: it rebuilds the canvas on them and keeps the thinking\",\n },\n \"from-idea\": {\n type: \"boolean\",\n required: false,\n default: false,\n description:\n \"Statics: skip the reference search and start from the idea (what make does by itself when no proven ad fits)\",\n },\n} as const;\n\nregisterSchema({ command: \"creatives.make\", description: DESCRIPTION, args: ARGS });\n\ntype Failure = { code: string; message: string; fix?: string };\n\nfunction fail(error: Failure): never {\n writeJson({ ok: false, error });\n process.exit(1);\n}\n\nasync function viewerTemperature(\n root: string,\n adSet: string | undefined,\n awareness: string,\n): Promise<ViewerTemperature> {\n if (adSet) {\n const read = await liveViewerLookups(root)\n .adSetViewer(adSet)\n .catch(() => null);\n if (read) return read.temperature;\n }\n return viewerFromKnowledge({ personas: [], awareness: awareness as never }).temperature;\n}\n\ntype Picked = {\n adId: string;\n platform: LibraryPlatform;\n advertiserId?: string;\n why: string;\n tried: number;\n /** The fit that kept it, with what made it win (`carry`); none for a reference chosen by hand that could not be checked. */\n fit?: FitAnswer;\n /** Its static container (`lifestyle_photo`), when the library knows it: it can differ from the idea's. */\n container?: string;\n /** Why the side-by-side look preferred it to the others that fit, when there were others. */\n preferred?: string;\n /** Every proven ad that fit, in the look's order (this one first), when several did. */\n board?: BoardAd[];\n /** What the look said our ad takes from which of them. */\n takes?: Take[];\n /** What it said our ad must not copy from them. */\n avoid?: Avoid[];\n /** The proven ads checked that did not fit, each with why (what stops the scroll or the proof that cannot be ours first). */\n passed?: PassedOver[];\n};\n\n/** A proven ad that fit, as the thinking lays it out. */\ntype BoardAd = { adId: string; advertiser?: string; mediaUrl?: string };\n\n/** A proven ad checked and not built on, and why. */\ntype PassedOver = { adId: string; advertiser?: string; why: string };\n\n/** How many of the proven ads passed over the person is told about. */\nconst PASSED_SAID = 3;\n\n/** The checked candidates that did not fit, in rank order, each with why; at most `PASSED_SAID`. Pure. */\nfunction passedOver(candidates: readonly Buildable[], fits: ReadonlyArray<FitResult | undefined>): PassedOver[] {\n return candidates\n .flatMap((candidate, i) => {\n const fit = fits[i];\n if (!fit?.ok || fitsIdea(fit.fit)) return [];\n return [\n {\n adId: String(candidate.ad_id),\n ...(candidate.advertiser ? { advertiser: candidate.advertiser } : {}),\n why: whyUnfit(fit.fit),\n },\n ];\n })\n .slice(0, PASSED_SAID);\n}\n\ntype Candidate = {\n ad_id?: string | null;\n platform?: unknown;\n advertiser_id?: string | null;\n format?: string | null;\n winner_score?: number | null;\n advertiser?: string | null;\n media_url?: string | null;\n dna?: {\n container?: string | null;\n industry?: string | null;\n business_model?: string | null;\n target_persona?: string | null;\n visual?: string | null;\n creative_concept?: string | null;\n mechanism?: string | null;\n } | null;\n};\n\n/** The library platform a candidate is on (none named is the library's default, meta); null for any other. Pure. */\nfunction candidatePlatform(c: Candidate): LibraryPlatform | null {\n const resolved = resolveSourcePlatform(typeof c.platform === \"string\" ? c.platform : undefined);\n return resolved.ok ? resolved.platform : null;\n}\n\n/** A candidate make can build on, its platform resolved. */\ntype Buildable = Candidate & { platform: LibraryPlatform };\n\n/**\n * The candidate with its platform, when it is a design make can build on: never one on a platform\n * the library does not index (it was once fitted as a Meta ad and silently failed), nor a Google\n * search text ad, which is wording, not a design. Pure.\n */\nfunction buildable(c: Candidate): Buildable[] {\n const platform = candidatePlatform(c);\n if (!platform || notADesignReference(platform, String(c.ad_id), { format: c.format ?? null })) return [];\n return [{ ...c, platform }];\n}\ntype FitResult = Awaited<ReturnType<typeof fitReference>>;\n\n/** A reference the fit kept, as the side-by-side pick is shown it. */\nexport type FittingReference = { adId: string; candidate: Candidate; fit: FitAnswer };\n\n/**\n * How references are found, ordered, checked and chosen between; the live library, decision\n * model, fit and pick by default, injected in tests. Without `rank` the search's order holds;\n * without `choose` the best-ranked reference that fits is kept.\n */\nexport type ReferenceDeps = {\n /** The ads one search found; null when the library could not search. */\n search: (body: Record<string, unknown>) => Promise<Candidate[] | null>;\n rank?: (found: Candidate[]) => Promise<Candidate[]>;\n fit: (platform: Picked[\"platform\"], adId: string) => Promise<FitResult>;\n choose?: (fitting: FittingReference[]) => Promise<ReferencePick | null>;\n /** What the workspace's other creatives are built on: checked after every other candidate. */\n taken?: TakenReferences;\n};\n\n/**\n * The live library, fit and, when the ad being made is known, the ranking and the side-by-side\n * pick: the company's own ads left out (its brand names, from the brief), the rest read against\n * the ad before the fits, and the ones that fit compared in one look.\n */\nfunction liveReferenceDeps(\n root: string,\n bet?: FitBet,\n rankedFor?: RankedFor,\n brands: readonly string[] = [],\n): ReferenceDeps {\n return {\n search: async (body) => {\n const ask = () =>\n apiPost<ScopedWinnersSearchResponse>(\"/api/ad-library/winners/search\", body, {\n timeoutMs: SEARCH_TIMEOUT_MS,\n }).catch(() => null);\n // A failed search is asked once more: the topic searches are the slow ones, and when they\n // fail only the quick browses of any category's winners are left (dev, Oct 2026, under load).\n return ((await ask()) ?? (await ask()))?.results ?? null;\n },\n fit: (platform, adId) => fitReference(root, platform, adId, bet),\n ...(rankedFor\n ? {\n rank: async (found) => {\n const spent: ReviewUsage[] = [];\n try {\n return await rankForBet(\n found.filter((c) => !isOwnBrand(c.advertiser, brands)),\n rankedFor,\n undefined,\n (u) => spent.push(u),\n );\n } finally {\n await holdUnbilledSpend(path.join(root, \"canvas\", \".cache\"), spent).catch(() => undefined);\n }\n },\n choose: (fitting) => chooseLive(root, fitting, rankedFor),\n }\n : {}),\n };\n}\n\n/** The side-by-side pick over the live pictures, its spend held for the workspace's next bill. */\nasync function chooseLive(root: string, fitting: FittingReference[], rankedFor: RankedFor) {\n const options = (\n await Promise.all(\n fitting.map(async (f) => {\n const picture = await pictureOf(f.candidate.media_url);\n return picture\n ? [\n {\n adId: f.adId,\n picture,\n fit: f.fit,\n ...(f.candidate.advertiser ? { advertiser: f.candidate.advertiser } : {}),\n },\n ]\n : [];\n }),\n )\n ).flat();\n if (options.length < 2) return null;\n const spent: ReviewUsage[] = [];\n const picked = await pickAmong(\n options,\n rankedFor,\n askPickModel((u) => spent.push(u)),\n );\n await holdUnbilledSpend(path.join(root, \"canvas\", \".cache\"), spent).catch(() => undefined);\n if (!picked) return null;\n // The look saw only the options with a picture: its order, in the indices of every one that fit.\n const byAd = new Map(fitting.map((f, i) => [f.adId, i]));\n const order = picked.order.flatMap((i) => {\n const at = byAd.get(options[i]?.adId ?? \"\");\n return at === undefined ? [] : [at];\n });\n return { ...picked, order };\n}\n\n/**\n * The candidates of every search, the better search's first (every search runs at once), then in\n * the order they are ranked for the ad being made, when they are; the first FITS_TRIED.\n */\nasync function findCandidates(\n searches: Record<string, unknown>[],\n deps: ReferenceDeps,\n): Promise<Buildable[] | \"unavailable\"> {\n const results = await Promise.all(searches.map((search) => deps.search(search).catch(() => null)));\n // Every topic search failed: what is left is any category's winners, never a reference for this ad.\n const topics = searches.flatMap((search, i) => (search.free_text_query ? [results[i]] : []));\n if (topics.length > 0 && topics.every((found) => found === null)) return \"unavailable\";\n const pooled = pooledCandidates(\n results.map((found) => (found ?? []).flatMap(buildable)),\n deps.rank ? RANKED_POOL : FITS_TRIED,\n );\n const fresh = (found: Buildable[]) => (deps.taken ? freshReferencesFirst(found, deps.taken) : found);\n if (!deps.rank) return fresh(pooled);\n const ranked = await deps.rank(pooled).catch(() => pooled);\n return fresh(ranked.flatMap(buildable)).slice(0, FITS_TRIED);\n}\n\n/**\n * Search the idea's container and keep the best-ranked reference whose load-bearing parts we can\n * supply. Three fits run at once (a few cents each): one after another, one make took 109 s.\n */\n/**\n * What building on a reference started before its fit was known left behind: `prepared` when the\n * reference kept is the one built on, `discarded` (to wait for before building over it) when not.\n */\ntype Speculated<T> = { prepared?: Promise<T>; discarded?: Promise<T> };\n\n/** The reference a build starts on, as `prepare` is handed it before its fit is known. */\nexport type ReferenceCandidate = Pick<Picked, \"adId\" | \"platform\" | \"advertiserId\">;\n\nconst candidateOf = (c: Buildable): ReferenceCandidate => ({\n adId: String(c.ad_id),\n platform: c.platform,\n ...(c.advertiser_id ? { advertiserId: c.advertiser_id } : {}),\n});\n\nexport async function pickReference<T = never>(\n root: string,\n searches: Record<string, unknown>[],\n deps: ReferenceDeps = liveReferenceDeps(root),\n /**\n * Building on the best-ranked reference, started while the fits are asked: it is usually the one\n * kept, and its scaffold (a 35 s describe) then no longer waits ~25 s for them (dev, Oct 2026).\n */\n prepare?: (candidate: ReferenceCandidate, signal: AbortSignal) => Promise<T>,\n /** Aborted when the time for a reference is out: no reference is kept, and the build started is stopped. */\n within?: AbortSignal,\n): Promise<(Picked & Speculated<T>) | (Failure & Speculated<T>)> {\n const out = whenAborted(within);\n const found = await Promise.race([findCandidates(searches, deps), out]);\n if (found === \"out\") return slowReference();\n if (found === \"unavailable\") return searchUnavailable();\n const candidates = found.slice(0, FITS_TRIED);\n const first = candidates[0];\n // A build on a reference that is not kept is stopped, not waited for (dev: 50 s for nothing).\n const stop = new AbortController();\n const building = first && prepare ? prepare(candidateOf(first), stop.signal) : undefined;\n // A failed speculative build is never this pick's failure: the kept reference is built again.\n void building?.catch(() => undefined);\n // Three fits are asked at once, and one that does not fit asks the next; the best-ranked one that\n // fits is kept as soon as it and every better-ranked one have answered, never waiting on slower\n // fits below it. Once the pick is made, no further fit is asked.\n let settled = false;\n const asked: Promise<FitResult>[] = [];\n const askNext = () => {\n const index = asked.length;\n const candidate = candidates[index];\n if (settled || !candidate) return;\n asked.push(\n askFit(deps, candidate).then((fit) => {\n if (!(fit.ok && fitsIdea(fit.fit))) askNext();\n return fit;\n }),\n );\n };\n for (let slot = 0; slot < FITS_AT_ONCE; slot++) askNext();\n const deciding = deps.choose\n ? chosenFitting(candidates, asked, deps.choose, deps.taken)\n : firstFitting(candidates, asked);\n const kept = await Promise.race([deciding, out]);\n settled = true;\n if (kept === \"out\") {\n stop.abort();\n return { ...slowReference(), ...(building ? { discarded: building } : {}) };\n }\n if (kept.index !== 0) stop.abort();\n const speculated = building ? (kept.index === 0 ? { prepared: building } : { discarded: building }) : {};\n return { ...kept.picked, ...speculated };\n}\n\n/**\n * One candidate's fit, a throw read as a fit not made: it is handled when asked, since the fits\n * below the one awaited can fail while it is awaited.\n */\nconst askFit = (deps: ReferenceDeps, c: Buildable): Promise<FitResult> =>\n Promise.resolve()\n .then(() => deps.fit(c.platform, String(c.ad_id)))\n .catch((e): FitResult => ({ ok: false, error: { code: \"UNAVAILABLE\", message: String(e), fix: \"\" } }));\n\n/** Resolves \"out\" once `signal` aborts (never without one). */\nconst whenAborted = (signal: AbortSignal | undefined) =>\n new Promise<\"out\">((resolve) => {\n if (signal?.aborted) resolve(\"out\");\n signal?.addEventListener(\"abort\", () => resolve(\"out\"), { once: true });\n });\n\n/** The reference kept: its candidate, the fit that kept it, its rank and why it was preferred. Pure. */\nfunction pickedOf(candidate: Buildable, fit: FitAnswer, index: number, preferred?: string): Picked {\n const layers = fit.why_it_wins;\n return {\n ...candidateOf(candidate),\n why: [layers.disguise, layers.trigger, layers.logic].filter(Boolean).join(\"; \"),\n tried: index + 1,\n fit,\n ...(candidate.dna?.container ? { container: candidate.dna.container } : {}),\n ...(preferred ? { preferred } : {}),\n };\n}\n\n/** The best-ranked candidate whose fit keeps it, with its rank; else why none was kept (index -1). */\nasync function firstFitting(\n candidates: readonly Buildable[],\n fits: readonly Promise<FitResult>[],\n): Promise<{ picked: Picked | Failure; index: number }> {\n let unchecked: FitFailure | null = null;\n let checked = 0;\n const lacking: string[] = [];\n const answered: Array<FitResult | undefined> = [];\n for (const [index, candidate] of candidates.entries()) {\n const fit = await fits[index];\n answered.push(fit);\n if (!fit) continue;\n if (!fit.ok) unchecked = fit.error;\n else checked += 1;\n if (fit.ok && !fitsIdea(fit.fit)) lacking.push(...missingElements(fit.fit));\n if (!(fit.ok && fitsIdea(fit.fit))) continue;\n const passed = passedOver(candidates, answered);\n return { picked: { ...pickedOf(candidate, fit.fit, index), ...(passed.length > 0 ? { passed } : {}) }, index };\n }\n return { picked: noReference(candidates.length, checked, unchecked, lacking), index: -1 };\n}\n\n/** Every fit asked, once no more are being asked: a fit that does not fit asks the next. */\nasync function allFits(fits: Promise<FitResult>[]): Promise<FitResult[]> {\n let seen = -1;\n while (seen !== fits.length) {\n seen = fits.length;\n await Promise.all(fits);\n }\n return await Promise.all(fits);\n}\n\n/**\n * The reference the side-by-side look prefers among every one that fits, with its rank and why;\n * the best-ranked that fits when only one does or the look does not answer.\n */\nasync function chosenFitting(\n candidates: readonly Buildable[],\n fits: Promise<FitResult>[],\n choose: NonNullable<ReferenceDeps[\"choose\"]>,\n taken?: TakenReferences,\n): Promise<{ picked: Picked | Failure; index: number }> {\n const answered = await allFits(fits);\n const fitted = answered.flatMap((fit, index) => {\n const candidate = candidates[index];\n return candidate && fit.ok && fitsIdea(fit.fit) ? [{ index, candidate, fit: fit.fit }] : [];\n });\n // Another creative's reference is compared only when none of the others fit.\n const fresh = taken ? fitted.filter((f) => !isTakenReference(f.candidate, taken)) : [];\n const fitting = fresh.length > 0 ? fresh : fitted;\n if (fitting.length < 2) return await firstFitting(candidates, fits);\n const chosen = await choose(\n fitting.map((f) => ({ adId: String(f.candidate.ad_id), candidate: f.candidate, fit: f.fit })),\n ).catch(() => null);\n const kept = (chosen && fitting[chosen.order[0] ?? 0]) || fitting[0];\n if (!kept) return await firstFitting(candidates, fits);\n const ordered = chosen ? chosen.order.flatMap((i) => fitting[i] ?? []) : fitting;\n const passed = passedOver(candidates, answered);\n return {\n picked: {\n ...pickedOf(kept.candidate, kept.fit, kept.index, chosen?.why),\n board: [kept, ...ordered.filter((f) => f !== kept)].map((f) => boardAdOf(f.candidate)),\n ...(chosen?.takes ? { takes: chosen.takes } : {}),\n ...(chosen?.avoid ? { avoid: chosen.avoid } : {}),\n ...(passed.length > 0 ? { passed } : {}),\n },\n index: kept.index,\n };\n}\n\n/** A fitting candidate as the board shows it. Pure. */\nconst boardAdOf = (c: Buildable): BoardAd => ({\n adId: String(c.ad_id),\n ...(c.advertiser ? { advertiser: c.advertiser } : {}),\n ...(c.media_url ? { mediaUrl: c.media_url } : {}),\n});\n\n/** What the rejected references won on that we lack, each once, at most three. Pure. */\nconst lackingText = (lacking: readonly string[]) => {\n const named = [...new Set(lacking.map((l) => l.trim()).filter(Boolean))].slice(0, 3);\n return named.length > 0 ? ` (they won on ${named.join(\", \")})` : \"\";\n};\n\nconst searchUnavailable = (): Failure => ({\n code: \"REFERENCE_SEARCH_UNAVAILABLE\",\n message: \"The ads library could not search for this ad's category just now.\",\n fix: \"Nothing to do to go on: the ad starts from the idea rather than from another category's winners. To build on a proven ad, run make again in a few minutes.\",\n});\n\nconst slowReference = (): Failure => ({\n code: \"REFERENCE_SLOW\",\n message: `Finding and checking a proven ad took longer than ${REFERENCE_MS / 1000} s.`,\n fix: \"Nothing to do: the ad starts from the idea. To build on a proven ad anyway, run make again (the checks already made are kept) or pass --reference <adId>.\",\n});\n\n/**\n * Why no reference was kept: none found, none fits (naming what the ones checked won on that we\n * lack), or the fit could not be checked. Pure.\n */\nexport function noReference(\n found: number,\n checked: number,\n unchecked: { message: string } | null,\n lacking: readonly string[] = [],\n): Failure {\n if (found > 0 && checked === 0 && unchecked) {\n return {\n code: \"FIT_UNAVAILABLE\",\n message: `Could not check whether the references fit (${unchecked.message})`,\n fix: \"Run make again in a moment. To build now, pass --reference <adId> with one you looked at yourself (`baker winning-ads search`).\",\n };\n }\n return {\n code: \"NO_REFERENCE_FITS\",\n message:\n found === 0\n ? \"The library has no proven ad in this idea's format.\"\n : `None of the ${found} proven ads checked wins on something this company has, for a viewer who would stop for it${lackingText(lacking)}.`,\n fix: \"Nothing to do to go on: the ad starts from the idea. To build on a proven ad instead, pass --reference <adId> for one you looked at (`baker winning-ads search --format static` with what the company sells or who the ad is for). Do not stop the batch: build the other ideas.\",\n };\n}\n\n/**\n * Refused when the creative's ad is already written: building again would put the idea's\n * placeholders over it (dev, Oct 2026: a chat agent re-ran make on a re-formatted idea and lost the\n * ad it had shown). Nothing there, or a failed make's placeholders, lets the build go ahead. Pure.\n */\nexport function alreadyWritten(promptJson: unknown, slug: string, draft?: string): Failure | null {\n if (promptJson === null || promptJson === undefined) return null;\n // The draft make wrote, untouched: the ad is not written yet, so a rebuild (`--avatar`) loses nothing.\n if (draft !== undefined && sameJson(promptJson, draft)) return null;\n try {\n if (unwrittenProblems(readAdSpec(promptJson)).length > 0) return null;\n } catch {\n // Unreadable is still someone's work: refuse rather than overwrite it.\n }\n return {\n code: \"ALREADY_MADE\",\n message: `\"${slug}\" is already made and its ad is written: building it again would replace that ad with placeholders.`,\n fix: `To change this ad, edit src/creatives/${slug}/prompt.json and run \\`baker canvas run\\` on it. For another ad of the same idea, run make again with --slug <new-slug>.`,\n };\n}\n\n/** Whether a parsed spec is the JSON text given, whatever its spacing. Pure. */\nfunction sameJson(parsed: unknown, text: string): boolean {\n try {\n return JSON.stringify(parsed) === JSON.stringify(JSON.parse(text));\n } catch {\n return false;\n }\n}\n\n/** Where make keeps the prompt.json it wrote, to know whether anyone has written the ad since (never committed). */\nconst draftPath = (root: string, slug: string) => path.join(root, \"canvas\", \".cache\", \"make-drafts\", `${slug}.json`);\n\ntype MakeArgs = {\n slug?: string;\n adset?: string;\n reference?: string;\n /** The library `--reference` is in (`--reference-platform`). */\n referencePlatform?: string;\n /** Where the ad runs (`--platforms`), the main platform first. */\n platforms?: string;\n /** Exactly the sizes to make (`--formats`). */\n formats?: string;\n spec?: string;\n /** The lead ad of the series this idea is made in (`--series`). */\n series?: string;\n fromIdea?: boolean;\n /** The Avatars the ad's people are cast as (`--avatar`). */\n avatar?: string;\n};\n\n/**\n * The proven ad a re-cast rebuilds on: the one the creative is built on, never a new search, when\n * make runs again with `--avatar` and no other reference. Null otherwise. Pure.\n */\nexport function castRebuild(\n definition: string | null,\n args: Pick<MakeArgs, \"avatar\" | \"reference\" | \"fromIdea\">,\n): { adId: string; platform: string } | null {\n if (!definition || !args.avatar || args.reference || args.fromIdea) return null;\n const { sourceAdId, sourcePlatform } = parseDefinitionSourceFields(definition);\n return sourceAdId ? { adId: sourceAdId, platform: sourcePlatform ?? \"meta\" } : null;\n}\n\n/**\n * True when `make --avatar` re-casts a creative that was built from its idea (its definition names\n * no proven ad): it is rebuilt from the idea, never given a proven ad found by a new search. Pure.\n */\nexport function ideaRecast(\n definition: string | null,\n args: Pick<MakeArgs, \"avatar\" | \"reference\" | \"fromIdea\">,\n): boolean {\n if (!definition || !args.avatar || args.reference || args.fromIdea) return false;\n return !parseDefinitionSourceFields(definition).sourceAdId;\n}\n\n/** The scaffold's cast flags for the Avatars a definition or `--avatar` names (`@eduard, @lucia`). Pure. */\nexport function castFlags(avatar: string | undefined): string[] {\n const handles = (avatar ?? \"\")\n .split(/[\\s,]+/)\n .map((h) => h.replace(/^@/, \"\").toLowerCase())\n .filter(Boolean);\n return handles.length > 0 ? [\"--avatar\", handles.join(\",\")] : [];\n}\n\nconst flag = (value: unknown): string | undefined => (typeof value === \"string\" && value ? value : undefined);\n\n/** The idea, checked: refused when unreadable, missing, or with a problem `creatives ideas` names. */\nasync function loadIdea(root: string, ideaId: string) {\n const { ideas, unreadable } = await readIdeas(root);\n const bad = unreadable.find((u) => u.id === ideaId);\n if (bad) {\n fail({\n code: \"INVALID_IDEA\",\n message: bad.problems.join(\"; \"),\n fix: `Fix ${IDEAS_DIR}/${ideaId}.md, then run make again.`,\n });\n }\n const idea = ideas.find((i) => i.id === ideaId);\n if (!idea) {\n fail({\n code: \"NOT_FOUND\",\n message: `No idea \"${ideaId}\" in ${IDEAS_DIR}/.`,\n fix: `Ideas on file: ${ideas.map((i) => i.id).join(\", \") || \"none\"}. Write it there first.`,\n });\n }\n const [insights, knowledge, personas, creatives] = await Promise.all([\n readInsights(root),\n readKnowledgeCorpus(root),\n readPersonaIds(root),\n readCreativeRecords(root),\n ]);\n const check = checkIdeas({ ideas, insights, knowledge, personas, ...coverageOf(ideas, creatives) }).find(\n (c) => c.id === idea.id,\n );\n if (check && check.problems.length > 0) {\n fail({\n code: \"IDEA_HAS_PROBLEMS\",\n message: check.problems.join(\"; \"),\n fix: \"Fix the idea file and run `baker creatives ideas` again.\",\n });\n }\n return { idea, check };\n}\n\ntype Scaffolded = {\n scaffold: Record<string, unknown>;\n reference: Picked | null;\n fromIdea?: string;\n /** Why the kept reference's concept could not be seeded: the render does not see it yet. */\n conceptUnseeded?: string;\n};\n\n/** Scaffold the creative: a video from its beats, a static from a reference that fits. */\nasync function scaffoldIdea(\n root: string,\n idea: Idea,\n args: MakeArgs,\n slug: string,\n temperature: ViewerTemperature,\n whereFlags: string[],\n): Promise<Scaffolded> {\n const viewerFlags = [\n ...(args.adset ? [\"--target-adset\", args.adset] : [\"--viewer-temperature\", temperature]),\n ...whereFlags,\n ];\n if (isVideoIdea(idea)) {\n if (!args.spec) {\n fail({\n code: \"SPEC_REQUIRED\",\n message: `\"${idea.id}\" is a video idea (${idea.format}): it is built from its beats.`,\n fix: `Write the beats spec (one spoken line plus one shot each; references/video-flow.md), message first, then: baker creatives make ${idea.id} --spec <file>.`,\n });\n }\n return {\n scaffold: await baker([\"canvas\", \"scaffold-ad\", \"--spec\", args.spec, \"--slug\", slug, ...viewerFlags]),\n reference: null,\n };\n }\n return await scaffoldStatic(root, idea, args, slug, temperature, [...viewerFlags, ...castFlags(args.avatar)]);\n}\n\ntype Chosen = Awaited<ReturnType<typeof pickReference<Record<string, unknown>>>>;\n\n/**\n * A proven ad named by hand (`--reference`, or the one a re-cast rebuilds on) with the fit made of\n * it for this ad (cached: free), so its thinking names what stops the scroll and the proof and asks\n * what of ours carries each, as for one make found. Built on unchecked when no fit can be made; an\n * unknown platform refused.\n */\nexport async function checkedByHand(\n adId: string,\n platform: string | undefined,\n deps: Pick<ReferenceDeps, \"fit\">,\n): Promise<Picked | Failure> {\n const byHand = handPickedReference(adId, platform);\n if (\"code\" in byHand) return byHand;\n const fit = await deps.fit(byHand.platform, byHand.adId).catch(() => null);\n if (!fit?.ok) return byHand;\n if (!fitsIdea(fit.fit)) {\n return {\n code: \"REFERENCE_UNFIT\",\n message: `The proven ad ${adId} does not fit this idea: ${whyUnfit(fit.fit)}.`,\n fix: \"Pick another proven ad (`baker winning-ads search`), or run make without --reference to build from the idea.\",\n };\n }\n const layers = fit.fit.why_it_wins;\n return { ...byHand, why: [layers.disguise, layers.trigger, layers.logic].filter(Boolean).join(\"; \"), fit: fit.fit };\n}\n\n/** The reference passed by hand, checked (an unknown platform refused), none when asked to start from the idea, else `pick`'s. */\nasync function chooseReference(args: MakeArgs, deps: ReferenceDeps, pick: () => Promise<Chosen>): Promise<Chosen> {\n if (args.reference) {\n const byHand = await checkedByHand(args.reference, args.referencePlatform, deps);\n if (\"code\" in byHand) fail(byHand);\n return byHand;\n }\n if (args.fromIdea) return { code: \"FROM_IDEA\", message: \"Asked to start from the idea.\" };\n return await pick();\n}\n\n/** Where this idea's reference is looked for, and the brief it is ranked by: the company's reading, its rules, the idea's persona. */\nasync function referenceTarget(root: string, idea: Idea) {\n const market = marketFromCompanyDoc(await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => \"\"));\n const personas = await readPersonas(root).catch(() => []);\n const [found, company, context] = await Promise.all([\n referenceBriefFor(root, { message: idea.message, who: personaWho(idea, personas) }),\n readCompanyReading(root),\n readCreativeContext(root, { kind: \"static\" }),\n ]);\n // What the brand never does is its rules, never a model's guess at them.\n const brief = found && { ...found, avoid: avoidOf(context.rules) };\n const category = company?.category ?? company?.sells;\n const where = referenceWhereOf(brief, {\n ...(market && market.country !== \"global\" ? { country: market.country } : {}),\n ...(category ? { category } : {}),\n audience: audienceQuery(idea, personas),\n });\n return { market, personas, brief, where };\n}\n\n/** The proven ads, and their brands, every creative of the workspace but `slug` is built on. */\nasync function takenReferencesIn(root: string, slug: string): Promise<TakenReferences> {\n const creatives = path.join(root, \"src\", \"creatives\");\n const names = await readdir(creatives).catch(() => []);\n const sources = await Promise.all(\n names\n .filter((name) => name !== slug && !name.startsWith(\"_\"))\n .map((name) =>\n readFile(path.join(creatives, name, \"_definition.md\"), \"utf8\").then(\n parseDefinitionSourceFields,\n (): DefinitionSourceFields => ({}),\n ),\n ),\n );\n return {\n adIds: new Set(sources.flatMap((s) => (s.sourceAdId ? [s.sourceAdId] : []))),\n advertiserIds: new Set(sources.flatMap((s) => (s.sourceAdvertiserId ? [s.sourceAdvertiserId] : []))),\n };\n}\n\n/** A static from a reference that fits, found within `REFERENCE_MS`; else from the idea itself. */\nasync function scaffoldStatic(\n root: string,\n idea: Idea,\n args: MakeArgs,\n slug: string,\n temperature: ViewerTemperature,\n viewerFlags: string[],\n): Promise<Scaffolded> {\n const onReference = (c: ReferenceCandidate, signal?: AbortSignal) =>\n baker(\n [\n \"canvas\",\n \"scaffold-static-ad\",\n \"--source-ad-id\",\n c.adId,\n \"--source-platform\",\n c.platform,\n ...(c.advertiserId ? [\"--source-advertiser-id\", c.advertiserId] : []),\n \"--slug\",\n slug,\n \"--title\",\n idea.message.slice(0, 120),\n ...viewerFlags,\n ],\n signal,\n );\n // Built on the best-ranked reference while the fits are asked, only into a new creative: a build\n // that is not kept is then removed whole, leaving nothing of that reference on the creative.\n const dir = path.join(root, \"src\", \"creatives\", slug);\n const fresh = !(await stat(dir).catch(() => null));\n // A reference found by make has its time: past it, the ad starts from the idea (`REFERENCE_MS`).\n const budget = AbortSignal.timeout(REFERENCE_MS);\n const { market, personas, brief, where } = await referenceTarget(root, idea);\n const bet = fitBetOf(\n idea,\n personas,\n await readInsights(root).catch(() => []),\n market ? describeMarket(market) : undefined,\n );\n const deps = {\n ...liveReferenceDeps(root, bet, rankedForOf(brief, where, bet), brief?.brands),\n taken: await takenReferencesIn(root, slug),\n };\n const definition = await readFile(path.join(dir, \"_definition.md\"), \"utf8\").catch(() => null);\n const recast = castRebuild(definition, args);\n const fromIdea = args.fromIdea || ideaRecast(definition, args);\n const reference = await chooseReference({ ...args, fromIdea }, deps, async () => {\n if (recast) {\n const kept = await checkedByHand(recast.adId, recast.platform, deps);\n if (\"code\" in kept) fail(kept);\n return kept;\n }\n return await pickReference(\n root,\n referenceSearchesFor(idea, temperature, where).map(buildSearchBody),\n deps,\n fresh ? (c, signal) => onReference(c, AbortSignal.any([signal, budget])) : undefined,\n budget,\n );\n });\n if (\"discarded\" in reference && reference.discarded) {\n await reference.discarded.catch(() => undefined);\n await rm(dir, { recursive: true, force: true });\n }\n if (\"code\" in reference) {\n return { scaffold: await scaffoldFromIdea(idea, slug, viewerFlags), reference: null, fromIdea: reference.message };\n }\n const prepared = \"prepared\" in reference ? await reference.prepared?.catch(() => null) : null;\n if (prepared?.ok !== true && budget.aborted && !args.reference) {\n await rm(dir, { recursive: true, force: true });\n const slow = slowReference().message;\n return { scaffold: await scaffoldFromIdea(idea, slug, viewerFlags), reference: null, fromIdea: slow };\n }\n const scaffold = prepared?.ok === true ? prepared : await onReference(reference);\n // An Avatar the scaffold refused is the agent's to fix, never a reason to leave the proven ad.\n if (scaffold.ok !== true && (scaffold.error as { code?: unknown } | undefined)?.code === \"avatar\") {\n fail(scaffoldFailure(scaffold));\n }\n const unbuilt = unbuiltReference(scaffold, { adId: reference.adId, byHand: Boolean(args.reference || recast) });\n if (!unbuilt) return await withKeptConcept(dir, slug, scaffold, reference);\n // What the failed build left of a new creative goes, so the idea's build starts clean.\n if (fresh) await rm(dir, { recursive: true, force: true });\n return { scaffold: await scaffoldFromIdea(idea, slug, viewerFlags), reference: null, fromIdea: unbuilt };\n}\n\n/** The reference passed with `--reference`, on its `--platform` (default meta); an unknown platform is refused. Pure. */\nexport function handPickedReference(adId: string, platform: string | undefined): Picked | Failure {\n const resolved = resolveSourcePlatform(platform);\n if (!resolved.ok) {\n return {\n code: \"INVALID_ARGUMENT\",\n message: resolved.message.replace(\"--source-platform\", \"--platform\"),\n fix: \"Pass the platform `baker winning-ads search` names beside the ad.\",\n };\n }\n return { adId, platform: resolved.platform, why: \"chosen by hand\", tried: 0 };\n}\n\n/**\n * Why the ad starts from the idea when the proven ad make picked could not be built on (its picture\n * not described, dev Oct 2026: twice running for one ad), else null: a build that went through, or a\n * reference chosen by hand, whose failure is the agent's to see. Pure.\n */\nexport function unbuiltReference(\n scaffold: Record<string, unknown>,\n reference: { adId: string; byHand: boolean },\n): string | null {\n if (scaffold.ok === true || reference.byHand) return null;\n return `The proven ad ${reference.adId} could not be read to build on.`;\n}\n\n/** The creative built on a reference, its fit's concept seeded, else why it could not be. */\nasync function withKeptConcept(\n dir: string,\n slug: string,\n scaffold: Record<string, unknown>,\n reference: Picked,\n): Promise<Scaffolded> {\n if (scaffold.ok !== true || !reference.fit) return { scaffold, reference };\n const unseeded = await seedConcept(dir, slug, conceptFromFit(reference.fit, reference.adId));\n return { scaffold, reference, ...(unseeded ? { conceptUnseeded: unseeded } : {}) };\n}\n\n/**\n * Seed the kept reference's concept into a creative built before its fit answered, and compile the\n * canvas from it: the render then sees the reference at the level that won (`concept.carry`).\n * Dev, Oct 2026: every build started on the best-ranked reference had no concept. Why it could not\n * be seeded, else null.\n */\nexport async function seedConcept(dir: string, slug: string, seeded: Record<string, unknown>): Promise<string | null> {\n const promptPath = path.join(dir, \"prompt.json\");\n const canvasPath = path.join(dir, `${slug}.canvas.json`);\n let prompt: string;\n try {\n prompt = withFitConcept(await readFile(promptPath, \"utf8\"), seeded);\n await writeFile(promptPath, prompt, \"utf8\");\n } catch (e) {\n return `prompt.json could not take the proven ad's concept (${e instanceof Error ? e.message : String(e)})`;\n }\n try {\n const spec: unknown = JSON.parse(prompt);\n // What the ad keeps of the proven ad decides its shape: a designed one is laid out again for each size.\n const { canvas, rerouted } = reroutedOnSpec(JSON.parse(await readFile(canvasPath, \"utf8\")), spec);\n // A picture of the one-picture shape is briefed apart from the rest (`projectFormatBriefs`).\n const briefed =\n projectStaticBriefs(canvas, spec) + projectAdaptBriefs(canvas, spec) + projectFormatBriefs(canvas, spec);\n if (rerouted || briefed > 0) {\n await writeFile(canvasPath, `${JSON.stringify(canvas, null, 2)}\\n`, \"utf8\");\n }\n } catch {\n // prompt.json holds the concept: the run compiles the canvas from it.\n }\n return null;\n}\n\n/** The static started from the idea's own spec: no reference picture, nothing described or billed. */\nasync function scaffoldFromIdea(idea: Idea, slug: string, viewerFlags: string[]): Promise<Record<string, unknown>> {\n const dir = await mkdtemp(path.join(tmpdir(), \"idea-spec-\"));\n const specPath = path.join(dir, \"prompt.json\");\n await writeFile(specPath, JSON.stringify(ideaSpec(idea, idea.who.replace(/[-_]/g, \" \")), null, 2), \"utf8\");\n try {\n return await baker([\n \"canvas\",\n \"scaffold-static-ad\",\n \"--spec\",\n specPath,\n \"--slug\",\n slug,\n \"--title\",\n idea.message.slice(0, 120),\n ...viewerFlags,\n ]);\n } finally {\n await rm(dir, { recursive: true, force: true });\n }\n}\n\n/** The address of the proven ad a canvas keeps as its `original` node; null on a canvas built from the idea. Pure. */\nexport function referencePictureUrl(canvas: unknown): string | null {\n const nodes = (canvas as { nodes?: unknown } | null)?.nodes;\n if (!Array.isArray(nodes)) return null;\n const original = nodes.find(\n (n): n is { id: string; params?: { url?: unknown } } => (n as { id?: unknown })?.id === \"original\",\n );\n const url = original?.params?.url;\n return typeof url === \"string\" && /^https?:\\/\\//.test(url) ? url : null;\n}\n\n/**\n * Save the proven ad's picture under canvas/references/ (never committed), so the agent looks at\n * the ad itself before it says why it won. Its workspace-relative path, or null when it could not\n * be fetched: the outline then says where to find it.\n */\nasync function saveReferencePicture(root: string, canvasPath: string, adId: string): Promise<string | null> {\n const url = await readFile(canvasPath, \"utf8\").then(\n (text) => referencePictureUrl(JSON.parse(text)),\n () => null,\n );\n return url ? await savePicture(root, url, adId) : null;\n}\n\n/** Save one proven ad's picture under canvas/references/; its workspace-relative path, or null. */\nasync function savePicture(root: string, url: string, adId: string): Promise<string | null> {\n try {\n const response = await fetch(url, { signal: AbortSignal.timeout(20_000) });\n if (!response.ok) return null;\n const ext = path.extname(new URL(url).pathname).toLowerCase() || \".jpg\";\n const relative = path.join(\"canvas\", \"references\", `${adId}${ext}`);\n await mkdir(path.join(root, \"canvas\", \"references\"), { recursive: true });\n await writeFile(path.join(root, relative), Buffer.from(await response.arrayBuffer()));\n return relative;\n } catch {\n return null;\n }\n}\n\n/** The kept reference with its picture, and every ad of its board with theirs, saved for the agent to open. */\nasync function withPictures(root: string, canvasPath: string, reference: Picked) {\n const picture = await saveReferencePicture(root, canvasPath, reference.adId);\n const board = reference.board ? await savedBoard(root, reference.board, reference.adId, picture) : undefined;\n return { ...reference, ...(picture ? { picture } : {}), ...(board ? { board } : {}) };\n}\n\n/** The board with each picture saved (the kept ad's already is), for the agent to open. */\nasync function savedBoard(root: string, board: readonly BoardAd[], keptId: string, keptPicture: string | null) {\n return await Promise.all(\n board.map(async ({ adId, advertiser, mediaUrl }) => {\n const picture = adId === keptId ? keptPicture : mediaUrl ? await savePicture(root, mediaUrl, adId) : null;\n return { adId, ...(advertiser ? { advertiser } : {}), ...(picture ? { picture } : {}) };\n }),\n );\n}\n\n/** Record the idea on the creative, outline the thinking it is made from, and set its message as the ad's one message; mark the idea built. */\nasync function recordIdea(\n root: string,\n slug: string,\n idea: Idea,\n evidence: EvidenceLevel | \"explore\",\n reference: Picked | null,\n): Promise<{ dir: string; unsourcedCopy: string[] }> {\n const dir = path.join(root, \"src\", \"creatives\", slug);\n const definitionPath = path.join(dir, \"_definition.md\");\n const definition = await readFile(definitionPath, \"utf8\").catch(() => null);\n if (definition !== null) {\n const recorded = setDefinitionFields(definition, { ...definitionFieldsOf(idea, evidence) });\n const thinkingReference = reference\n ? await withPictures(root, path.join(dir, `${slug}.canvas.json`), reference)\n : null;\n const inventory = await castInventory(root, idea.message, await companyName(root));\n // The company's rules on who appears, what shows and its logo, as they stand now: the cast is decided under them.\n const castRules = (\n await readCreativeContext(root, { kind: idea.format.startsWith(\"video_\") ? \"video\" : \"static\" })\n ).rules\n .filter((r) => r.applies === \"cast\" || r.applies === \"picture\" || r.applies === \"logo\")\n .map((r) => ({ id: r.id, strength: r.strength, text: r.text }));\n const audience = memeRegister(await readCompanyReading(root).catch(() => null));\n await writeFile(\n definitionPath,\n withThinking(\n recorded,\n thinkingOutline({\n idea,\n reference: thinkingReference,\n inventory,\n rules: castRules,\n ...(audience ? { audience } : {}),\n }),\n ),\n \"utf8\",\n );\n }\n const promptPath = path.join(dir, \"prompt.json\");\n const prompt = isVideoIdea(idea) ? null : await readFile(promptPath, \"utf8\").catch(() => null);\n // A spec that does not parse is the scaffold's to report; the message is set by hand then.\n if (prompt !== null) {\n const personas = await readPersonas(root).catch(() => []);\n const written = (() => {\n try {\n return setSpecViewer(setSpecMessage(prompt, idea.message), idea, personas);\n } catch {\n return null;\n }\n })();\n if (written !== null) await writeFile(promptPath, written, \"utf8\").catch(() => undefined);\n }\n const unsourcedCopy = prompt === null ? [] : await draftedClaims(root, prompt);\n await keepDraft(root, slug, promptPath);\n if (idea.status === \"idea\") {\n const ideaPath = path.join(root, IDEAS_DIR, `${idea.id}.md`);\n await writeFile(ideaPath, setDefinitionFields(await readFile(ideaPath, \"utf8\"), { status: \"built\" }), \"utf8\");\n }\n // The dashboard learns the idea now, not at Publish (where most verdicts are given already).\n await baker([\"canvas\", \"sync-definition\", dir]);\n return { dir, unsourcedCopy };\n}\n\n/** Keep the prompt.json make leaves, so a later make knows the ad is still its draft. */\nasync function keepDraft(root: string, slug: string, promptPath: string): Promise<void> {\n const written = await readFile(promptPath, \"utf8\").catch(() => null);\n if (written === null) return;\n await mkdir(path.dirname(draftPath(root, slug)), { recursive: true });\n await writeFile(draftPath(root, slug), written, \"utf8\");\n}\n\n/** The drafted lines claiming what neither the Knowledge nor our own customers said. */\nasync function draftedClaims(root: string, prompt: string): Promise<string[]> {\n const [knowledge, insights] = await Promise.all([readKnowledgeCorpus(root), readInsights(root)]);\n const own = insights.filter(sourcesClaims).map((i) => i.quote);\n try {\n return unsourcedCopyLines(prompt, `${knowledge}\\n${own.join(\"\\n\")}`);\n } catch {\n return [];\n }\n}\n\n/**\n * make's flags. `--platform` once named the reference's library, and agents read it as where the\n * ad runs: beside `--reference` it still means the library, alone it is refused. Pure.\n */\nexport function makeArgsOf(args: Record<string, unknown>): MakeArgs | Failure {\n const opts: MakeArgs = {};\n for (const key of [\"slug\", \"adset\", \"reference\", \"platforms\", \"formats\", \"spec\", \"series\", \"avatar\"] as const) {\n const value = flag(args[key]);\n if (value) opts[key] = value;\n }\n const referencePlatform = flag(args[\"reference-platform\"]) ?? (opts.reference ? flag(args.platform) : undefined);\n if (referencePlatform) opts.referencePlatform = referencePlatform;\n if (flag(args.platform) && !opts.reference) {\n return {\n code: \"INVALID_ARGUMENT\",\n message: `--platform ${flag(args.platform)} is ambiguous: it named the library of --reference.`,\n fix: \"--platforms says where the ad runs (baker creatives make <idea> --platforms linkedin); --reference-platform says which library the reference is in.\",\n };\n }\n if (args[\"from-idea\"] === true) opts.fromIdea = true;\n return opts;\n}\n\n/** Where the ad runs as the scaffold's flags: the platforms, and the sizes only when they were asked for. Pure. */\nexport function deliveryFlags(\n delivery: { platforms: readonly string[] },\n args: Pick<MakeArgs, \"formats\">,\n kind: \"static\" | \"video\" = \"static\",\n): string[] {\n const sizes = args.formats && kind === \"static\" ? [\"--formats\", args.formats] : [];\n return [\"--platforms\", delivery.platforms.join(\",\"), ...sizes];\n}\n\nfunction scaffoldFailure(scaffold: Record<string, unknown>): Failure {\n const error = (scaffold.error ?? {}) as Partial<Failure>;\n return {\n code: error.code ?? \"SCAFFOLD_FAILED\",\n message: error.message ?? \"The creative could not be scaffolded.\",\n ...(error.fix ? { fix: error.fix } : {}),\n };\n}\n\ntype Made = {\n slug: string;\n idea: Idea;\n check: IdeaCheck | undefined;\n reference: Picked | null;\n /** Why the static starts from the idea itself: no proven ad fits (or `--from-idea`). */\n fromIdea?: string;\n conceptUnseeded?: string;\n viewer: { adset: string } | { temperature: ViewerTemperature };\n canvasPath: string;\n scaffoldHints: string[];\n /** Drafted copy lines claiming a figure the company never wrote (often the reference's own promise). */\n unsourcedCopy: string[];\n /** Where the ad runs and the size designed first; absent for a video with no platform said. */\n delivery?: { platforms: readonly string[]; lead: string };\n /** How a static's sizes are made (cut from one picture, or laid out again) and why (`staticShapeFor`). */\n shape?: { shape: string; reason: string };\n};\n\nconst CARRY_WORDS: Record<ConceptCarry, string> = {\n whole_ad: \"the whole ad (its disguise, layout and hook)\",\n layout: \"its layout\",\n hook: \"its hook\",\n angle: \"its angle\",\n};\n\n/** What the agent tells the person about the proven ad a creative is built on. Pure. */\nfunction builtOnHint(reference: Picked): string {\n const tell = \"Tell the person which proven ad this builds on\";\n const ours = \"the words, brand, people and claims stay ours.\";\n if (!reference.fit) {\n // Chosen by hand: no fit read what made it win, so nothing is said of it.\n return `Built on proven ad ${reference.adId}, the one chosen for it; no check read what made it win. The canvas shows that ad as \\`original\\`. ${tell}; ${ours}`;\n }\n const carried = CARRY_WORDS[reference.fit.carry ?? \"whole_ad\"];\n const why = reference.fit.carry_why ? ` (${reference.fit.carry_why})` : \"\";\n const won = reference.why ? ` It won on: ${reference.why}.` : \"\";\n const chosen = reference.preferred\n ? ` Chosen over the other proven ads that fit because ${reference.preferred.replace(/\\.$/, \"\")}.`\n : \"\";\n const passed = (reference.passed ?? [])\n .map(\n (p) =>\n ` Passed over ${p.advertiser ? `${p.advertiser}'s proven ad` : \"proven ad\"} ${p.adId}: ${p.why.replace(/\\.$/, \"\")}.`,\n )\n .join(\"\");\n const whyNot = passed ? \", and in one line why not the ones passed over\" : \"\";\n // Named by hand (`--reference`, or the one a re-cast keeps): checked, never searched for.\n const byHand = reference.tried === 0 ? \", the one chosen for it\" : \"\";\n return `Built on proven ad ${reference.adId}${byHand}: it carries ${carried}${why}.${won}${chosen}${passed} The canvas shows that ad as \\`original\\`. ${tell} and what it takes from it${whyNot}; ${ours}`;\n}\n\n/** The fix for a concept make could not seed: the fit already made, written in by hand. Pure. */\nconst unseededHint = (reference: Picked, slug: string, why: string) =>\n `${why}, so the render does not see proven ad ${reference.adId} yet. \\`baker winning-ads fit ${reference.adId} --platform ${reference.platform} --full\\` prints the check already made (free): write its \\`read\\` into src/creatives/${slug}/prompt.json as \\`concept\\`, with \\`reference_ad_id: \"${reference.adId}\"\\`.`;\n\n/** The step before any word of the ad: answer the definition's thinking `make` outlined. Pure. */\nfunction thinkFirstHint(made: Made): string {\n const basis = made.reference ? \"what the proven ad is and why it won\" : \"why this bet should work\";\n const board =\n (made.reference?.board?.length ?? 0) > 1\n ? \" what to take from which of the proven ads that fit (the hook of one, the proof of another),\"\n : \"\";\n const survives = made.reference ? \" what of it must survive,\" : \"\";\n const read = made.reference\n ? \"first open the proven ads' pictures the outline names and read .claude/skills/creative-canvas-ads/references/reading-a-winner.md, then \"\n : \"\";\n // Only a creative built on a proven ad is re-cast on it; one built from its idea has nothing to keep.\n const recast = made.reference\n ? ` When the cast is an Avatar the canvas was not built with, \\`baker creatives make ${made.idea.id}${made.slug === made.idea.id ? \"\" : ` --slug ${made.slug}`} --avatar <handle>\\` rebuilds it on the same proven ad before you write prompt.json.`\n : \"\";\n return `Think first: ${read}answer every question under \"Thinking\" in src/creatives/${made.slug}/_definition.md before you touch prompt.json (how: .claude/skills/creative-canvas-ads/references/creative-intent.md): ${basis},${board} whether it fits our viewer, our hook, who appears and what of the product shows (decided from what the company has, listed there: its Avatars, real customers, founder, product pictures, logos),${survives} and the plan.${recast} This thinking decides the ad; the run renders nothing while a question is open or the cast is not ours.`;\n}\n\n/** The ad written from the definition's plan, in the files the render reads. Pure. */\nfunction writeTheAdHint(made: Made, quote: string | undefined): string {\n const words = `say the message in the customer's words${quote ? ` (\"${quote.slice(0, 80)}\")` : \"\"}; keep \\`message\\` as it is`;\n if (made.idea.format.startsWith(\"video_\")) {\n return `Then write the ad from \"The plan\": its scene files and prompt.json carry every decision (the render never reads the definition); ${words}.`;\n }\n const drafted = made.reference\n ? \" The drafted lines are the reference's: keep one only if the Knowledge says it (badges, ratings and guarantees too).\"\n : \"\";\n return `Then write the ad from \"The plan\" in src/creatives/${made.slug}/prompt.json, every decision in its fields (the render never reads the definition); ${words}.${drafted} Read static-image-flow.md first. Inspect existing Avatars before creating an actor. Keep interfaces native and requested overlays separate. Preserve plausible anatomy, device proportions, scale, perspective and support; reflow text rather than distort it. Honour the requested sizes.`;\n}\n\n/** What `make` prints: the creative, the idea it carries, and the two steps left to the agent. Pure. */\nexport function makeEnvelope(made: Made) {\n const quote = made.check?.quote;\n return {\n ok: true as const,\n data: {\n creative: made.slug,\n idea: made.idea.id,\n message: made.idea.message,\n evidence: made.check?.evidence ?? \"explore\",\n ...(quote ? { customer_quote: quote } : {}),\n ...(made.fromIdea ? { built_from: \"idea\" } : {}),\n ...(made.reference\n ? {\n reference: {\n ad_id: made.reference.adId,\n platform: made.reference.platform,\n why_it_wins: made.reference.why,\n ...(made.reference.fit?.carry ? { carry: made.reference.fit.carry } : {}),\n ...(made.reference.preferred ? { chosen_because: made.reference.preferred } : {}),\n },\n }\n : {}),\n viewer: made.viewer,\n ...(made.delivery ? { platforms: made.delivery.platforms, lead: made.delivery.lead } : {}),\n ...(made.shape ? { master_shape: made.shape } : {}),\n canvas_path: made.canvasPath,\n },\n hints: [\n ...(made.reference ? [builtOnHint(made.reference)] : []),\n ...(made.reference && made.conceptUnseeded\n ? [unseededHint(made.reference, made.slug, made.conceptUnseeded)]\n : []),\n ...(made.fromIdea\n ? [\n `${made.fromIdea} So this ad starts from the idea: write the scene and every line of copy in src/creatives/${made.slug}/prompt.json (a placeholder refuses to run). Tell the person this ad is not built on a proven ad, and why, in plain words.`,\n ]\n : []),\n ...(made.unsourcedCopy.length > 0\n ? [\n `Rewrite before running: ${made.unsourcedCopy.map((l) => JSON.stringify(l)).join(\", \")} claim a figure nothing the company wrote holds (the reference's promise, not ours).`,\n ]\n : []),\n thinkFirstHint(made),\n writeTheAdHint(made, quote),\n SPEC_SHAPES_HINT,\n `Then: baker canvas run ${made.canvasPath} (it validates and asks the viewer itself: nothing to run before it).`,\n // The scaffold's own next steps name a separate validate; the run does it (dev, Oct 2026: five validates before one run).\n ...made.scaffoldHints\n .filter((h) => !/canvas (?:validate|viewer-check)/.test(h))\n // make checked the reference and seeded its concept: the scaffold ran before the fit answered.\n .filter((h) => !(made.reference?.fit && h.startsWith(NO_FIT_HINT)))\n .slice(0, 4),\n ],\n };\n}\n\n/** Where the idea's ads run: its `platforms`, else the one platform its own words name. Pure. */\nexport function ideaPlatforms(idea: Idea): string[] | undefined {\n if (idea.platforms && idea.platforms.length > 0) return idea.platforms;\n const named = platformsNamedIn([idea.message, idea.who, idea.why, idea.format].join(\" \"));\n return named.length > 0 ? named : undefined;\n}\n\n/**\n * Where the ad runs: `--platforms`, else the creative's definition (with the sizes it records),\n * else the idea's, else its Meta ad set. A static with none is refused (the fix says where to take it from); a video's sizes do\n * not follow from it, so a video with none is made without.\n */\nasync function makeDelivery(\n root: string,\n idea: Idea,\n args: MakeArgs,\n slug: string,\n): Promise<{ delivery?: ResolvedDelivery; flags: string[] }> {\n const definition = await readFile(path.join(root, \"src\", \"creatives\", slug, \"_definition.md\"), \"utf8\").catch(\n () => null,\n );\n const flags = { platforms: args.platforms, formats: args.formats, \"target-adset\": args.adset };\n const resolved = await scaffoldDelivery(flags, definition, ideaPlatforms(idea));\n const video = isVideoIdea(idea);\n if (resolved.ok)\n return { delivery: resolved.delivery, flags: deliveryFlags(resolved.delivery, args, video ? \"video\" : \"static\") };\n if (video && resolved.error.code === \"platform_required\") return { flags: [] };\n return fail({ code: resolved.error.code.toUpperCase(), message: resolved.error.message, fix: resolved.error.fix });\n}\n\n/** `--series <lead>`: the idea made as another ad of the lead's series, printed or refused. */\nasync function makeInSeries(\n root: string,\n idea: Idea,\n slug: string,\n lead: string,\n evidence: EvidenceLevel | \"explore\",\n): Promise<void> {\n if (isVideoIdea(idea)) {\n fail({\n code: \"SERIES_STATIC_ONLY\",\n message: `\"${idea.id}\" is a video idea: a series repeats one static ad with other words.`,\n fix: `Make it on its own: baker creatives make ${idea.id} --spec <beats file>.`,\n });\n }\n const made = await makeSeriesAd(root, idea, slug, lead, evidence, {\n sync: (dir) => baker([\"canvas\", \"sync-definition\", dir, \"--title\"]),\n chatId: optionalChatId() ?? null,\n });\n if (\"code\" in made) fail(made);\n const leadDefinition = await readFile(path.join(root, \"src\", \"creatives\", lead, \"_definition.md\"), \"utf8\").catch(\n () => \"\",\n );\n const leadPlatforms = parseDefinitionDelivery(leadDefinition)?.platforms;\n writeJson(\n seriesMadeEnvelope(\n { ...made, canvasPath: path.relative(root, made.canvasPath), ...(leadPlatforms ? { leadPlatforms } : {}) },\n idea,\n ),\n );\n}\n\nexport const makeCommand = defineCommand({\n meta: { name: \"make\", description: DESCRIPTION },\n args: ARGS,\n async run({ args }) {\n const root = findWorkspaceRoot(process.cwd()) ?? process.cwd();\n const opts = makeArgsOf(args);\n if (\"code\" in opts) return fail(opts);\n const { idea, check } = await loadIdea(root, String(args.idea));\n const slug = opts.slug ?? idea.id;\n const written = await readFile(path.join(root, \"src\", \"creatives\", slug, \"prompt.json\"), \"utf8\").then(\n (text): unknown => {\n try {\n return JSON.parse(text);\n } catch {\n return {};\n }\n },\n (err: NodeJS.ErrnoException) => (err.code === \"ENOENT\" ? null : {}),\n );\n const draft = await readFile(draftPath(root, slug), \"utf8\").catch(() => undefined);\n const refused = alreadyWritten(written, slug, draft);\n if (refused) fail(refused);\n if (opts.series) {\n await makeInSeries(root, idea, slug, opts.series, check?.evidence ?? \"explore\");\n return;\n }\n // Where the ad runs decides its sizes: settled before any reference is searched, never defaulted.\n const { delivery, flags } = await makeDelivery(root, idea, opts, slug);\n const temperature = await viewerTemperature(root, opts.adset, idea.awareness);\n const { scaffold, reference, fromIdea, conceptUnseeded } = await scaffoldIdea(\n root,\n idea,\n opts,\n slug,\n temperature,\n flags,\n );\n if (scaffold.ok !== true) fail(scaffoldFailure(scaffold));\n const { dir, unsourcedCopy } = await recordIdea(root, slug, idea, check?.evidence ?? \"explore\", reference);\n const canvasPath = String(scaffold.canvas_path ?? path.join(dir, `${slug}.canvas.json`));\n const shape = recordedShape(await readFile(canvasPath, \"utf8\").then(JSON.parse, () => null));\n writeJson(\n makeEnvelope({\n slug,\n idea,\n check,\n reference,\n ...(fromIdea ? { fromIdea } : {}),\n ...(conceptUnseeded ? { conceptUnseeded } : {}),\n viewer: opts.adset ? { adset: opts.adset } : { temperature },\n canvasPath: path.relative(root, canvasPath),\n scaffoldHints: Array.isArray(scaffold.hints) ? (scaffold.hints as string[]) : [],\n unsourcedCopy,\n ...(delivery ? { delivery } : {}),\n ...(shape ? { shape } : {}),\n }),\n );\n },\n});\n","/**\n * What a proven ad for one idea is searched with: what this ad sells, its industry and the people\n * it is for, in the plain English the ads library files ads under, with who buys it and what the\n * brand never does. One small model reads the company's own notes and the idea once per idea.\n * Prod, Oct 2026: COMPANY.md's first line, the query until then, gave the library \"https\", a\n * brand name or a table header for 6 of 14 companies, and a company selling several lines (a\n * trade school's electricians, plumbers and data-centre technicians) searched one for all.\n */\nimport { createHash } from \"node:crypto\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { memeRegister, readCompanyReading } from \"../../engine/creative-context/company.ts\";\nimport { askAboutText, type ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport { holdUnbilledSpend } from \"../canvas/unbilled-spend.ts\";\n\nexport type ReferenceBuyer = \"consumer\" | \"small_business\" | \"enterprise\";\nexport type ReferenceHumour = \"fits\" | \"risky\" | \"off_brand\";\nexport type ReferenceMemes = \"fits\" | \"off_brand\";\n\nexport type ReferenceBrief = {\n /** What this ad sells, 2-6 words: \"trade school training program\". */\n category: string;\n /** The broader industry: \"vocational education\". */\n industry?: string;\n /** Who the ad is for and their problem: \"unemployed workers seeking stable technical trades\". */\n audience?: string;\n buyer?: ReferenceBuyer;\n /** ISO country the ad runs in; null when it runs in several. */\n country?: string | null;\n humour?: ReferenceHumour;\n /** Whether the brand's voice runs memes and reaction faces, and the voice line that says so. */\n memes?: ReferenceMemes;\n memesWhy?: string;\n /** What the brand's rules forbid in an ad: \"urgency\", \"price figures\". */\n avoid: string[];\n /** The company's own brand and product names: its own ads are never a reference for a new one. */\n brands: string[];\n /**\n * Searches that widen from this ad, closest first, for when ads of exactly this product are\n * few: an adjacent product the same buyer weighs, the same buyer buying something else, the same\n * kind of decision. Prod set, Oct 2026: a padel-court builder's buyer is a club investor, and a\n * real-estate developer's render with its key facts was the best reference for it.\n */\n wider: string[];\n};\n\nconst text = z\n .string()\n .transform((s) => s.trim())\n .pipe(z.string().min(1))\n .optional()\n .catch(undefined);\n\nconst shortList = (max: number) =>\n z\n .array(z.string())\n .transform((list) =>\n list\n .map((s) => s.trim())\n .filter(Boolean)\n .slice(0, max),\n )\n .catch([]);\n\nconst BriefSchema = z.object({\n category: text,\n industry: text,\n audience: text,\n buyer: z.enum([\"consumer\", \"small_business\", \"enterprise\"]).optional().catch(undefined),\n country: z\n .string()\n .transform((s) => s.trim().toUpperCase())\n .pipe(z.union([z.literal(\"\").transform(() => null), z.string().regex(/^[A-Z]{2}$/)]))\n .optional()\n .catch(undefined),\n humour: z.enum([\"fits\", \"risky\", \"off_brand\"]).optional().catch(undefined),\n avoid: shortList(5),\n brands: shortList(4),\n wider: shortList(4),\n});\n\n/** The model's answer as a brief, or null when it does not say what the ad sells. Pure. */\nexport function parseReferenceBrief(reply: unknown): ReferenceBrief | null {\n const parsed = BriefSchema.safeParse(reply);\n if (!parsed.success || !parsed.data.category) return null;\n const { category, avoid, brands, wider, ...rest } = parsed.data;\n const known = Object.fromEntries(Object.entries(rest).filter(([, v]) => v !== undefined));\n return { category, ...known, avoid, brands, wider };\n}\n\n/** Read once per idea, about a second (measured on 14 companies, Oct 2026). */\nexport const REFERENCE_BRIEF_MODEL = \"google/gemini-3.5-flash-lite\";\nconst REFERENCE_BRIEF_REQUEST = {\n provider: { order: [\"google-vertex\"], allow_fallbacks: false },\n seed: 0,\n temperature: 0,\n response_format: { type: \"json_object\" },\n};\nconst REFERENCE_BRIEF_TIMEOUT_MS = 20_000;\n/** The company's notes the brief reads: past this, the rest is detail the search does not need. */\nconst MAX_COMPANY_CHARS = 12_000;\n\n/** The ad a brief is read for: what it says and who it is for, in the persona's words. */\nexport type BriefedAd = { message: string; who: string };\n\n/** The question the model answers about this one ad; the company's own facts come from its reading. Pure. */\nexport function referenceBriefPrompt(companyDoc: string, ad: BriefedAd): string {\n return `You prepare a search of a library of proven ads (Meta, LinkedIn, TikTok, Google) for the ad below. The library's search reads short English phrases the way it files ads: by what the ad sells, its industry and who it is for.\n\nThe company (its own notes):\n\"\"\"\n${companyDoc.slice(0, MAX_COMPANY_CHARS)}\n\"\"\"\n\nThe ad we are making:\n- Says: ${ad.message}\n- For: ${ad.who}\n\nAnswer only JSON:\n{\n \"category\": \"what THIS ad sells, 2-6 plain English words a library would file it under, no brand names (e.g. 'electrician training course', 'pet health insurance', 'ecommerce customer service AI')\",\n \"industry\": \"the broader industry, 1-3 English words (e.g. 'vocational education', 'insurance', 'customer service software')\",\n \"audience\": \"who the ad is for and the problem they have, 4-9 plain English words (e.g. 'unemployed adults looking for a stable trade')\",\n \"wider\": [\"4 library searches of 2-6 English words that widen from this ad, closest first, for when ads of exactly this product are few. 1: an adjacent product the same buyer weighs (e.g. 'tennis court construction'). 2: the same buyer buying something else (e.g. 'gym and sports club owners'). 3 and 4: the same kind of decision with NO word of this product's category, as other industries sell it (e.g. for a padel-court builder: 'turnkey franchise investment', 'commercial real estate investment'; for an acne serum: 'skincare before and after'). Never brand names\"]\n}`;\n}\n\n/** Asks the model a prompt and returns its JSON answer, or null when nobody answered. */\nexport type AskBrief = (prompt: string) => Promise<unknown>;\n\n/** The live model, its spend held for the workspace's next bill like every other check's. */\nconst askBriefModel =\n (root: string): AskBrief =>\n async (prompt) => {\n const spent: ReviewUsage[] = [];\n const answer = await askAboutText(REFERENCE_BRIEF_MODEL, prompt, (u) => spent.push(u), {\n timeoutMs: REFERENCE_BRIEF_TIMEOUT_MS,\n request: REFERENCE_BRIEF_REQUEST,\n }).catch(() => null);\n await holdUnbilledSpend(path.join(root, \"canvas\", \".cache\"), spent).catch(() => undefined);\n return answer;\n };\n\nconst briefCachePath = (root: string, key: string) =>\n path.join(root, \"canvas\", \".cache\", \"reference-brief\", `${key}.json`);\n\n/**\n * The brief for one ad of this workspace's company: what this ad sells and to whom, read from the\n * cache when the company's notes and the ad are unchanged, else asked once, with the company's own\n * facts (its buyer, country, humour and brands) from its reading (`readCompanyReading`); null when\n * the model does not answer. What the brand never does is the caller's: its rules.\n */\nexport async function referenceBriefFor(\n root: string,\n ad: BriefedAd,\n ask: AskBrief = askBriefModel(root),\n): Promise<ReferenceBrief | null> {\n const companyDoc = await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => \"\");\n const [company, own] = await Promise.all([readCompanyReading(root, ask), adBrief(root, companyDoc, ad, ask)]);\n if (!own) return null;\n const {\n sells: _sells,\n category: _category,\n industry,\n memes: _memes,\n memes_why: _why,\n ...facts\n } = company ?? { brands: [] };\n const register = memeRegister(company);\n return {\n ...facts,\n ...(register ? { memes: register.memes, ...(register.why ? { memesWhy: register.why } : {}) } : {}),\n ...own,\n ...((own.industry ?? industry) ? { industry: own.industry ?? industry } : {}),\n brands: own.brands.length > 0 ? own.brands : facts.brands,\n };\n}\n\n/** This ad's own part of the brief, kept by the company's notes and the ad. */\nasync function adBrief(root: string, companyDoc: string, ad: BriefedAd, ask: AskBrief): Promise<ReferenceBrief | null> {\n const prompt = referenceBriefPrompt(companyDoc, ad);\n const file = briefCachePath(root, createHash(\"sha256\").update(prompt).digest(\"hex\").slice(0, 16));\n const cached = await readFile(file, \"utf8\")\n .then((raw) => parseReferenceBrief(JSON.parse(raw)))\n .catch(() => null);\n if (cached) return cached;\n const brief = parseReferenceBrief(await ask(prompt));\n if (!brief) return null;\n await mkdir(path.dirname(file), { recursive: true });\n await writeFile(file, `${JSON.stringify(brief, null, 2)}\\n`, \"utf8\");\n return brief;\n}\n","/**\n * The order the found references are checked in: each read against the ad being made by the\n * decision model (docs/decision-model.md), three yes/no questions an ad, all in one request of\n * about half a second. The search ranks an ad by how well it matches a few words; this asks\n * whether it was made for our kind of buyer, whether our viewer would see themselves in it, and\n * whether our brand could run something like it.\n * Prod set, Oct 2026, 14 companies judged blind (0-10, by a model the pick never used): the\n * reference kept scored 5.0 in the search's order and 6.3 read against the bet first.\n */\nimport { askJevQuestions, type JevAnswer, type JevQuestion } from \"../../engine/nodes/local/lib/jev.ts\";\nimport type { ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport type { ReferenceBuyer, ReferenceHumour, ReferenceMemes } from \"./reference-brief.ts\";\n\n/** The ad being made, as the ranking reads it. */\nexport type RankedFor = {\n category: string;\n industry?: string;\n buyer?: ReferenceBuyer;\n humour?: ReferenceHumour;\n memes?: ReferenceMemes;\n memesWhy?: string;\n avoid?: readonly string[];\n message: string;\n who: string;\n};\n\ntype RankCandidate = {\n ad_id?: string | null;\n advertiser?: string | null;\n format?: string | null;\n dna?: {\n industry?: string | null;\n business_model?: string | null;\n target_persona?: string | null;\n container?: string | null;\n visual?: string | null;\n creative_concept?: string | null;\n mechanism?: string | null;\n } | null;\n};\n\nexport type AskDecisions = (questions: readonly JevQuestion[]) => Promise<JevAnswer[] | null>;\n\nconst BUYERS: Record<ReferenceBuyer, string> = {\n consumer: \"people buying for themselves\",\n small_business: \"small businesses buying for work\",\n enterprise: \"large companies buying for work\",\n};\n\n/** Said to every model that ranks or picks a reference when our brand's voice does not run memes. Pure. */\nexport function memesLine(bet: Pick<RankedFor, \"memes\" | \"memesWhy\">): string {\n return bet.memes === \"off_brand\"\n ? ` Our brand's voice does not run memes${bet.memesWhy ? ` (${bet.memesWhy})` : \"\"}: rank meme and reaction-face ads last.`\n : \"\";\n}\n\n/** The ad being made, in the words every question reads it by. Pure. */\nfunction oursText(bet: RankedFor): string {\n const sells = `${bet.category}${bet.industry ? ` (${bet.industry})` : \"\"}`;\n const buyer = bet.buyer ? `, to ${BUYERS[bet.buyer]}` : \"\";\n const humour = bet.humour === \"off_brand\" ? \" Our brand does not joke in ads.\" : \"\";\n const avoid = bet.avoid?.length ? ` Our brand never uses: ${bet.avoid.join(\", \")}.` : \"\";\n return `We sell: ${sells}${buyer}. Our ad says: \"${bet.message}\". It is for: ${bet.who}.${humour}${memesLine(bet)}${avoid}`;\n}\n\n/** One reference as the questions read it: who made it, for whom, what it looks like and why it works. Pure. */\nfunction cardText(c: RankCandidate): string {\n const d = c.dna ?? {};\n const line = (label: string, value: string | null | undefined) => (value ? `${label}: ${value}` : \"\");\n return [\n line(\"Advertiser\", c.advertiser),\n line(\"Industry\", [d.industry, d.business_model].filter(Boolean).join(\", \")),\n line(\"Made for\", d.target_persona),\n line(\"Looks like\", [d.container ?? c.format, d.visual].filter(Boolean).join(\": \")),\n line(\"Concept\", d.creative_concept),\n line(\"Why it works\", d.mechanism),\n ]\n .filter(Boolean)\n .join(\"\\n\")\n .slice(0, 1400);\n}\n\n/** Twenty ads a request: what the eval measured answering inside the decision model's timeout. */\nconst QUESTIONS_PER_REQUEST = 60;\n\nconst QUESTIONS = [\n \"Was `ad` made for the same kind of buyer as `ours`: a person buying for themselves, or a business buying for work, of a similar size?\",\n \"Would the viewer `ours` is for feel that `ad` speaks to someone like them, about a problem like theirs?\",\n \"Could the brand of `ours` run an ad made like `ad` (its look, its tone, its kind of hook) without breaking its own rules or looking out of character?\",\n];\n\n/**\n * The candidates, those the decision model reads as made for our buyer and viewer and runnable by\n * our brand first (the product of its three answers; ties keep the search's order), or in the\n * search's order when it does not answer.\n */\nexport async function rankForBet<T extends RankCandidate>(\n candidates: readonly T[],\n bet: RankedFor,\n askOverride?: AskDecisions,\n onSpend?: (usage: ReviewUsage) => void,\n): Promise<T[]> {\n const ask: AskDecisions = askOverride ?? ((questions) => askJevQuestions(questions, onSpend));\n if (candidates.length < 2) return [...candidates];\n const ours = oursText(bet);\n const questions: JevQuestion[] = candidates.flatMap((c) =>\n QUESTIONS.map((question) => ({ type: \"noul\" as const, instructions: { ours, ad: cardText(c), question } })),\n );\n const parts: JevQuestion[][] = [];\n for (let start = 0; start < questions.length; start += QUESTIONS_PER_REQUEST) {\n parts.push(questions.slice(start, start + QUESTIONS_PER_REQUEST));\n }\n const replies = await Promise.all(parts.map((part) => ask(part).catch(() => null)));\n if (replies.some((r, i) => !r || r.length !== parts[i]?.length)) return [...candidates];\n const answers = replies.flatMap((r) => r ?? []);\n const scored = candidates.map((c, i) => ({\n c,\n i,\n score: QUESTIONS.reduce((product, _, k) => {\n const answer = answers[i * QUESTIONS.length + k];\n return product * (answer && \"noul\" in answer ? answer.noul : 0.5);\n }, 1),\n }));\n return scored.sort((a, b) => b.score - a.score || a.i - b.i).map((s) => s.c);\n}\n","/**\n * Which of the proven ads that fit the ad is built on: all of them looked at side by side, for\n * the viewer the ad is for, in one vision call. The fit checks one ad at a time and passes most\n * of what it is shown, so keeping the first that passed kept a good ad, rarely the best one.\n * Prod set, Oct 2026, 14 companies judged blind (0-10, by a model the pick never used): the\n * reference kept scored 6.3 kept as the first that fit and 7.4 picked side by side.\n */\nimport { askAboutImages, type ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport { decisionOf, isVital } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport type { FitAnswer } from \"../winning-ads/fit.ts\";\nimport { memesLine, type RankedFor } from \"./reference-rank.ts\";\n\n/** A stronger reader than the fit's: it compares, once per ad made. */\nexport const REFERENCE_PICK_MODEL = \"~google/gemini-pro-latest\";\nconst REFERENCE_PICK_TIMEOUT_MS = 60_000;\n\n/** One reference that fit, with its picture (a base64 JPEG) and the fit's read of it. */\nexport type PickOption = {\n adId: string;\n advertiser?: string;\n picture: string;\n fit: Pick<FitAnswer, \"why_it_wins\" | \"our_viewer\"> & Partial<Pick<FitAnswer, \"load_bearing\">>;\n};\n\n/** What stops the scroll in a reference and its proof, each with what of ours does its job, as the fit read them. Pure. */\nfunction vitalRead(fit: PickOption[\"fit\"]): string {\n const vital = (fit.load_bearing ?? []).filter(isVital).map((l) => {\n const ours = decisionOf(l) === \"keep\" ? \"kept as it is\" : l.ours?.trim() ? `ours: ${l.ours.trim()}` : \"\";\n return `${l.job === \"stop\" ? \"stops the scroll with\" : \"proof:\"} ${l.element}${ours ? ` (${ours})` : \"\"}`;\n });\n return vital.length > 0 ? ` It ${vital.join(\"; \")}.` : \"\";\n}\n\nexport type AskPick = (pictures: string[], prompt: string) => Promise<unknown>;\n\n/** The parts of an ad a media buyer takes from one proven ad or another. */\nexport const TAKE_ELEMENTS = [\"hook\", \"visual\", \"who_appears\", \"proof\", \"layout\", \"call_to_action\"] as const;\nexport type TakeElement = (typeof TAKE_ELEMENTS)[number];\n\n/** One element our ad takes from one proven ad, and why it applies to our viewer. */\nexport type Take = { element: TakeElement; adId: string; what: string; applies: string };\n/** Something of a proven ad our ad must not copy, and why. */\nexport type Avoid = { adId: string; what: string; why: string };\n\n/** The side-by-side pick: the options best first, why the first won, what to take from which and what not to copy. */\nexport type ReferencePick = { order: number[]; why?: string; takes?: Take[]; avoid?: Avoid[] };\n\n/** The question, the ad being made and what the fit read of each picture, numbered as shown. Pure. */\nexport function referencePickPrompt(options: readonly PickOption[], bet: RankedFor): string {\n const reads = options\n .map((o, i) => {\n const wins = Object.values(o.fit.why_it_wins ?? {})\n .filter(Boolean)\n .join(\"; \");\n const viewer = o.fit.our_viewer ? ` Our viewer: ${o.fit.our_viewer.stops}, ${o.fit.our_viewer.why}` : \"\";\n return `${i + 1}. ${o.advertiser ?? \"an advertiser\"}: wins on ${wins || \"(not read)\"}.${vitalRead(o.fit)}${viewer}`;\n })\n .join(\"\\n\");\n // Dev, Oct 2026: read past its words, \"no stock photography\" ranked a meme's reaction faces out.\n const avoid = bet.avoid?.length\n ? ` The brand never uses: ${bet.avoid.join(\", \").replace(/\\.$/, \"\")}. Its rules forbid only what they name: \"no stock photography\" never rules out a meme's reaction face, our own people or our Avatars.`\n : \"\";\n const humour = `${bet.humour === \"off_brand\" ? \" The brand does not joke in ads.\" : \"\"}${memesLine(bet)}`;\n return `Pick the proven ad our next ad should be built on. Images 1..${options.length} are proven ads of other advertisers, each already checked to be adaptable.\n\nWe sell: ${bet.category}${bet.industry ? ` (${bet.industry})` : \"\"}. Our ad says: \"${bet.message}\". It is for: ${bet.who}.${humour}${avoid}\n\nWhat the check read of each:\n${reads}\n\nRank them by how likely a version of each, made for us, stops this exact viewer and makes them act: the viewer must see themselves and their problem in it, its winning move must carry our offer as strongly as theirs, and our brand must be able to run it.\n\nThen, as a media buyer does, say what our ad takes. Our ad may combine several: the hook of one, the visual of another, the proof of a third. For each element worth taking (${TAKE_ELEMENTS.join(\", \")}), the image whose version of it would work best for us, exactly what to take, and why it applies to this viewer. Leave out an element no image does well for us. Then what our ad must not copy from them: a device that misleads or that the platform restricts (a fake newspaper or news page, a fake app notification), dated urgency, another brand's marks, words that hide what is sold; never what stops the scroll or the proof, which ours keeps as named above. A rule forbids only what it names: \"no stock photography\" never rules out a meme's reaction face, our own people or our Avatars; when a rule of ours is why, quote the rule word for word.\n\nAnswer only JSON: {\"ranking\": [image numbers, best first], \"why\": \"one sentence on why the first beats the others\", \"takes\": [{\"element\": \"hook\", \"from\": image number, \"what\": \"...\", \"applies\": \"...\"}], \"avoid\": [{\"from\": image number, \"what\": \"...\", \"why\": \"...\"}]}`;\n}\n\n/** The options' indices best first (each once, any it left out after, in order), or null. Pure. */\nexport function readPickRanking(reply: unknown, count: number): number[] | null {\n const ranking = (reply as { ranking?: unknown } | null)?.ranking;\n if (!Array.isArray(ranking)) return null;\n const order: number[] = [];\n for (const n of ranking) {\n const index = Number(n) - 1;\n if (Number.isInteger(index) && index >= 0 && index < count && !order.includes(index)) order.push(index);\n }\n if (order.length === 0) return null;\n for (let i = 0; i < count; i++) if (!order.includes(i)) order.push(i);\n return order;\n}\n\nconst text = (value: unknown): string => (typeof value === \"string\" ? value.trim() : \"\");\n\n/** The image a reply names (1-based), as its option's ad id; null when it names none shown. Pure. */\nfunction adOf(from: unknown, options: readonly PickOption[]): string | null {\n return options[Number(from) - 1]?.adId ?? null;\n}\n\n/** What the reply says to take from which option, only known elements of shown options, each element once. Pure. */\nexport function readTakes(reply: unknown, options: readonly PickOption[]): Take[] {\n const takes = (reply as { takes?: unknown } | null)?.takes;\n if (!Array.isArray(takes)) return [];\n const read: Take[] = [];\n for (const t of takes as Record<string, unknown>[]) {\n const element = TAKE_ELEMENTS.find((e) => e === t?.element);\n const adId = adOf(t?.from, options);\n if (!element || !adId || !text(t.what) || read.some((r) => r.element === element)) continue;\n read.push({ element, adId, what: text(t.what), applies: text(t.applies) });\n }\n return read;\n}\n\n/** What the reply says not to copy, only from shown options. Pure. */\nexport function readAvoid(reply: unknown, options: readonly PickOption[]): Avoid[] {\n const avoid = (reply as { avoid?: unknown } | null)?.avoid;\n if (!Array.isArray(avoid)) return [];\n return (avoid as Record<string, unknown>[]).flatMap((a) => {\n const adId = adOf(a?.from, options);\n return adId && text(a.what) ? [{ adId, what: text(a.what), why: text(a.why) }] : [];\n });\n}\n\n/** The live model, its spend handed to `onSpend`. */\nexport const askPickModel =\n (onSpend?: (usage: ReviewUsage) => void): AskPick =>\n (pictures, prompt) =>\n askAboutImages(REFERENCE_PICK_MODEL, pictures, prompt, onSpend, REFERENCE_PICK_TIMEOUT_MS).catch(() => null);\n\n/** The options in the order the side-by-side look prefers, why the first won and what to take from which; null when nobody answered. */\nexport async function pickAmong(\n options: readonly PickOption[],\n bet: RankedFor,\n ask: AskPick = askPickModel(),\n): Promise<ReferencePick | null> {\n const reply = await ask(\n options.map((o) => o.picture),\n referencePickPrompt(options, bet),\n );\n const order = readPickRanking(reply, options.length);\n if (!order) return null;\n const why = text((reply as { why?: unknown }).why);\n const takes = readTakes(reply, options);\n const avoid = readAvoid(reply, options);\n return {\n order,\n ...(why ? { why } : {}),\n ...(takes.length > 0 ? { takes } : {}),\n ...(avoid.length > 0 ? { avoid } : {}),\n };\n}\n"],"mappings":"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","names":["mkdir","readFile","writeFile","path","questions","text","path","text","readFile","writeFile","mkdir"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  withoutFields
3
- } from "./chunk-IDN4FOOP.js";
3
+ } from "./chunk-NBNLGJH5.js";
4
4
  import {
5
5
  claimNewCreativeInWorkspace,
6
6
  creativeLimitRefusal
@@ -27,7 +27,7 @@ import {
27
27
  import "./chunk-ABXTGAG7.js";
28
28
  import {
29
29
  setDefinitionFields
30
- } from "./chunk-WL6FWK2Q.js";
30
+ } from "./chunk-RDCYPWQZ.js";
31
31
  import "./chunk-BSEB55E6.js";
32
32
  import "./chunk-RCSOG2DV.js";
33
33
  import "./chunk-LD4CHA7U.js";
@@ -601,4 +601,4 @@ var translateCommand = defineCommand({
601
601
  export {
602
602
  translateCommand
603
603
  };
604
- //# sourceMappingURL=translate-AEOQJ5JN.js.map
604
+ //# sourceMappingURL=translate-K4D7KDYV.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koda-sl/baker-cli",
3
- "version": "0.479.0",
3
+ "version": "0.480.0",
4
4
  "description": "AI-agent-first CLI for interacting with Baker, including the Baker creative canvas.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/creatives/make-model.ts"],"sourcesContent":["/**\n * The rules `baker creatives make` applies to turn an idea into a creative: which reference to\n * look for, which one fits, and what the creative records about the idea it carries. Pure.\n */\nimport { proofStrength } from \"@baker/api/ad-library\";\nimport { parse, parseDocument, Scalar, visit } from \"yaml\";\nimport { AD_SPEC_SCHEMA, type AdSpec, unfitReasons } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport type { ViewerTemperature } from \"../../viewer-profile.ts\";\nimport type { PersonaEntry } from \"../canvas/viewer-check.ts\";\nimport type { FitAnswer, FitBet } from \"../winning-ads/fit.ts\";\nimport type { WinningAdsSearchArgs } from \"../winning-ads/search.ts\";\nimport { type EvidenceLevel, figuresIn, IDEA_VIDEO_FORMATS, type Idea, unsourcedClaims } from \"./ideas-model.ts\";\nimport type { ReferenceBrief } from \"./reference-brief.ts\";\nimport type { RankedFor } from \"./reference-rank.ts\";\n\nexport const REFERENCE_CANDIDATES = 6;\n\n/** Whether the idea is a video, built from beats, rather than a static from a reference. */\nexport function isVideoIdea(idea: Pick<Idea, \"format\">): boolean {\n return (IDEA_VIDEO_FORMATS as readonly string[]).includes(idea.format);\n}\n\n/** Who a reference was made for, by our viewer: a stranger's ad never leans on its own brand. */\nconst BY_TEMPERATURE: Record<ViewerTemperature, { audienceTemperature: string; excludeBrandReliant?: true }> = {\n cold: { audienceTemperature: \"0_cold\", excludeBrandReliant: true },\n warm: { audienceTemperature: \"1_warm_engaged,2_hot_visited\", excludeBrandReliant: true },\n hot: { audienceTemperature: \"3_customer\" },\n};\n\n/**\n * Where a reference is looked for: the company's market (`GB`), what it sells (\"rooftop solar\") and\n * who the ad is for (\"Bill-shocked homeowner\") and its broader industry (\"home energy\"), when known.\n */\nexport type ReferenceWhere = {\n country?: string;\n category?: string;\n audience?: string;\n /** Searches that widen from the ad, closest first: adjacent products, the same buyer, the same decision. */\n wider?: readonly string[];\n industry?: string;\n};\n\n/**\n * The library search for a static idea's reference: its container, made for our viewer, on what\n * the company sells (else the idea's message), in its market when given.\n */\nexport function referenceSearchFor(\n idea: Idea,\n temperature: ViewerTemperature,\n where: ReferenceWhere = {},\n): WinningAdsSearchArgs {\n return {\n query: where.category || idea.message,\n scope: \"followed-first\",\n platform: \"meta\",\n format: \"static\",\n formatPattern: idea.format,\n awareness: idea.awareness,\n ...BY_TEMPERATURE[temperature],\n ...(where.country ? { country: where.country } : {}),\n maxPerAdvertiser: 1,\n limit: REFERENCE_CANDIDATES,\n diverse: true,\n };\n}\n\n/**\n * The searches whose candidates are tried, best first. A proven ad of what the company sells comes\n * before the idea's container: its market, viewer and objections are ours, and its container is one\n * the thinking can keep or change. So: what the company sells, in its market (in the idea's\n * container for our viewer, loosened in turn, then any container), then anywhere; then ads made for\n * the same people, whatever they sell; then wider (an adjacent product, the same buyer buying\n * something else, the same kind of decision); then ads of the broader industry; then the message;\n * then the container's proven winners from any category, in the market and anywhere.\n * The library's judge scores an ad against the query: prod, Oct 2026, a customer's sentence about\n * one product matched no ad of another category and 13 of 15 ideas found nothing; dev, Oct 2026,\n * searched with the whole message, a UK solar installer's ads were checked against a crypto\n * exchange, a clinic and an English course, while the library held UK solar ads; and with the\n * container a filter, 7 of 10 companies found 0–2 ads of their own category.\n */\nexport function referenceSearchesFor(\n idea: Idea,\n temperature: ViewerTemperature,\n where: ReferenceWhere = {},\n): WinningAdsSearchArgs[] {\n const strict = referenceSearchFor(idea, temperature, where);\n const { awareness: _awareness, ...anyStage } = strict;\n const { audienceTemperature: _temperature, excludeBrandReliant: _reliant, ...viewerAny } = anyStage;\n const anyViewer = { ...viewerAny, scope: \"all\" as const };\n const { formatPattern: _pattern, ...anyContainer } = anyViewer;\n const { country: _country, ...anywhere } = anyViewer;\n const { country: _anyCountry, ...anyContainerAnywhere } = anyContainer;\n const { query: _query, ...winners } = anyStage;\n const { query: _anyQuery, country: _winnersCountry, ...winnersAnywhere } = anyViewer;\n const inMarket = (steps: WinningAdsSearchArgs[]) => (where.country ? steps : []);\n const anyAd = (query: string | undefined) =>\n query?.trim()\n ? [...inMarket([{ ...anyContainer, query: query.trim() }]), { ...anyContainerAnywhere, query: query.trim() }]\n : [];\n return [\n ...(where.country ? [strict, anyStage, anyContainer] : [strict, anyStage]),\n anywhere,\n anyContainerAnywhere,\n ...anyAd(where.audience),\n ...(where.wider ?? []).flatMap((q) => (q.trim() ? [{ ...anyContainerAnywhere, query: q.trim() }] : [])),\n ...anyAd(where.industry),\n ...(where.category ? [{ ...anyContainerAnywhere, query: idea.message }] : []),\n ...inMarket([{ ...winners, sort: \"winner\" }]),\n { ...winnersAnywhere, sort: \"winner\" },\n ];\n}\n\n/**\n * Where a reference is looked for, from the brief when the model read one (its market over the\n * notes' guess; every market when it says the ad runs in several), else from the notes. Pure.\n */\nexport function referenceWhereOf(brief: ReferenceBrief | null, fallback: ReferenceWhere): ReferenceWhere {\n if (!brief) return fallback;\n const country = brief.country === null ? undefined : (brief.country ?? fallback.country);\n const audience = brief.audience ?? fallback.audience;\n return {\n ...(country ? { country } : {}),\n category: brief.category,\n ...(brief.industry ? { industry: brief.industry } : {}),\n ...(audience ? { audience } : {}),\n ...(brief.wider.length ? { wider: brief.wider } : {}),\n };\n}\n\n/** The ad being made, as candidates are ranked and picked for it: the brief's read, else the search's words. Pure. */\nexport function rankedForOf(\n brief: ReferenceBrief | null,\n where: ReferenceWhere,\n bet: Pick<FitBet, \"who\" | \"message\">,\n): RankedFor {\n return {\n category: brief?.category ?? where.category ?? bet.message,\n ...(brief?.industry ? { industry: brief.industry } : {}),\n ...(brief?.buyer ? { buyer: brief.buyer } : {}),\n ...(brief?.humour ? { humour: brief.humour } : {}),\n ...(brief?.memes ? { memes: brief.memes } : {}),\n ...(brief?.memesWhy ? { memesWhy: brief.memesWhy } : {}),\n ...(brief?.avoid.length ? { avoid: brief.avoid } : {}),\n message: bet.message,\n who: bet.who,\n };\n}\n\n/** A name as the library and a person may both spell it: no accents, case or punctuation. Pure. */\nconst brandKey = (name: string) =>\n name\n .normalize(\"NFD\")\n .replace(/\\p{M}/gu, \"\")\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]/gu, \"\");\n\n/** Whether an ad's advertiser is the company itself, by its brand names (three letters or more). Pure. */\nexport function isOwnBrand(advertiser: string | null | undefined, brands: readonly string[]): boolean {\n const page = brandKey(advertiser ?? \"\");\n return page !== \"\" && brands.some((b) => brandKey(b).length >= 3 && page.includes(brandKey(b)));\n}\n\ntype PoolCandidate = { ad_id?: string | null; advertiser_id?: string | null; winner_score?: number | null };\n\n/**\n * Every search's candidates in one list, the better search's first, one ad per brand (each fit\n * tried is another brand's move), the ads whose run barely proves them (`proofStrength` \"little\")\n * after the proven ones, at most `limit`. Pure.\n */\nexport function pooledCandidates<T extends PoolCandidate>(searches: readonly T[][], limit: number): T[] {\n const seen = new Set<string>();\n const pooled: T[] = [];\n for (const candidate of searches.flat()) {\n const brand = candidate.advertiser_id ? `brand:${candidate.advertiser_id}` : null;\n if (!candidate.ad_id || seen.has(candidate.ad_id) || (brand && seen.has(brand))) continue;\n seen.add(candidate.ad_id);\n if (brand) seen.add(brand);\n pooled.push(candidate);\n }\n const proven = (c: T) => proofStrength(c.winner_score) !== \"little\";\n return [...pooled.filter(proven), ...pooled.filter((c) => !proven(c))].slice(0, limit);\n}\n\n/** A reference fits when what it wins on is something we can supply, and our viewer would stop for it. */\nexport function fitsIdea(fit: Pick<FitAnswer, \"verdict\" | \"load_bearing\" | \"our_viewer\">): boolean {\n return fit.verdict !== \"reject\" && missingElements(fit).length === 0 && fit.our_viewer?.stops !== \"no\";\n}\n\n/** The load-bearing elements a reference wins on that we have nothing for. Pure. */\nexport function missingElements(fit: Pick<FitAnswer, \"load_bearing\">): string[] {\n return fit.load_bearing.filter((l) => l.have === \"missing\" && !l.ours?.trim()).map((l) => l.element);\n}\n\n/**\n * Why a checked reference was not built on, in one line the person can hear: what stops the scroll\n * or the proof that cannot be ours first, with the rule that forbids it; else that our viewer would\n * not stop for it; else the check's own note. Pure.\n */\nexport function whyUnfit(fit: Pick<FitAnswer, \"load_bearing\" | \"our_viewer\" | \"transfer_note\">): string {\n const reasons = unfitReasons(fit);\n if (reasons.length > 0) return reasons.join(\"; \");\n if (fit.our_viewer?.stops === \"no\") {\n return `our viewer would not stop for it${fit.our_viewer.why ? `: ${fit.our_viewer.why}` : \"\"}`;\n }\n return fit.transfer_note?.trim() || \"the check found it does not carry this ad\";\n}\n\nexport type DefinitionStrategyFields = {\n idea: string;\n message: string;\n evidence?: EvidenceLevel;\n angle: string;\n persona: string;\n awareness: string;\n hypothesis: string;\n};\n\n/** What a creative records about the idea it executes. */\nexport function definitionFieldsOf(idea: Idea, evidence: EvidenceLevel | \"explore\"): DefinitionStrategyFields {\n return {\n idea: idea.id,\n message: idea.message,\n ...(evidence !== \"explore\" ? { evidence } : {}),\n angle: idea.angle,\n persona: idea.who,\n awareness: idea.awareness,\n hypothesis: idea.why,\n };\n}\n\nconst FRONTMATTER = /^---\\r?\\n([\\s\\S]*?\\r?\\n)?---/;\n\n/** Whether a bare string reads back as the same text under YAML 1.1. */\nfunction readsAsText11(text: string): boolean {\n try {\n return parse(text, { version: \"1.1\" }) === text;\n } catch {\n return false;\n }\n}\n\n/** Set fields in a markdown file's frontmatter, keeping every other field and the body. */\nexport function setDefinitionFields(raw: string, fields: Record<string, unknown>): string {\n const match = raw.match(FRONTMATTER);\n if (!match) return raw;\n const doc = parseDocument(match[1] ?? \"\");\n if (doc.errors.length > 0) return raw;\n for (const [key, value] of Object.entries(fields)) {\n if (value === undefined) continue;\n const node = doc.createNode(value);\n // The site reads frontmatter as YAML 1.1, where a bare 2026-10-04 is a date, not text.\n visit(node, {\n Scalar(_, scalar) {\n if (typeof scalar.value === \"string\" && !readsAsText11(scalar.value)) {\n scalar.type = Scalar.QUOTE_DOUBLE;\n }\n },\n });\n doc.set(key, node);\n }\n return `---\\n${doc.toString()}---${raw.slice(match[0].length)}`;\n}\n\n/** The ad spec with the idea's message as the one thing it tells the viewer. */\nexport function setSpecMessage(specJson: string, message: string): string {\n const spec = JSON.parse(specJson) as Record<string, unknown>;\n return `${JSON.stringify({ ...spec, message }, null, 2)}\\n`;\n}\n\n/**\n * The ad spec made for the idea's persona: its title and segment from the Knowledge (\"The owner on\n * the move (Owner, 30–55, 1–10 staff)\"), else the idea's own words. The image prompt, the casting\n * check and the viewer check all read `viewer.who`; a reference-built spec held only the\n * scaffold's placeholder. The market and what the viewer knows are kept. Pure.\n */\nexport function setSpecViewer(specJson: string, idea: Pick<Idea, \"who\">, personas: readonly PersonaEntry[]): string {\n const spec = JSON.parse(specJson) as Record<string, unknown>;\n const viewer = (spec.viewer ?? {}) as Record<string, unknown>;\n return `${JSON.stringify({ ...spec, viewer: { ...viewer, who: personaWho(idea, personas) } }, null, 2)}\\n`;\n}\n\n/** Who an idea is for, in its persona's words (\"The owner on the move (Owner, 30–55)\"), else its own. Pure. */\nexport function personaWho(idea: Pick<Idea, \"who\">, personas: readonly PersonaEntry[]): string {\n const persona = personas.find((p) => p.slug === idea.who);\n if (persona?.title) return `${persona.title}${persona.segment ? ` (${persona.segment})` : \"\"}`;\n return persona?.segment ?? idea.who.replace(/[-_]/g, \" \");\n}\n\n/** The most words the audience search keeps: the library's judge reads a long query slowly. */\nconst AUDIENCE_QUERY_WORDS = 9;\n\n/**\n * The people the idea is for, as a library search: its persona's own words, cut short. Dev, Oct\n * 2026: \"homeowners worried about rising energy bills\" found twelve proven energy ads where\n * \"rooftop solar\" in the idea's container found one. Pure.\n */\nexport function audienceQuery(idea: Pick<Idea, \"who\">, personas: readonly PersonaEntry[]): string {\n return personaWho(idea, personas)\n .replace(/\\(/g, \" \")\n .replace(/\\)/g, \"\")\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, AUDIENCE_QUERY_WORDS)\n .join(\" \")\n .replace(/[\\s,;:.–—-]+$/, \"\");\n}\n\n/** The ad being made, as the fit judges a reference for it: its persona, message and the customers' words it stands on. Pure. */\nexport function fitBetOf(\n idea: Pick<Idea, \"who\" | \"message\" | \"awareness\" | \"angle\" | \"evidence\">,\n personas: readonly PersonaEntry[],\n insights: readonly { id: string; quote: string }[],\n market?: string,\n): FitBet {\n const quotes = insights.filter((i) => idea.evidence.includes(i.id)).map((i) => i.quote);\n return {\n who: personaWho(idea, personas),\n message: idea.message,\n awareness: idea.awareness,\n angle: idea.angle,\n ...(quotes.length > 0 ? { quotes } : {}),\n ...(market ? { market } : {}),\n };\n}\n\n/**\n * The ad spec with the concept the reference's fit read (`conceptFromFit`): a build started before\n * the fit answered has none, or only the one the scaffold drafted from its describe, which names no\n * reference and nothing of what we have; without the fit's, the render never sees the reference at\n * the level that won. A concept a fit already seeded (it names its reference) stays. Pure.\n */\nexport function withFitConcept(specJson: string, seeded: Record<string, unknown>): string {\n const spec = JSON.parse(specJson) as Record<string, unknown>;\n const held = spec.concept as { reference_ad_id?: unknown } | undefined;\n if (held?.reference_ad_id) return specJson;\n return `${JSON.stringify({ ...spec, ...seeded }, null, 2)}\\n`;\n}\n\n/**\n * The copy lines the scaffold drafted that claim a figure the company never wrote: a draft written\n * beside a competitor's ad can carry the competitor's promise. `corpus` is what the company wrote.\n */\nexport function unsourcedCopyLines(specJson: string, corpus: string): string[] {\n const spec = JSON.parse(specJson) as { copy?: unknown };\n const figures = figuresIn(corpus);\n const lines = Array.isArray(spec.copy) ? spec.copy : [];\n return lines.flatMap((line) => {\n const text = typeof line === \"object\" && line !== null ? (line as { text?: unknown }).text : undefined;\n return typeof text === \"string\" && unsourcedClaims(text, figures).length > 0 ? [text] : [];\n });\n}\n\n/** Containers shown as a photograph; every other container is a designed graphic or a screen. */\nconst PHOTO_FORMATS = /photo|lifestyle|before_after|ugc|product|selfie|street/;\n\n/**\n * The ad spec an idea starts from when no proven ad fits it: the message and who it is for are\n * the idea's; the scene and the copy are placeholders the agent writes before anything renders\n * (`canvas run` refuses a placeholder). Pure.\n */\nexport function ideaSpec(idea: Idea, who: string): AdSpec {\n const container = idea.format.replace(/_/g, \" \");\n return {\n schema: AD_SPEC_SCHEMA,\n viewer: { who },\n message: idea.message,\n copy: [{ text: \"[TODO: the headline, in the customer's words]\", lettering: \"designed\", role: \"headline\" }],\n scene: {\n description: `[TODO: what the viewer sees, as a ${container}, that shows: ${idea.message}]`,\n look: PHOTO_FORMATS.test(idea.format) ? \"photo\" : \"designed\",\n },\n colors: [],\n references: [],\n logo: true,\n third_party_brands: [],\n scene_text: [],\n mechanism: [],\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/creatives/make.ts","../src/commands/creatives/reference-brief.ts","../src/commands/creatives/reference-rank.ts","../src/commands/creatives/reference-pick.ts"],"sourcesContent":["/**\n * `baker creatives make <idea>`: one idea becomes one creative. For a static it finds a reference\n * for the job itself (the idea's container, made for our viewer), keeps the first whose\n * load-bearing parts we can supply, scaffolds from it, and records the idea on the creative and\n * its message in the ad spec. The agent then writes only the copy lines and the scene, and runs it.\n */\n\nimport { mkdir, mkdtemp, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport type { ScopedWinnersSearchResponse } from \"@baker/api/ad-library\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { memeRegister, readCompanyReading } from \"../../engine/creative-context/company.ts\";\nimport { avoidOf, readCreativeContext } from \"../../engine/creative-context/index.ts\";\nimport type { ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport type { ConceptCarry } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport { readAdSpec, SPEC_SHAPES_HINT, unwrittenProblems } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport { projectAdaptBriefs } from \"../../engine/scaffold/static-adapt-briefs.ts\";\nimport {\n parseDefinitionDelivery,\n platformsNamedIn,\n type ResolvedDelivery,\n} from \"../../engine/scaffold/static-delivery.ts\";\nimport { projectFormatBriefs } from \"../../engine/scaffold/static-format-briefs.ts\";\nimport { projectStaticBriefs } from \"../../engine/scaffold/static-render-briefs.ts\";\nimport { recordedShape } from \"../../engine/scaffold/static-shape-route.ts\";\nimport { reroutedOnSpec } from \"../../engine/scaffold/static-upgrade.ts\";\nimport { optionalChatId } from \"../../env.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport {\n describeMarket,\n marketFromCompanyDoc,\n type ViewerTemperature,\n viewerFromKnowledge,\n} from \"../../viewer-profile.ts\";\nimport { runBaker as baker } from \"../baker-child.ts\";\nimport { parseDefinitionSourceFields } from \"../canvas/creative-definition.ts\";\nimport { type LibraryPlatform, notADesignReference, resolveSourcePlatform } from \"../canvas/library-reference.ts\";\nimport { findWorkspaceRoot } from \"../canvas/normalize-paths.ts\";\nimport { scaffoldDelivery } from \"../canvas/scaffold-delivery.ts\";\nimport { holdUnbilledSpend } from \"../canvas/unbilled-spend.ts\";\nimport { liveViewerLookups, readPersonas } from \"../canvas/viewer-check.ts\";\nimport {\n conceptFromFit,\n type FitAnswer,\n type FitBet,\n type FitFailure,\n fitReference,\n NO_FIT_HINT,\n pictureOf,\n} from \"../winning-ads/fit.ts\";\nimport { buildSearchBody } from \"../winning-ads/search.ts\";\nimport { castInventory, companyName } from \"./cast-inventory.ts\";\nimport { checkIdeas, type EvidenceLevel, type Idea, type IdeaCheck, sourcesClaims } from \"./ideas-model.ts\";\nimport {\n coverageOf,\n IDEAS_DIR,\n readCreativeRecords,\n readIdeas,\n readInsights,\n readKnowledgeCorpus,\n readPersonaIds,\n} from \"./ideas-workspace.ts\";\nimport {\n audienceQuery,\n definitionFieldsOf,\n fitBetOf,\n fitsIdea,\n ideaSpec,\n isOwnBrand,\n isVideoIdea,\n missingElements,\n personaWho,\n pooledCandidates,\n rankedForOf,\n referenceSearchesFor,\n referenceWhereOf,\n setDefinitionFields,\n setSpecMessage,\n setSpecViewer,\n unsourcedCopyLines,\n whyUnfit,\n withFitConcept,\n} from \"./make-model.ts\";\nimport { makeSeriesAd, seriesMadeEnvelope } from \"./make-series.ts\";\nimport { referenceBriefFor } from \"./reference-brief.ts\";\nimport { type Avoid, askPickModel, pickAmong, type ReferencePick, type Take } from \"./reference-pick.ts\";\nimport { type RankedFor, rankForBet } from \"./reference-rank.ts\";\nimport { thinkingOutline, withThinking } from \"./thinking.ts\";\n\n/** Candidates whose fit may be asked (a few cents each, cached per workspace). */\nconst FITS_TRIED = 6;\n/**\n * Fits asked at a time: the best-ranked candidate is usually kept, so the rest wait for a slot that\n * one not fitting frees (six at once billed six fits where one was kept).\n */\nconst FITS_AT_ONCE = 3;\n/** How many found ads are ranked for the ad being made before the best FITS_TRIED are checked. */\nconst RANKED_POOL = 24;\nconst SEARCH_TIMEOUT_MS = 120_000;\n/**\n * How long make looks for, checks and describes a reference before it starts the ad from the idea.\n * Every ad starts from a proven one when it can: dev, Oct 2026, a search took 3-30 s, a fit 20-50 s\n * and the describe ~35 s beside them, so the 50 s this once was sent good references to the idea.\n */\nconst REFERENCE_MS = 150_000;\n\nconst DESCRIPTION = `Build one idea from src/creatives/_ideas/ into a creative. For a static it builds on a proven winning ad: it reads what this ad sells and for whom, searches ads of that in its market (the idea's container first, then any), then ads made for the idea's persona, its industry, the idea's message, then the container's strongest winners from any category; leaves out the company's own ads, ranks the rest for this ad's buyer, viewer and brand, checks which fit us (one whose scroll-stopper or proof cannot be ours is passed over, and the first hint says which and why) and, when several do, compares them side by side, scaffolds the creative on the best-ranked one, records the idea on it and sets the ad's message. The fit says what made that ad win, so what ours carries of it (\\`reference.carry\\`: whole_ad, layout, hook or angle); its first hint names the ad: tell the person. When no proven ad fits, it starts the ad from the idea itself and says why (never a dead end, never retry with another format). You then write the copy lines and the scene in prompt.json and run it. Takes up to about two and a half minutes: run it in the foreground, once per idea.\n\nWhere the ad runs decides its sizes (Meta 4:5 + 9:16, LinkedIn 1:1, TikTok 9:16): it is the idea's \\`platforms\\`, or --platforms from the person's request; nothing saying so is refused, never defaulted to Meta.\n\nStart here, with an idea from \\`baker creatives ideas\\` build_next:\n baker creatives make phone-payroll # static: reference found and checked for you\n baker creatives make phone-payroll --platforms linkedin # where it runs, when the idea does not say\n baker creatives make phone-payroll --adset 120210000000 # written for that ad set's viewer\n baker creatives make phone-payroll --reference 1310524137919413 # your own reference instead\n baker creatives make founder-story --spec beats.json # a video idea: from its beats spec\n baker creatives make phone-payroll --slug phone-payroll-h2 # another hook of the same idea\n baker creatives make tiktok-speed --series zernio-live # another message in the style of a ready ad\nThen: edit src/creatives/<slug>/prompt.json (copy + scene; the message is set), and \\`baker canvas run src/creatives/<slug>/<slug>.canvas.json\\`.`;\n\nconst ARGS = {\n idea: { type: \"positional\", required: true, description: \"The idea id (src/creatives/_ideas/<idea>.md)\" },\n slug: { type: \"string\", required: false, description: \"Creative slug (default: the idea id)\" },\n adset: { type: \"string\", required: false, description: \"Meta ad set the ad is for: its viewer and placements\" },\n reference: {\n type: \"string\",\n required: false,\n description: \"A library ad id to build on instead of searching (statics)\",\n },\n platforms: {\n type: \"string\",\n required: false,\n description:\n \"Where the ad runs, the main platform first: meta (4:5 + 9:16), linkedin (1:1), tiktok (9:16), google_demandgen, … Take it from the person's request; default the creative's definition (and the sizes it records), then the idea's `platforms`, then the ad set's (Meta). Nothing saying so is refused, never defaulted.\",\n },\n formats: {\n type: \"string\",\n required: false,\n description:\n \"Exactly the sizes to make, when the person asks for others than the platform's (`--platforms linkedin --formats 1:1,4:5`).\",\n },\n \"reference-platform\": {\n type: \"string\",\n required: false,\n description:\n \"Library platform of --reference: meta|linkedin|tiktok|google (default meta). On google only display ads are built on (a static needs a picture)\",\n },\n platform: {\n type: \"string\",\n required: false,\n description:\n \"Retired: --platforms says where the ad runs; --reference-platform says which library --reference is in.\",\n },\n spec: {\n type: \"string\",\n required: false,\n description: \"Video ideas: the beats spec for `baker canvas scaffold-ad --spec`\",\n },\n series: {\n type: \"string\",\n required: false,\n description:\n \"Statics: make this idea as another ad of the series led by this creative (its slug): the same design, only its words changed. No reference is searched; seconds. The lead must have a ready version. Then write its words and run the whole series: baker canvas run --series <lead>\",\n },\n avatar: {\n type: \"string\",\n required: false,\n description:\n \"Statics: the Avatar(s) the ad's people are cast as (`@eduard` or `eduard,lucia`; `baker avatars list`). Run make again with it once the definition decides the cast, before prompt.json is written: it rebuilds the canvas on them and keeps the thinking\",\n },\n \"from-idea\": {\n type: \"boolean\",\n required: false,\n default: false,\n description:\n \"Statics: skip the reference search and start from the idea (what make does by itself when no proven ad fits)\",\n },\n} as const;\n\nregisterSchema({ command: \"creatives.make\", description: DESCRIPTION, args: ARGS });\n\ntype Failure = { code: string; message: string; fix?: string };\n\nfunction fail(error: Failure): never {\n writeJson({ ok: false, error });\n process.exit(1);\n}\n\nasync function viewerTemperature(\n root: string,\n adSet: string | undefined,\n awareness: string,\n): Promise<ViewerTemperature> {\n if (adSet) {\n const read = await liveViewerLookups(root)\n .adSetViewer(adSet)\n .catch(() => null);\n if (read) return read.temperature;\n }\n return viewerFromKnowledge({ personas: [], awareness: awareness as never }).temperature;\n}\n\ntype Picked = {\n adId: string;\n platform: LibraryPlatform;\n advertiserId?: string;\n why: string;\n tried: number;\n /** The fit that kept it, with what made it win (`carry`); none for a reference chosen by hand that could not be checked. */\n fit?: FitAnswer;\n /** Its static container (`lifestyle_photo`), when the library knows it: it can differ from the idea's. */\n container?: string;\n /** Why the side-by-side look preferred it to the others that fit, when there were others. */\n preferred?: string;\n /** Every proven ad that fit, in the look's order (this one first), when several did. */\n board?: BoardAd[];\n /** What the look said our ad takes from which of them. */\n takes?: Take[];\n /** What it said our ad must not copy from them. */\n avoid?: Avoid[];\n /** The proven ads checked that did not fit, each with why (what stops the scroll or the proof that cannot be ours first). */\n passed?: PassedOver[];\n};\n\n/** A proven ad that fit, as the thinking lays it out. */\ntype BoardAd = { adId: string; advertiser?: string; mediaUrl?: string };\n\n/** A proven ad checked and not built on, and why. */\ntype PassedOver = { adId: string; advertiser?: string; why: string };\n\n/** How many of the proven ads passed over the person is told about. */\nconst PASSED_SAID = 3;\n\n/** The checked candidates that did not fit, in rank order, each with why; at most `PASSED_SAID`. Pure. */\nfunction passedOver(candidates: readonly Buildable[], fits: ReadonlyArray<FitResult | undefined>): PassedOver[] {\n return candidates\n .flatMap((candidate, i) => {\n const fit = fits[i];\n if (!fit?.ok || fitsIdea(fit.fit)) return [];\n return [\n {\n adId: String(candidate.ad_id),\n ...(candidate.advertiser ? { advertiser: candidate.advertiser } : {}),\n why: whyUnfit(fit.fit),\n },\n ];\n })\n .slice(0, PASSED_SAID);\n}\n\ntype Candidate = {\n ad_id?: string | null;\n platform?: unknown;\n advertiser_id?: string | null;\n format?: string | null;\n winner_score?: number | null;\n advertiser?: string | null;\n media_url?: string | null;\n dna?: {\n container?: string | null;\n industry?: string | null;\n business_model?: string | null;\n target_persona?: string | null;\n visual?: string | null;\n creative_concept?: string | null;\n mechanism?: string | null;\n } | null;\n};\n\n/** The library platform a candidate is on (none named is the library's default, meta); null for any other. Pure. */\nfunction candidatePlatform(c: Candidate): LibraryPlatform | null {\n const resolved = resolveSourcePlatform(typeof c.platform === \"string\" ? c.platform : undefined);\n return resolved.ok ? resolved.platform : null;\n}\n\n/** A candidate make can build on, its platform resolved. */\ntype Buildable = Candidate & { platform: LibraryPlatform };\n\n/**\n * The candidate with its platform, when it is a design make can build on: never one on a platform\n * the library does not index (it was once fitted as a Meta ad and silently failed), nor a Google\n * search text ad, which is wording, not a design. Pure.\n */\nfunction buildable(c: Candidate): Buildable[] {\n const platform = candidatePlatform(c);\n if (!platform || notADesignReference(platform, String(c.ad_id), { format: c.format ?? null })) return [];\n return [{ ...c, platform }];\n}\ntype FitResult = Awaited<ReturnType<typeof fitReference>>;\n\n/** A reference the fit kept, as the side-by-side pick is shown it. */\nexport type FittingReference = { adId: string; candidate: Candidate; fit: FitAnswer };\n\n/**\n * How references are found, ordered, checked and chosen between; the live library, decision\n * model, fit and pick by default, injected in tests. Without `rank` the search's order holds;\n * without `choose` the best-ranked reference that fits is kept.\n */\nexport type ReferenceDeps = {\n /** The ads one search found; null when the library could not search. */\n search: (body: Record<string, unknown>) => Promise<Candidate[] | null>;\n rank?: (found: Candidate[]) => Promise<Candidate[]>;\n fit: (platform: Picked[\"platform\"], adId: string) => Promise<FitResult>;\n choose?: (fitting: FittingReference[]) => Promise<ReferencePick | null>;\n};\n\n/**\n * The live library, fit and, when the ad being made is known, the ranking and the side-by-side\n * pick: the company's own ads left out (its brand names, from the brief), the rest read against\n * the ad before the fits, and the ones that fit compared in one look.\n */\nfunction liveReferenceDeps(\n root: string,\n bet?: FitBet,\n rankedFor?: RankedFor,\n brands: readonly string[] = [],\n): ReferenceDeps {\n return {\n search: async (body) => {\n const ask = () =>\n apiPost<ScopedWinnersSearchResponse>(\"/api/ad-library/winners/search\", body, {\n timeoutMs: SEARCH_TIMEOUT_MS,\n }).catch(() => null);\n // A failed search is asked once more: the topic searches are the slow ones, and when they\n // fail only the quick browses of any category's winners are left (dev, Oct 2026, under load).\n return ((await ask()) ?? (await ask()))?.results ?? null;\n },\n fit: (platform, adId) => fitReference(root, platform, adId, bet),\n ...(rankedFor\n ? {\n rank: async (found) => {\n const spent: ReviewUsage[] = [];\n try {\n return await rankForBet(\n found.filter((c) => !isOwnBrand(c.advertiser, brands)),\n rankedFor,\n undefined,\n (u) => spent.push(u),\n );\n } finally {\n await holdUnbilledSpend(path.join(root, \"canvas\", \".cache\"), spent).catch(() => undefined);\n }\n },\n choose: (fitting) => chooseLive(root, fitting, rankedFor),\n }\n : {}),\n };\n}\n\n/** The side-by-side pick over the live pictures, its spend held for the workspace's next bill. */\nasync function chooseLive(root: string, fitting: FittingReference[], rankedFor: RankedFor) {\n const options = (\n await Promise.all(\n fitting.map(async (f) => {\n const picture = await pictureOf(f.candidate.media_url);\n return picture\n ? [\n {\n adId: f.adId,\n picture,\n fit: f.fit,\n ...(f.candidate.advertiser ? { advertiser: f.candidate.advertiser } : {}),\n },\n ]\n : [];\n }),\n )\n ).flat();\n if (options.length < 2) return null;\n const spent: ReviewUsage[] = [];\n const picked = await pickAmong(\n options,\n rankedFor,\n askPickModel((u) => spent.push(u)),\n );\n await holdUnbilledSpend(path.join(root, \"canvas\", \".cache\"), spent).catch(() => undefined);\n if (!picked) return null;\n // The look saw only the options with a picture: its order, in the indices of every one that fit.\n const byAd = new Map(fitting.map((f, i) => [f.adId, i]));\n const order = picked.order.flatMap((i) => {\n const at = byAd.get(options[i]?.adId ?? \"\");\n return at === undefined ? [] : [at];\n });\n return { ...picked, order };\n}\n\n/**\n * The candidates of every search, the better search's first (every search runs at once), then in\n * the order they are ranked for the ad being made, when they are; the first FITS_TRIED.\n */\nasync function findCandidates(\n searches: Record<string, unknown>[],\n deps: ReferenceDeps,\n): Promise<Buildable[] | \"unavailable\"> {\n const results = await Promise.all(searches.map((search) => deps.search(search).catch(() => null)));\n // Every topic search failed: what is left is any category's winners, never a reference for this ad.\n const topics = searches.flatMap((search, i) => (search.free_text_query ? [results[i]] : []));\n if (topics.length > 0 && topics.every((found) => found === null)) return \"unavailable\";\n const pooled = pooledCandidates(\n results.map((found) => (found ?? []).flatMap(buildable)),\n deps.rank ? RANKED_POOL : FITS_TRIED,\n );\n if (!deps.rank) return pooled;\n const ranked = await deps.rank(pooled).catch(() => pooled);\n return ranked.flatMap(buildable).slice(0, FITS_TRIED);\n}\n\n/**\n * Search the idea's container and keep the best-ranked reference whose load-bearing parts we can\n * supply. Three fits run at once (a few cents each): one after another, one make took 109 s.\n */\n/**\n * What building on a reference started before its fit was known left behind: `prepared` when the\n * reference kept is the one built on, `discarded` (to wait for before building over it) when not.\n */\ntype Speculated<T> = { prepared?: Promise<T>; discarded?: Promise<T> };\n\n/** The reference a build starts on, as `prepare` is handed it before its fit is known. */\nexport type ReferenceCandidate = Pick<Picked, \"adId\" | \"platform\" | \"advertiserId\">;\n\nconst candidateOf = (c: Buildable): ReferenceCandidate => ({\n adId: String(c.ad_id),\n platform: c.platform,\n ...(c.advertiser_id ? { advertiserId: c.advertiser_id } : {}),\n});\n\nexport async function pickReference<T = never>(\n root: string,\n searches: Record<string, unknown>[],\n deps: ReferenceDeps = liveReferenceDeps(root),\n /**\n * Building on the best-ranked reference, started while the fits are asked: it is usually the one\n * kept, and its scaffold (a 35 s describe) then no longer waits ~25 s for them (dev, Oct 2026).\n */\n prepare?: (candidate: ReferenceCandidate, signal: AbortSignal) => Promise<T>,\n /** Aborted when the time for a reference is out: no reference is kept, and the build started is stopped. */\n within?: AbortSignal,\n): Promise<(Picked & Speculated<T>) | (Failure & Speculated<T>)> {\n const out = whenAborted(within);\n const found = await Promise.race([findCandidates(searches, deps), out]);\n if (found === \"out\") return slowReference();\n if (found === \"unavailable\") return searchUnavailable();\n const candidates = found.slice(0, FITS_TRIED);\n const first = candidates[0];\n // A build on a reference that is not kept is stopped, not waited for (dev: 50 s for nothing).\n const stop = new AbortController();\n const building = first && prepare ? prepare(candidateOf(first), stop.signal) : undefined;\n // A failed speculative build is never this pick's failure: the kept reference is built again.\n void building?.catch(() => undefined);\n // Three fits are asked at once, and one that does not fit asks the next; the best-ranked one that\n // fits is kept as soon as it and every better-ranked one have answered, never waiting on slower\n // fits below it. Once the pick is made, no further fit is asked.\n let settled = false;\n const asked: Promise<FitResult>[] = [];\n const askNext = () => {\n const index = asked.length;\n const candidate = candidates[index];\n if (settled || !candidate) return;\n asked.push(\n askFit(deps, candidate).then((fit) => {\n if (!(fit.ok && fitsIdea(fit.fit))) askNext();\n return fit;\n }),\n );\n };\n for (let slot = 0; slot < FITS_AT_ONCE; slot++) askNext();\n const deciding = deps.choose ? chosenFitting(candidates, asked, deps.choose) : firstFitting(candidates, asked);\n const kept = await Promise.race([deciding, out]);\n settled = true;\n if (kept === \"out\") {\n stop.abort();\n return { ...slowReference(), ...(building ? { discarded: building } : {}) };\n }\n if (kept.index !== 0) stop.abort();\n const speculated = building ? (kept.index === 0 ? { prepared: building } : { discarded: building }) : {};\n return { ...kept.picked, ...speculated };\n}\n\n/**\n * One candidate's fit, a throw read as a fit not made: it is handled when asked, since the fits\n * below the one awaited can fail while it is awaited.\n */\nconst askFit = (deps: ReferenceDeps, c: Buildable): Promise<FitResult> =>\n Promise.resolve()\n .then(() => deps.fit(c.platform, String(c.ad_id)))\n .catch((e): FitResult => ({ ok: false, error: { code: \"UNAVAILABLE\", message: String(e), fix: \"\" } }));\n\n/** Resolves \"out\" once `signal` aborts (never without one). */\nconst whenAborted = (signal: AbortSignal | undefined) =>\n new Promise<\"out\">((resolve) => {\n if (signal?.aborted) resolve(\"out\");\n signal?.addEventListener(\"abort\", () => resolve(\"out\"), { once: true });\n });\n\n/** The reference kept: its candidate, the fit that kept it, its rank and why it was preferred. Pure. */\nfunction pickedOf(candidate: Buildable, fit: FitAnswer, index: number, preferred?: string): Picked {\n const layers = fit.why_it_wins;\n return {\n ...candidateOf(candidate),\n why: [layers.disguise, layers.trigger, layers.logic].filter(Boolean).join(\"; \"),\n tried: index + 1,\n fit,\n ...(candidate.dna?.container ? { container: candidate.dna.container } : {}),\n ...(preferred ? { preferred } : {}),\n };\n}\n\n/** The best-ranked candidate whose fit keeps it, with its rank; else why none was kept (index -1). */\nasync function firstFitting(\n candidates: readonly Buildable[],\n fits: readonly Promise<FitResult>[],\n): Promise<{ picked: Picked | Failure; index: number }> {\n let unchecked: FitFailure | null = null;\n let checked = 0;\n const lacking: string[] = [];\n const answered: Array<FitResult | undefined> = [];\n for (const [index, candidate] of candidates.entries()) {\n const fit = await fits[index];\n answered.push(fit);\n if (!fit) continue;\n if (!fit.ok) unchecked = fit.error;\n else checked += 1;\n if (fit.ok && !fitsIdea(fit.fit)) lacking.push(...missingElements(fit.fit));\n if (!(fit.ok && fitsIdea(fit.fit))) continue;\n const passed = passedOver(candidates, answered);\n return { picked: { ...pickedOf(candidate, fit.fit, index), ...(passed.length > 0 ? { passed } : {}) }, index };\n }\n return { picked: noReference(candidates.length, checked, unchecked, lacking), index: -1 };\n}\n\n/** Every fit asked, once no more are being asked: a fit that does not fit asks the next. */\nasync function allFits(fits: Promise<FitResult>[]): Promise<FitResult[]> {\n let seen = -1;\n while (seen !== fits.length) {\n seen = fits.length;\n await Promise.all(fits);\n }\n return await Promise.all(fits);\n}\n\n/**\n * The reference the side-by-side look prefers among every one that fits, with its rank and why;\n * the best-ranked that fits when only one does or the look does not answer.\n */\nasync function chosenFitting(\n candidates: readonly Buildable[],\n fits: Promise<FitResult>[],\n choose: NonNullable<ReferenceDeps[\"choose\"]>,\n): Promise<{ picked: Picked | Failure; index: number }> {\n const answered = await allFits(fits);\n const fitting = answered.flatMap((fit, index) => {\n const candidate = candidates[index];\n return candidate && fit.ok && fitsIdea(fit.fit) ? [{ index, candidate, fit: fit.fit }] : [];\n });\n if (fitting.length < 2) return await firstFitting(candidates, fits);\n const chosen = await choose(\n fitting.map((f) => ({ adId: String(f.candidate.ad_id), candidate: f.candidate, fit: f.fit })),\n ).catch(() => null);\n const kept = (chosen && fitting[chosen.order[0] ?? 0]) || fitting[0];\n if (!kept) return await firstFitting(candidates, fits);\n const ordered = chosen ? chosen.order.flatMap((i) => fitting[i] ?? []) : fitting;\n const passed = passedOver(candidates, answered);\n return {\n picked: {\n ...pickedOf(kept.candidate, kept.fit, kept.index, chosen?.why),\n board: [kept, ...ordered.filter((f) => f !== kept)].map((f) => boardAdOf(f.candidate)),\n ...(chosen?.takes ? { takes: chosen.takes } : {}),\n ...(chosen?.avoid ? { avoid: chosen.avoid } : {}),\n ...(passed.length > 0 ? { passed } : {}),\n },\n index: kept.index,\n };\n}\n\n/** A fitting candidate as the board shows it. Pure. */\nconst boardAdOf = (c: Buildable): BoardAd => ({\n adId: String(c.ad_id),\n ...(c.advertiser ? { advertiser: c.advertiser } : {}),\n ...(c.media_url ? { mediaUrl: c.media_url } : {}),\n});\n\n/** What the rejected references won on that we lack, each once, at most three. Pure. */\nconst lackingText = (lacking: readonly string[]) => {\n const named = [...new Set(lacking.map((l) => l.trim()).filter(Boolean))].slice(0, 3);\n return named.length > 0 ? ` (they won on ${named.join(\", \")})` : \"\";\n};\n\nconst searchUnavailable = (): Failure => ({\n code: \"REFERENCE_SEARCH_UNAVAILABLE\",\n message: \"The ads library could not search for this ad's category just now.\",\n fix: \"Nothing to do to go on: the ad starts from the idea rather than from another category's winners. To build on a proven ad, run make again in a few minutes.\",\n});\n\nconst slowReference = (): Failure => ({\n code: \"REFERENCE_SLOW\",\n message: `Finding and checking a proven ad took longer than ${REFERENCE_MS / 1000} s.`,\n fix: \"Nothing to do: the ad starts from the idea. To build on a proven ad anyway, run make again (the checks already made are kept) or pass --reference <adId>.\",\n});\n\n/**\n * Why no reference was kept: none found, none fits (naming what the ones checked won on that we\n * lack), or the fit could not be checked. Pure.\n */\nexport function noReference(\n found: number,\n checked: number,\n unchecked: { message: string } | null,\n lacking: readonly string[] = [],\n): Failure {\n if (found > 0 && checked === 0 && unchecked) {\n return {\n code: \"FIT_UNAVAILABLE\",\n message: `Could not check whether the references fit (${unchecked.message})`,\n fix: \"Run make again in a moment. To build now, pass --reference <adId> with one you looked at yourself (`baker winning-ads search`).\",\n };\n }\n return {\n code: \"NO_REFERENCE_FITS\",\n message:\n found === 0\n ? \"The library has no proven ad in this idea's format.\"\n : `None of the ${found} proven ads checked wins on something this company has, for a viewer who would stop for it${lackingText(lacking)}.`,\n fix: \"Nothing to do to go on: the ad starts from the idea. To build on a proven ad instead, pass --reference <adId> for one you looked at (`baker winning-ads search --format static` with what the company sells or who the ad is for). Do not stop the batch: build the other ideas.\",\n };\n}\n\n/**\n * Refused when the creative's ad is already written: building again would put the idea's\n * placeholders over it (dev, Oct 2026: a chat agent re-ran make on a re-formatted idea and lost the\n * ad it had shown). Nothing there, or a failed make's placeholders, lets the build go ahead. Pure.\n */\nexport function alreadyWritten(promptJson: unknown, slug: string, draft?: string): Failure | null {\n if (promptJson === null || promptJson === undefined) return null;\n // The draft make wrote, untouched: the ad is not written yet, so a rebuild (`--avatar`) loses nothing.\n if (draft !== undefined && sameJson(promptJson, draft)) return null;\n try {\n if (unwrittenProblems(readAdSpec(promptJson)).length > 0) return null;\n } catch {\n // Unreadable is still someone's work: refuse rather than overwrite it.\n }\n return {\n code: \"ALREADY_MADE\",\n message: `\"${slug}\" is already made and its ad is written: building it again would replace that ad with placeholders.`,\n fix: `To change this ad, edit src/creatives/${slug}/prompt.json and run \\`baker canvas run\\` on it. For another ad of the same idea, run make again with --slug <new-slug>.`,\n };\n}\n\n/** Whether a parsed spec is the JSON text given, whatever its spacing. Pure. */\nfunction sameJson(parsed: unknown, text: string): boolean {\n try {\n return JSON.stringify(parsed) === JSON.stringify(JSON.parse(text));\n } catch {\n return false;\n }\n}\n\n/** Where make keeps the prompt.json it wrote, to know whether anyone has written the ad since (never committed). */\nconst draftPath = (root: string, slug: string) => path.join(root, \"canvas\", \".cache\", \"make-drafts\", `${slug}.json`);\n\ntype MakeArgs = {\n slug?: string;\n adset?: string;\n reference?: string;\n /** The library `--reference` is in (`--reference-platform`). */\n referencePlatform?: string;\n /** Where the ad runs (`--platforms`), the main platform first. */\n platforms?: string;\n /** Exactly the sizes to make (`--formats`). */\n formats?: string;\n spec?: string;\n /** The lead ad of the series this idea is made in (`--series`). */\n series?: string;\n fromIdea?: boolean;\n /** The Avatars the ad's people are cast as (`--avatar`). */\n avatar?: string;\n};\n\n/**\n * The proven ad a re-cast rebuilds on: the one the creative is built on, never a new search, when\n * make runs again with `--avatar` and no other reference. Null otherwise. Pure.\n */\nexport function castRebuild(\n definition: string | null,\n args: Pick<MakeArgs, \"avatar\" | \"reference\" | \"fromIdea\">,\n): { adId: string; platform: string } | null {\n if (!definition || !args.avatar || args.reference || args.fromIdea) return null;\n const { sourceAdId, sourcePlatform } = parseDefinitionSourceFields(definition);\n return sourceAdId ? { adId: sourceAdId, platform: sourcePlatform ?? \"meta\" } : null;\n}\n\n/**\n * True when `make --avatar` re-casts a creative that was built from its idea (its definition names\n * no proven ad): it is rebuilt from the idea, never given a proven ad found by a new search. Pure.\n */\nexport function ideaRecast(\n definition: string | null,\n args: Pick<MakeArgs, \"avatar\" | \"reference\" | \"fromIdea\">,\n): boolean {\n if (!definition || !args.avatar || args.reference || args.fromIdea) return false;\n return !parseDefinitionSourceFields(definition).sourceAdId;\n}\n\n/** The scaffold's cast flags for the Avatars a definition or `--avatar` names (`@eduard, @lucia`). Pure. */\nexport function castFlags(avatar: string | undefined): string[] {\n const handles = (avatar ?? \"\")\n .split(/[\\s,]+/)\n .map((h) => h.replace(/^@/, \"\").toLowerCase())\n .filter(Boolean);\n return handles.length > 0 ? [\"--avatar\", handles.join(\",\")] : [];\n}\n\nconst flag = (value: unknown): string | undefined => (typeof value === \"string\" && value ? value : undefined);\n\n/** The idea, checked: refused when unreadable, missing, or with a problem `creatives ideas` names. */\nasync function loadIdea(root: string, ideaId: string) {\n const { ideas, unreadable } = await readIdeas(root);\n const bad = unreadable.find((u) => u.id === ideaId);\n if (bad) {\n fail({\n code: \"INVALID_IDEA\",\n message: bad.problems.join(\"; \"),\n fix: `Fix ${IDEAS_DIR}/${ideaId}.md, then run make again.`,\n });\n }\n const idea = ideas.find((i) => i.id === ideaId);\n if (!idea) {\n fail({\n code: \"NOT_FOUND\",\n message: `No idea \"${ideaId}\" in ${IDEAS_DIR}/.`,\n fix: `Ideas on file: ${ideas.map((i) => i.id).join(\", \") || \"none\"}. Write it there first.`,\n });\n }\n const [insights, knowledge, personas, creatives] = await Promise.all([\n readInsights(root),\n readKnowledgeCorpus(root),\n readPersonaIds(root),\n readCreativeRecords(root),\n ]);\n const check = checkIdeas({ ideas, insights, knowledge, personas, ...coverageOf(ideas, creatives) }).find(\n (c) => c.id === idea.id,\n );\n if (check && check.problems.length > 0) {\n fail({\n code: \"IDEA_HAS_PROBLEMS\",\n message: check.problems.join(\"; \"),\n fix: \"Fix the idea file and run `baker creatives ideas` again.\",\n });\n }\n return { idea, check };\n}\n\ntype Scaffolded = {\n scaffold: Record<string, unknown>;\n reference: Picked | null;\n fromIdea?: string;\n /** Why the kept reference's concept could not be seeded: the render does not see it yet. */\n conceptUnseeded?: string;\n};\n\n/** Scaffold the creative: a video from its beats, a static from a reference that fits. */\nasync function scaffoldIdea(\n root: string,\n idea: Idea,\n args: MakeArgs,\n slug: string,\n temperature: ViewerTemperature,\n whereFlags: string[],\n): Promise<Scaffolded> {\n const viewerFlags = [\n ...(args.adset ? [\"--target-adset\", args.adset] : [\"--viewer-temperature\", temperature]),\n ...whereFlags,\n ];\n if (isVideoIdea(idea)) {\n if (!args.spec) {\n fail({\n code: \"SPEC_REQUIRED\",\n message: `\"${idea.id}\" is a video idea (${idea.format}): it is built from its beats.`,\n fix: `Write the beats spec (one spoken line plus one shot each; references/video-flow.md), message first, then: baker creatives make ${idea.id} --spec <file>.`,\n });\n }\n return {\n scaffold: await baker([\"canvas\", \"scaffold-ad\", \"--spec\", args.spec, \"--slug\", slug, ...viewerFlags]),\n reference: null,\n };\n }\n return await scaffoldStatic(root, idea, args, slug, temperature, [...viewerFlags, ...castFlags(args.avatar)]);\n}\n\ntype Chosen = Awaited<ReturnType<typeof pickReference<Record<string, unknown>>>>;\n\n/**\n * A proven ad named by hand (`--reference`, or the one a re-cast rebuilds on) with the fit made of\n * it for this ad (cached: free), so its thinking names what stops the scroll and the proof and asks\n * what of ours carries each, as for one make found. Built on unchecked when no fit can be made; an\n * unknown platform refused.\n */\nexport async function checkedByHand(\n adId: string,\n platform: string | undefined,\n deps: Pick<ReferenceDeps, \"fit\">,\n): Promise<Picked | Failure> {\n const byHand = handPickedReference(adId, platform);\n if (\"code\" in byHand) return byHand;\n const fit = await deps.fit(byHand.platform, byHand.adId).catch(() => null);\n if (!fit?.ok) return byHand;\n if (!fitsIdea(fit.fit)) {\n return {\n code: \"REFERENCE_UNFIT\",\n message: `The proven ad ${adId} does not fit this idea: ${whyUnfit(fit.fit)}.`,\n fix: \"Pick another proven ad (`baker winning-ads search`), or run make without --reference to build from the idea.\",\n };\n }\n const layers = fit.fit.why_it_wins;\n return { ...byHand, why: [layers.disguise, layers.trigger, layers.logic].filter(Boolean).join(\"; \"), fit: fit.fit };\n}\n\n/** The reference passed by hand, checked (an unknown platform refused), none when asked to start from the idea, else `pick`'s. */\nasync function chooseReference(args: MakeArgs, deps: ReferenceDeps, pick: () => Promise<Chosen>): Promise<Chosen> {\n if (args.reference) {\n const byHand = await checkedByHand(args.reference, args.referencePlatform, deps);\n if (\"code\" in byHand) fail(byHand);\n return byHand;\n }\n if (args.fromIdea) return { code: \"FROM_IDEA\", message: \"Asked to start from the idea.\" };\n return await pick();\n}\n\n/** Where this idea's reference is looked for, and the brief it is ranked by: the company's reading, its rules, the idea's persona. */\nasync function referenceTarget(root: string, idea: Idea) {\n const market = marketFromCompanyDoc(await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => \"\"));\n const personas = await readPersonas(root).catch(() => []);\n const [found, company, context] = await Promise.all([\n referenceBriefFor(root, { message: idea.message, who: personaWho(idea, personas) }),\n readCompanyReading(root),\n readCreativeContext(root, { kind: \"static\" }),\n ]);\n // What the brand never does is its rules, never a model's guess at them.\n const brief = found && { ...found, avoid: avoidOf(context.rules) };\n const category = company?.category ?? company?.sells;\n const where = referenceWhereOf(brief, {\n ...(market && market.country !== \"global\" ? { country: market.country } : {}),\n ...(category ? { category } : {}),\n audience: audienceQuery(idea, personas),\n });\n return { market, personas, brief, where };\n}\n\n/** A static from a reference that fits, found within `REFERENCE_MS`; else from the idea itself. */\nasync function scaffoldStatic(\n root: string,\n idea: Idea,\n args: MakeArgs,\n slug: string,\n temperature: ViewerTemperature,\n viewerFlags: string[],\n): Promise<Scaffolded> {\n const onReference = (c: ReferenceCandidate, signal?: AbortSignal) =>\n baker(\n [\n \"canvas\",\n \"scaffold-static-ad\",\n \"--source-ad-id\",\n c.adId,\n \"--source-platform\",\n c.platform,\n ...(c.advertiserId ? [\"--source-advertiser-id\", c.advertiserId] : []),\n \"--slug\",\n slug,\n \"--title\",\n idea.message.slice(0, 120),\n ...viewerFlags,\n ],\n signal,\n );\n // Built on the best-ranked reference while the fits are asked, only into a new creative: a build\n // that is not kept is then removed whole, leaving nothing of that reference on the creative.\n const dir = path.join(root, \"src\", \"creatives\", slug);\n const fresh = !(await stat(dir).catch(() => null));\n // A reference found by make has its time: past it, the ad starts from the idea (`REFERENCE_MS`).\n const budget = AbortSignal.timeout(REFERENCE_MS);\n const { market, personas, brief, where } = await referenceTarget(root, idea);\n const bet = fitBetOf(\n idea,\n personas,\n await readInsights(root).catch(() => []),\n market ? describeMarket(market) : undefined,\n );\n const deps = liveReferenceDeps(root, bet, rankedForOf(brief, where, bet), brief?.brands);\n const definition = await readFile(path.join(dir, \"_definition.md\"), \"utf8\").catch(() => null);\n const recast = castRebuild(definition, args);\n const fromIdea = args.fromIdea || ideaRecast(definition, args);\n const reference = await chooseReference({ ...args, fromIdea }, deps, async () => {\n if (recast) {\n const kept = await checkedByHand(recast.adId, recast.platform, deps);\n if (\"code\" in kept) fail(kept);\n return kept;\n }\n return await pickReference(\n root,\n referenceSearchesFor(idea, temperature, where).map(buildSearchBody),\n deps,\n fresh ? (c, signal) => onReference(c, AbortSignal.any([signal, budget])) : undefined,\n budget,\n );\n });\n if (\"discarded\" in reference && reference.discarded) {\n await reference.discarded.catch(() => undefined);\n await rm(dir, { recursive: true, force: true });\n }\n if (\"code\" in reference) {\n return { scaffold: await scaffoldFromIdea(idea, slug, viewerFlags), reference: null, fromIdea: reference.message };\n }\n const prepared = \"prepared\" in reference ? await reference.prepared?.catch(() => null) : null;\n if (prepared?.ok !== true && budget.aborted && !args.reference) {\n await rm(dir, { recursive: true, force: true });\n const slow = slowReference().message;\n return { scaffold: await scaffoldFromIdea(idea, slug, viewerFlags), reference: null, fromIdea: slow };\n }\n const scaffold = prepared?.ok === true ? prepared : await onReference(reference);\n // An Avatar the scaffold refused is the agent's to fix, never a reason to leave the proven ad.\n if (scaffold.ok !== true && (scaffold.error as { code?: unknown } | undefined)?.code === \"avatar\") {\n fail(scaffoldFailure(scaffold));\n }\n const unbuilt = unbuiltReference(scaffold, { adId: reference.adId, byHand: Boolean(args.reference || recast) });\n if (!unbuilt) return await withKeptConcept(dir, slug, scaffold, reference);\n // What the failed build left of a new creative goes, so the idea's build starts clean.\n if (fresh) await rm(dir, { recursive: true, force: true });\n return { scaffold: await scaffoldFromIdea(idea, slug, viewerFlags), reference: null, fromIdea: unbuilt };\n}\n\n/** The reference passed with `--reference`, on its `--platform` (default meta); an unknown platform is refused. Pure. */\nexport function handPickedReference(adId: string, platform: string | undefined): Picked | Failure {\n const resolved = resolveSourcePlatform(platform);\n if (!resolved.ok) {\n return {\n code: \"INVALID_ARGUMENT\",\n message: resolved.message.replace(\"--source-platform\", \"--platform\"),\n fix: \"Pass the platform `baker winning-ads search` names beside the ad.\",\n };\n }\n return { adId, platform: resolved.platform, why: \"chosen by hand\", tried: 0 };\n}\n\n/**\n * Why the ad starts from the idea when the proven ad make picked could not be built on (its picture\n * not described, dev Oct 2026: twice running for one ad), else null: a build that went through, or a\n * reference chosen by hand, whose failure is the agent's to see. Pure.\n */\nexport function unbuiltReference(\n scaffold: Record<string, unknown>,\n reference: { adId: string; byHand: boolean },\n): string | null {\n if (scaffold.ok === true || reference.byHand) return null;\n return `The proven ad ${reference.adId} could not be read to build on.`;\n}\n\n/** The creative built on a reference, its fit's concept seeded, else why it could not be. */\nasync function withKeptConcept(\n dir: string,\n slug: string,\n scaffold: Record<string, unknown>,\n reference: Picked,\n): Promise<Scaffolded> {\n if (scaffold.ok !== true || !reference.fit) return { scaffold, reference };\n const unseeded = await seedConcept(dir, slug, conceptFromFit(reference.fit, reference.adId));\n return { scaffold, reference, ...(unseeded ? { conceptUnseeded: unseeded } : {}) };\n}\n\n/**\n * Seed the kept reference's concept into a creative built before its fit answered, and compile the\n * canvas from it: the render then sees the reference at the level that won (`concept.carry`).\n * Dev, Oct 2026: every build started on the best-ranked reference had no concept. Why it could not\n * be seeded, else null.\n */\nexport async function seedConcept(dir: string, slug: string, seeded: Record<string, unknown>): Promise<string | null> {\n const promptPath = path.join(dir, \"prompt.json\");\n const canvasPath = path.join(dir, `${slug}.canvas.json`);\n let prompt: string;\n try {\n prompt = withFitConcept(await readFile(promptPath, \"utf8\"), seeded);\n await writeFile(promptPath, prompt, \"utf8\");\n } catch (e) {\n return `prompt.json could not take the proven ad's concept (${e instanceof Error ? e.message : String(e)})`;\n }\n try {\n const spec: unknown = JSON.parse(prompt);\n // What the ad keeps of the proven ad decides its shape: a designed one is laid out again for each size.\n const { canvas, rerouted } = reroutedOnSpec(JSON.parse(await readFile(canvasPath, \"utf8\")), spec);\n // A picture of the one-picture shape is briefed apart from the rest (`projectFormatBriefs`).\n const briefed =\n projectStaticBriefs(canvas, spec) + projectAdaptBriefs(canvas, spec) + projectFormatBriefs(canvas, spec);\n if (rerouted || briefed > 0) {\n await writeFile(canvasPath, `${JSON.stringify(canvas, null, 2)}\\n`, \"utf8\");\n }\n } catch {\n // prompt.json holds the concept: the run compiles the canvas from it.\n }\n return null;\n}\n\n/** The static started from the idea's own spec: no reference picture, nothing described or billed. */\nasync function scaffoldFromIdea(idea: Idea, slug: string, viewerFlags: string[]): Promise<Record<string, unknown>> {\n const dir = await mkdtemp(path.join(tmpdir(), \"idea-spec-\"));\n const specPath = path.join(dir, \"prompt.json\");\n await writeFile(specPath, JSON.stringify(ideaSpec(idea, idea.who.replace(/[-_]/g, \" \")), null, 2), \"utf8\");\n try {\n return await baker([\n \"canvas\",\n \"scaffold-static-ad\",\n \"--spec\",\n specPath,\n \"--slug\",\n slug,\n \"--title\",\n idea.message.slice(0, 120),\n ...viewerFlags,\n ]);\n } finally {\n await rm(dir, { recursive: true, force: true });\n }\n}\n\n/** The address of the proven ad a canvas keeps as its `original` node; null on a canvas built from the idea. Pure. */\nexport function referencePictureUrl(canvas: unknown): string | null {\n const nodes = (canvas as { nodes?: unknown } | null)?.nodes;\n if (!Array.isArray(nodes)) return null;\n const original = nodes.find(\n (n): n is { id: string; params?: { url?: unknown } } => (n as { id?: unknown })?.id === \"original\",\n );\n const url = original?.params?.url;\n return typeof url === \"string\" && /^https?:\\/\\//.test(url) ? url : null;\n}\n\n/**\n * Save the proven ad's picture under canvas/references/ (never committed), so the agent looks at\n * the ad itself before it says why it won. Its workspace-relative path, or null when it could not\n * be fetched: the outline then says where to find it.\n */\nasync function saveReferencePicture(root: string, canvasPath: string, adId: string): Promise<string | null> {\n const url = await readFile(canvasPath, \"utf8\").then(\n (text) => referencePictureUrl(JSON.parse(text)),\n () => null,\n );\n return url ? await savePicture(root, url, adId) : null;\n}\n\n/** Save one proven ad's picture under canvas/references/; its workspace-relative path, or null. */\nasync function savePicture(root: string, url: string, adId: string): Promise<string | null> {\n try {\n const response = await fetch(url, { signal: AbortSignal.timeout(20_000) });\n if (!response.ok) return null;\n const ext = path.extname(new URL(url).pathname).toLowerCase() || \".jpg\";\n const relative = path.join(\"canvas\", \"references\", `${adId}${ext}`);\n await mkdir(path.join(root, \"canvas\", \"references\"), { recursive: true });\n await writeFile(path.join(root, relative), Buffer.from(await response.arrayBuffer()));\n return relative;\n } catch {\n return null;\n }\n}\n\n/** The kept reference with its picture, and every ad of its board with theirs, saved for the agent to open. */\nasync function withPictures(root: string, canvasPath: string, reference: Picked) {\n const picture = await saveReferencePicture(root, canvasPath, reference.adId);\n const board = reference.board ? await savedBoard(root, reference.board, reference.adId, picture) : undefined;\n return { ...reference, ...(picture ? { picture } : {}), ...(board ? { board } : {}) };\n}\n\n/** The board with each picture saved (the kept ad's already is), for the agent to open. */\nasync function savedBoard(root: string, board: readonly BoardAd[], keptId: string, keptPicture: string | null) {\n return await Promise.all(\n board.map(async ({ adId, advertiser, mediaUrl }) => {\n const picture = adId === keptId ? keptPicture : mediaUrl ? await savePicture(root, mediaUrl, adId) : null;\n return { adId, ...(advertiser ? { advertiser } : {}), ...(picture ? { picture } : {}) };\n }),\n );\n}\n\n/** Record the idea on the creative, outline the thinking it is made from, and set its message as the ad's one message; mark the idea built. */\nasync function recordIdea(\n root: string,\n slug: string,\n idea: Idea,\n evidence: EvidenceLevel | \"explore\",\n reference: Picked | null,\n): Promise<{ dir: string; unsourcedCopy: string[] }> {\n const dir = path.join(root, \"src\", \"creatives\", slug);\n const definitionPath = path.join(dir, \"_definition.md\");\n const definition = await readFile(definitionPath, \"utf8\").catch(() => null);\n if (definition !== null) {\n const recorded = setDefinitionFields(definition, { ...definitionFieldsOf(idea, evidence) });\n const thinkingReference = reference\n ? await withPictures(root, path.join(dir, `${slug}.canvas.json`), reference)\n : null;\n const inventory = await castInventory(root, idea.message, await companyName(root));\n // The company's rules on who appears, what shows and its logo, as they stand now: the cast is decided under them.\n const castRules = (\n await readCreativeContext(root, { kind: idea.format.startsWith(\"video_\") ? \"video\" : \"static\" })\n ).rules\n .filter((r) => r.applies === \"cast\" || r.applies === \"picture\" || r.applies === \"logo\")\n .map((r) => ({ id: r.id, strength: r.strength, text: r.text }));\n const audience = memeRegister(await readCompanyReading(root).catch(() => null));\n await writeFile(\n definitionPath,\n withThinking(\n recorded,\n thinkingOutline({\n idea,\n reference: thinkingReference,\n inventory,\n rules: castRules,\n ...(audience ? { audience } : {}),\n }),\n ),\n \"utf8\",\n );\n }\n const promptPath = path.join(dir, \"prompt.json\");\n const prompt = isVideoIdea(idea) ? null : await readFile(promptPath, \"utf8\").catch(() => null);\n // A spec that does not parse is the scaffold's to report; the message is set by hand then.\n if (prompt !== null) {\n const personas = await readPersonas(root).catch(() => []);\n const written = (() => {\n try {\n return setSpecViewer(setSpecMessage(prompt, idea.message), idea, personas);\n } catch {\n return null;\n }\n })();\n if (written !== null) await writeFile(promptPath, written, \"utf8\").catch(() => undefined);\n }\n const unsourcedCopy = prompt === null ? [] : await draftedClaims(root, prompt);\n await keepDraft(root, slug, promptPath);\n if (idea.status === \"idea\") {\n const ideaPath = path.join(root, IDEAS_DIR, `${idea.id}.md`);\n await writeFile(ideaPath, setDefinitionFields(await readFile(ideaPath, \"utf8\"), { status: \"built\" }), \"utf8\");\n }\n // The dashboard learns the idea now, not at Publish (where most verdicts are given already).\n await baker([\"canvas\", \"sync-definition\", dir]);\n return { dir, unsourcedCopy };\n}\n\n/** Keep the prompt.json make leaves, so a later make knows the ad is still its draft. */\nasync function keepDraft(root: string, slug: string, promptPath: string): Promise<void> {\n const written = await readFile(promptPath, \"utf8\").catch(() => null);\n if (written === null) return;\n await mkdir(path.dirname(draftPath(root, slug)), { recursive: true });\n await writeFile(draftPath(root, slug), written, \"utf8\");\n}\n\n/** The drafted lines claiming what neither the Knowledge nor our own customers said. */\nasync function draftedClaims(root: string, prompt: string): Promise<string[]> {\n const [knowledge, insights] = await Promise.all([readKnowledgeCorpus(root), readInsights(root)]);\n const own = insights.filter(sourcesClaims).map((i) => i.quote);\n try {\n return unsourcedCopyLines(prompt, `${knowledge}\\n${own.join(\"\\n\")}`);\n } catch {\n return [];\n }\n}\n\n/**\n * make's flags. `--platform` once named the reference's library, and agents read it as where the\n * ad runs: beside `--reference` it still means the library, alone it is refused. Pure.\n */\nexport function makeArgsOf(args: Record<string, unknown>): MakeArgs | Failure {\n const opts: MakeArgs = {};\n for (const key of [\"slug\", \"adset\", \"reference\", \"platforms\", \"formats\", \"spec\", \"series\", \"avatar\"] as const) {\n const value = flag(args[key]);\n if (value) opts[key] = value;\n }\n const referencePlatform = flag(args[\"reference-platform\"]) ?? (opts.reference ? flag(args.platform) : undefined);\n if (referencePlatform) opts.referencePlatform = referencePlatform;\n if (flag(args.platform) && !opts.reference) {\n return {\n code: \"INVALID_ARGUMENT\",\n message: `--platform ${flag(args.platform)} is ambiguous: it named the library of --reference.`,\n fix: \"--platforms says where the ad runs (baker creatives make <idea> --platforms linkedin); --reference-platform says which library the reference is in.\",\n };\n }\n if (args[\"from-idea\"] === true) opts.fromIdea = true;\n return opts;\n}\n\n/** Where the ad runs as the scaffold's flags: the platforms, and the sizes only when they were asked for. Pure. */\nexport function deliveryFlags(\n delivery: { platforms: readonly string[] },\n args: Pick<MakeArgs, \"formats\">,\n kind: \"static\" | \"video\" = \"static\",\n): string[] {\n const sizes = args.formats && kind === \"static\" ? [\"--formats\", args.formats] : [];\n return [\"--platforms\", delivery.platforms.join(\",\"), ...sizes];\n}\n\nfunction scaffoldFailure(scaffold: Record<string, unknown>): Failure {\n const error = (scaffold.error ?? {}) as Partial<Failure>;\n return {\n code: error.code ?? \"SCAFFOLD_FAILED\",\n message: error.message ?? \"The creative could not be scaffolded.\",\n ...(error.fix ? { fix: error.fix } : {}),\n };\n}\n\ntype Made = {\n slug: string;\n idea: Idea;\n check: IdeaCheck | undefined;\n reference: Picked | null;\n /** Why the static starts from the idea itself: no proven ad fits (or `--from-idea`). */\n fromIdea?: string;\n conceptUnseeded?: string;\n viewer: { adset: string } | { temperature: ViewerTemperature };\n canvasPath: string;\n scaffoldHints: string[];\n /** Drafted copy lines claiming a figure the company never wrote (often the reference's own promise). */\n unsourcedCopy: string[];\n /** Where the ad runs and the size designed first; absent for a video with no platform said. */\n delivery?: { platforms: readonly string[]; lead: string };\n /** How a static's sizes are made (cut from one picture, or laid out again) and why (`staticShapeFor`). */\n shape?: { shape: string; reason: string };\n};\n\nconst CARRY_WORDS: Record<ConceptCarry, string> = {\n whole_ad: \"the whole ad (its disguise, layout and hook)\",\n layout: \"its layout\",\n hook: \"its hook\",\n angle: \"its angle\",\n};\n\n/** What the agent tells the person about the proven ad a creative is built on. Pure. */\nfunction builtOnHint(reference: Picked): string {\n const tell = \"Tell the person which proven ad this builds on\";\n const ours = \"the words, brand, people and claims stay ours.\";\n if (!reference.fit) {\n // Chosen by hand: no fit read what made it win, so nothing is said of it.\n return `Built on proven ad ${reference.adId}, the one chosen for it; no check read what made it win. The canvas shows that ad as \\`original\\`. ${tell}; ${ours}`;\n }\n const carried = CARRY_WORDS[reference.fit.carry ?? \"whole_ad\"];\n const why = reference.fit.carry_why ? ` (${reference.fit.carry_why})` : \"\";\n const won = reference.why ? ` It won on: ${reference.why}.` : \"\";\n const chosen = reference.preferred\n ? ` Chosen over the other proven ads that fit because ${reference.preferred.replace(/\\.$/, \"\")}.`\n : \"\";\n const passed = (reference.passed ?? [])\n .map(\n (p) =>\n ` Passed over ${p.advertiser ? `${p.advertiser}'s proven ad` : \"proven ad\"} ${p.adId}: ${p.why.replace(/\\.$/, \"\")}.`,\n )\n .join(\"\");\n const whyNot = passed ? \", and in one line why not the ones passed over\" : \"\";\n // Named by hand (`--reference`, or the one a re-cast keeps): checked, never searched for.\n const byHand = reference.tried === 0 ? \", the one chosen for it\" : \"\";\n return `Built on proven ad ${reference.adId}${byHand}: it carries ${carried}${why}.${won}${chosen}${passed} The canvas shows that ad as \\`original\\`. ${tell} and what it takes from it${whyNot}; ${ours}`;\n}\n\n/** The fix for a concept make could not seed: the fit already made, written in by hand. Pure. */\nconst unseededHint = (reference: Picked, slug: string, why: string) =>\n `${why}, so the render does not see proven ad ${reference.adId} yet. \\`baker winning-ads fit ${reference.adId} --platform ${reference.platform} --full\\` prints the check already made (free): write its \\`read\\` into src/creatives/${slug}/prompt.json as \\`concept\\`, with \\`reference_ad_id: \"${reference.adId}\"\\`.`;\n\n/** The step before any word of the ad: answer the definition's thinking `make` outlined. Pure. */\nfunction thinkFirstHint(made: Made): string {\n const basis = made.reference ? \"what the proven ad is and why it won\" : \"why this bet should work\";\n const board =\n (made.reference?.board?.length ?? 0) > 1\n ? \" what to take from which of the proven ads that fit (the hook of one, the proof of another),\"\n : \"\";\n const survives = made.reference ? \" what of it must survive,\" : \"\";\n const read = made.reference\n ? \"first open the proven ads' pictures the outline names and read .claude/skills/creative-canvas-ads/references/reading-a-winner.md, then \"\n : \"\";\n // Only a creative built on a proven ad is re-cast on it; one built from its idea has nothing to keep.\n const recast = made.reference\n ? ` When the cast is an Avatar the canvas was not built with, \\`baker creatives make ${made.idea.id}${made.slug === made.idea.id ? \"\" : ` --slug ${made.slug}`} --avatar <handle>\\` rebuilds it on the same proven ad before you write prompt.json.`\n : \"\";\n return `Think first: ${read}answer every question under \"Thinking\" in src/creatives/${made.slug}/_definition.md before you touch prompt.json (how: .claude/skills/creative-canvas-ads/references/creative-intent.md): ${basis},${board} whether it fits our viewer, our hook, who appears and what of the product shows (decided from what the company has, listed there: its Avatars, real customers, founder, product pictures, logos),${survives} and the plan.${recast} This thinking decides the ad; the run renders nothing while a question is open or the cast is not ours.`;\n}\n\n/** The ad written from the definition's plan, in the files the render reads. Pure. */\nfunction writeTheAdHint(made: Made, quote: string | undefined): string {\n const words = `say the message in the customer's words${quote ? ` (\"${quote.slice(0, 80)}\")` : \"\"}; keep \\`message\\` as it is`;\n if (made.idea.format.startsWith(\"video_\")) {\n return `Then write the ad from \"The plan\": its scene files and prompt.json carry every decision (the render never reads the definition); ${words}.`;\n }\n const drafted = made.reference\n ? \" The drafted lines are the reference's: keep one only if the Knowledge says it (badges, ratings and guarantees too).\"\n : \"\";\n return `Then write the ad from \"The plan\" in src/creatives/${made.slug}/prompt.json, every decision in its fields (the render never reads the definition); ${words}.${drafted} Read static-image-flow.md first. Inspect existing Avatars before creating an actor. Keep interfaces native and requested overlays separate. Preserve plausible anatomy, device proportions, scale, perspective and support; reflow text rather than distort it. Honour the requested sizes.`;\n}\n\n/** What `make` prints: the creative, the idea it carries, and the two steps left to the agent. Pure. */\nexport function makeEnvelope(made: Made) {\n const quote = made.check?.quote;\n return {\n ok: true as const,\n data: {\n creative: made.slug,\n idea: made.idea.id,\n message: made.idea.message,\n evidence: made.check?.evidence ?? \"explore\",\n ...(quote ? { customer_quote: quote } : {}),\n ...(made.fromIdea ? { built_from: \"idea\" } : {}),\n ...(made.reference\n ? {\n reference: {\n ad_id: made.reference.adId,\n platform: made.reference.platform,\n why_it_wins: made.reference.why,\n ...(made.reference.fit?.carry ? { carry: made.reference.fit.carry } : {}),\n ...(made.reference.preferred ? { chosen_because: made.reference.preferred } : {}),\n },\n }\n : {}),\n viewer: made.viewer,\n ...(made.delivery ? { platforms: made.delivery.platforms, lead: made.delivery.lead } : {}),\n ...(made.shape ? { master_shape: made.shape } : {}),\n canvas_path: made.canvasPath,\n },\n hints: [\n ...(made.reference ? [builtOnHint(made.reference)] : []),\n ...(made.reference && made.conceptUnseeded\n ? [unseededHint(made.reference, made.slug, made.conceptUnseeded)]\n : []),\n ...(made.fromIdea\n ? [\n `${made.fromIdea} So this ad starts from the idea: write the scene and every line of copy in src/creatives/${made.slug}/prompt.json (a placeholder refuses to run). Tell the person this ad is not built on a proven ad, and why, in plain words.`,\n ]\n : []),\n ...(made.unsourcedCopy.length > 0\n ? [\n `Rewrite before running: ${made.unsourcedCopy.map((l) => JSON.stringify(l)).join(\", \")} claim a figure nothing the company wrote holds (the reference's promise, not ours).`,\n ]\n : []),\n thinkFirstHint(made),\n writeTheAdHint(made, quote),\n SPEC_SHAPES_HINT,\n `Then: baker canvas run ${made.canvasPath} (it validates and asks the viewer itself: nothing to run before it).`,\n // The scaffold's own next steps name a separate validate; the run does it (dev, Oct 2026: five validates before one run).\n ...made.scaffoldHints\n .filter((h) => !/canvas (?:validate|viewer-check)/.test(h))\n // make checked the reference and seeded its concept: the scaffold ran before the fit answered.\n .filter((h) => !(made.reference?.fit && h.startsWith(NO_FIT_HINT)))\n .slice(0, 4),\n ],\n };\n}\n\n/** Where the idea's ads run: its `platforms`, else the one platform its own words name. Pure. */\nexport function ideaPlatforms(idea: Idea): string[] | undefined {\n if (idea.platforms && idea.platforms.length > 0) return idea.platforms;\n const named = platformsNamedIn([idea.message, idea.who, idea.why, idea.format].join(\" \"));\n return named.length > 0 ? named : undefined;\n}\n\n/**\n * Where the ad runs: `--platforms`, else the creative's definition (with the sizes it records),\n * else the idea's, else its Meta ad set. A static with none is refused (the fix says where to take it from); a video's sizes do\n * not follow from it, so a video with none is made without.\n */\nasync function makeDelivery(\n root: string,\n idea: Idea,\n args: MakeArgs,\n slug: string,\n): Promise<{ delivery?: ResolvedDelivery; flags: string[] }> {\n const definition = await readFile(path.join(root, \"src\", \"creatives\", slug, \"_definition.md\"), \"utf8\").catch(\n () => null,\n );\n const flags = { platforms: args.platforms, formats: args.formats, \"target-adset\": args.adset };\n const resolved = await scaffoldDelivery(flags, definition, ideaPlatforms(idea));\n const video = isVideoIdea(idea);\n if (resolved.ok)\n return { delivery: resolved.delivery, flags: deliveryFlags(resolved.delivery, args, video ? \"video\" : \"static\") };\n if (video && resolved.error.code === \"platform_required\") return { flags: [] };\n return fail({ code: resolved.error.code.toUpperCase(), message: resolved.error.message, fix: resolved.error.fix });\n}\n\n/** `--series <lead>`: the idea made as another ad of the lead's series, printed or refused. */\nasync function makeInSeries(\n root: string,\n idea: Idea,\n slug: string,\n lead: string,\n evidence: EvidenceLevel | \"explore\",\n): Promise<void> {\n if (isVideoIdea(idea)) {\n fail({\n code: \"SERIES_STATIC_ONLY\",\n message: `\"${idea.id}\" is a video idea: a series repeats one static ad with other words.`,\n fix: `Make it on its own: baker creatives make ${idea.id} --spec <beats file>.`,\n });\n }\n const made = await makeSeriesAd(root, idea, slug, lead, evidence, {\n sync: (dir) => baker([\"canvas\", \"sync-definition\", dir, \"--title\"]),\n chatId: optionalChatId() ?? null,\n });\n if (\"code\" in made) fail(made);\n const leadDefinition = await readFile(path.join(root, \"src\", \"creatives\", lead, \"_definition.md\"), \"utf8\").catch(\n () => \"\",\n );\n const leadPlatforms = parseDefinitionDelivery(leadDefinition)?.platforms;\n writeJson(\n seriesMadeEnvelope(\n { ...made, canvasPath: path.relative(root, made.canvasPath), ...(leadPlatforms ? { leadPlatforms } : {}) },\n idea,\n ),\n );\n}\n\nexport const makeCommand = defineCommand({\n meta: { name: \"make\", description: DESCRIPTION },\n args: ARGS,\n async run({ args }) {\n const root = findWorkspaceRoot(process.cwd()) ?? process.cwd();\n const opts = makeArgsOf(args);\n if (\"code\" in opts) return fail(opts);\n const { idea, check } = await loadIdea(root, String(args.idea));\n const slug = opts.slug ?? idea.id;\n const written = await readFile(path.join(root, \"src\", \"creatives\", slug, \"prompt.json\"), \"utf8\").then(\n (text): unknown => {\n try {\n return JSON.parse(text);\n } catch {\n return {};\n }\n },\n (err: NodeJS.ErrnoException) => (err.code === \"ENOENT\" ? null : {}),\n );\n const draft = await readFile(draftPath(root, slug), \"utf8\").catch(() => undefined);\n const refused = alreadyWritten(written, slug, draft);\n if (refused) fail(refused);\n if (opts.series) {\n await makeInSeries(root, idea, slug, opts.series, check?.evidence ?? \"explore\");\n return;\n }\n // Where the ad runs decides its sizes: settled before any reference is searched, never defaulted.\n const { delivery, flags } = await makeDelivery(root, idea, opts, slug);\n const temperature = await viewerTemperature(root, opts.adset, idea.awareness);\n const { scaffold, reference, fromIdea, conceptUnseeded } = await scaffoldIdea(\n root,\n idea,\n opts,\n slug,\n temperature,\n flags,\n );\n if (scaffold.ok !== true) fail(scaffoldFailure(scaffold));\n const { dir, unsourcedCopy } = await recordIdea(root, slug, idea, check?.evidence ?? \"explore\", reference);\n const canvasPath = String(scaffold.canvas_path ?? path.join(dir, `${slug}.canvas.json`));\n const shape = recordedShape(await readFile(canvasPath, \"utf8\").then(JSON.parse, () => null));\n writeJson(\n makeEnvelope({\n slug,\n idea,\n check,\n reference,\n ...(fromIdea ? { fromIdea } : {}),\n ...(conceptUnseeded ? { conceptUnseeded } : {}),\n viewer: opts.adset ? { adset: opts.adset } : { temperature },\n canvasPath: path.relative(root, canvasPath),\n scaffoldHints: Array.isArray(scaffold.hints) ? (scaffold.hints as string[]) : [],\n unsourcedCopy,\n ...(delivery ? { delivery } : {}),\n ...(shape ? { shape } : {}),\n }),\n );\n },\n});\n","/**\n * What a proven ad for one idea is searched with: what this ad sells, its industry and the people\n * it is for, in the plain English the ads library files ads under, with who buys it and what the\n * brand never does. One small model reads the company's own notes and the idea once per idea.\n * Prod, Oct 2026: COMPANY.md's first line, the query until then, gave the library \"https\", a\n * brand name or a table header for 6 of 14 companies, and a company selling several lines (a\n * trade school's electricians, plumbers and data-centre technicians) searched one for all.\n */\nimport { createHash } from \"node:crypto\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { memeRegister, readCompanyReading } from \"../../engine/creative-context/company.ts\";\nimport { askAboutText, type ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport { holdUnbilledSpend } from \"../canvas/unbilled-spend.ts\";\n\nexport type ReferenceBuyer = \"consumer\" | \"small_business\" | \"enterprise\";\nexport type ReferenceHumour = \"fits\" | \"risky\" | \"off_brand\";\nexport type ReferenceMemes = \"fits\" | \"off_brand\";\n\nexport type ReferenceBrief = {\n /** What this ad sells, 2-6 words: \"trade school training program\". */\n category: string;\n /** The broader industry: \"vocational education\". */\n industry?: string;\n /** Who the ad is for and their problem: \"unemployed workers seeking stable technical trades\". */\n audience?: string;\n buyer?: ReferenceBuyer;\n /** ISO country the ad runs in; null when it runs in several. */\n country?: string | null;\n humour?: ReferenceHumour;\n /** Whether the brand's voice runs memes and reaction faces, and the voice line that says so. */\n memes?: ReferenceMemes;\n memesWhy?: string;\n /** What the brand's rules forbid in an ad: \"urgency\", \"price figures\". */\n avoid: string[];\n /** The company's own brand and product names: its own ads are never a reference for a new one. */\n brands: string[];\n /**\n * Searches that widen from this ad, closest first, for when ads of exactly this product are\n * few: an adjacent product the same buyer weighs, the same buyer buying something else, the same\n * kind of decision. Prod set, Oct 2026: a padel-court builder's buyer is a club investor, and a\n * real-estate developer's render with its key facts was the best reference for it.\n */\n wider: string[];\n};\n\nconst text = z\n .string()\n .transform((s) => s.trim())\n .pipe(z.string().min(1))\n .optional()\n .catch(undefined);\n\nconst shortList = (max: number) =>\n z\n .array(z.string())\n .transform((list) =>\n list\n .map((s) => s.trim())\n .filter(Boolean)\n .slice(0, max),\n )\n .catch([]);\n\nconst BriefSchema = z.object({\n category: text,\n industry: text,\n audience: text,\n buyer: z.enum([\"consumer\", \"small_business\", \"enterprise\"]).optional().catch(undefined),\n country: z\n .string()\n .transform((s) => s.trim().toUpperCase())\n .pipe(z.union([z.literal(\"\").transform(() => null), z.string().regex(/^[A-Z]{2}$/)]))\n .optional()\n .catch(undefined),\n humour: z.enum([\"fits\", \"risky\", \"off_brand\"]).optional().catch(undefined),\n avoid: shortList(5),\n brands: shortList(4),\n wider: shortList(4),\n});\n\n/** The model's answer as a brief, or null when it does not say what the ad sells. Pure. */\nexport function parseReferenceBrief(reply: unknown): ReferenceBrief | null {\n const parsed = BriefSchema.safeParse(reply);\n if (!parsed.success || !parsed.data.category) return null;\n const { category, avoid, brands, wider, ...rest } = parsed.data;\n const known = Object.fromEntries(Object.entries(rest).filter(([, v]) => v !== undefined));\n return { category, ...known, avoid, brands, wider };\n}\n\n/** Read once per idea, about a second (measured on 14 companies, Oct 2026). */\nexport const REFERENCE_BRIEF_MODEL = \"google/gemini-3.5-flash-lite\";\nconst REFERENCE_BRIEF_REQUEST = {\n provider: { order: [\"google-vertex\"], allow_fallbacks: false },\n seed: 0,\n temperature: 0,\n response_format: { type: \"json_object\" },\n};\nconst REFERENCE_BRIEF_TIMEOUT_MS = 20_000;\n/** The company's notes the brief reads: past this, the rest is detail the search does not need. */\nconst MAX_COMPANY_CHARS = 12_000;\n\n/** The ad a brief is read for: what it says and who it is for, in the persona's words. */\nexport type BriefedAd = { message: string; who: string };\n\n/** The question the model answers about this one ad; the company's own facts come from its reading. Pure. */\nexport function referenceBriefPrompt(companyDoc: string, ad: BriefedAd): string {\n return `You prepare a search of a library of proven ads (Meta, LinkedIn, TikTok, Google) for the ad below. The library's search reads short English phrases the way it files ads: by what the ad sells, its industry and who it is for.\n\nThe company (its own notes):\n\"\"\"\n${companyDoc.slice(0, MAX_COMPANY_CHARS)}\n\"\"\"\n\nThe ad we are making:\n- Says: ${ad.message}\n- For: ${ad.who}\n\nAnswer only JSON:\n{\n \"category\": \"what THIS ad sells, 2-6 plain English words a library would file it under, no brand names (e.g. 'electrician training course', 'pet health insurance', 'ecommerce customer service AI')\",\n \"industry\": \"the broader industry, 1-3 English words (e.g. 'vocational education', 'insurance', 'customer service software')\",\n \"audience\": \"who the ad is for and the problem they have, 4-9 plain English words (e.g. 'unemployed adults looking for a stable trade')\",\n \"wider\": [\"4 library searches of 2-6 English words that widen from this ad, closest first, for when ads of exactly this product are few. 1: an adjacent product the same buyer weighs (e.g. 'tennis court construction'). 2: the same buyer buying something else (e.g. 'gym and sports club owners'). 3 and 4: the same kind of decision with NO word of this product's category, as other industries sell it (e.g. for a padel-court builder: 'turnkey franchise investment', 'commercial real estate investment'; for an acne serum: 'skincare before and after'). Never brand names\"]\n}`;\n}\n\n/** Asks the model a prompt and returns its JSON answer, or null when nobody answered. */\nexport type AskBrief = (prompt: string) => Promise<unknown>;\n\n/** The live model, its spend held for the workspace's next bill like every other check's. */\nconst askBriefModel =\n (root: string): AskBrief =>\n async (prompt) => {\n const spent: ReviewUsage[] = [];\n const answer = await askAboutText(REFERENCE_BRIEF_MODEL, prompt, (u) => spent.push(u), {\n timeoutMs: REFERENCE_BRIEF_TIMEOUT_MS,\n request: REFERENCE_BRIEF_REQUEST,\n }).catch(() => null);\n await holdUnbilledSpend(path.join(root, \"canvas\", \".cache\"), spent).catch(() => undefined);\n return answer;\n };\n\nconst briefCachePath = (root: string, key: string) =>\n path.join(root, \"canvas\", \".cache\", \"reference-brief\", `${key}.json`);\n\n/**\n * The brief for one ad of this workspace's company: what this ad sells and to whom, read from the\n * cache when the company's notes and the ad are unchanged, else asked once, with the company's own\n * facts (its buyer, country, humour and brands) from its reading (`readCompanyReading`); null when\n * the model does not answer. What the brand never does is the caller's: its rules.\n */\nexport async function referenceBriefFor(\n root: string,\n ad: BriefedAd,\n ask: AskBrief = askBriefModel(root),\n): Promise<ReferenceBrief | null> {\n const companyDoc = await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => \"\");\n const [company, own] = await Promise.all([readCompanyReading(root, ask), adBrief(root, companyDoc, ad, ask)]);\n if (!own) return null;\n const {\n sells: _sells,\n category: _category,\n industry,\n memes: _memes,\n memes_why: _why,\n ...facts\n } = company ?? { brands: [] };\n const register = memeRegister(company);\n return {\n ...facts,\n ...(register ? { memes: register.memes, ...(register.why ? { memesWhy: register.why } : {}) } : {}),\n ...own,\n ...((own.industry ?? industry) ? { industry: own.industry ?? industry } : {}),\n brands: own.brands.length > 0 ? own.brands : facts.brands,\n };\n}\n\n/** This ad's own part of the brief, kept by the company's notes and the ad. */\nasync function adBrief(root: string, companyDoc: string, ad: BriefedAd, ask: AskBrief): Promise<ReferenceBrief | null> {\n const prompt = referenceBriefPrompt(companyDoc, ad);\n const file = briefCachePath(root, createHash(\"sha256\").update(prompt).digest(\"hex\").slice(0, 16));\n const cached = await readFile(file, \"utf8\")\n .then((raw) => parseReferenceBrief(JSON.parse(raw)))\n .catch(() => null);\n if (cached) return cached;\n const brief = parseReferenceBrief(await ask(prompt));\n if (!brief) return null;\n await mkdir(path.dirname(file), { recursive: true });\n await writeFile(file, `${JSON.stringify(brief, null, 2)}\\n`, \"utf8\");\n return brief;\n}\n","/**\n * The order the found references are checked in: each read against the ad being made by the\n * decision model (docs/decision-model.md), three yes/no questions an ad, all in one request of\n * about half a second. The search ranks an ad by how well it matches a few words; this asks\n * whether it was made for our kind of buyer, whether our viewer would see themselves in it, and\n * whether our brand could run something like it.\n * Prod set, Oct 2026, 14 companies judged blind (0-10, by a model the pick never used): the\n * reference kept scored 5.0 in the search's order and 6.3 read against the bet first.\n */\nimport { askJevQuestions, type JevAnswer, type JevQuestion } from \"../../engine/nodes/local/lib/jev.ts\";\nimport type { ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport type { ReferenceBuyer, ReferenceHumour, ReferenceMemes } from \"./reference-brief.ts\";\n\n/** The ad being made, as the ranking reads it. */\nexport type RankedFor = {\n category: string;\n industry?: string;\n buyer?: ReferenceBuyer;\n humour?: ReferenceHumour;\n memes?: ReferenceMemes;\n memesWhy?: string;\n avoid?: readonly string[];\n message: string;\n who: string;\n};\n\ntype RankCandidate = {\n ad_id?: string | null;\n advertiser?: string | null;\n format?: string | null;\n dna?: {\n industry?: string | null;\n business_model?: string | null;\n target_persona?: string | null;\n container?: string | null;\n visual?: string | null;\n creative_concept?: string | null;\n mechanism?: string | null;\n } | null;\n};\n\nexport type AskDecisions = (questions: readonly JevQuestion[]) => Promise<JevAnswer[] | null>;\n\nconst BUYERS: Record<ReferenceBuyer, string> = {\n consumer: \"people buying for themselves\",\n small_business: \"small businesses buying for work\",\n enterprise: \"large companies buying for work\",\n};\n\n/** Said to every model that ranks or picks a reference when our brand's voice does not run memes. Pure. */\nexport function memesLine(bet: Pick<RankedFor, \"memes\" | \"memesWhy\">): string {\n return bet.memes === \"off_brand\"\n ? ` Our brand's voice does not run memes${bet.memesWhy ? ` (${bet.memesWhy})` : \"\"}: rank meme and reaction-face ads last.`\n : \"\";\n}\n\n/** The ad being made, in the words every question reads it by. Pure. */\nfunction oursText(bet: RankedFor): string {\n const sells = `${bet.category}${bet.industry ? ` (${bet.industry})` : \"\"}`;\n const buyer = bet.buyer ? `, to ${BUYERS[bet.buyer]}` : \"\";\n const humour = bet.humour === \"off_brand\" ? \" Our brand does not joke in ads.\" : \"\";\n const avoid = bet.avoid?.length ? ` Our brand never uses: ${bet.avoid.join(\", \")}.` : \"\";\n return `We sell: ${sells}${buyer}. Our ad says: \"${bet.message}\". It is for: ${bet.who}.${humour}${memesLine(bet)}${avoid}`;\n}\n\n/** One reference as the questions read it: who made it, for whom, what it looks like and why it works. Pure. */\nfunction cardText(c: RankCandidate): string {\n const d = c.dna ?? {};\n const line = (label: string, value: string | null | undefined) => (value ? `${label}: ${value}` : \"\");\n return [\n line(\"Advertiser\", c.advertiser),\n line(\"Industry\", [d.industry, d.business_model].filter(Boolean).join(\", \")),\n line(\"Made for\", d.target_persona),\n line(\"Looks like\", [d.container ?? c.format, d.visual].filter(Boolean).join(\": \")),\n line(\"Concept\", d.creative_concept),\n line(\"Why it works\", d.mechanism),\n ]\n .filter(Boolean)\n .join(\"\\n\")\n .slice(0, 1400);\n}\n\n/** Twenty ads a request: what the eval measured answering inside the decision model's timeout. */\nconst QUESTIONS_PER_REQUEST = 60;\n\nconst QUESTIONS = [\n \"Was `ad` made for the same kind of buyer as `ours`: a person buying for themselves, or a business buying for work, of a similar size?\",\n \"Would the viewer `ours` is for feel that `ad` speaks to someone like them, about a problem like theirs?\",\n \"Could the brand of `ours` run an ad made like `ad` (its look, its tone, its kind of hook) without breaking its own rules or looking out of character?\",\n];\n\n/**\n * The candidates, those the decision model reads as made for our buyer and viewer and runnable by\n * our brand first (the product of its three answers; ties keep the search's order), or in the\n * search's order when it does not answer.\n */\nexport async function rankForBet<T extends RankCandidate>(\n candidates: readonly T[],\n bet: RankedFor,\n askOverride?: AskDecisions,\n onSpend?: (usage: ReviewUsage) => void,\n): Promise<T[]> {\n const ask: AskDecisions = askOverride ?? ((questions) => askJevQuestions(questions, onSpend));\n if (candidates.length < 2) return [...candidates];\n const ours = oursText(bet);\n const questions: JevQuestion[] = candidates.flatMap((c) =>\n QUESTIONS.map((question) => ({ type: \"noul\" as const, instructions: { ours, ad: cardText(c), question } })),\n );\n const parts: JevQuestion[][] = [];\n for (let start = 0; start < questions.length; start += QUESTIONS_PER_REQUEST) {\n parts.push(questions.slice(start, start + QUESTIONS_PER_REQUEST));\n }\n const replies = await Promise.all(parts.map((part) => ask(part).catch(() => null)));\n if (replies.some((r, i) => !r || r.length !== parts[i]?.length)) return [...candidates];\n const answers = replies.flatMap((r) => r ?? []);\n const scored = candidates.map((c, i) => ({\n c,\n i,\n score: QUESTIONS.reduce((product, _, k) => {\n const answer = answers[i * QUESTIONS.length + k];\n return product * (answer && \"noul\" in answer ? answer.noul : 0.5);\n }, 1),\n }));\n return scored.sort((a, b) => b.score - a.score || a.i - b.i).map((s) => s.c);\n}\n","/**\n * Which of the proven ads that fit the ad is built on: all of them looked at side by side, for\n * the viewer the ad is for, in one vision call. The fit checks one ad at a time and passes most\n * of what it is shown, so keeping the first that passed kept a good ad, rarely the best one.\n * Prod set, Oct 2026, 14 companies judged blind (0-10, by a model the pick never used): the\n * reference kept scored 6.3 kept as the first that fit and 7.4 picked side by side.\n */\nimport { askAboutImages, type ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport { decisionOf, isVital } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport type { FitAnswer } from \"../winning-ads/fit.ts\";\nimport { memesLine, type RankedFor } from \"./reference-rank.ts\";\n\n/** A stronger reader than the fit's: it compares, once per ad made. */\nexport const REFERENCE_PICK_MODEL = \"~google/gemini-pro-latest\";\nconst REFERENCE_PICK_TIMEOUT_MS = 60_000;\n\n/** One reference that fit, with its picture (a base64 JPEG) and the fit's read of it. */\nexport type PickOption = {\n adId: string;\n advertiser?: string;\n picture: string;\n fit: Pick<FitAnswer, \"why_it_wins\" | \"our_viewer\"> & Partial<Pick<FitAnswer, \"load_bearing\">>;\n};\n\n/** What stops the scroll in a reference and its proof, each with what of ours does its job, as the fit read them. Pure. */\nfunction vitalRead(fit: PickOption[\"fit\"]): string {\n const vital = (fit.load_bearing ?? []).filter(isVital).map((l) => {\n const ours = decisionOf(l) === \"keep\" ? \"kept as it is\" : l.ours?.trim() ? `ours: ${l.ours.trim()}` : \"\";\n return `${l.job === \"stop\" ? \"stops the scroll with\" : \"proof:\"} ${l.element}${ours ? ` (${ours})` : \"\"}`;\n });\n return vital.length > 0 ? ` It ${vital.join(\"; \")}.` : \"\";\n}\n\nexport type AskPick = (pictures: string[], prompt: string) => Promise<unknown>;\n\n/** The parts of an ad a media buyer takes from one proven ad or another. */\nexport const TAKE_ELEMENTS = [\"hook\", \"visual\", \"who_appears\", \"proof\", \"layout\", \"call_to_action\"] as const;\nexport type TakeElement = (typeof TAKE_ELEMENTS)[number];\n\n/** One element our ad takes from one proven ad, and why it applies to our viewer. */\nexport type Take = { element: TakeElement; adId: string; what: string; applies: string };\n/** Something of a proven ad our ad must not copy, and why. */\nexport type Avoid = { adId: string; what: string; why: string };\n\n/** The side-by-side pick: the options best first, why the first won, what to take from which and what not to copy. */\nexport type ReferencePick = { order: number[]; why?: string; takes?: Take[]; avoid?: Avoid[] };\n\n/** The question, the ad being made and what the fit read of each picture, numbered as shown. Pure. */\nexport function referencePickPrompt(options: readonly PickOption[], bet: RankedFor): string {\n const reads = options\n .map((o, i) => {\n const wins = Object.values(o.fit.why_it_wins ?? {})\n .filter(Boolean)\n .join(\"; \");\n const viewer = o.fit.our_viewer ? ` Our viewer: ${o.fit.our_viewer.stops}, ${o.fit.our_viewer.why}` : \"\";\n return `${i + 1}. ${o.advertiser ?? \"an advertiser\"}: wins on ${wins || \"(not read)\"}.${vitalRead(o.fit)}${viewer}`;\n })\n .join(\"\\n\");\n // Dev, Oct 2026: read past its words, \"no stock photography\" ranked a meme's reaction faces out.\n const avoid = bet.avoid?.length\n ? ` The brand never uses: ${bet.avoid.join(\", \").replace(/\\.$/, \"\")}. Its rules forbid only what they name: \"no stock photography\" never rules out a meme's reaction face, our own people or our Avatars.`\n : \"\";\n const humour = `${bet.humour === \"off_brand\" ? \" The brand does not joke in ads.\" : \"\"}${memesLine(bet)}`;\n return `Pick the proven ad our next ad should be built on. Images 1..${options.length} are proven ads of other advertisers, each already checked to be adaptable.\n\nWe sell: ${bet.category}${bet.industry ? ` (${bet.industry})` : \"\"}. Our ad says: \"${bet.message}\". It is for: ${bet.who}.${humour}${avoid}\n\nWhat the check read of each:\n${reads}\n\nRank them by how likely a version of each, made for us, stops this exact viewer and makes them act: the viewer must see themselves and their problem in it, its winning move must carry our offer as strongly as theirs, and our brand must be able to run it.\n\nThen, as a media buyer does, say what our ad takes. Our ad may combine several: the hook of one, the visual of another, the proof of a third. For each element worth taking (${TAKE_ELEMENTS.join(\", \")}), the image whose version of it would work best for us, exactly what to take, and why it applies to this viewer. Leave out an element no image does well for us. Then what our ad must not copy from them: a device that misleads or that the platform restricts (a fake newspaper or news page, a fake app notification), dated urgency, another brand's marks, words that hide what is sold; never what stops the scroll or the proof, which ours keeps as named above. A rule forbids only what it names: \"no stock photography\" never rules out a meme's reaction face, our own people or our Avatars; when a rule of ours is why, quote the rule word for word.\n\nAnswer only JSON: {\"ranking\": [image numbers, best first], \"why\": \"one sentence on why the first beats the others\", \"takes\": [{\"element\": \"hook\", \"from\": image number, \"what\": \"...\", \"applies\": \"...\"}], \"avoid\": [{\"from\": image number, \"what\": \"...\", \"why\": \"...\"}]}`;\n}\n\n/** The options' indices best first (each once, any it left out after, in order), or null. Pure. */\nexport function readPickRanking(reply: unknown, count: number): number[] | null {\n const ranking = (reply as { ranking?: unknown } | null)?.ranking;\n if (!Array.isArray(ranking)) return null;\n const order: number[] = [];\n for (const n of ranking) {\n const index = Number(n) - 1;\n if (Number.isInteger(index) && index >= 0 && index < count && !order.includes(index)) order.push(index);\n }\n if (order.length === 0) return null;\n for (let i = 0; i < count; i++) if (!order.includes(i)) order.push(i);\n return order;\n}\n\nconst text = (value: unknown): string => (typeof value === \"string\" ? value.trim() : \"\");\n\n/** The image a reply names (1-based), as its option's ad id; null when it names none shown. Pure. */\nfunction adOf(from: unknown, options: readonly PickOption[]): string | null {\n return options[Number(from) - 1]?.adId ?? null;\n}\n\n/** What the reply says to take from which option, only known elements of shown options, each element once. Pure. */\nexport function readTakes(reply: unknown, options: readonly PickOption[]): Take[] {\n const takes = (reply as { takes?: unknown } | null)?.takes;\n if (!Array.isArray(takes)) return [];\n const read: Take[] = [];\n for (const t of takes as Record<string, unknown>[]) {\n const element = TAKE_ELEMENTS.find((e) => e === t?.element);\n const adId = adOf(t?.from, options);\n if (!element || !adId || !text(t.what) || read.some((r) => r.element === element)) continue;\n read.push({ element, adId, what: text(t.what), applies: text(t.applies) });\n }\n return read;\n}\n\n/** What the reply says not to copy, only from shown options. Pure. */\nexport function readAvoid(reply: unknown, options: readonly PickOption[]): Avoid[] {\n const avoid = (reply as { avoid?: unknown } | null)?.avoid;\n if (!Array.isArray(avoid)) return [];\n return (avoid as Record<string, unknown>[]).flatMap((a) => {\n const adId = adOf(a?.from, options);\n return adId && text(a.what) ? [{ adId, what: text(a.what), why: text(a.why) }] : [];\n });\n}\n\n/** The live model, its spend handed to `onSpend`. */\nexport const askPickModel =\n (onSpend?: (usage: ReviewUsage) => void): AskPick =>\n (pictures, prompt) =>\n askAboutImages(REFERENCE_PICK_MODEL, pictures, prompt, onSpend, REFERENCE_PICK_TIMEOUT_MS).catch(() => null);\n\n/** The options in the order the side-by-side look prefers, why the first won and what to take from which; null when nobody answered. */\nexport async function pickAmong(\n options: readonly PickOption[],\n bet: RankedFor,\n ask: AskPick = askPickModel(),\n): Promise<ReferencePick | null> {\n const reply = await ask(\n options.map((o) => o.picture),\n referencePickPrompt(options, bet),\n );\n const order = readPickRanking(reply, options.length);\n if (!order) return null;\n const why = text((reply as { why?: unknown }).why);\n const takes = readTakes(reply, options);\n const avoid = readAvoid(reply, options);\n return {\n order,\n ...(why ? { why } : {}),\n ...(takes.length > 0 ? { takes } : {}),\n ...(avoid.length > 0 ? { avoid } : {}),\n };\n}\n"],"mappings":"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","names":["mkdir","readFile","writeFile","path","questions","text","path","text","readFile","writeFile","mkdir"]}