@koda-sl/baker-cli 0.495.0-dev.c2b64ccca → 0.498.0-dev.e2ca08ce6
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.
- package/dist/{brief-B7C3SYDP.js → brief-ECEIKJFK.js} +5 -5
- package/dist/{canvas-XCP2WPYO.js → canvas-MNZLQZ74.js} +12 -12
- package/dist/{check-NDPR32FH.js → check-R7IMU36G.js} +3 -3
- package/dist/{chunk-7XH4UQWS.js → chunk-5OAFKP6L.js} +5 -2
- package/dist/{chunk-7XH4UQWS.js.map → chunk-5OAFKP6L.js.map} +1 -1
- package/dist/{chunk-SQQ4VBNI.js → chunk-5OLCELV7.js} +2 -2
- package/dist/{chunk-IGOOLUE2.js → chunk-A7MTWTMM.js} +3 -3
- package/dist/{chunk-WZDKROPU.js → chunk-FHYUIYU5.js} +2 -2
- package/dist/{chunk-PPMSWLQC.js → chunk-GPWT42O3.js} +2 -2
- package/dist/{chunk-G2AZCDX4.js → chunk-HGTLGFKV.js} +3 -3
- package/dist/{chunk-QAOEVZYY.js → chunk-HY6DIWDV.js} +4 -4
- package/dist/{chunk-7FDDOOM4.js → chunk-IBJA2A4E.js} +2 -2
- package/dist/{chunk-OFTU5XBQ.js → chunk-MKL7CL4P.js} +2 -2
- package/dist/{chunk-3AOMKBDC.js → chunk-NDIBFOFB.js} +8 -8
- package/dist/{chunk-72QBQS63.js → chunk-OTLYELOW.js} +2 -2
- package/dist/{chunk-T5HB6R4I.js → chunk-T235G4C7.js} +2 -2
- package/dist/{chunk-BVMXTD4B.js → chunk-ZPMGYAYZ.js} +3 -3
- package/dist/{chunk-BVMXTD4B.js.map → chunk-ZPMGYAYZ.js.map} +1 -1
- package/dist/cli.js +3 -3
- package/dist/{creatives-NJ7SZ3S4.js → creatives-NHH4J2XW.js} +9 -9
- package/dist/{critique-LINKOKOE.js → critique-7OGWN5Q4.js} +4 -4
- package/dist/{feedback-HT2M63QW.js → feedback-XF2TOS4P.js} +2 -2
- package/dist/{feedback-record-V7UU6CG3.js → feedback-record-YPNGCJWS.js} +6 -6
- package/dist/{fit-S5ZGPNE3.js → fit-INDYA6KP.js} +3 -3
- package/dist/{ideas-HHTLPC6Y.js → ideas-ZFODHYVK.js} +3 -3
- package/dist/{make-4XCSN76S.js → make-GJPQRROG.js} +10 -10
- package/dist/{rerun-NWOGRYHU.js → rerun-77XP2DAH.js} +9 -9
- package/dist/{rules-DSLE6LVU.js → rules-HJGFA6OT.js} +4 -4
- package/dist/{rules-add-NBOMKFAI.js → rules-add-3YBX7UGL.js} +7 -5
- package/dist/rules-add-3YBX7UGL.js.map +1 -0
- package/dist/{run-IRJWKZ3K.js → run-WBFKGA42.js} +9 -9
- package/dist/{scaffold-ad-3BSA7BWT.js → scaffold-ad-6YO574PA.js} +6 -6
- package/dist/{scaffold-static-ad-Q26LLBWQ.js → scaffold-static-ad-WBC2U5U4.js} +11 -11
- package/dist/{scaffold-video-WE52C7YZ.js → scaffold-video-2ZJMQMEZ.js} +6 -6
- package/dist/{select-4IQQNKLN.js → select-ONK2GLKS.js} +6 -6
- package/dist/{set-prompt-DE4TD2V7.js → set-prompt-KQSUL77B.js} +4 -4
- package/dist/{stale-E34H24C3.js → stale-G25M2P7Q.js} +5 -5
- package/dist/{sync-definition-DTWEW6ZC.js → sync-definition-PGVMZTOX.js} +6 -6
- package/dist/{translate-V6XPDX4M.js → translate-SI6LSIY6.js} +8 -8
- package/dist/{validate-VTAKQGD5.js → validate-QNBI74BM.js} +4 -4
- package/dist/{viewer-check-3T2EZOSH.js → viewer-check-TEQ3WP2N.js} +4 -4
- package/dist/{winning-ads-F765TFLS.js → winning-ads-EVOFUO3N.js} +2 -2
- package/package.json +1 -1
- package/dist/rules-add-NBOMKFAI.js.map +0 -1
- /package/dist/{brief-B7C3SYDP.js.map → brief-ECEIKJFK.js.map} +0 -0
- /package/dist/{canvas-XCP2WPYO.js.map → canvas-MNZLQZ74.js.map} +0 -0
- /package/dist/{check-NDPR32FH.js.map → check-R7IMU36G.js.map} +0 -0
- /package/dist/{chunk-SQQ4VBNI.js.map → chunk-5OLCELV7.js.map} +0 -0
- /package/dist/{chunk-IGOOLUE2.js.map → chunk-A7MTWTMM.js.map} +0 -0
- /package/dist/{chunk-WZDKROPU.js.map → chunk-FHYUIYU5.js.map} +0 -0
- /package/dist/{chunk-PPMSWLQC.js.map → chunk-GPWT42O3.js.map} +0 -0
- /package/dist/{chunk-G2AZCDX4.js.map → chunk-HGTLGFKV.js.map} +0 -0
- /package/dist/{chunk-QAOEVZYY.js.map → chunk-HY6DIWDV.js.map} +0 -0
- /package/dist/{chunk-7FDDOOM4.js.map → chunk-IBJA2A4E.js.map} +0 -0
- /package/dist/{chunk-OFTU5XBQ.js.map → chunk-MKL7CL4P.js.map} +0 -0
- /package/dist/{chunk-3AOMKBDC.js.map → chunk-NDIBFOFB.js.map} +0 -0
- /package/dist/{chunk-72QBQS63.js.map → chunk-OTLYELOW.js.map} +0 -0
- /package/dist/{chunk-T5HB6R4I.js.map → chunk-T235G4C7.js.map} +0 -0
- /package/dist/{creatives-NJ7SZ3S4.js.map → creatives-NHH4J2XW.js.map} +0 -0
- /package/dist/{critique-LINKOKOE.js.map → critique-7OGWN5Q4.js.map} +0 -0
- /package/dist/{feedback-HT2M63QW.js.map → feedback-XF2TOS4P.js.map} +0 -0
- /package/dist/{feedback-record-V7UU6CG3.js.map → feedback-record-YPNGCJWS.js.map} +0 -0
- /package/dist/{fit-S5ZGPNE3.js.map → fit-INDYA6KP.js.map} +0 -0
- /package/dist/{ideas-HHTLPC6Y.js.map → ideas-ZFODHYVK.js.map} +0 -0
- /package/dist/{make-4XCSN76S.js.map → make-GJPQRROG.js.map} +0 -0
- /package/dist/{rerun-NWOGRYHU.js.map → rerun-77XP2DAH.js.map} +0 -0
- /package/dist/{rules-DSLE6LVU.js.map → rules-HJGFA6OT.js.map} +0 -0
- /package/dist/{run-IRJWKZ3K.js.map → run-WBFKGA42.js.map} +0 -0
- /package/dist/{scaffold-ad-3BSA7BWT.js.map → scaffold-ad-6YO574PA.js.map} +0 -0
- /package/dist/{scaffold-static-ad-Q26LLBWQ.js.map → scaffold-static-ad-WBC2U5U4.js.map} +0 -0
- /package/dist/{scaffold-video-WE52C7YZ.js.map → scaffold-video-2ZJMQMEZ.js.map} +0 -0
- /package/dist/{select-4IQQNKLN.js.map → select-ONK2GLKS.js.map} +0 -0
- /package/dist/{set-prompt-DE4TD2V7.js.map → set-prompt-KQSUL77B.js.map} +0 -0
- /package/dist/{stale-E34H24C3.js.map → stale-G25M2P7Q.js.map} +0 -0
- /package/dist/{sync-definition-DTWEW6ZC.js.map → sync-definition-PGVMZTOX.js.map} +0 -0
- /package/dist/{translate-V6XPDX4M.js.map → translate-SI6LSIY6.js.map} +0 -0
- /package/dist/{validate-VTAKQGD5.js.map → validate-QNBI74BM.js.map} +0 -0
- /package/dist/{viewer-check-3T2EZOSH.js.map → viewer-check-TEQ3WP2N.js.map} +0 -0
- /package/dist/{winning-ads-F765TFLS.js.map → winning-ads-EVOFUO3N.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engine/creative-context/ad-words.ts","../src/commands/creatives/cast-inventory.ts","../src/commands/canvas/rule-gate.ts"],"sourcesContent":["/**\n * What one ad says, as the company's wording rules are checked on it: a static's printed words, or\n * a video's script, every spoken line and every word on screen (its subtitles are its spoken\n * words); the language it is in, the product it sells and the rules it waives.\n */\nimport { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { frontmatterOf } from \"../../commands/creatives/ideas-model.ts\";\nimport { nativeCopy } from \"../scaffold/native-surface.ts\";\nimport { isAdSpec, readAdSpec } from \"../scaffold/static-ad-spec.ts\";\n\nexport type AdWords = {\n kind: \"static\" | \"video\";\n lines: string[];\n /** The language its words are in (a BCP-47 tag), when the ad or its definition says. */\n language?: string;\n product?: string;\n /** The platform it runs on, as its definition names it: a platform's rules hold for it. */\n platform?: string;\n /** The rules the person asked this ad to depart from (`waive`). */\n waived: string[];\n};\n\nconst json = (file: string): Promise<unknown> =>\n readFile(file, \"utf8\")\n .then((raw): unknown => JSON.parse(raw))\n .catch(() => null);\n\nconst text = (value: unknown): string | undefined =>\n typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n\n/** The rules a spec waives, by id. Pure. */\nfunction waivedOf(spec: unknown): string[] {\n const waive = (spec as { waive?: unknown } | null)?.waive;\n return Array.isArray(waive) ? waive.flatMap((w) => text((w as { rule?: unknown } | null)?.rule) ?? []) : [];\n}\n\n/** A video scene's spoken lines and on-screen words. Pure. */\nfunction sceneWords(scene: unknown): string[] {\n const s = (scene ?? {}) as { dialogue?: unknown; overlays?: unknown };\n const spoken = Array.isArray(s.dialogue)\n ? s.dialogue.flatMap((d) => text((d as { line?: unknown })?.line) ?? [])\n : [];\n const shown = Array.isArray(s.overlays) ? s.overlays.flatMap((o) => text((o as { text?: unknown })?.text) ?? []) : [];\n return [...spoken, ...shown];\n}\n\n/** A video's scene files, in order. */\nasync function sceneFiles(creativeDir: string): Promise<unknown[]> {\n const dir = path.join(creativeDir, \"scenes\");\n const files = (await readdir(dir).catch(() => [] as string[])).filter((f) => f.endsWith(\".json\")).sort();\n return await Promise.all(files.map((f) => json(path.join(dir, f))));\n}\n\n/** The language a video is spoken in: its definition's, else its beats spec's voice. */\nasync function videoLanguage(creativeDir: string): Promise<string | undefined> {\n const definition = frontmatterOf(await readFile(path.join(creativeDir, \"_definition.md\"), \"utf8\").catch(() => \"\"));\n const beats = (await json(path.join(creativeDir, \"ad.spec.json\"))) as { voice?: { language?: unknown } } | null;\n return text(definition?.language) ?? text(beats?.voice?.language);\n}\n\n/** A video's script, spoken lines and on-screen words, and the language it is spoken in. */\nasync function videoWords(raw: Record<string, unknown>, creativeDir: string): Promise<Omit<AdWords, \"waived\">> {\n const global = (raw.global ?? {}) as { transcript?: unknown };\n const transcript = text(global.transcript);\n const scenes = [...(Array.isArray(raw.scenes) ? raw.scenes : []), ...(await sceneFiles(creativeDir))];\n const lines = [...new Set([...(transcript ? [transcript] : []), ...scenes.flatMap(sceneWords)])];\n const language = await videoLanguage(creativeDir);\n return { kind: \"video\", lines, ...(language ? { language } : {}) };\n}\n\n/** A static's printed words and the language its viewer reads; null when it is not an ad spec. Pure. */\nfunction staticWords(raw: unknown): Omit<AdWords, \"waived\"> | null {\n try {\n const spec = readAdSpec(raw);\n const lines = spec.native ? nativeCopy(spec.native) : spec.copy.map((l) => l.text);\n const language = spec.viewer?.market?.language;\n return { kind: \"static\", lines, ...(language ? { language } : {}) };\n } catch {\n return null;\n }\n}\n\n/** One creative folder's words for the wording rules; null when it has no ad written yet. */\nexport async function readAdWords(creativeDir: string): Promise<AdWords | null> {\n const raw = (await json(path.join(creativeDir, \"prompt.json\"))) as Record<string, unknown> | null;\n if (!raw || typeof raw !== \"object\") return null;\n const video = !isAdSpec(raw) && (\"global\" in raw || \"scenes\" in raw);\n const words = video ? await videoWords(raw, creativeDir) : staticWords(raw);\n if (!words) return null;\n const product = text(raw.product);\n const definition = frontmatterOf(await readFile(path.join(creativeDir, \"_definition.md\"), \"utf8\").catch(() => \"\"));\n const platform = text(definition?.platform);\n return { ...words, ...(product ? { product } : {}), ...(platform ? { platform } : {}), waived: waivedOf(raw) };\n}\n","/**\n * What the company has to cast and show in an ad, read before anyone is cast: its Avatars (real\n * people and ones made for a role), customers' own words for this message, and its logos. A media\n * buyer starts from the material in hand; production chats started from the image model.\n */\nimport { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { AvatarsListResponse, TestimonialsSearchResponse } from \"@baker/api\";\nimport { apiPost } from \"../../client.ts\";\nimport { readAvatars } from \"../avatars/transport.ts\";\n\nexport type CastInventory = {\n /** Ready Avatars: `real` when built from a real person's own pictures or profile. */\n avatars: { handle: string; real: boolean; who: string }[];\n /** Customers' own words for this message, best first. */\n customers: { name?: string; words: string; source: string; photo: boolean }[];\n /** The brand's logo files, workspace-relative. */\n logos: string[];\n /** The company's name, for finding its founder. */\n company?: string;\n};\n\nconst short = (text: string, max: number) => (text.length > max ? `${text.slice(0, max - 1).trimEnd()}…` : text);\n\n/** The ready Avatars, as the inventory lists them. Pure. */\nexport function avatarsOf(response: AvatarsListResponse): CastInventory[\"avatars\"] {\n return response.avatars\n .filter((a) => a.status === \"ready\")\n .map((a) => {\n const real = a.likeness === \"licensed\" || Boolean(a.person);\n const role = [a.person?.role, a.person?.company].filter(Boolean).join(\" at \");\n return { handle: a.handle, real, who: short(role || a.subjectDescription || a.name, 90) };\n });\n}\n\n/** Customers' words for this message, the ones with something to say first, at most three. Pure. */\nexport function customersOf(found: TestimonialsSearchResponse): CastInventory[\"customers\"] {\n return found\n .filter((t) => t.sentiment !== \"negative\" && (t.highlight || t.reviewText).trim())\n .slice(0, 3)\n .map((t) => ({\n ...(t.reviewerName ? { name: t.reviewerName } : {}),\n words: short((t.highlight || t.reviewText).trim().replace(/\\s+/g, \" \"), 140),\n source: t.sourceType,\n photo: Boolean(t.reviewerImageUrl || t.reviewerImageId || t.imageIds?.length || t.videoIds?.length),\n }));\n}\n\nconst LOGO_FILE = /\\.(svg|png|webp|jpe?g)$/i;\n\n/** Everything the company has to build with; each part empty when it cannot be read. */\nexport async function castInventory(root: string, message: string, company?: string): Promise<CastInventory> {\n const [avatars, customers, logos] = await Promise.all([\n readAvatars<AvatarsListResponse>(\"/api/avatars\", { status: \"ready\" }).then(avatarsOf, () => []),\n apiPost<TestimonialsSearchResponse>(\"/api/testimonials/search\", { query: message, limit: 6 }).then(\n customersOf,\n () => [],\n ),\n readdir(path.join(root, \"src\", \"brand\", \"logos\")).then(\n (files) => files.filter((f) => LOGO_FILE.test(f)).map((f) => `src/brand/logos/${f}`),\n () => [],\n ),\n ]);\n return { avatars, customers, logos, ...(company ? { company } : {}) };\n}\n","/**\n * The company's wording rules, held before a render: an ad whose words break a never or a must\n * (a phrase it bans, or one every ad must say) is refused, free, naming the line, the rule and the\n * person's own words. Prod, Oct 2026: '\"100 % online\", no \"online\"' was rejected on five ads of one\n * company in one day, each after it had rendered. A person's explicit ask keeps the words: the ad\n * waives the rule in its prompt.json, visibly.\n */\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { type AdWords, readAdWords } from \"../../engine/creative-context/ad-words.ts\";\nimport type { CreativeRule } from \"../../engine/creative-rules/schema.ts\";\nimport { readCreativeContext, workspaceOfCreative } from \"../../engine/creative-context/index.ts\";\nimport { type RuleTell, ruleTells } from \"../../engine/copy-tells/rule-tells.ts\";\nimport { marketFromCompanyDoc } from \"../../viewer-profile.ts\";\nimport { findWorkspaceRoot } from \"./normalize-paths.ts\";\nimport { readAvatars } from \"../avatars/transport.ts\";\nimport { avatarsOf } from \"../creatives/cast-inventory.ts\";\nimport type { RealPeopleOnly } from \"../creatives/cast-decision.ts\";\nimport type { AvatarsListResponse } from \"@baker/api\";\n\nexport type RuleRefusal = { problems: string[]; fix: string };\n\n/** One broken rule, as the refusal names it. Pure. */\nfunction tellLine(tell: RuleTell): string {\n const where =\n tell.kind === \"forbidden\" ? `\"${tell.line ?? \"\"}\" says \"${tell.phrase}\"` : `No line says \"${tell.phrase}\"`;\n const words = tell.quote ? ` Their words: ${tell.quote}` : \"\";\n return `${where}: ${tell.rule} (${tell.strength}) — ${tell.text}${words}`;\n}\n\n/** The refusal for the rules an ad's words break; null when they break none. Pure. */\nexport function ruleRefusal(tells: readonly RuleTell[]): RuleRefusal | null {\n if (tells.length === 0) return null;\n return {\n problems: tells.map(tellLine),\n fix: 'Rewrite each line named above within its rule (a static: its `copy` in prompt.json; a video: its scene files and ad.spec.json), then re-run. Only when the person explicitly asked for these words in this ad, keep them and add to prompt.json `\"waive\": [{\"rule\": \"<id>\", \"why\": \"<their ask>\"}]`.',\n };\n}\n\n/** The Avatars on the company's roster, each real or made for a role; null when it cannot be read. */\nexport type ReadRoster = () => Promise<ReadonlyArray<{ handle: string; real: boolean }> | null>;\n\nconst liveRoster: ReadRoster = () =>\n readAvatars<AvatarsListResponse>(\"/api/avatars\", { status: \"ready\" }).then(avatarsOf, () => null);\n\n/** The rules that hold the ad in `creativeDir` and the language its words are in (else the company market's). */\nexport async function heldRules(\n creativeDir: string,\n ad?: AdWords | null,\n): Promise<{ rules: CreativeRule[]; language?: string }> {\n const words = ad === undefined ? await readAdWords(creativeDir) : ad;\n const root = findWorkspaceRoot(creativeDir) ?? workspaceOfCreative(creativeDir);\n const context = await readCreativeContext(\n root,\n {\n ...(words ? { kind: words.kind } : {}),\n ...(words?.product ? { product: words.product } : {}),\n ...(words?.platform ? { platform: words.platform } : {}),\n },\n { waived: words?.waived ?? [] },\n );\n const language =\n words?.language ??\n marketFromCompanyDoc(await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => null))?.language;\n return { rules: context.rules, ...(language ? { language } : {}) };\n}\n\n/**\n * The company's rules as they hold the ad in `creativeDir`, read from the workspace as it stands:\n * the wording rules its words break (`broken`), and the rule that only real people appear, with the\n * roster to hold its cast to (`realOnly`, read only when such a rule holds).\n */\nexport async function ruleGate(\n creativeDir: string,\n roster: ReadRoster = liveRoster,\n): Promise<{ broken: RuleRefusal | null; realOnly: RealPeopleOnly | null }> {\n const ad = await readAdWords(creativeDir);\n if (!ad) return { broken: null, realOnly: null };\n const { rules, language } = await heldRules(creativeDir, ad);\n const people = rules.find((r) => r.check?.people === \"real\" && r.strength !== \"prefer\");\n return {\n broken: ruleRefusal(ruleTells(ad.lines, rules, language)),\n realOnly: people\n ? {\n rule: { id: people.id, text: people.text, ...(people.source.quote ? { quote: people.source.quote } : {}) },\n avatars: await roster().catch(() => null),\n }\n : null,\n };\n}\n"],"mappings":"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","names":["readdir","path","text","readdir","path","readFile","path","readFile","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/engine/creative-context/ad-words.ts","../src/commands/creatives/cast-inventory.ts","../src/commands/canvas/rule-gate.ts"],"sourcesContent":["/**\n * What one ad says, as the company's wording rules are checked on it: a static's printed words, or\n * a video's script, every spoken line and every word on screen (its subtitles are its spoken\n * words); the language it is in, the product it sells and the rules it waives.\n */\nimport { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { frontmatterOf } from \"../../commands/creatives/ideas-model.ts\";\nimport { nativeCopy } from \"../scaffold/native-surface.ts\";\nimport { isAdSpec, readAdSpec } from \"../scaffold/static-ad-spec.ts\";\n\nexport type AdWords = {\n kind: \"static\" | \"video\";\n lines: string[];\n /** The language its words are in (a BCP-47 tag), when the ad or its definition says. */\n language?: string;\n product?: string;\n /** The platform it runs on, as its definition names it: a platform's rules hold for it. */\n platform?: string;\n /** The rules the person asked this ad to depart from (`waive`). */\n waived: string[];\n};\n\nconst json = (file: string): Promise<unknown> =>\n readFile(file, \"utf8\")\n .then((raw): unknown => JSON.parse(raw))\n .catch(() => null);\n\nconst text = (value: unknown): string | undefined =>\n typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n\n/** The rules a spec waives, by id. Pure. */\nfunction waivedOf(spec: unknown): string[] {\n const waive = (spec as { waive?: unknown } | null)?.waive;\n return Array.isArray(waive) ? waive.flatMap((w) => text((w as { rule?: unknown } | null)?.rule) ?? []) : [];\n}\n\n/** A video scene's spoken lines and on-screen words. Pure. */\nfunction sceneWords(scene: unknown): string[] {\n const s = (scene ?? {}) as { dialogue?: unknown; overlays?: unknown };\n const spoken = Array.isArray(s.dialogue)\n ? s.dialogue.flatMap((d) => text((d as { line?: unknown })?.line) ?? [])\n : [];\n const shown = Array.isArray(s.overlays) ? s.overlays.flatMap((o) => text((o as { text?: unknown })?.text) ?? []) : [];\n return [...spoken, ...shown];\n}\n\n/** A video's scene files, in order. */\nasync function sceneFiles(creativeDir: string): Promise<unknown[]> {\n const dir = path.join(creativeDir, \"scenes\");\n const files = (await readdir(dir).catch(() => [] as string[])).filter((f) => f.endsWith(\".json\")).sort();\n return await Promise.all(files.map((f) => json(path.join(dir, f))));\n}\n\n/** The language a video is spoken in: its definition's, else its beats spec's voice. */\nasync function videoLanguage(creativeDir: string): Promise<string | undefined> {\n const definition = frontmatterOf(await readFile(path.join(creativeDir, \"_definition.md\"), \"utf8\").catch(() => \"\"));\n const beats = (await json(path.join(creativeDir, \"ad.spec.json\"))) as { voice?: { language?: unknown } } | null;\n return text(definition?.language) ?? text(beats?.voice?.language);\n}\n\n/** A video's script, spoken lines and on-screen words, and the language it is spoken in. */\nasync function videoWords(raw: Record<string, unknown>, creativeDir: string): Promise<Omit<AdWords, \"waived\">> {\n const global = (raw.global ?? {}) as { transcript?: unknown };\n const transcript = text(global.transcript);\n const scenes = [...(Array.isArray(raw.scenes) ? raw.scenes : []), ...(await sceneFiles(creativeDir))];\n const lines = [...new Set([...(transcript ? [transcript] : []), ...scenes.flatMap(sceneWords)])];\n const language = await videoLanguage(creativeDir);\n return { kind: \"video\", lines, ...(language ? { language } : {}) };\n}\n\n/** A static's printed words and the language its viewer reads; null when it is not an ad spec. Pure. */\nfunction staticWords(raw: unknown): Omit<AdWords, \"waived\"> | null {\n try {\n const spec = readAdSpec(raw);\n const lines = spec.native ? nativeCopy(spec.native) : spec.copy.map((l) => l.text);\n const language = spec.viewer?.market?.language;\n return { kind: \"static\", lines, ...(language ? { language } : {}) };\n } catch {\n return null;\n }\n}\n\n/** One creative folder's words for the wording rules; null when it has no ad written yet. */\nexport async function readAdWords(creativeDir: string): Promise<AdWords | null> {\n const raw = (await json(path.join(creativeDir, \"prompt.json\"))) as Record<string, unknown> | null;\n if (!raw || typeof raw !== \"object\") return null;\n const video = !isAdSpec(raw) && (\"global\" in raw || \"scenes\" in raw);\n const words = video ? await videoWords(raw, creativeDir) : staticWords(raw);\n if (!words) return null;\n const product = text(raw.product);\n const definition = frontmatterOf(await readFile(path.join(creativeDir, \"_definition.md\"), \"utf8\").catch(() => \"\"));\n const platform = text(definition?.platform);\n return { ...words, ...(product ? { product } : {}), ...(platform ? { platform } : {}), waived: waivedOf(raw) };\n}\n","/**\n * What the company has to cast and show in an ad, read before anyone is cast: its Avatars (real\n * people and ones made for a role), customers' own words for this message, and its logos. A media\n * buyer starts from the material in hand; production chats started from the image model.\n */\nimport { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { AvatarsListResponse, TestimonialsSearchResponse } from \"@baker/api\";\nimport { apiPost } from \"../../client.ts\";\nimport { readAvatars } from \"../avatars/transport.ts\";\n\nexport type CastInventory = {\n /** Ready Avatars: `real` when built from a real person's own pictures or profile. */\n avatars: { handle: string; real: boolean; who: string }[];\n /** Customers' own words for this message, best first. */\n customers: { name?: string; words: string; source: string; photo: boolean }[];\n /** The brand's logo files, workspace-relative. */\n logos: string[];\n /** The company's name, for finding its founder. */\n company?: string;\n};\n\nconst short = (text: string, max: number) => (text.length > max ? `${text.slice(0, max - 1).trimEnd()}…` : text);\n\n/** The ready Avatars, as the inventory lists them. Pure. */\nexport function avatarsOf(response: AvatarsListResponse): CastInventory[\"avatars\"] {\n return response.avatars\n .filter((a) => a.status === \"ready\")\n .map((a) => {\n const real = a.likeness === \"licensed\" || Boolean(a.person);\n const role = [a.person?.role, a.person?.company].filter(Boolean).join(\" at \");\n return { handle: a.handle, real, who: short(role || a.subjectDescription || a.name, 90) };\n });\n}\n\n/** Customers' words for this message, the ones with something to say first, at most three. Pure. */\nexport function customersOf(found: TestimonialsSearchResponse): CastInventory[\"customers\"] {\n return found\n .filter((t) => t.sentiment !== \"negative\" && (t.highlight || t.reviewText).trim())\n .slice(0, 3)\n .map((t) => ({\n ...(t.reviewerName ? { name: t.reviewerName } : {}),\n words: short((t.highlight || t.reviewText).trim().replace(/\\s+/g, \" \"), 140),\n source: t.sourceType,\n photo: Boolean(t.reviewerImageUrl || t.reviewerImageId || t.imageIds?.length || t.videoIds?.length),\n }));\n}\n\nconst LOGO_FILE = /\\.(svg|png|webp|jpe?g)$/i;\n\n/** Everything the company has to build with; each part empty when it cannot be read. */\nexport async function castInventory(root: string, message: string, company?: string): Promise<CastInventory> {\n const [avatars, customers, logos] = await Promise.all([\n readAvatars<AvatarsListResponse>(\"/api/avatars\", { status: \"ready\" }).then(avatarsOf, () => []),\n apiPost<TestimonialsSearchResponse>(\"/api/testimonials/search\", { query: message, limit: 6 }).then(\n customersOf,\n () => [],\n ),\n readdir(path.join(root, \"src\", \"brand\", \"logos\")).then(\n (files) => files.filter((f) => LOGO_FILE.test(f)).map((f) => `src/brand/logos/${f}`),\n () => [],\n ),\n ]);\n return { avatars, customers, logos, ...(company ? { company } : {}) };\n}\n","/**\n * The company's wording rules, held before a render: an ad whose words break a never or a must\n * (a phrase it bans, or one every ad must say) is refused, free, naming the line, the rule and the\n * person's own words. Prod, Oct 2026: '\"100 % online\", no \"online\"' was rejected on five ads of one\n * company in one day, each after it had rendered. A person's explicit ask keeps the words: the ad\n * waives the rule in its prompt.json, visibly.\n */\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { type AdWords, readAdWords } from \"../../engine/creative-context/ad-words.ts\";\nimport type { CreativeRule } from \"../../engine/creative-rules/schema.ts\";\nimport { readCreativeContext, workspaceOfCreative } from \"../../engine/creative-context/index.ts\";\nimport { type RuleTell, ruleTells } from \"../../engine/copy-tells/rule-tells.ts\";\nimport { marketFromCompanyDoc } from \"../../viewer-profile.ts\";\nimport { findWorkspaceRoot } from \"./normalize-paths.ts\";\nimport { readAvatars } from \"../avatars/transport.ts\";\nimport { avatarsOf } from \"../creatives/cast-inventory.ts\";\nimport type { RealPeopleOnly } from \"../creatives/cast-decision.ts\";\nimport type { AvatarsListResponse } from \"@baker/api\";\n\nexport type RuleRefusal = { problems: string[]; fix: string };\n\n/** One broken rule, as the refusal names it. Pure. */\nfunction tellLine(tell: RuleTell): string {\n const where =\n tell.kind === \"forbidden\" ? `\"${tell.line ?? \"\"}\" says \"${tell.phrase}\"` : `No line says \"${tell.phrase}\"`;\n const words = tell.quote ? ` Their words: ${tell.quote}` : \"\";\n return `${where}: ${tell.rule} (${tell.strength}) — ${tell.text}${words}`;\n}\n\n/** The refusal for the rules an ad's words break; null when they break none. Pure. */\nexport function ruleRefusal(tells: readonly RuleTell[]): RuleRefusal | null {\n if (tells.length === 0) return null;\n return {\n problems: [...new Set(tells.map(tellLine))],\n fix: 'Rewrite each line named above within its rule (a static: its `copy` in prompt.json; a video: its scene files and ad.spec.json), then re-run. Only when the person explicitly asked for these words in this ad, keep them and add to prompt.json `\"waive\": [{\"rule\": \"<id>\", \"why\": \"<their ask>\"}]`.',\n };\n}\n\n/** The Avatars on the company's roster, each real or made for a role; null when it cannot be read. */\nexport type ReadRoster = () => Promise<ReadonlyArray<{ handle: string; real: boolean }> | null>;\n\nconst liveRoster: ReadRoster = () =>\n readAvatars<AvatarsListResponse>(\"/api/avatars\", { status: \"ready\" }).then(avatarsOf, () => null);\n\n/** The rules that hold the ad in `creativeDir` and the language its words are in (else the company market's). */\nexport async function heldRules(\n creativeDir: string,\n ad?: AdWords | null,\n): Promise<{ rules: CreativeRule[]; language?: string }> {\n const words = ad === undefined ? await readAdWords(creativeDir) : ad;\n const root = findWorkspaceRoot(creativeDir) ?? workspaceOfCreative(creativeDir);\n const context = await readCreativeContext(\n root,\n {\n ...(words ? { kind: words.kind } : {}),\n ...(words?.product ? { product: words.product } : {}),\n ...(words?.platform ? { platform: words.platform } : {}),\n },\n { waived: words?.waived ?? [] },\n );\n const language =\n words?.language ??\n marketFromCompanyDoc(await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => null))?.language;\n return { rules: context.rules, ...(language ? { language } : {}) };\n}\n\n/**\n * The company's rules as they hold the ad in `creativeDir`, read from the workspace as it stands:\n * the wording rules its words break (`broken`), and the rule that only real people appear, with the\n * roster to hold its cast to (`realOnly`, read only when such a rule holds).\n */\nexport async function ruleGate(\n creativeDir: string,\n roster: ReadRoster = liveRoster,\n): Promise<{ broken: RuleRefusal | null; realOnly: RealPeopleOnly | null }> {\n const ad = await readAdWords(creativeDir);\n if (!ad) return { broken: null, realOnly: null };\n const { rules, language } = await heldRules(creativeDir, ad);\n const people = rules.find((r) => r.check?.people === \"real\" && r.strength !== \"prefer\");\n return {\n broken: ruleRefusal(ruleTells(ad.lines, rules, language)),\n realOnly: people\n ? {\n rule: { id: people.id, text: people.text, ...(people.source.quote ? { quote: people.source.quote } : {}) },\n avatars: await roster().catch(() => null),\n }\n : null,\n };\n}\n"],"mappings":"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","names":["readdir","path","text","readdir","path","readFile","path","readFile","path"]}
|
package/dist/cli.js
CHANGED
|
@@ -118,7 +118,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
|
118
118
|
gsc: () => import("./gsc-WHMPFTYA.js").then((m) => m.gscCommand),
|
|
119
119
|
research: () => import("./research-XRVD2GSG.js").then((m) => m.researchCommand),
|
|
120
120
|
decide: () => import("./decide-ZODJU7DY.js").then((m) => m.decideCommand),
|
|
121
|
-
creatives: () => import("./creatives-
|
|
121
|
+
creatives: () => import("./creatives-NHH4J2XW.js").then((m) => m.creativesCommand),
|
|
122
122
|
flows: () => import("./flows-5SXT5F22.js").then((m) => m.flowsCommand),
|
|
123
123
|
funnel: () => import("./funnel-QDYX3UH5.js").then((m) => m.funnelCommand),
|
|
124
124
|
images: () => import("./images-PV6TZQLL.js").then((m) => m.imagesCommand),
|
|
@@ -127,7 +127,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
|
127
127
|
landing: () => import("./landing-4V7HMYCZ.js").then((m) => m.landingCommand),
|
|
128
128
|
videos: () => import("./videos-M6VK66NI.js").then((m) => m.videosCommand),
|
|
129
129
|
testimonials: () => import("./testimonials-PA2FUV4H.js").then((m) => m.testimonialsCommand),
|
|
130
|
-
canvas: () => import("./canvas-
|
|
130
|
+
canvas: () => import("./canvas-MNZLQZ74.js").then((m) => m.canvasCommand),
|
|
131
131
|
tags: () => import("./tags-DOJUSHJB.js").then((m) => m.tagsCommand),
|
|
132
132
|
"tag-manager": () => import("./tag-manager-ARFZU46G.js").then((m) => m.tagManagerCommand),
|
|
133
133
|
chats: () => import("./chats-JKCUA26S.js").then((m) => m.chatsCommand),
|
|
@@ -136,7 +136,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
|
136
136
|
hubspot: () => import("./hubspot-B4IUIOYX.js").then((m) => m.hubspotCommand),
|
|
137
137
|
activecampaign: () => import("./activecampaign-77V5X3FQ.js").then((m) => m.activecampaignCommand),
|
|
138
138
|
accounts: () => import("./accounts-GBRGCLE3.js").then((m) => m.accountsCommand),
|
|
139
|
-
"winning-ads": () => import("./winning-ads-
|
|
139
|
+
"winning-ads": () => import("./winning-ads-EVOFUO3N.js").then((m) => m.winningAdsCommand),
|
|
140
140
|
"media-sources": () => import("./media-sources-ZLBIC4RM.js").then((m) => m.mediaSourcesCommand),
|
|
141
141
|
site: () => import("./site-VTJU5CRE.js").then((m) => m.siteCommand),
|
|
142
142
|
mcp: () => import("./mcp-RQJAEJCJ.js").then((m) => m.mcpCommand),
|
|
@@ -39,15 +39,15 @@ How published creatives are doing in live Meta ads (results, fatigue, angle; hoo
|
|
|
39
39
|
Full guide: __tooling__/docs/tools/baker/creatives.md`
|
|
40
40
|
},
|
|
41
41
|
subCommands: {
|
|
42
|
-
brief: () => import("./brief-
|
|
43
|
-
ideas: () => import("./ideas-
|
|
44
|
-
make: () => import("./make-
|
|
45
|
-
translate: () => import("./translate-
|
|
42
|
+
brief: () => import("./brief-ECEIKJFK.js").then((m) => m.briefCommand),
|
|
43
|
+
ideas: () => import("./ideas-ZFODHYVK.js").then((m) => m.ideasCommand),
|
|
44
|
+
make: () => import("./make-GJPQRROG.js").then((m) => m.makeCommand),
|
|
45
|
+
translate: () => import("./translate-SI6LSIY6.js").then((m) => m.translateCommand),
|
|
46
46
|
learn: () => import("./learn-RL66WKHT.js").then((m) => m.learnCommand),
|
|
47
|
-
feedback: () => import("./feedback-
|
|
48
|
-
rules: () => import("./rules-
|
|
49
|
-
check: () => import("./check-
|
|
50
|
-
select: () => import("./select-
|
|
47
|
+
feedback: () => import("./feedback-XF2TOS4P.js").then((m) => m.feedbackCommand),
|
|
48
|
+
rules: () => import("./rules-HJGFA6OT.js").then((m) => m.rulesCommand),
|
|
49
|
+
check: () => import("./check-R7IMU36G.js").then((m) => m.checkCommand),
|
|
50
|
+
select: () => import("./select-ONK2GLKS.js").then((m) => m.selectCommand),
|
|
51
51
|
publish: () => import("./publish-U73OR33K.js").then((m) => m.publishCommand),
|
|
52
52
|
performance: () => import("./performance-BQSWGNFO.js").then((m) => m.performanceCommand)
|
|
53
53
|
}
|
|
@@ -55,4 +55,4 @@ Full guide: __tooling__/docs/tools/baker/creatives.md`
|
|
|
55
55
|
export {
|
|
56
56
|
creativesCommand
|
|
57
57
|
};
|
|
58
|
-
//# sourceMappingURL=creatives-
|
|
58
|
+
//# sourceMappingURL=creatives-NHH4J2XW.js.map
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
FRAME_PLACEHOLDER_NOTE,
|
|
3
3
|
exitOnPrepareError,
|
|
4
4
|
prepareCanvas
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-FHYUIYU5.js";
|
|
6
6
|
import "./chunk-B2SAOVMU.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-ZPMGYAYZ.js";
|
|
8
8
|
import "./chunk-AN7CMLYY.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-5OAFKP6L.js";
|
|
10
10
|
import "./chunk-S4ROJTDY.js";
|
|
11
11
|
import "./chunk-YJAQWTS6.js";
|
|
12
12
|
import "./chunk-MNPBPU3G.js";
|
|
@@ -217,4 +217,4 @@ var critiqueCommand = defineCommand({
|
|
|
217
217
|
export {
|
|
218
218
|
critiqueCommand
|
|
219
219
|
};
|
|
220
|
-
//# sourceMappingURL=critique-
|
|
220
|
+
//# sourceMappingURL=critique-7OGWN5Q4.js.map
|
|
@@ -51,7 +51,7 @@ var feedbackCommand = defineCommand({
|
|
|
51
51
|
meta: { name: "feedback", description: DESCRIPTION },
|
|
52
52
|
subCommands: {
|
|
53
53
|
read: feedbackReadCommand,
|
|
54
|
-
record: () => import("./feedback-record-
|
|
54
|
+
record: () => import("./feedback-record-YPNGCJWS.js").then((m) => m.feedbackRecordCommand)
|
|
55
55
|
},
|
|
56
56
|
// `args` stays although the parent has no `run`: citty finds the subcommand
|
|
57
57
|
// name with THIS command's arg defs, so without them `--slug spring-offer`
|
|
@@ -63,4 +63,4 @@ var feedbackCommand = defineCommand({
|
|
|
63
63
|
export {
|
|
64
64
|
feedbackCommand
|
|
65
65
|
};
|
|
66
|
-
//# sourceMappingURL=feedback-
|
|
66
|
+
//# sourceMappingURL=feedback-XF2TOS4P.js.map
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
} from "./chunk-ELYP6BOS.js";
|
|
8
8
|
import {
|
|
9
9
|
versionOf
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-IBJA2A4E.js";
|
|
11
|
+
import "./chunk-OTLYELOW.js";
|
|
12
|
+
import "./chunk-FHYUIYU5.js";
|
|
13
13
|
import "./chunk-B2SAOVMU.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-ZPMGYAYZ.js";
|
|
15
15
|
import "./chunk-AN7CMLYY.js";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-5OAFKP6L.js";
|
|
17
17
|
import {
|
|
18
18
|
frontmatterOf
|
|
19
19
|
} from "./chunk-S4ROJTDY.js";
|
|
@@ -243,4 +243,4 @@ var feedbackRecordCommand = defineCommand({
|
|
|
243
243
|
export {
|
|
244
244
|
feedbackRecordCommand
|
|
245
245
|
};
|
|
246
|
-
//# sourceMappingURL=feedback-record-
|
|
246
|
+
//# sourceMappingURL=feedback-record-YPNGCJWS.js.map
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
readCachedFit,
|
|
13
13
|
readKnowledge,
|
|
14
14
|
reviewsForFit
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-T235G4C7.js";
|
|
16
|
+
import "./chunk-5OAFKP6L.js";
|
|
17
17
|
import "./chunk-S4ROJTDY.js";
|
|
18
18
|
import "./chunk-WJNLQEOZ.js";
|
|
19
19
|
import "./chunk-6FHP2HIK.js";
|
|
@@ -53,4 +53,4 @@ export {
|
|
|
53
53
|
readKnowledge,
|
|
54
54
|
reviewsForFit
|
|
55
55
|
};
|
|
56
|
-
//# sourceMappingURL=fit-
|
|
56
|
+
//# sourceMappingURL=fit-INDYA6KP.js.map
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
ideasCommand,
|
|
5
5
|
ideasHints,
|
|
6
6
|
ideasReport
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GPWT42O3.js";
|
|
8
8
|
import "./chunk-B2SAOVMU.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-5OAFKP6L.js";
|
|
10
10
|
import "./chunk-S4ROJTDY.js";
|
|
11
11
|
import "./chunk-WJNLQEOZ.js";
|
|
12
12
|
import "./chunk-MMU6XHCH.js";
|
|
@@ -36,4 +36,4 @@ export {
|
|
|
36
36
|
ideasHints,
|
|
37
37
|
ideasReport
|
|
38
38
|
};
|
|
39
|
-
//# sourceMappingURL=ideas-
|
|
39
|
+
//# sourceMappingURL=ideas-ZFODHYVK.js.map
|
|
@@ -10,24 +10,24 @@ import {
|
|
|
10
10
|
notADesignReference,
|
|
11
11
|
pictureOf,
|
|
12
12
|
resolveSourcePlatform
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-T235G4C7.js";
|
|
14
14
|
import {
|
|
15
15
|
makeSeriesAd,
|
|
16
16
|
seriesMadeEnvelope
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-MKL7CL4P.js";
|
|
18
18
|
import "./chunk-WDAWTHQK.js";
|
|
19
19
|
import {
|
|
20
20
|
runBaker
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-HY6DIWDV.js";
|
|
22
22
|
import {
|
|
23
23
|
parseDefinitionSourceFields
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-5OLCELV7.js";
|
|
25
|
+
import "./chunk-OTLYELOW.js";
|
|
26
26
|
import {
|
|
27
27
|
projectStaticBriefs,
|
|
28
28
|
thinkingOutline,
|
|
29
29
|
withThinking
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-FHYUIYU5.js";
|
|
31
31
|
import "./chunk-L44WSWSZ.js";
|
|
32
32
|
import {
|
|
33
33
|
audienceQuery,
|
|
@@ -61,16 +61,16 @@ import {
|
|
|
61
61
|
import {
|
|
62
62
|
liveViewerLookups,
|
|
63
63
|
readPersonas
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-A7MTWTMM.js";
|
|
65
65
|
import {
|
|
66
66
|
castInventory
|
|
67
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-ZPMGYAYZ.js";
|
|
68
68
|
import "./chunk-AN7CMLYY.js";
|
|
69
69
|
import {
|
|
70
70
|
avoidOf,
|
|
71
71
|
readCompanyReading,
|
|
72
72
|
readCreativeContext
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-5OAFKP6L.js";
|
|
74
74
|
import {
|
|
75
75
|
checkIdeas,
|
|
76
76
|
sourcesClaims
|
|
@@ -1134,4 +1134,4 @@ export {
|
|
|
1134
1134
|
seedConcept,
|
|
1135
1135
|
unbuiltReference
|
|
1136
1136
|
};
|
|
1137
|
-
//# sourceMappingURL=make-
|
|
1137
|
+
//# sourceMappingURL=make-GJPQRROG.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
executeCanvasRun
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NDIBFOFB.js";
|
|
4
4
|
import "./chunk-IVRXPYQ7.js";
|
|
5
5
|
import "./chunk-3PL2QRF2.js";
|
|
6
6
|
import "./chunk-WN4KX7GE.js";
|
|
@@ -10,16 +10,16 @@ import "./chunk-IOGKJZ4Z.js";
|
|
|
10
10
|
import "./chunk-Q6ULQMWG.js";
|
|
11
11
|
import "./chunk-KKJ4KJCW.js";
|
|
12
12
|
import "./chunk-3ACMDRSE.js";
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-HY6DIWDV.js";
|
|
14
|
+
import "./chunk-5OLCELV7.js";
|
|
15
|
+
import "./chunk-OTLYELOW.js";
|
|
16
|
+
import "./chunk-FHYUIYU5.js";
|
|
17
17
|
import "./chunk-L44WSWSZ.js";
|
|
18
18
|
import "./chunk-B2SAOVMU.js";
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-A7MTWTMM.js";
|
|
20
|
+
import "./chunk-ZPMGYAYZ.js";
|
|
21
21
|
import "./chunk-AN7CMLYY.js";
|
|
22
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-5OAFKP6L.js";
|
|
23
23
|
import "./chunk-S4ROJTDY.js";
|
|
24
24
|
import "./chunk-YJAQWTS6.js";
|
|
25
25
|
import "./chunk-MNPBPU3G.js";
|
|
@@ -86,4 +86,4 @@ var rerunCommand = defineCommand({
|
|
|
86
86
|
export {
|
|
87
87
|
rerunCommand
|
|
88
88
|
};
|
|
89
|
-
//# sourceMappingURL=rerun-
|
|
89
|
+
//# sourceMappingURL=rerun-77XP2DAH.js.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-QVQKCVP7.js";
|
|
7
7
|
import {
|
|
8
8
|
readAllRules
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-5OAFKP6L.js";
|
|
10
10
|
import "./chunk-S4ROJTDY.js";
|
|
11
11
|
import "./chunk-WJNLQEOZ.js";
|
|
12
12
|
import "./chunk-6FHP2HIK.js";
|
|
@@ -84,12 +84,12 @@ var rulesCommand = defineCommand({
|
|
|
84
84
|
},
|
|
85
85
|
subCommands: {
|
|
86
86
|
list: listCommand,
|
|
87
|
-
add: () => import("./rules-add-
|
|
88
|
-
retire: () => import("./rules-add-
|
|
87
|
+
add: () => import("./rules-add-3YBX7UGL.js").then((m) => m.rulesAddCommand),
|
|
88
|
+
retire: () => import("./rules-add-3YBX7UGL.js").then((m) => m.rulesRetireCommand)
|
|
89
89
|
},
|
|
90
90
|
default: "list"
|
|
91
91
|
});
|
|
92
92
|
export {
|
|
93
93
|
rulesCommand
|
|
94
94
|
};
|
|
95
|
-
//# sourceMappingURL=rules-
|
|
95
|
+
//# sourceMappingURL=rules-HJGFA6OT.js.map
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "./chunk-L44WSWSZ.js";
|
|
10
10
|
import {
|
|
11
11
|
readAllRules
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5OAFKP6L.js";
|
|
13
13
|
import {
|
|
14
14
|
RULES_DIR,
|
|
15
15
|
RULE_APPLIES,
|
|
@@ -325,6 +325,9 @@ var ADD_ARGS = {
|
|
|
325
325
|
}
|
|
326
326
|
};
|
|
327
327
|
registerSchema({ command: "creatives.rules.add", description: ADD_DESCRIPTION, args: ADD_ARGS });
|
|
328
|
+
function brandMdHint(declared, relation) {
|
|
329
|
+
return relation === "same" ? `BRAND.md states this too ("${declared.text}"): now the person confirmed it, every finished ad is checked against it.` : `BRAND.md says otherwise ("${declared.text}"): tell the person, and change only that line of BRAND.md (/brand-build) so it no longer says otherwise; never write the rule itself into BRAND.md, or retiring it would leave it in force.`;
|
|
330
|
+
}
|
|
328
331
|
var rulesAddCommand = defineCommand({
|
|
329
332
|
meta: { name: "add", description: ADD_DESCRIPTION },
|
|
330
333
|
args: ADD_ARGS,
|
|
@@ -405,9 +408,7 @@ var rulesAddCommand = defineCommand({
|
|
|
405
408
|
...compared.judged ? [] : [
|
|
406
409
|
"Whether it repeats or contradicts another rule could not be read (the decision model did not answer): look at `baker creatives rules list`."
|
|
407
410
|
],
|
|
408
|
-
...declared.map(
|
|
409
|
-
(r) => compared.same.includes(r) ? `BRAND.md states this too ("${r.text}"): now the person confirmed it, every finished ad is checked against it.` : `BRAND.md says otherwise ("${r.text}"): tell the person, and update BRAND.md so the two agree (/brand-build).`
|
|
410
|
-
)
|
|
411
|
+
...declared.map((r) => brandMdHint(r, compared.same.includes(r) ? "same" : "conflict"))
|
|
411
412
|
]
|
|
412
413
|
});
|
|
413
414
|
}
|
|
@@ -439,8 +440,9 @@ var rulesRetireCommand = defineCommand({
|
|
|
439
440
|
}
|
|
440
441
|
});
|
|
441
442
|
export {
|
|
443
|
+
brandMdHint,
|
|
442
444
|
ruleFromInputs,
|
|
443
445
|
rulesAddCommand,
|
|
444
446
|
rulesRetireCommand
|
|
445
447
|
};
|
|
446
|
-
//# sourceMappingURL=rules-add-
|
|
448
|
+
//# sourceMappingURL=rules-add-3YBX7UGL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/creatives/rules-add.ts","../src/engine/creative-rules/admission.ts","../src/engine/creative-rules/compare.ts","../src/engine/creative-rules/write.ts"],"sourcesContent":["/**\n * `baker creatives rules add` and `retire`: a rule a person agreed to, saved for every ad from now\n * on as one file in src/content/creative-rules/ (staged in the Session and published with it), and\n * a rule retired, never deleted. A rule is saved only when it is not one the company already has,\n * contradicts none without the person picking the winner, catches the version it came from and\n * blocks none the person approved.\n */\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { CreativesFeedbackResponse } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport sharp from \"sharp\";\nimport { apiPost } from \"../../client.ts\";\nimport { readAllRules } from \"../../engine/creative-context/index.ts\";\nimport {\n type Admission,\n admissionRefusal,\n admissionTest,\n type ReviewedVersion,\n} from \"../../engine/creative-rules/admission.ts\";\nimport { compareRule, jevPairs } from \"../../engine/creative-rules/compare.ts\";\nimport { parseRuleFile, RULES_DIR } from \"../../engine/creative-rules/read.ts\";\nimport {\n type CreativeRule,\n RULE_APPLIES,\n RULE_KINDS,\n RULE_STRENGTHS,\n type RuleCheck,\n type RuleScope,\n} from \"../../engine/creative-rules/schema.ts\";\nimport { ruleFileText, ruleSlug } from \"../../engine/creative-rules/write.ts\";\nimport { reviewAgainstRules } from \"../../engine/nodes/local/lib/rules-review.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { findWorkspaceRoot } from \"../canvas/normalize-paths.ts\";\nimport { fetchRunRecord } from \"../canvas/run-history.ts\";\nimport { holdWorkspaceSpend } from \"../canvas/unbilled-spend.ts\";\nimport { loadCandidate, type SavedCandidate } from \"./rule-candidate.ts\";\nimport { rulesView } from \"./rules-view.ts\";\n\n/** What the flags say of the rule; each overrides the candidate's. */\nexport type RuleFlags = {\n text?: string;\n strength?: string;\n applies?: string;\n forbid?: string[];\n require?: string[];\n allow?: string[];\n people?: string;\n kinds?: string[];\n products?: string[];\n platforms?: string[];\n language?: string;\n quote?: string;\n slug?: string;\n run?: string;\n why?: string;\n id?: string;\n};\n\nconst oneOf = <T extends string>(values: readonly T[], value: string | undefined): T | undefined =>\n value && (values as readonly string[]).includes(value) ? (value as T) : undefined;\n\nconst defined = <T extends object>(value: T): T =>\n Object.fromEntries(\n Object.entries(value).filter(([, v]) => v !== undefined && !(Array.isArray(v) && v.length === 0)),\n ) as T;\n\n/** Where the rule holds: the flags over the candidate's. Pure. */\nfunction scopeOf(f: RuleFlags, c: SavedCandidate | undefined): RuleScope {\n return defined<RuleScope>({\n kinds: (f.kinds ?? c?.kinds)?.flatMap((k) => oneOf(RULE_KINDS, k) ?? []),\n products: f.products,\n platforms: f.platforms ?? c?.platforms,\n language: f.language ?? c?.language,\n });\n}\n\n/** What code decides of the rule: the flags over the candidate's. Pure. */\nfunction checkOf(f: RuleFlags, c: SavedCandidate | undefined): RuleCheck {\n const realPeople = f.people === undefined ? c?.people === \"real\" : f.people === \"real\";\n return defined<RuleCheck>({\n forbid: f.forbid ?? c?.forbid,\n require: f.require ?? c?.require,\n allow: f.allow ?? c?.allow,\n people: realPeople ? \"real\" : undefined,\n });\n}\n\n/** The rule to save, from a drafted candidate and the flags over it; what is missing when there is none. Pure. */\nexport function ruleFromInputs(\n inputs: { candidate?: SavedCandidate; flags?: RuleFlags },\n at: { today: string; taken: readonly string[] },\n): CreativeRule | { error: string } {\n const c = inputs.candidate;\n const f = inputs.flags ?? {};\n const text = (f.text ?? c?.text)?.trim();\n if (!text) return { error: \"--text: the rule, in the person's words (or --candidate <id> from `feedback record`).\" };\n const check = checkOf(f, c);\n const source = defined({\n kind: c ? (\"feedback\" as const) : (\"user\" as const),\n slug: f.slug ?? c?.source.slug,\n runId: f.run ?? c?.source.runId,\n quote: f.quote ?? c?.source.quote,\n date: at.today,\n });\n return {\n id: ruleSlug(f.id ?? text, at.taken),\n origin: \"learned\",\n strength: oneOf(RULE_STRENGTHS, f.strength) ?? c?.strength ?? \"must\",\n applies: oneOf(RULE_APPLIES, f.applies) ?? c?.applies ?? \"any\",\n scope: scopeOf(f, c),\n ...(Object.keys(check).length > 0 ? { check } : {}),\n text,\n ...(f.why ? { why: f.why } : {}),\n source,\n status: \"active\",\n };\n}\n\n/** One version's finished sizes as review stills, from the run history; null when it has no picture. */\nasync function versionOf(runId: string): Promise<ReviewedVersion | null> {\n const record = await fetchRunRecord(runId).catch(() => null);\n const images = (record?.finalOutputs ?? []).filter((o) => o.kind === \"image\" && o.url);\n const stills = await Promise.all(\n images.map(async (o) => {\n const response = await fetch(o.url as string).catch(() => null);\n if (!response?.ok) return null;\n const bytes = Buffer.from(await response.arrayBuffer());\n return (await sharp(bytes).resize({ width: 1024 }).jpeg({ quality: 85 }).toBuffer()).toString(\"base64\");\n }),\n );\n const kept = images.flatMap((o, i) =>\n stills[i] ? [{ still: stills[i] as string, format: o.label ?? \"image\" }] : [],\n );\n return kept.length > 0 ? { runId, stills: kept.map((k) => k.still), formats: kept.map((k) => k.format) } : null;\n}\n\n/** How many approved versions a rule is tested against: a few, other creatives' first. */\nconst APPROVED_VERSIONS = 3;\n\n/** The company's approved versions to test a rule against, other creatives' first. */\nasync function approvedVersions(except: string | undefined, slug: string | undefined): Promise<ReviewedVersion[]> {\n const feedback = await apiPost<CreativesFeedbackResponse>(\"/api/creatives/feedback\", { full: true }).catch(\n () => null,\n );\n const approved = (feedback?.data.recent ?? []).filter((e) => e.verdict === \"approved\" && e.runId !== except);\n const ordered = [...approved.filter((e) => e.creative !== slug), ...approved.filter((e) => e.creative === slug)];\n const runIds = [...new Set(ordered.map((e) => e.runId))];\n const versions: ReviewedVersion[] = [];\n for (const runId of runIds) {\n if (versions.length === APPROVED_VERSIONS) break;\n const version = await versionOf(runId);\n if (version) versions.push(version);\n }\n return versions;\n}\n\n/** The rule on the version it came from and on the company's approved ones (`admissionTest`). */\nasync function admit(rule: CreativeRule): Promise<Admission> {\n const spent: Parameters<typeof holdWorkspaceSpend>[0][number][] = [];\n const review = (version: ReviewedVersion, rules: CreativeRule[]) =>\n reviewAgainstRules({ ...version, rules, onSpend: (u) => spent.push(u) });\n const [origin, approved] = await Promise.all([\n rule.source.runId ? versionOf(rule.source.runId) : Promise.resolve(null),\n approvedVersions(rule.source.runId, rule.source.slug),\n ]);\n const admission = await admissionTest(rule, origin, approved, review);\n await holdWorkspaceSpend(spent);\n return admission;\n}\n\n/** A learned rule's file, retired by `by`; null when there is no such file. */\nasync function retireFile(root: string, id: string, by: string | undefined): Promise<CreativeRule | null> {\n const file = path.join(root, RULES_DIR, `${id}.md`);\n const rule = parseRuleFile(id, await readFile(file, \"utf8\").catch(() => \"\"));\n if (!rule) return null;\n const retired: CreativeRule = { ...rule, status: \"retired\", ...(by ? { retiredBy: by } : {}) };\n await writeFile(file, ruleFileText(retired), \"utf8\");\n return retired;\n}\n\nfunction fail(code: string, message: string, fix?: string, extra: Record<string, unknown> = {}): never {\n writeJson({ ok: false, error: { code, message, ...(fix ? { fix } : {}), ...extra } });\n process.exit(1);\n}\n\nconst list = (value: unknown): string[] | undefined =>\n typeof value === \"string\" && value.trim()\n ? value\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : undefined;\nconst text = (value: unknown): string | undefined =>\n typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n\nconst ADD_DESCRIPTION = `Save a rule the person agreed to, for every ad from now on: one file in src/content/creative-rules/, published with the Session. Only after they said yes to \"make this a rule for every ad?\".\nStart here: baker creatives rules add --candidate rc-1a2b3c4d # a rule \\`feedback record\\` drafted from their words\n baker creatives rules add --text \"No AI-generated people.\" --strength never --applies cast --people real --quote \"<their words>\" --slug <ad> --run <r_…>\nIt is refused when the company already has it (DUPLICATE_RULE), when it contradicts one (RULE_CONFLICT: ask which wins, then --replaces <id>), when it does not catch the version it came from (RULE_MISSES_ITS_AD), or would block versions the person approved (RULE_BLOCKS_APPROVED): ask the person, never save it anyway.`;\n\nconst ADD_ARGS = {\n candidate: {\n type: \"string\",\n description: \"A rule `feedback record` drafted (rc-…): the flags below override its parts\",\n required: false,\n },\n text: {\n type: \"string\",\n description: \"The rule, one sentence, in the person's own language and words\",\n required: false,\n },\n strength: {\n type: \"string\",\n description: `${RULE_STRENGTHS.join(\" | \")}: never and must are checked and block; prefer is a note`,\n required: false,\n },\n applies: { type: \"string\", description: `What of the ad it is about: ${RULE_APPLIES.join(\", \")}`, required: false },\n forbid: {\n type: \"string\",\n description: 'Words it bans, comma-separated, only when a word decides it (\"online\")',\n required: false,\n },\n allow: { type: \"string\", description: 'The right phrase that holds a banned word (\"100 % online\")', required: false },\n require: { type: \"string\", description: \"Words every ad must say, comma-separated (rare)\", required: false },\n people: {\n type: \"string\",\n description: \"real: only real people appear (a real person's Avatar, a customer, footage or nobody)\",\n required: false,\n },\n kinds: { type: \"string\", description: \"static,video: only ads of these kinds\", required: false },\n products: { type: \"string\", description: \"Product slugs (a business unit): only ads of these\", required: false },\n platforms: { type: \"string\", description: \"meta,linkedin,…: only ads for these\", required: false },\n language: {\n type: \"string\",\n description: \"The language its words are in (es): its banned words are checked only in ads in it\",\n required: false,\n },\n quote: { type: \"string\", description: \"The person's own words it came from, verbatim\", required: false },\n slug: { type: \"string\", description: \"The creative they said it about\", required: false },\n run: { type: \"string\", description: \"The version they said it about (r_…): the rule must catch it\", required: false },\n why: { type: \"string\", description: \"Why, in a sentence, when the person said\", required: false },\n id: { type: \"string\", description: \"The rule's id (its file name); default: from its words\", required: false },\n replaces: {\n type: \"string\",\n description: \"A rule of the person's it contradicts and wins over: retired, never deleted\",\n required: false,\n },\n} as const;\n\nregisterSchema({ command: \"creatives.rules.add\", description: ADD_DESCRIPTION, args: ADD_ARGS });\n\n/**\n * What to do about a BRAND.md rule the new one repeats or contradicts. The rule a person taught lives\n * in its own file only: a copy in BRAND.md would stay in force after it is retired. Pure.\n */\nexport function brandMdHint(declared: Pick<CreativeRule, \"text\">, relation: \"same\" | \"conflict\"): string {\n return relation === \"same\"\n ? `BRAND.md states this too (\"${declared.text}\"): now the person confirmed it, every finished ad is checked against it.`\n : `BRAND.md says otherwise (\"${declared.text}\"): tell the person, and change only that line of BRAND.md (/brand-build) so it no longer says otherwise; never write the rule itself into BRAND.md, or retiring it would leave it in force.`;\n}\n\nexport const rulesAddCommand = defineCommand({\n meta: { name: \"add\", description: ADD_DESCRIPTION },\n args: ADD_ARGS,\n async run({ args }) {\n const root = findWorkspaceRoot(process.cwd()) ?? process.cwd();\n const cacheDir = path.join(root, \"canvas\", \".cache\");\n const candidateId = text(args.candidate);\n const candidate = candidateId ? await loadCandidate(cacheDir, candidateId) : undefined;\n if (candidateId && !candidate) {\n fail(\n \"VALIDATION_ERROR\",\n `No drafted rule ${candidateId} here.`,\n \"Use the id `feedback record` printed in this chat, or pass --text.\",\n );\n }\n const all = await readAllRules(root);\n const rule = ruleFromInputs(\n {\n ...(candidate ? { candidate } : {}),\n flags: {\n text: text(args.text),\n strength: text(args.strength),\n applies: text(args.applies),\n forbid: list(args.forbid),\n allow: list(args.allow),\n require: list(args.require),\n people: text(args.people),\n kinds: list(args.kinds),\n products: list(args.products),\n platforms: list(args.platforms),\n language: text(args.language),\n quote: text(args.quote),\n slug: text(args.slug),\n run: text(args.run),\n why: text(args.why),\n id: text(args.id),\n },\n },\n { today: new Date().toISOString().slice(0, 10), taken: all.map((r) => r.id) },\n );\n if (\"error\" in rule) fail(\"VALIDATION_ERROR\", rule.error);\n const replaces = text(args.replaces);\n const compared = await compareRule(rule, all, jevPairs());\n const sameTaught = compared.same.filter((r) => r.origin === \"learned\");\n if (sameTaught.length > 0) {\n fail(\n \"DUPLICATE_RULE\",\n `The company already has this rule: ${sameTaught.map((r) => `${r.id} (\"${r.text}\")`).join(\"; \")}.`,\n \"Nothing to add. If the person wants it worded otherwise, retire that one and add this.\",\n );\n }\n const conflicts = compared.conflicts.filter((r) => r.origin === \"learned\" && r.id !== replaces);\n if (conflicts.length > 0) {\n fail(\n \"RULE_CONFLICT\",\n `It contradicts ${conflicts.map((r) => `${r.id} (\"${r.text}\")`).join(\"; \")}.`,\n \"Ask the person which one wins. This one: add it again with --replaces <id> (that rule is retired, never deleted). The other: do not add this one.\",\n );\n }\n const admission = await admit(rule);\n const refusal = admissionRefusal(rule, admission);\n if (refusal) fail(refusal.code, refusal.message, refusal.fix, { admission });\n await mkdir(path.join(root, RULES_DIR), { recursive: true });\n const file = path.join(RULES_DIR, `${rule.id}.md`);\n await writeFile(path.join(root, file), ruleFileText(rule), \"utf8\");\n const retired = replaces ? await retireFile(root, replaces, rule.id) : null;\n const declared = [...compared.same, ...compared.conflicts].filter((r) => r.origin === \"declared\");\n writeJson({\n ok: true,\n data: {\n rule: rulesView([rule], { full: true })[0],\n file,\n admission,\n ...(retired ? { retired: retired.id } : {}),\n },\n hints: [\n `Saved for every ad from now on${admission.origin === \"untested\" ? \" (not tested on a version: nothing a picture shows decides it, or the version had no picture)\" : \"\"}. Tell the person in one line, then run \\`baker creatives check\\`: which ads already made break it.`,\n ...(compared.judged\n ? []\n : [\n \"Whether it repeats or contradicts another rule could not be read (the decision model did not answer): look at `baker creatives rules list`.\",\n ]),\n ...declared.map((r) => brandMdHint(r, compared.same.includes(r) ? \"same\" : \"conflict\")),\n ],\n });\n },\n});\n\nconst RETIRE_DESCRIPTION = `Retire a rule a person taught, when they say it no longer holds or another replaces it: it stays in its file as retired, never deleted, and no ad is held to it.\nStart here: baker creatives rules retire cien-por-cien-online [--by <rule id>|BRAND.md]\nA rule of BRAND.md is changed in BRAND.md (/brand-build).`;\n\nconst RETIRE_ARGS = {\n id: { type: \"positional\", description: \"The rule's id (`baker creatives rules list`)\", required: true },\n by: { type: \"string\", description: \"What replaces it: another rule's id, or BRAND.md\", required: false },\n} as const;\n\nregisterSchema({ command: \"creatives.rules.retire\", description: RETIRE_DESCRIPTION, args: RETIRE_ARGS });\n\nexport const rulesRetireCommand = defineCommand({\n meta: { name: \"retire\", description: RETIRE_DESCRIPTION },\n args: RETIRE_ARGS,\n async run({ args }) {\n const root = findWorkspaceRoot(process.cwd()) ?? process.cwd();\n const id = String(args.id);\n if (/^brand-[0-9a-f]{8}$/.test(id)) {\n fail(\"VALIDATION_ERROR\", `${id} is a rule of BRAND.md.`, \"Change it in BRAND.md with /brand-build.\");\n }\n const retired = await retireFile(root, id, text(args.by));\n if (!retired) fail(\"NOT_FOUND\", `No rule ${id} in ${RULES_DIR}.`, \"See `baker creatives rules list --all`.\");\n writeJson({\n ok: true,\n data: { rule: rulesView([retired], { full: true })[0] },\n hints: [\"Retired: no ad is held to it from now on.\"],\n });\n },\n});\n","/**\n * A rule's admission test, before it is saved for every ad: it must catch the version it came from\n * (the rejected one), and stay silent on versions of the company the person approved. A rule that\n * misses its own ad is worded for something else; one that would block approved ads is stricter\n * than the person. Either way the person is asked again, never the rule saved as drafted. Only the\n * rules the finished-ad review holds an ad to by eye are tested (`reviewedRules`); a voice or a\n * sound needs the video playing, and is saved untested, saying so.\n */\nimport type { RenderFinding } from \"../nodes/local/lib/render-review.ts\";\nimport { reviewedRules } from \"../nodes/local/lib/rules-findings.ts\";\nimport type { CreativeRule } from \"./schema.ts\";\n\n/** One version as the rules review looks at it: its sizes as base64 JPEG, in `formats` order. */\nexport type ReviewedVersion = { runId: string; stills: string[]; formats: string[] };\n\n/** The rules review on one version (`reviewAgainstRules`); null when nobody looked. */\nexport type ReviewVersion = (version: ReviewedVersion, rules: CreativeRule[]) => Promise<RenderFinding[] | null>;\n\nexport type Admission = {\n origin: \"caught\" | \"missed\" | \"untested\";\n approved: { checked: number; blocked: Array<{ runId: string; what: string }> };\n};\n\n/** The rule's blocking findings on a version; null when nobody looked. */\nasync function breaks(\n rule: CreativeRule,\n version: ReviewedVersion,\n review: ReviewVersion,\n): Promise<RenderFinding[] | null> {\n const found = await review(version, [rule]).catch(() => null);\n return found === null ? null : found.filter((f) => f.kind?.rule === rule.id && f.severity === \"blocking\");\n}\n\n/** The rule on the version it came from and on up to a few the person approved. */\nexport async function admissionTest(\n rule: CreativeRule,\n origin: ReviewedVersion | null,\n approved: readonly ReviewedVersion[],\n review: ReviewVersion,\n): Promise<Admission> {\n const untested: Admission = { origin: \"untested\", approved: { checked: 0, blocked: [] } };\n // A prefer never blocks: it is tested as if it did, since the person reads it the same.\n const tested = { ...rule, strength: rule.strength === \"prefer\" ? (\"must\" as const) : rule.strength };\n if (reviewedRules([tested]).length === 0) return untested;\n const own = origin ? await breaks(tested, origin, review) : null;\n const results = await Promise.all(\n approved.map(async (v) => ({ runId: v.runId, found: await breaks(tested, v, review) })),\n );\n const looked = results.filter((r) => r.found !== null);\n return {\n origin: own === null ? \"untested\" : own.length > 0 ? \"caught\" : \"missed\",\n approved: {\n checked: looked.length,\n blocked: looked.flatMap((r) =>\n r.found?.[0] ? [{ runId: r.runId, what: r.found[0].what.replace(/^.*?\\): /, \"\") }] : [],\n ),\n },\n };\n}\n\n/** Why the rule is not saved as drafted, and what to ask the person; null when it passed or was not tested. Pure. */\nexport function admissionRefusal(\n rule: CreativeRule,\n admission: Admission,\n): { code: \"RULE_MISSES_ITS_AD\" | \"RULE_BLOCKS_APPROVED\"; message: string; fix: string } | null {\n if (admission.origin === \"missed\") {\n return {\n code: \"RULE_MISSES_ITS_AD\",\n message: `Not saved: \"${rule.text}\" does not catch the version it came from (${rule.source.runId ?? \"the rejected one\"}), so it is worded for something else.`,\n fix: \"Reword it to name exactly what was wrong on that version, in the person's words, and add it again; or ask the person what the rule is.\",\n };\n }\n const blocked = admission.approved.blocked;\n if (blocked.length > 0) {\n return {\n code: \"RULE_BLOCKS_APPROVED\",\n message: `Not saved: \"${rule.text}\" would block ${blocked.length} version${blocked.length === 1 ? \"\" : \"s\"} the person approved: ${blocked.map((b) => `${b.runId} (${b.what})`).join(\"; \")}.`,\n fix: \"Ask the person whether those approved ads break it. If they do not, reword the rule so it names only what they reject, and add it again.\",\n };\n }\n return null;\n}\n","/**\n * A new rule against the ones the company already has, read by the decision model in any language:\n * which say the same (a duplicate), and which it contradicts (an ad could not keep both). `rules add`\n * refuses a duplicate of a rule a person taught, and a contradiction until the person picks the winner;\n * the loser is retired, never deleted.\n */\nimport { askJev } from \"../nodes/local/lib/jev.ts\";\nimport type { ReviewUsage } from \"../nodes/local/lib/render-review.ts\";\nimport type { CreativeRule } from \"./schema.ts\";\n\nconst SAME =\n \"Do rules `a` and `b` ask the same thing of an ad, in any words or language, so that an ad keeping one keeps the other?\";\nconst CONFLICT =\n \"Do rules `a` and `b` contradict each other, so that no ad could keep both: following one breaks the other?\";\n\n/** Above these, two rules are the same or contradict: refusing a rule by mistake costs the person a rule. */\nconst SAME_BAND = 0.6;\nconst CONFLICT_BAND = 0.6;\n\nexport type RulePair = { a: string; b: string; question: \"same\" | \"conflict\" };\n\n/** Each pair's probability of yes, in order; null when the decision model did not answer. */\nexport type AskPairs = (pairs: readonly RulePair[]) => Promise<number[] | null>;\n\n/** The most questions one request carries. */\nconst BATCH = 40;\n\n/** The decision model asked about each pair, a batch at a time. */\nexport function jevPairs(onSpend?: (usage: ReviewUsage) => void): AskPairs {\n return async (pairs) => {\n const answers: number[] = [];\n for (let i = 0; i < pairs.length; i += BATCH) {\n const batch = pairs.slice(i, i + BATCH);\n const got = await askJev(\n batch.map((p) => ({ instructions: { a: p.a, b: p.b, question: p.question === \"same\" ? SAME : CONFLICT } })),\n onSpend,\n );\n if (!got) return null;\n answers.push(...got);\n }\n return answers;\n };\n}\n\nexport type Comparison = { same: CreativeRule[]; conflicts: CreativeRule[]; judged: boolean };\n\n/** The active rules `candidate` duplicates and the ones it contradicts. */\nexport async function compareRule(\n candidate: CreativeRule,\n existing: readonly CreativeRule[],\n ask: AskPairs,\n): Promise<Comparison> {\n const active = existing.filter((r) => r.status === \"active\" && r.id !== candidate.id);\n if (active.length === 0) return { same: [], conflicts: [], judged: true };\n const pairs = active.flatMap((r): RulePair[] => [\n { a: candidate.text, b: r.text, question: \"same\" },\n { a: candidate.text, b: r.text, question: \"conflict\" },\n ]);\n const answers = await ask(pairs).catch(() => null);\n if (!answers || answers.length !== pairs.length) return { same: [], conflicts: [], judged: false };\n return {\n same: active.filter((_, i) => (answers[2 * i] ?? 0) >= SAME_BAND),\n conflicts: active.filter((_, i) => (answers[2 * i + 1] ?? 0) >= CONFLICT_BAND),\n judged: true,\n };\n}\n","/**\n * A rule a person agreed to, as the file it lives in (`src/content/creative-rules/<slug>.md`): its\n * frontmatter (what decides it, where it came from) and its words, then why. The reader\n * (`parseRuleFile`) reads it back the same. Pure.\n */\nimport { stringify as stringifyYaml } from \"yaml\";\nimport type { CreativeRule } from \"./schema.ts\";\n\n/** The rule's file: frontmatter, its words, then why. Pure. */\nexport function ruleFileText(rule: CreativeRule): string {\n const frontmatter = {\n strength: rule.strength,\n applies: rule.applies,\n ...(Object.keys(rule.scope).length > 0 ? { scope: rule.scope } : {}),\n ...(rule.check && Object.keys(rule.check).length > 0 ? { check: rule.check } : {}),\n source: rule.source,\n status: rule.status,\n ...(rule.retiredBy ? { retiredBy: rule.retiredBy } : {}),\n };\n // Every string quoted: a date stays a date's words, and a quote with a colon stays one value.\n const yaml = stringifyYaml(frontmatter, { defaultStringType: \"QUOTE_DOUBLE\", defaultKeyType: \"PLAIN\", lineWidth: 0 });\n return `---\\n${yaml}---\\n${rule.text.trim()}\\n${rule.why ? `\\nWhy: ${rule.why.trim()}\\n` : \"\"}`;\n}\n\nconst SLUG_WORDS = 8;\n\n/** A file name from the rule's words, not one of `taken`. Pure. */\nexport function ruleSlug(text: string, taken: readonly string[]): string {\n const base =\n text\n .normalize(\"NFKD\")\n .replace(/\\p{M}/gu, \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \" \")\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, SLUG_WORDS)\n .join(\"-\") || \"rule\";\n if (!taken.includes(base)) return base;\n let n = 2;\n while (taken.includes(`${base}-${n}`)) n++;\n return `${base}-${n}`;\n}\n"],"mappings":"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","names":["text","text"]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
executeCanvasRun,
|
|
4
4
|
runCommand,
|
|
5
5
|
stopBeforeKinds
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NDIBFOFB.js";
|
|
7
7
|
import "./chunk-IVRXPYQ7.js";
|
|
8
8
|
import "./chunk-3PL2QRF2.js";
|
|
9
9
|
import "./chunk-WN4KX7GE.js";
|
|
@@ -13,16 +13,16 @@ import "./chunk-IOGKJZ4Z.js";
|
|
|
13
13
|
import "./chunk-Q6ULQMWG.js";
|
|
14
14
|
import "./chunk-KKJ4KJCW.js";
|
|
15
15
|
import "./chunk-3ACMDRSE.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-HY6DIWDV.js";
|
|
17
|
+
import "./chunk-5OLCELV7.js";
|
|
18
|
+
import "./chunk-OTLYELOW.js";
|
|
19
|
+
import "./chunk-FHYUIYU5.js";
|
|
20
20
|
import "./chunk-L44WSWSZ.js";
|
|
21
21
|
import "./chunk-B2SAOVMU.js";
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-A7MTWTMM.js";
|
|
23
|
+
import "./chunk-ZPMGYAYZ.js";
|
|
24
24
|
import "./chunk-AN7CMLYY.js";
|
|
25
|
-
import "./chunk-
|
|
25
|
+
import "./chunk-5OAFKP6L.js";
|
|
26
26
|
import "./chunk-S4ROJTDY.js";
|
|
27
27
|
import "./chunk-YJAQWTS6.js";
|
|
28
28
|
import "./chunk-MNPBPU3G.js";
|
|
@@ -61,4 +61,4 @@ export {
|
|
|
61
61
|
runCommand,
|
|
62
62
|
stopBeforeKinds
|
|
63
63
|
};
|
|
64
|
-
//# sourceMappingURL=run-
|
|
64
|
+
//# sourceMappingURL=run-WBFKGA42.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-CCFZB42B.js";
|
|
8
8
|
import {
|
|
9
9
|
syncCreativeDefinitionBestEffort
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HGTLGFKV.js";
|
|
11
11
|
import "./chunk-IVRXPYQ7.js";
|
|
12
12
|
import {
|
|
13
13
|
pinnedModelHint
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
resolveFormats,
|
|
22
22
|
resolvePlatform,
|
|
23
23
|
titleFromSlug
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-5OLCELV7.js";
|
|
25
25
|
import {
|
|
26
26
|
BRAND_DIR,
|
|
27
27
|
REBUILD_FILE,
|
|
@@ -51,13 +51,13 @@ import {
|
|
|
51
51
|
voiceGenderModel,
|
|
52
52
|
webFontUrl,
|
|
53
53
|
writeSceneFiles
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-FHYUIYU5.js";
|
|
55
55
|
import "./chunk-B2SAOVMU.js";
|
|
56
|
-
import "./chunk-
|
|
56
|
+
import "./chunk-ZPMGYAYZ.js";
|
|
57
57
|
import {
|
|
58
58
|
readAvatars
|
|
59
59
|
} from "./chunk-AN7CMLYY.js";
|
|
60
|
-
import "./chunk-
|
|
60
|
+
import "./chunk-5OAFKP6L.js";
|
|
61
61
|
import "./chunk-S4ROJTDY.js";
|
|
62
62
|
import {
|
|
63
63
|
fetchJson,
|
|
@@ -1550,4 +1550,4 @@ async function stageBrandDisplayFace(outDir, compositionDir) {
|
|
|
1550
1550
|
export {
|
|
1551
1551
|
scaffoldAdCommand
|
|
1552
1552
|
};
|
|
1553
|
-
//# sourceMappingURL=scaffold-ad-
|
|
1553
|
+
//# sourceMappingURL=scaffold-ad-6YO574PA.js.map
|