@koda-sl/baker-cli 0.150.0 → 0.151.0-dev.4932063cd

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/cli.js CHANGED
@@ -36,7 +36,7 @@ import {
36
36
  toModelSafeImage,
37
37
  ulid,
38
38
  validateCanvasDeep
39
- } from "./chunk-OO5BDH3J.js";
39
+ } from "./chunk-S43JQWI2.js";
40
40
  import {
41
41
  csvOrJson,
42
42
  daysAgoIso,
@@ -75,7 +75,7 @@ import {
75
75
  } from "./chunk-RK67WL4O.js";
76
76
 
77
77
  // src/cli.ts
78
- import { defineCommand as defineCommand180, runMain } from "citty";
78
+ import { defineCommand as defineCommand178, runMain } from "citty";
79
79
 
80
80
  // src/commands/actions/index.ts
81
81
  import { defineCommand as defineCommand18 } from "citty";
@@ -5686,11 +5686,11 @@ function rawTextEntries(value) {
5686
5686
  const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
5687
5687
  return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
5688
5688
  }
5689
- function rawFileEntries(path28) {
5690
- if (typeof path28 !== "string" || path28.length === 0) {
5689
+ function rawFileEntries(path27) {
5690
+ if (typeof path27 !== "string" || path27.length === 0) {
5691
5691
  return [];
5692
5692
  }
5693
- return readFileSync2(path28, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
5693
+ return readFileSync2(path27, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
5694
5694
  }
5695
5695
  function keywordEntries(args) {
5696
5696
  const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
@@ -5713,19 +5713,19 @@ function keywordEntries(args) {
5713
5713
  }
5714
5714
  return entries;
5715
5715
  }
5716
- function loadJsonFileArg(path28) {
5717
- if (typeof path28 !== "string" || path28.length === 0) {
5716
+ function loadJsonFileArg(path27) {
5717
+ if (typeof path27 !== "string" || path27.length === 0) {
5718
5718
  return {};
5719
5719
  }
5720
5720
  try {
5721
- const parsed = JSON.parse(readFileSync2(path28, "utf8"));
5721
+ const parsed = JSON.parse(readFileSync2(path27, "utf8"));
5722
5722
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
5723
- failWriteValidation(`${path28} must contain a JSON object`);
5723
+ failWriteValidation(`${path27} must contain a JSON object`);
5724
5724
  }
5725
5725
  return parsed;
5726
5726
  } catch (err) {
5727
5727
  if (err instanceof SyntaxError) {
5728
- failWriteValidation(`${path28} is not valid JSON: ${err.message}`);
5728
+ failWriteValidation(`${path27} is not valid JSON: ${err.message}`);
5729
5729
  }
5730
5730
  throw err;
5731
5731
  }
@@ -5847,10 +5847,10 @@ async function stageUpdate(kind, customerId, target, payload) {
5847
5847
  async function stageTarget(kind, customerId, target) {
5848
5848
  await stageGoogleOp({ kind, customerId, target });
5849
5849
  }
5850
- async function draftAction(path28, body) {
5850
+ async function draftAction(path27, body) {
5851
5851
  try {
5852
5852
  const chatId = requireChatId();
5853
- const response = await apiPost(path28, { chatId, ...body });
5853
+ const response = await apiPost(path27, { chatId, ...body });
5854
5854
  writeJsonEnvelope(response);
5855
5855
  } catch (err) {
5856
5856
  handleGoogleError(err);
@@ -9433,19 +9433,19 @@ function failWriteValidation2(message) {
9433
9433
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
9434
9434
  process.exit(1);
9435
9435
  }
9436
- function loadJsonFileArg2(path28) {
9437
- if (typeof path28 !== "string" || path28.length === 0) {
9436
+ function loadJsonFileArg2(path27) {
9437
+ if (typeof path27 !== "string" || path27.length === 0) {
9438
9438
  return {};
9439
9439
  }
9440
9440
  try {
9441
- const parsed = JSON.parse(readFileSync6(path28, "utf8"));
9441
+ const parsed = JSON.parse(readFileSync6(path27, "utf8"));
9442
9442
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
9443
- failWriteValidation2(`${path28} must contain a JSON object`);
9443
+ failWriteValidation2(`${path27} must contain a JSON object`);
9444
9444
  }
9445
9445
  return parsed;
9446
9446
  } catch (err) {
9447
9447
  if (err instanceof SyntaxError) {
9448
- failWriteValidation2(`${path28} is not valid JSON: ${err.message}`);
9448
+ failWriteValidation2(`${path27} is not valid JSON: ${err.message}`);
9449
9449
  }
9450
9450
  throw err;
9451
9451
  }
@@ -9530,15 +9530,15 @@ function parseLocaleFlag(value) {
9530
9530
  }
9531
9531
  return { language: match[1], country: match[2].toUpperCase() };
9532
9532
  }
9533
- function loadTargetingFileArg(path28) {
9534
- if (typeof path28 !== "string" || path28.length === 0) {
9533
+ function loadTargetingFileArg(path27) {
9534
+ if (typeof path27 !== "string" || path27.length === 0) {
9535
9535
  return void 0;
9536
9536
  }
9537
- const parsed = loadJsonFileArg2(path28);
9537
+ const parsed = loadJsonFileArg2(path27);
9538
9538
  const criteria = parsed.targetingCriteria ?? parsed;
9539
9539
  if (!criteria.include) {
9540
9540
  failWriteValidation2(
9541
- `${path28} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
9541
+ `${path27} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
9542
9542
  );
9543
9543
  }
9544
9544
  return criteria;
@@ -9573,14 +9573,14 @@ function parseCsvLine(line) {
9573
9573
  cells.push(current);
9574
9574
  return cells.map((cell) => cell.trim());
9575
9575
  }
9576
- function parseListFileArg(path28, maxRows) {
9577
- if (typeof path28 !== "string" || path28.length === 0) {
9576
+ function parseListFileArg(path27, maxRows) {
9577
+ if (typeof path27 !== "string" || path27.length === 0) {
9578
9578
  return void 0;
9579
9579
  }
9580
- const raw = readFileSync6(path28, "utf8");
9580
+ const raw = readFileSync6(path27, "utf8");
9581
9581
  const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
9582
9582
  if (lines.length < 2) {
9583
- failWriteValidation2(`${path28} needs a header row and at least one data row`);
9583
+ failWriteValidation2(`${path27} needs a header row and at least one data row`);
9584
9584
  }
9585
9585
  const columns = parseCsvLine(lines[0]).map((column) => column.trim());
9586
9586
  const rows = [];
@@ -9599,7 +9599,7 @@ function parseListFileArg(path28, maxRows) {
9599
9599
  }
9600
9600
  }
9601
9601
  if (rows.length > maxRows) {
9602
- failWriteValidation2(`${path28} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
9602
+ failWriteValidation2(`${path27} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
9603
9603
  }
9604
9604
  return { columns, rows };
9605
9605
  }
@@ -11699,11 +11699,11 @@ var updateStatusSchema = z14.enum(UPDATE_STATUSES);
11699
11699
  function currencyMinimums2(currencyCode) {
11700
11700
  return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
11701
11701
  }
11702
- function validateDailyBudgetFloor(money, ctx, path28) {
11702
+ function validateDailyBudgetFloor(money, ctx, path27) {
11703
11703
  if (money?.currencyCode) {
11704
11704
  const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
11705
11705
  if (Number(money.amount) < min) {
11706
- ctx.addIssue({ code: "custom", path: path28, message: `below the ${min} ${money.currencyCode} daily minimum` });
11706
+ ctx.addIssue({ code: "custom", path: path27, message: `below the ${min} ${money.currencyCode} daily minimum` });
11707
11707
  }
11708
11708
  }
11709
11709
  }
@@ -12335,19 +12335,19 @@ function failWriteValidation3(message) {
12335
12335
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
12336
12336
  process.exit(1);
12337
12337
  }
12338
- function loadJsonFileArg3(path28) {
12339
- if (typeof path28 !== "string" || path28.length === 0) {
12338
+ function loadJsonFileArg3(path27) {
12339
+ if (typeof path27 !== "string" || path27.length === 0) {
12340
12340
  return {};
12341
12341
  }
12342
12342
  try {
12343
- const parsed = JSON.parse(readFileSync8(path28, "utf8"));
12343
+ const parsed = JSON.parse(readFileSync8(path27, "utf8"));
12344
12344
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
12345
- failWriteValidation3(`${path28} must contain a JSON object`);
12345
+ failWriteValidation3(`${path27} must contain a JSON object`);
12346
12346
  }
12347
12347
  return parsed;
12348
12348
  } catch (err) {
12349
12349
  if (err instanceof SyntaxError) {
12350
- failWriteValidation3(`${path28} is not valid JSON: ${err.message}`);
12350
+ failWriteValidation3(`${path27} is not valid JSON: ${err.message}`);
12351
12351
  }
12352
12352
  throw err;
12353
12353
  }
@@ -15286,346 +15286,12 @@ Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedi
15286
15286
  }
15287
15287
  });
15288
15288
 
15289
- // src/commands/brand/index.ts
15290
- import { defineCommand as defineCommand86 } from "citty";
15291
-
15292
- // src/commands/brand/fonts.ts
15293
- import { mkdir, readFile, writeFile } from "fs/promises";
15294
- import path from "path";
15295
- import { defineCommand as defineCommand85 } from "citty";
15296
-
15297
- // src/engine/brand/fonts.ts
15298
- var GOOGLE_CSS2 = "https://fonts.googleapis.com/css2";
15299
- function parseGoogleFontFaces(css) {
15300
- const faces = [];
15301
- const re = /\/\*\s*([\w-]+)\s*\*\/\s*@font-face\s*\{([^}]*)\}/g;
15302
- for (const match of String(css).matchAll(re)) {
15303
- const subset = match[1] ?? "";
15304
- const body = match[2] ?? "";
15305
- const family = body.match(/font-family\s*:\s*['"]?([^'";]+)['"]?\s*;/i)?.[1]?.trim();
15306
- const url = body.match(/src\s*:\s*url\(\s*['"]?([^'")]+)['"]?\s*\)/i)?.[1]?.trim();
15307
- const weight = body.match(/font-weight\s*:\s*(\d{3})\s*;/i)?.[1];
15308
- if (!family || !url || !weight) continue;
15309
- faces.push({
15310
- subset,
15311
- family,
15312
- style: body.match(/font-style\s*:\s*([\w-]+)\s*;/i)?.[1]?.trim() ?? "normal",
15313
- weight: Number(weight),
15314
- url,
15315
- unicodeRange: body.match(/unicode-range\s*:\s*([^;]+);/i)?.[1]?.trim() ?? ""
15316
- });
15317
- }
15318
- return faces;
15319
- }
15320
- function fontFileName(face) {
15321
- const family = face.family.replace(/[^A-Za-z0-9]/g, "");
15322
- const style = face.style === "italic" ? "italic" : "";
15323
- return `${family}-${face.weight}${style}-${face.subset}.woff2`;
15324
- }
15325
- function renderFontFaceCss(faces, hrefFor) {
15326
- return faces.map(
15327
- (face) => [
15328
- "@font-face {",
15329
- ` font-family: '${face.family}';`,
15330
- ` font-style: ${face.style};`,
15331
- ` font-weight: ${face.weight};`,
15332
- " font-display: swap;",
15333
- ` src: url('${hrefFor(face)}') format('woff2');`,
15334
- ...face.unicodeRange ? [` unicode-range: ${face.unicodeRange};`] : [],
15335
- "}"
15336
- ].join("\n")
15337
- ).join("\n");
15338
- }
15339
- function parseWeightAxis(spec) {
15340
- const axis = spec.match(/wght@([^&]+)/i)?.[1] ?? "";
15341
- const weights = /* @__PURE__ */ new Set();
15342
- for (const tuple of axis.split(";")) {
15343
- const last = tuple.split(",").pop()?.trim() ?? "";
15344
- const range = last.match(/^(\d{3})\.\.(\d{3})$/);
15345
- if (range) {
15346
- for (let w = Number(range[1]); w <= Number(range[2]); w += 100) weights.add(w);
15347
- } else if (/^\d{3}$/.test(last)) {
15348
- weights.add(Number(last));
15349
- }
15350
- }
15351
- return [...weights].sort((a, b) => a - b);
15352
- }
15353
- function googleFontRequests(css) {
15354
- const out = [];
15355
- for (const link of String(css).matchAll(/fonts\.googleapis\.com\/[^\s"')]+/gi)) {
15356
- for (const param of link[0].matchAll(/[?&]family=([^&]+)/gi)) {
15357
- const [namePart, ...specParts] = (param[1] ?? "").split(":");
15358
- const family = decodeURIComponent((namePart ?? "").replaceAll("+", " ")).trim();
15359
- if (!family) continue;
15360
- out.push({ family, weights: parseWeightAxis(specParts.join(":")) });
15361
- }
15362
- }
15363
- return out;
15364
- }
15365
- function resolveFetchWeights(flag, declared) {
15366
- if (flag) {
15367
- return String(flag).split(",").map((w) => Number(w.trim())).filter((w) => Number.isInteger(w) && w >= 100 && w <= 900);
15368
- }
15369
- return declared?.length ? declared : [400];
15370
- }
15371
- function googleFontCssUrl(family, weights) {
15372
- const name = family.trim().split(/\s+/).map(encodeURIComponent).join("+");
15373
- const axis = [...new Set(weights)].sort((a, b) => a - b).join(";");
15374
- const spec = axis ? `${name}:wght@${axis}` : name;
15375
- return `${GOOGLE_CSS2}?family=${spec}&display=swap`;
15376
- }
15377
- var STANDARD_WEIGHTS = [100, 200, 300, 400, 500, 600, 700, 800, 900];
15378
- async function probeServedWeights(family, fetchCss) {
15379
- const probes = await Promise.all(
15380
- STANDARD_WEIGHTS.map(async (weight) => await fetchCss(googleFontCssUrl(family, [weight])) ? weight : null)
15381
- );
15382
- return probes.filter((w) => w !== null);
15383
- }
15384
- async function checkFontRequests(requests, fetchCss) {
15385
- const results = [];
15386
- for (const request of requests) {
15387
- const css = await fetchCss(googleFontCssUrl(request.family, request.weights));
15388
- if (css === null) {
15389
- const served2 = await probeServedWeights(request.family, fetchCss);
15390
- results.push({
15391
- family: request.family,
15392
- requested: request.weights,
15393
- served: served2,
15394
- missing: request.weights.filter((w) => !served2.includes(w)),
15395
- subsets: [],
15396
- cause: served2.length === 0 ? "unknown-family" : "unavailable-weight"
15397
- });
15398
- continue;
15399
- }
15400
- const faces = parseGoogleFontFaces(css);
15401
- const served = [...new Set(faces.map((f) => f.weight))].sort((a, b) => a - b);
15402
- results.push({
15403
- family: request.family,
15404
- requested: request.weights,
15405
- served,
15406
- missing: request.weights.filter((w) => !served.includes(w)),
15407
- subsets: [...new Set(faces.map((f) => f.subset))]
15408
- });
15409
- }
15410
- return results;
15411
- }
15412
-
15413
- // src/commands/brand/fonts.ts
15414
- var GLOBAL_CSS = path.join("src", "styles", "global.css");
15415
- var FONTS_DIR = path.join("src", "brand", "fonts");
15416
- var DEFAULT_SUBSETS = "latin";
15417
- var BROWSER_UA = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120.0 Safari/537.36";
15418
- registerSchema({
15419
- command: "brand.fonts.check",
15420
- description: "Start here when a brand's fonts are 'confirmed' but nobody verified it. Asks Google Fonts what it ACTUALLY serves for every family/weight src/styles/global.css requests, and reports any the brand promises but Google will not serve.",
15421
- args: {}
15422
- });
15423
- registerSchema({
15424
- command: "brand.fonts.fetch",
15425
- description: "Download a Google font into src/brand/fonts/ so the brand stops depending on a third party at page load, and print the @font-face block to paste above @theme in src/styles/global.css.",
15426
- args: {
15427
- family: { type: "string", description: 'Font family, e.g. "DM Sans"', required: true },
15428
- weights: {
15429
- type: "string",
15430
- description: "Comma-separated weights (default: what global.css requests, else 400)",
15431
- required: false
15432
- },
15433
- subsets: {
15434
- type: "string",
15435
- description: `Comma-separated unicode subsets (default: ${DEFAULT_SUBSETS})`,
15436
- required: false
15437
- }
15438
- }
15439
- });
15440
- function fail(code, message, fix) {
15441
- writeJson({ ok: false, error: { code, message, ...fix ? { fix } : {} } });
15442
- process.exit(2);
15443
- }
15444
- var REQUEST_TIMEOUT_MS = 15e3;
15445
- async function fetchGoogleCss(url) {
15446
- try {
15447
- const res = await fetch(url, {
15448
- headers: { "User-Agent": BROWSER_UA },
15449
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
15450
- });
15451
- if (!res.ok) return null;
15452
- return await res.text();
15453
- } catch {
15454
- return null;
15455
- }
15456
- }
15457
- async function readGlobalCss() {
15458
- try {
15459
- return await readFile(path.resolve(process.cwd(), GLOBAL_CSS), "utf8");
15460
- } catch {
15461
- return "";
15462
- }
15463
- }
15464
- var fontsCheckCommand = defineCommand85({
15465
- meta: {
15466
- name: "check",
15467
- description: "Verify the brand's fonts really exist. For every family/weight src/styles/global.css requests from Google Fonts, ask Google what it actually serves and report anything missing \u2014 a weight nobody serves renders as a synthesized fallback and looks off-brand everywhere."
15468
- },
15469
- async run() {
15470
- const css = await readGlobalCss();
15471
- const requests = googleFontRequests(css);
15472
- if (requests.length === 0) {
15473
- writeJson({
15474
- ok: true,
15475
- data: { families: [], selfHosted: true },
15476
- hints: [
15477
- `No Google Fonts requested in ${GLOBAL_CSS}. If the brand self-hosts, the offline validator already checks those files; nothing to verify against Google.`
15478
- ]
15479
- });
15480
- return;
15481
- }
15482
- const families = await checkFontRequests(requests, fetchGoogleCss);
15483
- const broken = families.filter((f) => f.missing.length > 0);
15484
- if (broken.length > 0) {
15485
- const summary = broken.map(
15486
- (f) => f.cause === "unknown-family" ? `${f.family} (no such family on Google Fonts \u2014 check the exact spelling)` : `${f.family} ${f.missing.join("/")} (served: ${f.served.join("/") || "none"})`
15487
- ).join("; ");
15488
- fail("FONT_NOT_SERVED", `Google Fonts does not serve: ${summary}`, {
15489
- action: `Correct the family name or weight in ${GLOBAL_CSS} and src/brand/BRAND.md, picking from the \`served\` weights below.`,
15490
- explanation: "A requested weight Google does not serve is silently synthesized by the browser, so the page looks subtly wrong with nothing failing.",
15491
- // The per-family breakdown is the point of the command, so it ships on
15492
- // the failure path too — otherwise the only remedy is re-running the
15493
- // command that just failed. Healthy families are included so a
15494
- // multi-family brand shows what NOT to touch.
15495
- families
15496
- });
15497
- }
15498
- writeJson({
15499
- ok: true,
15500
- data: { families },
15501
- hints: [
15502
- "Every requested family and weight is really served by Google.",
15503
- `To stop depending on Google at page load, run \`baker brand fonts fetch "<family>"\` to self-host into ${FONTS_DIR}.`
15504
- ]
15505
- });
15506
- }
15507
- });
15508
- var fontsFetchCommand = defineCommand85({
15509
- meta: {
15510
- name: "fetch",
15511
- description: "Download a Google font into src/brand/fonts/ and print the @font-face block to paste above @theme in src/styles/global.css. Use when a brand font should be self-hosted rather than requested from Google on every page load."
15512
- },
15513
- args: {
15514
- family: { type: "positional", required: true, description: 'Font family, e.g. "DM Sans"' },
15515
- weights: { type: "string", description: "Comma-separated weights (default: what global.css requests, else 400)" },
15516
- subsets: { type: "string", description: `Comma-separated unicode subsets (default: ${DEFAULT_SUBSETS})` }
15517
- },
15518
- async run({ args }) {
15519
- const family = String(args.family).trim();
15520
- if (!family) fail("INVALID_FAMILY", 'Pass a font family, e.g. `baker brand fonts fetch "DM Sans"`.');
15521
- const css = await readGlobalCss();
15522
- const declared = googleFontRequests(css).find((r) => r.family.toLowerCase() === family.toLowerCase());
15523
- const weights = resolveFetchWeights(args.weights, declared?.weights);
15524
- if (weights.length === 0) {
15525
- fail("INVALID_WEIGHTS", `"${args.weights}" has no usable weight \u2014 pass whole hundreds, e.g. --weights 400,700.`);
15526
- }
15527
- const wanted = new Set(
15528
- String(args.subsets ?? DEFAULT_SUBSETS).split(",").map((s) => s.trim()).filter(Boolean)
15529
- );
15530
- const servedCss = await fetchGoogleCss(googleFontCssUrl(family, weights));
15531
- if (servedCss === null) {
15532
- const [diagnosis] = await checkFontRequests([{ family, weights }], fetchGoogleCss);
15533
- const served = diagnosis?.served ?? [];
15534
- fail(
15535
- "FONT_NOT_SERVED",
15536
- served.length === 0 ? `Google Fonts has no family called "${family}".` : `"${family}" exists on Google Fonts but not at weight ${weights.join("/")}.`,
15537
- served.length === 0 ? {
15538
- action: "Check the exact family name at fonts.google.com, then retry.",
15539
- explanation: "Family names are case- and space-sensitive in the Google Fonts API."
15540
- } : {
15541
- action: `Retry with --weights set to one of these: ${served.join(",")}.`,
15542
- explanation: "Google rejects the whole request when one requested weight does not exist.",
15543
- served
15544
- }
15545
- );
15546
- }
15547
- const faces = parseGoogleFontFaces(servedCss).filter((f) => wanted.has(f.subset));
15548
- if (faces.length === 0) {
15549
- fail("SUBSET_NOT_SERVED", `"${family}" has no ${[...wanted].join("/")} subset.`, {
15550
- action: `Retry with --subsets set to one Google actually serves for this family.`,
15551
- explanation: "Google splits each family into unicode subsets; not every family ships every subset."
15552
- });
15553
- }
15554
- const fontsDir = path.resolve(process.cwd(), FONTS_DIR);
15555
- await mkdir(fontsDir, { recursive: true });
15556
- const downloaded = [];
15557
- for (const face of faces) {
15558
- const res = await fetch(face.url, {
15559
- headers: { "User-Agent": BROWSER_UA },
15560
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
15561
- });
15562
- if (!res.ok) continue;
15563
- await writeFile(path.join(fontsDir, fontFileName(face)), Buffer.from(await res.arrayBuffer()));
15564
- downloaded.push(face);
15565
- }
15566
- const written = downloaded.map(fontFileName);
15567
- if (written.length === 0) {
15568
- fail("DOWNLOAD_FAILED", `Could not download any file for "${family}".`, {
15569
- action: "Retry; if it keeps failing, keep the Google @import and note it in BRAND.md.",
15570
- explanation: "The font stylesheet resolved but the font files themselves did not download."
15571
- });
15572
- }
15573
- const fontFace = renderFontFaceCss(downloaded, (f) => `/${FONTS_DIR}/${fontFileName(f)}`);
15574
- const downloadedWeights = [...new Set(downloaded.map((f) => f.weight))].sort((a, b) => a - b);
15575
- const incomplete = weights.filter((w) => !downloadedWeights.includes(w));
15576
- writeJson({
15577
- ok: true,
15578
- data: { family, weights: downloadedWeights, files: written, fontFace },
15579
- hints: [
15580
- `Paste the \`fontFace\` block ABOVE the @theme block in ${GLOBAL_CSS}, then remove "${family}" from the Google @import so the page stops fetching it at load.`,
15581
- `Record the exact weights (${downloadedWeights.join(", ")}) in src/brand/BRAND.md \u2014 a weight listed there but not downloaded renders as a synthesized fallback.`,
15582
- ...incomplete.length > 0 ? [
15583
- `PARTIAL: ${incomplete.join(", ")} did not download and is NOT in the \`fontFace\` block. Keep "${family}" in the Google @import for those weights, or re-run \`baker brand fonts fetch "${family}" --weights ${incomplete.join(",")}\`.`
15584
- ] : [],
15585
- "Licensing: Google Fonts are open-licensed and safe to self-host. A client's own commercial face is not \u2014 confirm before re-hosting one."
15586
- ]
15587
- });
15588
- }
15589
- });
15590
- var fontsCommand = defineCommand85({
15591
- meta: {
15592
- name: "fonts",
15593
- description: `Verify and self-host the brand's typefaces.
15594
-
15595
- Start here: \`baker brand fonts check\` \u2014 confirms the fonts the brand claims are really served.
15596
-
15597
- Subcommands:
15598
- baker brand fonts check \u2014 ask Google what it actually serves for every family/weight global.css requests
15599
- baker brand fonts fetch <family> \u2014 download a family into src/brand/fonts/ and print its @font-face block`
15600
- },
15601
- subCommands: {
15602
- check: fontsCheckCommand,
15603
- fetch: fontsFetchCommand
15604
- }
15605
- });
15606
-
15607
- // src/commands/brand/index.ts
15608
- var brandCommand = defineCommand86({
15609
- meta: {
15610
- name: "brand",
15611
- description: `Brand asset verification for src/brand/.
15612
-
15613
- Start here: \`baker brand fonts check\` after defining or editing the brand's typography.
15614
-
15615
- Subcommands:
15616
- baker brand fonts \u2014 verify the brand's typefaces really load, and self-host them into src/brand/fonts/`
15617
- },
15618
- subCommands: {
15619
- fonts: fontsCommand
15620
- }
15621
- });
15622
-
15623
15289
  // src/commands/canvas/index.ts
15624
- import { defineCommand as defineCommand97 } from "citty";
15290
+ import { defineCommand as defineCommand95 } from "citty";
15625
15291
 
15626
15292
  // src/commands/canvas/catalog.ts
15627
- import { defineCommand as defineCommand87 } from "citty";
15628
- var catalogCommand = defineCommand87({
15293
+ import { defineCommand as defineCommand85 } from "citty";
15294
+ var catalogCommand = defineCommand85({
15629
15295
  meta: {
15630
15296
  name: "catalog",
15631
15297
  description: "Print the agent-facing node catalog (JSON Schema). Includes every registered node grouped by category."
@@ -15638,9 +15304,9 @@ var catalogCommand = defineCommand87({
15638
15304
  });
15639
15305
 
15640
15306
  // src/commands/canvas/critique.ts
15641
- import { readFile as readFile2 } from "fs/promises";
15642
- import path2 from "path";
15643
- import { defineCommand as defineCommand88 } from "citty";
15307
+ import { readFile } from "fs/promises";
15308
+ import path from "path";
15309
+ import { defineCommand as defineCommand86 } from "citty";
15644
15310
 
15645
15311
  // src/engine/scaffold/lib/critique.ts
15646
15312
  var VIBE_CUE = /\b(light|lighting|golden|moody|warm|cool|tone|grade|contrast|shadow|glow|rim|backlit|neon|soft)\b/i;
@@ -15760,15 +15426,15 @@ function critiqueCanvas(canvas) {
15760
15426
  }
15761
15427
 
15762
15428
  // src/commands/canvas/critique.ts
15763
- var critiqueCommand = defineCommand88({
15429
+ var critiqueCommand = defineCommand86({
15764
15430
  meta: {
15765
15431
  name: "critique",
15766
15432
  description: "Pre-spend creative critic (ADVISORY \u2014 never blocks). Scores a scaffolded creative BEFORE the billed render, so weak spots get fixed for free. A VIDEO creative is scored on hook strength, sound-off first-frame legibility, retention risk, and mechanism clarity; a STATIC ad on baked-text legibility risk, identity grounding, brand-type fidelity, and mechanism clarity. Ground a video hook against `baker winning-ads hooks` for a proven pattern."
15767
15433
  },
15768
15434
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
15769
15435
  async run({ args }) {
15770
- const filePath = path2.resolve(String(args.file));
15771
- const raw = await readFile2(filePath, "utf8");
15436
+ const filePath = path.resolve(String(args.file));
15437
+ const raw = await readFile(filePath, "utf8");
15772
15438
  let parsed;
15773
15439
  try {
15774
15440
  parsed = JSON.parse(raw);
@@ -15799,12 +15465,12 @@ var critiqueCommand = defineCommand88({
15799
15465
 
15800
15466
  // src/commands/canvas/inspect.ts
15801
15467
  import { execFile } from "child_process";
15802
- import { readdir, readFile as readFile3, stat } from "fs/promises";
15803
- import path3 from "path";
15468
+ import { readdir, readFile as readFile2, stat } from "fs/promises";
15469
+ import path2 from "path";
15804
15470
  import { promisify } from "util";
15805
- import { defineCommand as defineCommand89 } from "citty";
15471
+ import { defineCommand as defineCommand87 } from "citty";
15806
15472
  var execFileAsync = promisify(execFile);
15807
- var inspectCommand = defineCommand89({
15473
+ var inspectCommand = defineCommand87({
15808
15474
  meta: {
15809
15475
  name: "inspect",
15810
15476
  description: "Dump a one-page summary of a canvas run: per-node duration + cache status, list of output files in the run dir, and optionally three thumbnail frames per video output. Pass either a run_id (resolved against --outputs-dir) or an absolute run directory."
@@ -15818,7 +15484,7 @@ var inspectCommand = defineCommand89({
15818
15484
  }
15819
15485
  },
15820
15486
  async run({ args }) {
15821
- const outputsDir = path3.resolve(String(args["outputs-dir"] ?? "canvas"));
15487
+ const outputsDir = path2.resolve(String(args["outputs-dir"] ?? "canvas"));
15822
15488
  const runArg = String(args.run);
15823
15489
  const runDir = await resolveRunDir(runArg, outputsDir);
15824
15490
  const manifest = await loadManifest(runDir);
@@ -15830,7 +15496,7 @@ var inspectCommand = defineCommand89({
15830
15496
  }
15831
15497
  const summary = {
15832
15498
  ok: true,
15833
- run_id: manifest.run_id ?? path3.basename(runDir),
15499
+ run_id: manifest.run_id ?? path2.basename(runDir),
15834
15500
  run_dir: runDir,
15835
15501
  stats: manifest.stats ?? null,
15836
15502
  output: manifest.output ?? null,
@@ -15843,20 +15509,20 @@ var inspectCommand = defineCommand89({
15843
15509
  }
15844
15510
  });
15845
15511
  async function resolveRunDir(run, outputsDir) {
15846
- if (path3.isAbsolute(run)) {
15512
+ if (path2.isAbsolute(run)) {
15847
15513
  const s2 = await stat(run).catch(() => null);
15848
15514
  if (s2?.isDirectory()) return run;
15849
15515
  throw new Error(`inspect: ${run} is not a directory`);
15850
15516
  }
15851
- const candidate = path3.join(outputsDir, run);
15517
+ const candidate = path2.join(outputsDir, run);
15852
15518
  const s = await stat(candidate).catch(() => null);
15853
15519
  if (s?.isDirectory()) return candidate;
15854
15520
  throw new Error(`inspect: no run directory at ${candidate}`);
15855
15521
  }
15856
15522
  async function loadManifest(runDir) {
15857
- const manifestPath = path3.join(runDir, "manifest.json");
15523
+ const manifestPath = path2.join(runDir, "manifest.json");
15858
15524
  try {
15859
- const raw = await readFile3(manifestPath, "utf-8");
15525
+ const raw = await readFile2(manifestPath, "utf-8");
15860
15526
  return JSON.parse(raw);
15861
15527
  } catch {
15862
15528
  return {};
@@ -15866,7 +15532,7 @@ async function listRunFiles(runDir) {
15866
15532
  const out = [];
15867
15533
  const names = await readdir(runDir);
15868
15534
  for (const name of names) {
15869
- const abs = path3.join(runDir, name);
15535
+ const abs = path2.join(runDir, name);
15870
15536
  const s = await stat(abs).catch(() => null);
15871
15537
  if (!s?.isFile()) continue;
15872
15538
  out.push({ name, path: abs, size: s.size });
@@ -15911,13 +15577,13 @@ async function probeDuration(filePath) {
15911
15577
  }
15912
15578
 
15913
15579
  // src/commands/canvas/rerun.ts
15914
- import path14 from "path";
15915
- import { defineCommand as defineCommand91 } from "citty";
15580
+ import path13 from "path";
15581
+ import { defineCommand as defineCommand89 } from "citty";
15916
15582
 
15917
15583
  // src/commands/canvas/run.ts
15918
- import { readFile as readFile10 } from "fs/promises";
15919
- import path13 from "path";
15920
- import { defineCommand as defineCommand90 } from "citty";
15584
+ import { readFile as readFile9 } from "fs/promises";
15585
+ import path12 from "path";
15586
+ import { defineCommand as defineCommand88 } from "citty";
15921
15587
 
15922
15588
  // src/commands/canvas/placeholders.ts
15923
15589
  function unsuppliedPlaceholderAssets(canvas) {
@@ -15936,7 +15602,7 @@ function unsuppliedPlaceholderAssets(canvas) {
15936
15602
  }
15937
15603
 
15938
15604
  // src/commands/canvas/resolve-paths.ts
15939
- import path4 from "path";
15605
+ import path3 from "path";
15940
15606
  function resolveRelativeCanvasPaths(canvas, baseDir) {
15941
15607
  if (!canvas || typeof canvas !== "object") return canvas;
15942
15608
  const c = canvas;
@@ -15949,24 +15615,24 @@ function resolveNode(node, baseDir) {
15949
15615
  const params = n.params;
15950
15616
  if (!params || typeof params !== "object") return node;
15951
15617
  if (n.type === "ingest" && params.source === "path" && isResolvableRelative(params.path)) {
15952
- return { ...node, params: { ...params, path: path4.resolve(baseDir, params.path) } };
15618
+ return { ...node, params: { ...params, path: path3.resolve(baseDir, params.path) } };
15953
15619
  }
15954
15620
  if (n.type === "hyperframe_render" && isResolvableRelative(params.composition)) {
15955
- return { ...node, params: { ...params, composition: path4.resolve(baseDir, params.composition) } };
15621
+ return { ...node, params: { ...params, composition: path3.resolve(baseDir, params.composition) } };
15956
15622
  }
15957
15623
  return node;
15958
15624
  }
15959
15625
  function isResolvableRelative(value) {
15960
- return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !looksLikeHttpUrl(value) && !path4.isAbsolute(value);
15626
+ return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !looksLikeHttpUrl(value) && !path3.isAbsolute(value);
15961
15627
  }
15962
15628
 
15963
15629
  // src/commands/canvas/source-version.ts
15964
- import { readFile as readFile5 } from "fs/promises";
15965
- import path6 from "path";
15630
+ import { readFile as readFile4 } from "fs/promises";
15631
+ import path5 from "path";
15966
15632
 
15967
15633
  // src/commands/canvas/scene-files.ts
15968
- import { mkdir as mkdir2, readFile as readFile4, readdir as readdir2, rm, writeFile as writeFile2 } from "fs/promises";
15969
- import path5 from "path";
15634
+ import { mkdir, readFile as readFile3, readdir as readdir2, rm, writeFile } from "fs/promises";
15635
+ import path4 from "path";
15970
15636
  var SCENES_DIR = "scenes";
15971
15637
  var GLOBAL_PROMPT_FILE = "prompt.json";
15972
15638
  var REBUILD_FILE = "prompt.rebuild.json";
@@ -15983,19 +15649,19 @@ function splitBlueprint(blueprint) {
15983
15649
  }
15984
15650
  async function writeSceneFiles(outDir, blueprint) {
15985
15651
  const { global, scenes } = splitBlueprint(blueprint);
15986
- await writeFile2(path5.join(outDir, GLOBAL_PROMPT_FILE), `${JSON.stringify(global, null, 2)}
15652
+ await writeFile(path4.join(outDir, GLOBAL_PROMPT_FILE), `${JSON.stringify(global, null, 2)}
15987
15653
  `, "utf8");
15988
- const scenesDir = path5.join(outDir, SCENES_DIR);
15989
- await mkdir2(scenesDir, { recursive: true });
15654
+ const scenesDir = path4.join(outDir, SCENES_DIR);
15655
+ await mkdir(scenesDir, { recursive: true });
15990
15656
  const written = /* @__PURE__ */ new Set();
15991
15657
  for (let i = 0; i < scenes.length; i++) {
15992
15658
  const name = sceneFileName(i, scenes.length);
15993
15659
  written.add(name);
15994
- await writeFile2(path5.join(scenesDir, name), `${JSON.stringify(scenes[i], null, 2)}
15660
+ await writeFile(path4.join(scenesDir, name), `${JSON.stringify(scenes[i], null, 2)}
15995
15661
  `, "utf8");
15996
15662
  }
15997
15663
  for (const name of await listSceneFileNames(scenesDir)) {
15998
- if (!written.has(name)) await rm(path5.join(scenesDir, name), { force: true });
15664
+ if (!written.has(name)) await rm(path4.join(scenesDir, name), { force: true });
15999
15665
  }
16000
15666
  }
16001
15667
  async function listSceneFileNames(scenesDir) {
@@ -16008,17 +15674,17 @@ async function listSceneFileNames(scenesDir) {
16008
15674
  return entries.filter((n) => /^s\d+\.json$/.test(n)).sort(bySceneIndex);
16009
15675
  }
16010
15676
  async function listSceneFiles(creativeDir) {
16011
- const scenesDir = path5.join(creativeDir, SCENES_DIR);
16012
- return (await listSceneFileNames(scenesDir)).map((n) => path5.join(scenesDir, n));
15677
+ const scenesDir = path4.join(creativeDir, SCENES_DIR);
15678
+ return (await listSceneFileNames(scenesDir)).map((n) => path4.join(scenesDir, n));
16013
15679
  }
16014
15680
  async function reassembleBlueprint(creativeDir) {
16015
15681
  const files = await listSceneFiles(creativeDir);
16016
15682
  if (files.length === 0) return null;
16017
- const globalRaw = await readFile4(path5.join(creativeDir, GLOBAL_PROMPT_FILE), "utf8");
15683
+ const globalRaw = await readFile3(path4.join(creativeDir, GLOBAL_PROMPT_FILE), "utf8");
16018
15684
  const global = JSON.parse(globalRaw);
16019
15685
  const scenes = [];
16020
15686
  for (const file of files) {
16021
- scenes.push(JSON.parse(await readFile4(file, "utf8")));
15687
+ scenes.push(JSON.parse(await readFile3(file, "utf8")));
16022
15688
  }
16023
15689
  return { ...global, scenes };
16024
15690
  }
@@ -16032,15 +15698,15 @@ function bySceneIndex(a, b) {
16032
15698
  async function computeSourceSha(canvasPath) {
16033
15699
  let canvasBytes;
16034
15700
  try {
16035
- canvasBytes = await readFile5(canvasPath);
15701
+ canvasBytes = await readFile4(canvasPath);
16036
15702
  } catch {
16037
15703
  return void 0;
16038
15704
  }
16039
- const canvasDir = path6.dirname(canvasPath);
16040
- const promptPath = path6.join(canvasDir, "prompt.json");
15705
+ const canvasDir = path5.dirname(canvasPath);
15706
+ const promptPath = path5.join(canvasDir, "prompt.json");
16041
15707
  let promptBytes;
16042
15708
  try {
16043
- promptBytes = await readFile5(promptPath);
15709
+ promptBytes = await readFile4(promptPath);
16044
15710
  } catch {
16045
15711
  promptBytes = Buffer.alloc(0);
16046
15712
  }
@@ -16053,7 +15719,7 @@ async function computeSourceSha(canvasPath) {
16053
15719
  for (const sceneFile of await listSceneFiles(canvasDir)) {
16054
15720
  let sceneBytes;
16055
15721
  try {
16056
- sceneBytes = await readFile5(sceneFile);
15722
+ sceneBytes = await readFile4(sceneFile);
16057
15723
  } catch {
16058
15724
  sceneBytes = Buffer.alloc(0);
16059
15725
  }
@@ -16063,8 +15729,8 @@ async function computeSourceSha(canvasPath) {
16063
15729
  }
16064
15730
 
16065
15731
  // src/commands/canvas/scene-projection.ts
16066
- import { readFile as readFile6 } from "fs/promises";
16067
- import path7 from "path";
15732
+ import { readFile as readFile5 } from "fs/promises";
15733
+ import path6 from "path";
16068
15734
 
16069
15735
  // src/engine/scaffold/video.ts
16070
15736
  import { toCardinal as nwAr } from "n2words/ar-SA";
@@ -19323,12 +18989,12 @@ function nonPromptParamsDiverge(live = {}, rebuilt = {}) {
19323
18989
  return false;
19324
18990
  }
19325
18991
  async function syncSceneNodeParams(canvas, canvasPath, log) {
19326
- const creativeDir = path7.dirname(canvasPath);
18992
+ const creativeDir = path6.dirname(canvasPath);
19327
18993
  const blueprint = await reassembleBlueprint(creativeDir);
19328
18994
  if (!blueprint) return "not_applicable";
19329
18995
  let rebuildRaw;
19330
18996
  try {
19331
- rebuildRaw = await readFile6(path7.join(creativeDir, REBUILD_FILE), "utf8");
18997
+ rebuildRaw = await readFile5(path6.join(creativeDir, REBUILD_FILE), "utf8");
19332
18998
  } catch {
19333
18999
  return "not_applicable";
19334
19000
  }
@@ -19369,7 +19035,7 @@ async function syncSceneNodeParams(canvas, canvasPath, log) {
19369
19035
  }
19370
19036
 
19371
19037
  // src/commands/canvas/style-projection.ts
19372
- import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
19038
+ import { readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
19373
19039
  function findBlueprintProjection(canvas) {
19374
19040
  if (!canvas || typeof canvas !== "object") return null;
19375
19041
  const nodes = canvas.nodes;
@@ -19397,10 +19063,10 @@ function renderStyleProjectionFromValue(blueprint) {
19397
19063
  async function syncStyleProjection(canvas, log) {
19398
19064
  const pair = findBlueprintProjection(canvas);
19399
19065
  if (!pair) return "not_applicable";
19400
- const rendered = renderStyleProjection(await readFile7(pair.promptPath, "utf8"));
19401
- const current = await readFile7(pair.stylePath, "utf8").catch(() => null);
19066
+ const rendered = renderStyleProjection(await readFile6(pair.promptPath, "utf8"));
19067
+ const current = await readFile6(pair.stylePath, "utf8").catch(() => null);
19402
19068
  if (current === rendered) return "up_to_date";
19403
- await writeFile3(pair.stylePath, rendered, "utf8");
19069
+ await writeFile2(pair.stylePath, rendered, "utf8");
19404
19070
  log(
19405
19071
  "[style] prompt.style.json regenerated from prompt.json \u2014 every frame's shared ad spec changed; affected image frames will re-bill on the next run"
19406
19072
  );
@@ -19460,13 +19126,13 @@ ${body}` : header || body || compactJson(record);
19460
19126
  }
19461
19127
 
19462
19128
  // src/commands/canvas/run-record.ts
19463
- import path8 from "path";
19129
+ import path7 from "path";
19464
19130
  var MAX_RUN_NODES = 200;
19465
19131
  var MAX_OUTPUTS_PER_NODE = 10;
19466
19132
  var MAX_FINAL_OUTPUTS = 10;
19467
19133
  var MAX_CREATIVE_SLUG_LENGTH = 100;
19468
19134
  function creativeSlugFromCanvasPath(filePath) {
19469
- const normalized = filePath.split(path8.sep).join("/");
19135
+ const normalized = filePath.split(path7.sep).join("/");
19470
19136
  const match = normalized.match(/(?:^|\/)src\/creatives\/([a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\//);
19471
19137
  const slug = match?.[1] ?? null;
19472
19138
  return slug && slug.length <= MAX_CREATIVE_SLUG_LENGTH ? slug : null;
@@ -19754,7 +19420,7 @@ var RunRecordPoster = class {
19754
19420
 
19755
19421
  // src/commands/canvas/run-retention.ts
19756
19422
  import { rm as rm2 } from "fs/promises";
19757
- import path9 from "path";
19423
+ import path8 from "path";
19758
19424
  function runDirsToPrune(entries, keep, currentRunId) {
19759
19425
  const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
19760
19426
  if (keep <= 0) return runs;
@@ -19771,7 +19437,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
19771
19437
  const toPrune = runDirsToPrune(entries, keep, currentRunId);
19772
19438
  if (toPrune.length === 0) return;
19773
19439
  for (const dir of toPrune) {
19774
- await rm2(path9.join(outputsDir, dir), { recursive: true, force: true }).catch(
19440
+ await rm2(path8.join(outputsDir, dir), { recursive: true, force: true }).catch(
19775
19441
  (e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
19776
19442
  );
19777
19443
  }
@@ -19779,13 +19445,13 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
19779
19445
  }
19780
19446
 
19781
19447
  // src/commands/canvas/dirty-marker.ts
19782
- import { mkdir as mkdir3, readdir as readdir3, rm as rm3, writeFile as writeFile4 } from "fs/promises";
19783
- import path10 from "path";
19448
+ import { mkdir as mkdir2, readdir as readdir3, rm as rm3, writeFile as writeFile3 } from "fs/promises";
19449
+ import path9 from "path";
19784
19450
  function creativeDirtyDir(base) {
19785
- return base ?? path10.resolve("canvas", ".dirty");
19451
+ return base ?? path9.resolve("canvas", ".dirty");
19786
19452
  }
19787
19453
  function dirtyMarkerFile(slug, base) {
19788
- return path10.join(creativeDirtyDir(base), `${slug}.json`);
19454
+ return path9.join(creativeDirtyDir(base), `${slug}.json`);
19789
19455
  }
19790
19456
  async function clearCreativeDirty(slug, base) {
19791
19457
  try {
@@ -19795,18 +19461,18 @@ async function clearCreativeDirty(slug, base) {
19795
19461
  }
19796
19462
 
19797
19463
  // src/commands/canvas/run-resume.ts
19798
- import { mkdir as mkdir4, readFile as readFile8, rm as rm4, writeFile as writeFile5 } from "fs/promises";
19799
- import path11 from "path";
19464
+ import { mkdir as mkdir3, readFile as readFile7, rm as rm4, writeFile as writeFile4 } from "fs/promises";
19465
+ import path10 from "path";
19800
19466
  function markerKey(canvasPath) {
19801
19467
  const slug = creativeSlugFromCanvasPath(canvasPath);
19802
- const identity = slug ?? path11.relative(process.cwd(), path11.resolve(canvasPath));
19468
+ const identity = slug ?? path10.relative(process.cwd(), path10.resolve(canvasPath));
19803
19469
  return sha256Hex(Buffer.from(identity)).slice(0, 32);
19804
19470
  }
19805
19471
  function legacyMarkerKey(canvasPath) {
19806
- return sha256Hex(Buffer.from(path11.resolve(canvasPath))).slice(0, 32);
19472
+ return sha256Hex(Buffer.from(path10.resolve(canvasPath))).slice(0, 32);
19807
19473
  }
19808
19474
  function markerFile(outputsDir, key) {
19809
- return path11.join(outputsDir, ".inflight", `${key}.json`);
19475
+ return path10.join(outputsDir, ".inflight", `${key}.json`);
19810
19476
  }
19811
19477
  var REMOTE_ADOPT_STALE_MS = 12e4;
19812
19478
  function classifyRemoteRun(run, now) {
@@ -19842,7 +19508,7 @@ async function resolveRunId(opts) {
19842
19508
  async function readMarkerRunId(outputsDir, canvasPath) {
19843
19509
  for (const key of [markerKey(canvasPath), legacyMarkerKey(canvasPath)]) {
19844
19510
  try {
19845
- const raw = await readFile8(markerFile(outputsDir, key), "utf8");
19511
+ const raw = await readFile7(markerFile(outputsDir, key), "utf8");
19846
19512
  const parsed = JSON.parse(raw);
19847
19513
  if (typeof parsed.runId === "string" && parsed.runId.length > 0) return parsed.runId;
19848
19514
  } catch {
@@ -19853,8 +19519,8 @@ async function readMarkerRunId(outputsDir, canvasPath) {
19853
19519
  async function markRunInFlight(outputsDir, canvasPath, runId) {
19854
19520
  try {
19855
19521
  const file = markerFile(outputsDir, markerKey(canvasPath));
19856
- await mkdir4(path11.dirname(file), { recursive: true });
19857
- await writeFile5(file, JSON.stringify({ runId, canvasPath: path11.resolve(canvasPath), startedAt: Date.now() }));
19522
+ await mkdir3(path10.dirname(file), { recursive: true });
19523
+ await writeFile4(file, JSON.stringify({ runId, canvasPath: path10.resolve(canvasPath), startedAt: Date.now() }));
19858
19524
  } catch {
19859
19525
  }
19860
19526
  }
@@ -19868,8 +19534,8 @@ async function clearRunMarker(outputsDir, canvasPath) {
19868
19534
  }
19869
19535
 
19870
19536
  // src/commands/canvas/run-snapshot.ts
19871
- import { mkdir as mkdir5, readdir as readdir4, readFile as readFile9, stat as stat2, writeFile as writeFile6 } from "fs/promises";
19872
- import path12 from "path";
19537
+ import { mkdir as mkdir4, readdir as readdir4, readFile as readFile8, stat as stat2, writeFile as writeFile5 } from "fs/promises";
19538
+ import path11 from "path";
19873
19539
  var SNAPSHOT_SCHEMA = "baker-canvas-snapshot/1";
19874
19540
  var MAX_SNAPSHOT_FILE_BYTES = 32 * 1024 * 1024;
19875
19541
  var EXT_TO_MIME = {
@@ -19896,11 +19562,11 @@ var EXT_TO_MIME = {
19896
19562
  woff2: "font/woff2"
19897
19563
  };
19898
19564
  function mimeForFile(filePath) {
19899
- const ext = path12.extname(filePath).slice(1).toLowerCase();
19565
+ const ext = path11.extname(filePath).slice(1).toLowerCase();
19900
19566
  return EXT_TO_MIME[ext] ?? "application/octet-stream";
19901
19567
  }
19902
19568
  function toPosix(p) {
19903
- return p.split(path12.sep).join("/");
19569
+ return p.split(path11.sep).join("/");
19904
19570
  }
19905
19571
  function localPathRefsFromCanvas(parsed) {
19906
19572
  const nodes = parsed?.nodes;
@@ -19925,37 +19591,37 @@ function isSnapshotablePath(value) {
19925
19591
  async function sourceRefsToSnapshot(canvasDir, parsed) {
19926
19592
  const refs = new Set(localPathRefsFromCanvas(parsed));
19927
19593
  for (const sceneFile of await listSceneFiles(canvasDir)) {
19928
- refs.add(toPosix(path12.relative(canvasDir, sceneFile)));
19594
+ refs.add(toPosix(path11.relative(canvasDir, sceneFile)));
19929
19595
  }
19930
19596
  refs.add(REBUILD_FILE);
19931
19597
  return [...refs];
19932
19598
  }
19933
19599
  async function uploadRunSnapshot(client, opts) {
19934
19600
  try {
19935
- const canvasDir = path12.dirname(opts.canvasPath);
19601
+ const canvasDir = path11.dirname(opts.canvasPath);
19936
19602
  const put = (bytes, mime) => putContentAddressed(client, bytes, mime, opts.signal);
19937
19603
  const canvasBytes = Buffer.from(opts.raw);
19938
19604
  const canvasUpload = await put(canvasBytes, "application/json");
19939
19605
  const files = [];
19940
19606
  const skipped = [];
19941
19607
  for (const refPath of await sourceRefsToSnapshot(canvasDir, opts.parsed)) {
19942
- const abs = path12.isAbsolute(refPath) ? refPath : path12.resolve(canvasDir, refPath);
19608
+ const abs = path11.isAbsolute(refPath) ? refPath : path11.resolve(canvasDir, refPath);
19943
19609
  let st;
19944
19610
  try {
19945
19611
  st = await stat2(abs);
19946
19612
  } catch {
19947
- skipped.push({ path: toPosix(path12.relative(canvasDir, abs)), reason: "missing" });
19613
+ skipped.push({ path: toPosix(path11.relative(canvasDir, abs)), reason: "missing" });
19948
19614
  continue;
19949
19615
  }
19950
19616
  const fileList = st.isDirectory() ? await listFilesRecursive(abs) : [abs];
19951
19617
  for (const file of fileList) {
19952
- const rel = toPosix(path12.relative(canvasDir, file));
19618
+ const rel = toPosix(path11.relative(canvasDir, file));
19953
19619
  const size = (await stat2(file)).size;
19954
19620
  if (size > MAX_SNAPSHOT_FILE_BYTES) {
19955
19621
  skipped.push({ path: rel, reason: `too large (${size} bytes)` });
19956
19622
  continue;
19957
19623
  }
19958
- const bytes = await readFile9(file);
19624
+ const bytes = await readFile8(file);
19959
19625
  const upload = await put(bytes, mimeForFile(file));
19960
19626
  files.push({ path: rel, sha256: upload.sha256, url: upload.url });
19961
19627
  }
@@ -19964,7 +19630,7 @@ async function uploadRunSnapshot(client, opts) {
19964
19630
  schema: SNAPSHOT_SCHEMA,
19965
19631
  creativeSlug: opts.creativeSlug,
19966
19632
  canvasSha: canvasUpload.sha256,
19967
- canvas: { path: path12.basename(opts.canvasPath), sha256: canvasUpload.sha256, url: canvasUpload.url },
19633
+ canvas: { path: path11.basename(opts.canvasPath), sha256: canvasUpload.sha256, url: canvasUpload.url },
19968
19634
  files,
19969
19635
  skipped: skipped.length > 0 ? skipped : void 0
19970
19636
  };
@@ -19991,7 +19657,7 @@ async function putContentAddressed(client, bytes, mime, signal) {
19991
19657
  }
19992
19658
  async function listFilesRecursive(dir) {
19993
19659
  const entries = await readdir4(dir, { recursive: true, withFileTypes: true });
19994
- return entries.filter((d) => d.isFile()).map((d) => path12.join(d.parentPath, d.name));
19660
+ return entries.filter((d) => d.isFile()).map((d) => path11.join(d.parentPath, d.name));
19995
19661
  }
19996
19662
  var SnapshotConflictError = class extends Error {
19997
19663
  conflicts;
@@ -20003,19 +19669,19 @@ var SnapshotConflictError = class extends Error {
20003
19669
  };
20004
19670
  async function restoreRunSnapshot(manifest, targetDir, opts = {}) {
20005
19671
  const entries = [manifest.canvas, ...manifest.files];
20006
- const resolvedTarget = path12.resolve(targetDir);
19672
+ const resolvedTarget = path11.resolve(targetDir);
20007
19673
  const planned = [];
20008
19674
  const conflicts = [];
20009
19675
  const upToDate = [];
20010
19676
  for (const entry of entries) {
20011
- if (path12.isAbsolute(entry.path) || entry.path.split("/").includes("..")) {
19677
+ if (path11.isAbsolute(entry.path) || entry.path.split("/").includes("..")) {
20012
19678
  throw new Error(`snapshot entry escapes the creative directory: ${entry.path}`);
20013
19679
  }
20014
- const target = path12.resolve(resolvedTarget, entry.path);
20015
- if (target !== resolvedTarget && !target.startsWith(resolvedTarget + path12.sep)) {
19680
+ const target = path11.resolve(resolvedTarget, entry.path);
19681
+ if (target !== resolvedTarget && !target.startsWith(resolvedTarget + path11.sep)) {
20016
19682
  throw new Error(`snapshot entry escapes the creative directory: ${entry.path}`);
20017
19683
  }
20018
- const existing = await readFile9(target).catch(() => null);
19684
+ const existing = await readFile8(target).catch(() => null);
20019
19685
  if (existing) {
20020
19686
  if (sha256Hex(existing) === entry.sha256) {
20021
19687
  upToDate.push(entry.path);
@@ -20037,15 +19703,15 @@ async function restoreRunSnapshot(manifest, targetDir, opts = {}) {
20037
19703
  if (sha256Hex(bytes) !== entry.sha256) {
20038
19704
  throw new Error(`snapshot download for ${entry.path} does not match its recorded sha256`);
20039
19705
  }
20040
- await mkdir5(path12.dirname(target), { recursive: true });
20041
- await writeFile6(target, bytes);
19706
+ await mkdir4(path11.dirname(target), { recursive: true });
19707
+ await writeFile5(target, bytes);
20042
19708
  restored.push(entry.path);
20043
19709
  }
20044
- return { canvasPath: path12.resolve(resolvedTarget, manifest.canvas.path), restored, upToDate };
19710
+ return { canvasPath: path11.resolve(resolvedTarget, manifest.canvas.path), restored, upToDate };
20045
19711
  }
20046
19712
 
20047
19713
  // src/commands/canvas/run.ts
20048
- var runCommand = defineCommand90({
19714
+ var runCommand = defineCommand88({
20049
19715
  meta: { name: "run", description: "Validate and execute a canvas JSON file." },
20050
19716
  args: {
20051
19717
  file: { type: "positional", required: true, description: "Path to canvas JSON" },
@@ -20121,8 +19787,8 @@ function resolveMaxCredits(...candidates) {
20121
19787
  return void 0;
20122
19788
  }
20123
19789
  async function executeCanvasRun(opts) {
20124
- const filePath = path13.resolve(opts.file);
20125
- const raw = await readFile10(filePath, "utf8");
19790
+ const filePath = path12.resolve(opts.file);
19791
+ const raw = await readFile9(filePath, "utf8");
20126
19792
  let parsed;
20127
19793
  try {
20128
19794
  parsed = JSON.parse(raw);
@@ -20134,7 +19800,7 @@ async function executeCanvasRun(opts) {
20134
19800
  }
20135
19801
  const attemptedSlug = creativeSlugFromCanvasPath(filePath);
20136
19802
  if (attemptedSlug) await clearCreativeDirty(attemptedSlug);
20137
- parsed = resolveRelativeCanvasPaths(parsed, path13.dirname(filePath));
19803
+ parsed = resolveRelativeCanvasPaths(parsed, path12.dirname(filePath));
20138
19804
  try {
20139
19805
  await syncStyleProjection(parsed, (line) => process.stderr.write(`${line}
20140
19806
  `));
@@ -20240,7 +19906,7 @@ async function executeCanvasRun(opts) {
20240
19906
  const canvasSha = sha256Hex(Buffer.from(raw));
20241
19907
  const creativeSlug = creativeSlugFromCanvasPath(filePath) ?? void 0;
20242
19908
  const client = opts.record === false ? null : buildBackendClient();
20243
- const outputsDir = opts.outputsDir ? path13.resolve(opts.outputsDir) : path13.resolve("canvas");
19909
+ const outputsDir = opts.outputsDir ? path12.resolve(opts.outputsDir) : path12.resolve("canvas");
20244
19910
  const { runId, resumed, source, concurrentRunId } = await resolveRunId({
20245
19911
  explicitRunId: opts.runId,
20246
19912
  fresh: opts.fresh === true,
@@ -20274,7 +19940,7 @@ async function executeCanvasRun(opts) {
20274
19940
  const canvasSnapshotUrl = client && creativeSlug ? await uploadRunSnapshot(client, { canvasPath: filePath, raw, creativeSlug, parsed }) ?? void 0 : void 0;
20275
19941
  const recordMeta = {
20276
19942
  creativeSlug,
20277
- canvasPath: path13.relative(process.cwd(), filePath) || void 0,
19943
+ canvasPath: path12.relative(process.cwd(), filePath) || void 0,
20278
19944
  canvasSha,
20279
19945
  // The fingerprint the dashboard compares against the current source to flag
20280
19946
  // "edited since last render". Computed from the on-disk canvas.json +
@@ -20415,7 +20081,7 @@ async function postInitialRunRecord(client, payload) {
20415
20081
 
20416
20082
  // src/commands/canvas/rerun.ts
20417
20083
  var SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
20418
- var rerunCommand = defineCommand91({
20084
+ var rerunCommand = defineCommand89({
20419
20085
  meta: {
20420
20086
  name: "rerun",
20421
20087
  description: "Re-run a creative's latest recorded canvas. Restores its definition files from run history first, so it works in a fresh workspace that never had the source chat's files \u2014 an interrupted run resumes (in-flight jobs re-attach), a completed one re-renders from the cache."
@@ -20444,24 +20110,24 @@ var rerunCommand = defineCommand91({
20444
20110
  async run({ args }) {
20445
20111
  const slug = String(args.slug);
20446
20112
  if (!SLUG_PATTERN.test(slug)) {
20447
- fail2("invalid_slug", `"${slug}" is not a valid creative slug`);
20113
+ fail("invalid_slug", `"${slug}" is not a valid creative slug`);
20448
20114
  }
20449
20115
  const client = buildBackendClient();
20450
20116
  if (!client) {
20451
- fail2("missing_credentials", "rerun needs backend credentials (BAKER_API_URL / BAKER_API_KEY)");
20117
+ fail("missing_credentials", "rerun needs backend credentials (BAKER_API_URL / BAKER_API_KEY)");
20452
20118
  }
20453
20119
  const latest = await client.getLatestSnapshotRun(slug);
20454
20120
  if (!latest) {
20455
- fail2(
20121
+ fail(
20456
20122
  "no_snapshot_run",
20457
20123
  `no rerunnable history for "${slug}" \u2014 the creative was never run by a CLI that records canvas snapshots`
20458
20124
  );
20459
20125
  }
20460
20126
  const manifest = await fetchManifest(latest.canvasSnapshotUrl);
20461
20127
  if (latest.canvasSha && manifest.canvasSha !== latest.canvasSha) {
20462
- fail2("snapshot_mismatch", `snapshot manifest for run ${latest.runId} does not match its recorded canvas sha`);
20128
+ fail("snapshot_mismatch", `snapshot manifest for run ${latest.runId} does not match its recorded canvas sha`);
20463
20129
  }
20464
- const targetDir = path14.resolve("src", "creatives", slug);
20130
+ const targetDir = path13.resolve("src", "creatives", slug);
20465
20131
  let restoredCanvasPath;
20466
20132
  try {
20467
20133
  const restore = await restoreRunSnapshot(manifest, targetDir, { force: args["force-remote"] === true });
@@ -20479,7 +20145,7 @@ var rerunCommand = defineCommand91({
20479
20145
  }
20480
20146
  } catch (e) {
20481
20147
  if (e instanceof SnapshotConflictError) {
20482
- fail2(
20148
+ fail(
20483
20149
  "local_files_differ",
20484
20150
  `local files differ from the recorded snapshot: ${e.conflicts.join(", ")}. Re-run with --force-remote to overwrite them, or run the local canvas directly with \`baker canvas run\`.`
20485
20151
  );
@@ -20494,25 +20160,25 @@ var rerunCommand = defineCommand91({
20494
20160
  });
20495
20161
  }
20496
20162
  });
20497
- function fail2(code, message) {
20163
+ function fail(code, message) {
20498
20164
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code, message } }, null, 2)}
20499
20165
  `);
20500
20166
  process.exit(2);
20501
20167
  }
20502
20168
  async function fetchManifest(url) {
20503
20169
  const res = await fetch(url);
20504
- if (!res.ok) fail2("snapshot_unavailable", `snapshot manifest download failed: ${res.status} ${res.statusText}`);
20170
+ if (!res.ok) fail("snapshot_unavailable", `snapshot manifest download failed: ${res.status} ${res.statusText}`);
20505
20171
  const manifest = await res.json();
20506
20172
  if (manifest?.schema !== SNAPSHOT_SCHEMA || typeof manifest.canvas?.path !== "string") {
20507
- fail2("snapshot_invalid", "snapshot manifest has an unexpected shape");
20173
+ fail("snapshot_invalid", "snapshot manifest has an unexpected shape");
20508
20174
  }
20509
20175
  return manifest;
20510
20176
  }
20511
20177
 
20512
20178
  // src/commands/canvas/scaffold-static-ad.ts
20513
- import { access, mkdir as mkdir6, readFile as readFile12, writeFile as writeFile7 } from "fs/promises";
20514
- import path18 from "path";
20515
- import { defineCommand as defineCommand93 } from "citty";
20179
+ import { access, mkdir as mkdir5, readFile as readFile11, writeFile as writeFile6 } from "fs/promises";
20180
+ import path17 from "path";
20181
+ import { defineCommand as defineCommand91 } from "citty";
20516
20182
 
20517
20183
  // src/engine/scaffold/staticAd.ts
20518
20184
  import { z as z17 } from "zod";
@@ -20789,7 +20455,7 @@ function staticAdReport(input, elementsInput, opts) {
20789
20455
  }
20790
20456
 
20791
20457
  // src/commands/canvas/creative-definition.ts
20792
- import path15 from "path";
20458
+ import path14 from "path";
20793
20459
  var PLATFORM_VALUES = ["meta", "google", "linkedin", "tiktok", "youtube", "x", "other"];
20794
20460
  var FORMAT_VALUES = ["1:1", "4:5", "9:16", "16:9", "1.91:1"];
20795
20461
  function titleFromSlug(slug) {
@@ -20837,16 +20503,16 @@ function buildCreativeDefinition(input) {
20837
20503
  }
20838
20504
 
20839
20505
  // src/commands/canvas/scaffold-static-ad-paths.ts
20840
- import path16 from "path";
20506
+ import path15 from "path";
20841
20507
  function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
20842
20508
  const file = rawFile.trim();
20843
20509
  const imageIsUrl = /^https?:\/\//i.test(file);
20844
- const imageSource = imageIsUrl ? file : path16.resolve(cwd, file);
20845
- const outPath = out ? path16.resolve(cwd, out) : slug ? path16.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path16.join(cwd, "static-ad.canvas.json") : path16.join(path16.dirname(imageSource), "static-ad.canvas.json");
20846
- const blueprintPath = path16.join(path16.dirname(outPath), "prompt.json");
20847
- const creativeDir = slug ? path16.dirname(outPath) : null;
20848
- const definitionPath = creativeDir ? path16.join(creativeDir, "_definition.md") : null;
20849
- const referencesDir = creativeDir ? path16.join(creativeDir, "references") : null;
20510
+ const imageSource = imageIsUrl ? file : path15.resolve(cwd, file);
20511
+ const outPath = out ? path15.resolve(cwd, out) : slug ? path15.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path15.join(cwd, "static-ad.canvas.json") : path15.join(path15.dirname(imageSource), "static-ad.canvas.json");
20512
+ const blueprintPath = path15.join(path15.dirname(outPath), "prompt.json");
20513
+ const creativeDir = slug ? path15.dirname(outPath) : null;
20514
+ const definitionPath = creativeDir ? path15.join(creativeDir, "_definition.md") : null;
20515
+ const referencesDir = creativeDir ? path15.join(creativeDir, "references") : null;
20850
20516
  return { imageIsUrl, imageSource, outPath, blueprintPath, creativeDir, definitionPath, referencesDir };
20851
20517
  }
20852
20518
  var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
@@ -20856,9 +20522,9 @@ function isValidScaffoldSlug(slug) {
20856
20522
  }
20857
20523
 
20858
20524
  // src/commands/canvas/sync-definition.ts
20859
- import { readdir as readdir5, readFile as readFile11, stat as stat3 } from "fs/promises";
20860
- import path17 from "path";
20861
- import { defineCommand as defineCommand92 } from "citty";
20525
+ import { readdir as readdir5, readFile as readFile10, stat as stat3 } from "fs/promises";
20526
+ import path16 from "path";
20527
+ import { defineCommand as defineCommand90 } from "citty";
20862
20528
 
20863
20529
  // src/commands/canvas/definition-graph.ts
20864
20530
  var MAX_NODES = 300;
@@ -20950,15 +20616,15 @@ async function syncCreativeDefinitionBestEffort(input) {
20950
20616
  }
20951
20617
  }
20952
20618
  async function resolveCanvasPath(inputPath) {
20953
- const resolved = path17.resolve(inputPath);
20619
+ const resolved = path16.resolve(inputPath);
20954
20620
  let dir = resolved;
20955
20621
  try {
20956
20622
  if ((await stat3(resolved)).isFile()) {
20957
20623
  if (resolved.endsWith(".canvas.json")) return resolved;
20958
- dir = path17.dirname(resolved);
20624
+ dir = path16.dirname(resolved);
20959
20625
  }
20960
20626
  } catch {
20961
- dir = resolved.endsWith(".canvas.json") ? path17.dirname(resolved) : resolved;
20627
+ dir = resolved.endsWith(".canvas.json") ? path16.dirname(resolved) : resolved;
20962
20628
  }
20963
20629
  let entries;
20964
20630
  try {
@@ -20969,9 +20635,9 @@ async function resolveCanvasPath(inputPath) {
20969
20635
  const canvases = entries.filter((name) => name.endsWith(".canvas.json"));
20970
20636
  const slug = creativeSlugFromCanvasPath(`${dir}/x/`);
20971
20637
  const chosen = (slug ? canvases.find((name) => name === `${slug}.canvas.json`) : void 0) ?? canvases[0];
20972
- return chosen ? path17.join(dir, chosen) : null;
20638
+ return chosen ? path16.join(dir, chosen) : null;
20973
20639
  }
20974
- var syncDefinitionCommand = defineCommand92({
20640
+ var syncDefinitionCommand = defineCommand90({
20975
20641
  meta: {
20976
20642
  name: "sync-definition",
20977
20643
  description: "Push a creative's current node-graph + input thumbnails to the dashboard without rendering. Runs automatically when you edit a creative's canvas.json or prompt.json."
@@ -20992,7 +20658,7 @@ var syncDefinitionCommand = defineCommand92({
20992
20658
  if (!slug) return;
20993
20659
  let canvas;
20994
20660
  try {
20995
- canvas = JSON.parse(await readFile11(canvasPath, "utf8"));
20661
+ canvas = JSON.parse(await readFile10(canvasPath, "utf8"));
20996
20662
  } catch {
20997
20663
  return;
20998
20664
  }
@@ -21017,7 +20683,7 @@ async function uploadSourceAsReference(source, isUrl, client) {
21017
20683
  if (!res.ok) throw new Error(`failed to download source image (${res.status})`);
21018
20684
  bytes = Buffer.from(await res.arrayBuffer());
21019
20685
  } else {
21020
- bytes = await readFile12(source);
20686
+ bytes = await readFile11(source);
21021
20687
  }
21022
20688
  const safe = await toModelSafeImage(bytes);
21023
20689
  const sha256 = sha256Hex(safe.bytes);
@@ -21072,7 +20738,7 @@ DROP background extras, decorative props, generic scenery, and anything small or
21072
20738
  For each kept element return: { "type": one of logo|product|person|animal|badge, "label": a short UPPER_SNAKE_CASE name (e.g. LOGO, PRODUCT, HERO_DOG, TRUSTPILOT), "description": a concrete reusable description to source/shoot the real asset (include the exact expression for a living subject, and its castable attributes \u2014 breed/species for an animal, apparent age band, apparent origin/ethnicity, and wardrobe/setting for a person \u2014 so it can be recast to fit OUR audience/market), "expression": the facial expression for a living subject or null, "reason": why it is identity-critical, "locator": the blueprint entry this element came from as { "collection": one of "subjects" | "people" | "brands_logos", "index": its 0-based position in that array } (people -> people; logos/badges -> brands_logos; products/animals/objects -> subjects). Output ONLY the JSON object.`;
21073
20739
  async function loadAssetText(ref, label) {
21074
20740
  const r = ref;
21075
- if (typeof r?.path === "string") return readFile12(r.path, "utf8");
20741
+ if (typeof r?.path === "string") return readFile11(r.path, "utf8");
21076
20742
  if (typeof r?.url === "string") {
21077
20743
  const res = await fetch(r.url);
21078
20744
  if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
@@ -21096,7 +20762,7 @@ function parseLayout(raw) {
21096
20762
  }
21097
20763
  return null;
21098
20764
  }
21099
- function fail3(code, message) {
20765
+ function fail2(code, message) {
21100
20766
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code, message } }, null, 2)}
21101
20767
  `);
21102
20768
  process.exit(2);
@@ -21187,8 +20853,8 @@ async function runVisionPasses(canvas) {
21187
20853
  outputsByNode = result.outputs_by_node;
21188
20854
  creditsSpent = result.stats?.total_credits;
21189
20855
  } catch (e) {
21190
- if (e instanceof ValidationError) return fail3("validation", JSON.stringify(e.issues));
21191
- return fail3("describe", e instanceof Error ? e.message : String(e));
20856
+ if (e instanceof ValidationError) return fail2("validation", JSON.stringify(e.issues));
20857
+ return fail2("describe", e instanceof Error ? e.message : String(e));
21192
20858
  }
21193
20859
  try {
21194
20860
  const blueprint = JSON.parse(await loadAssetText(outputsByNode.describe?.description, "describe output"));
@@ -21196,10 +20862,10 @@ async function runVisionPasses(canvas) {
21196
20862
  const layout = parseLayout(await loadAssetText(outputsByNode.layout?.text, "layout output"));
21197
20863
  return { blueprint, elements, layout, creditsSpent };
21198
20864
  } catch (e) {
21199
- return fail3("read_outputs", e instanceof Error ? e.message : String(e));
20865
+ return fail2("read_outputs", e instanceof Error ? e.message : String(e));
21200
20866
  }
21201
20867
  }
21202
- var scaffoldStaticAdCommand = defineCommand93({
20868
+ var scaffoldStaticAdCommand = defineCommand91({
21203
20869
  meta: {
21204
20870
  name: "scaffold-static-ad",
21205
20871
  description: "Turn a source/inspiration image into a runnable static-ad canvas. Runs billed passes \u2014 image_describe (the blueprint, baked to prompt.json as the editable 'prompt'), an AI selection of the image's MAIN identity elements, and a structured global-layout pass (the column/row grid with per-region bounds and text sizes) \u2014 then scaffolds a canvas that wires one [TODO] ingest slot per element (logo/product/subject/badge + brand font) into image_generate. By default it also fans the hero out to the platform's placement ratios (via image_aspect_adapt \u2014 the hero ratio is free, the rest are billed AI recompositions); pass --placements none for a single base ad, or a preset to pick the set. Edit prompt.json and drop the real assets, then `baker canvas run` it."
@@ -21248,7 +20914,7 @@ var scaffoldStaticAdCommand = defineCommand93({
21248
20914
  process.cwd(),
21249
20915
  slug
21250
20916
  );
21251
- await mkdir6(path18.dirname(outPath), { recursive: true });
20917
+ await mkdir5(path17.dirname(outPath), { recursive: true });
21252
20918
  const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
21253
20919
  let durableSourceUrl;
21254
20920
  if (referencesDir) {
@@ -21257,7 +20923,7 @@ var scaffoldStaticAdCommand = defineCommand93({
21257
20923
  try {
21258
20924
  durableSourceUrl = await uploadSourceAsReference(imageSource, imageIsUrl, client);
21259
20925
  } catch (e) {
21260
- return fail3("source_unavailable", e instanceof Error ? e.message : String(e));
20926
+ return fail2("source_unavailable", e instanceof Error ? e.message : String(e));
21261
20927
  }
21262
20928
  }
21263
20929
  }
@@ -21274,7 +20940,7 @@ var scaffoldStaticAdCommand = defineCommand93({
21274
20940
  if (layout && annotated && typeof annotated === "object") {
21275
20941
  annotated.layout = layout;
21276
20942
  }
21277
- await writeFile7(blueprintPath, `${JSON.stringify(annotated, null, 2)}
20943
+ await writeFile6(blueprintPath, `${JSON.stringify(annotated, null, 2)}
21278
20944
  `, "utf8");
21279
20945
  let canvasImagePath = imageSource;
21280
20946
  let canvasImageIsUrl = imageIsUrl;
@@ -21291,7 +20957,7 @@ var scaffoldStaticAdCommand = defineCommand93({
21291
20957
  args.placements ? String(args.placements) : void 0,
21292
20958
  definitionPlatform
21293
20959
  );
21294
- if (!placementsResult.ok) return fail3("invalid_placements", placementsResult.message);
20960
+ if (!placementsResult.ok) return fail2("invalid_placements", placementsResult.message);
21295
20961
  const placements = placementsResult.placements;
21296
20962
  const opts = {
21297
20963
  genModel,
@@ -21309,7 +20975,7 @@ var scaffoldStaticAdCommand = defineCommand93({
21309
20975
  canvas = scaffoldStaticAd(blueprint, elements, opts);
21310
20976
  report = staticAdReport(blueprint, elements, opts);
21311
20977
  } catch (e) {
21312
- return fail3("scaffold", e instanceof Error ? e.message : String(e));
20978
+ return fail2("scaffold", e instanceof Error ? e.message : String(e));
21313
20979
  }
21314
20980
  const validation = await validateCanvasDeep(canvas, defaultRegistry());
21315
20981
  if (!validation.ok) {
@@ -21319,10 +20985,10 @@ var scaffoldStaticAdCommand = defineCommand93({
21319
20985
  );
21320
20986
  process.exit(2);
21321
20987
  }
21322
- await writeFile7(outPath, `${JSON.stringify(canvas, null, 2)}
20988
+ await writeFile6(outPath, `${JSON.stringify(canvas, null, 2)}
21323
20989
  `, "utf8");
21324
20990
  if (definitionPath && !await fileExists(definitionPath)) {
21325
- await writeFile7(
20991
+ await writeFile6(
21326
20992
  definitionPath,
21327
20993
  buildCreativeDefinition({
21328
20994
  title: args.title ? String(args.title) : titleFromSlug(slug ?? ""),
@@ -21368,7 +21034,7 @@ var scaffoldStaticAdCommand = defineCommand93({
21368
21034
  run_estimated_credits: validation.estimatedCredits
21369
21035
  },
21370
21036
  checklist: {
21371
- edit_prompt: `Edit ${path18.basename(blueprintPath)} \u2014 it is the blueprint generated from your image; rewrite it into the ad you want (palette, copy, claims, subjects). It feeds the generator directly.`,
21037
+ edit_prompt: `Edit ${path17.basename(blueprintPath)} \u2014 it is the blueprint generated from your image; rewrite it into the ad you want (palette, copy, claims, subjects). It feeds the generator directly.`,
21372
21038
  assets_to_supply: report.elements,
21373
21039
  font_slot: report.includes_font ? "Drop a brand font at the [TODO] brandfont path (the describe pass recorded the ad's typefaces under `fonts` in prompt.json \u2014 match those). The font is wired into the render as a TYPE SPECIMEN reference so generated text takes the brand letterforms. Delete the brandfont + type_ref nodes to skip it." : "skipped (--skip-font)",
21374
21040
  actor_sheets: report.actor_sheets.length > 0 ? `Each living hero (${report.actor_sheets.join(", ")}) is fused into a generated multi-view reference sheet (image_reference_sheet) that the render grounds on \u2014 so drop ONE clean photo at that hero's ingest and the sheet builds the consistent turnaround. Pass --skip-actor-sheets to ground on the lone photo instead.` : "none (no person/animal heroes detected, or --skip-actor-sheets)",
@@ -21385,10 +21051,10 @@ var scaffoldStaticAdCommand = defineCommand93({
21385
21051
  });
21386
21052
 
21387
21053
  // src/commands/canvas/scaffold-video.ts
21388
- import { access as access2, cp, mkdir as mkdir7, readFile as readFile15, rm as rm6, writeFile as writeFile8 } from "fs/promises";
21054
+ import { access as access2, cp, mkdir as mkdir6, readFile as readFile14, rm as rm6, writeFile as writeFile7 } from "fs/promises";
21389
21055
  import { tmpdir as tmpdir2 } from "os";
21390
- import path21 from "path";
21391
- import { defineCommand as defineCommand94 } from "citty";
21056
+ import path20 from "path";
21057
+ import { defineCommand as defineCommand92 } from "citty";
21392
21058
 
21393
21059
  // src/engine/scaffold/lib/model-router.ts
21394
21060
  var SEEDANCE = "bytedance/seedance-2.0";
@@ -21426,7 +21092,7 @@ function routeVideoModel(input) {
21426
21092
 
21427
21093
  // src/engine/nodes/local/lib/sceneDetect.ts
21428
21094
  import { execFile as execFile2 } from "child_process";
21429
- import { mkdtemp, readdir as readdir6, readFile as readFile13, rm as rm5 } from "fs/promises";
21095
+ import { mkdtemp, readdir as readdir6, readFile as readFile12, rm as rm5 } from "fs/promises";
21430
21096
  import { tmpdir } from "os";
21431
21097
  import { join as join2 } from "path";
21432
21098
  import { promisify as promisify2 } from "util";
@@ -21502,7 +21168,7 @@ async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs)
21502
21168
  );
21503
21169
  const csvName = (await readdir6(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
21504
21170
  if (!csvName) return [];
21505
- return parsePySceneDetectCsvCuts(await readFile13(join2(outDir, csvName), "utf-8"));
21171
+ return parsePySceneDetectCsvCuts(await readFile12(join2(outDir, csvName), "utf-8"));
21506
21172
  } finally {
21507
21173
  await rm5(outDir, { recursive: true, force: true });
21508
21174
  }
@@ -21527,23 +21193,23 @@ async function detectSceneCutsPySceneDetect(filePath, opts = {}) {
21527
21193
 
21528
21194
  // src/commands/canvas/composition-path.ts
21529
21195
  import { existsSync as existsSync3 } from "fs";
21530
- import path19 from "path";
21196
+ import path18 from "path";
21531
21197
  function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
21532
- const rel = path19.join("canvas", name);
21198
+ const rel = path18.join("canvas", name);
21533
21199
  let dir = startDir;
21534
21200
  for (let i = 0; i < maxDepth; i++) {
21535
- const candidate = path19.join(dir, rel);
21536
- if (exists(path19.join(candidate, "meta.json"))) return candidate;
21537
- const parent = path19.dirname(dir);
21201
+ const candidate = path18.join(dir, rel);
21202
+ if (exists(path18.join(candidate, "meta.json"))) return candidate;
21203
+ const parent = path18.dirname(dir);
21538
21204
  if (parent === dir) break;
21539
21205
  dir = parent;
21540
21206
  }
21541
- return path19.resolve(startDir, "../../../", rel);
21207
+ return path18.resolve(startDir, "../../../", rel);
21542
21208
  }
21543
21209
 
21544
21210
  // src/commands/canvas/gitignore.ts
21545
- import { appendFile, readFile as readFile14 } from "fs/promises";
21546
- import path20 from "path";
21211
+ import { appendFile, readFile as readFile13 } from "fs/promises";
21212
+ import path19 from "path";
21547
21213
  function missingGitignoreEntries(existing, entries) {
21548
21214
  const present2 = new Set(
21549
21215
  existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
@@ -21551,10 +21217,10 @@ function missingGitignoreEntries(existing, entries) {
21551
21217
  return entries.filter((e) => !present2.has(e.trim().replace(/\/+$/, "")));
21552
21218
  }
21553
21219
  async function ensureGitignore(dir, entries) {
21554
- const file = path20.join(dir, ".gitignore");
21220
+ const file = path19.join(dir, ".gitignore");
21555
21221
  let existing;
21556
21222
  try {
21557
- existing = await readFile14(file, "utf8");
21223
+ existing = await readFile13(file, "utf8");
21558
21224
  } catch {
21559
21225
  return;
21560
21226
  }
@@ -21593,7 +21259,7 @@ ONE PERSON, MULTIPLE LOOKS: if a single individual plays MULTIPLE personas or wa
21593
21259
  For each kept element return: { "type": one of person|animal|product|logo|badge|location, "label": a short UPPER_SNAKE_CASE name (e.g. HERO, CREATOR_SKEPTIC, INSURANCE_CARD, LOGO), "description": a concrete reusable description to source/shoot the real asset \u2014 for a person/animal give a NEUTRAL castable role (e.g. "hero pet-owner, woman in her 30s" or "a small beagle"), NOT the original individual's literal face/identity: we RECAST with a FRESH person/animal, so never tell the agent to reuse the original. "expression": a living subject's typical expression or null, "cast_id": the global.cast id if it maps to one else null, "same_as": the label of another element this is the SAME individual as (different wardrobe/persona) else null, "scenes": the 0-based indices of ONLY the scenes where the element is ACTUALLY VISIBLE ON SCREEN \u2014 judged from that scene's start_frame_prompt / end_frame_prompt subjects and its action_detail, NOT from who is merely speaking. A narrator heard over b-roll is NOT present in that b-roll scene; a dog-running cutaway does NOT contain the couch creator just because she talks across it. Do NOT pad the list \u2014 an element wrongly listed in a scene makes the reproduction render the wrong subject there (e.g. the creator appearing in a pure-dog b-roll). When in doubt, leave a scene OUT. Output ONLY the JSON object.`;
21594
21260
  async function loadAssetText2(ref, label) {
21595
21261
  const r = ref;
21596
- if (typeof r?.path === "string") return readFile15(r.path, "utf8");
21262
+ if (typeof r?.path === "string") return readFile14(r.path, "utf8");
21597
21263
  if (typeof r?.url === "string") {
21598
21264
  const res = await fetch(r.url);
21599
21265
  if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
@@ -21612,7 +21278,7 @@ async function loadTranscriptBestEffort(ref) {
21612
21278
  async function stageCaptions(outDir, transcript) {
21613
21279
  const text = transcript?.trim();
21614
21280
  if (!text || text === "[]") return {};
21615
- const compositionPath = path21.join(outDir, "tiktok-captions-composition");
21281
+ const compositionPath = path20.join(outDir, "tiktok-captions-composition");
21616
21282
  await cp(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
21617
21283
  return { compositionPath };
21618
21284
  }
@@ -21630,12 +21296,12 @@ function patchCompositionHtml(html, dims) {
21630
21296
  return html.replace(/(<meta\s+name="viewport"\s+content="width=)\d+(,\s*height=)\d+(")/i, `$1${dims.w}$2${dims.h}$3`).replace(/(width:\s*)\d+(px;\s*height:\s*)\d+(px;)/i, `$1${dims.w}$2${dims.h}$3`).replace(/(data-width=")\d+(")/i, `$1${dims.w}$2`).replace(/(data-height=")\d+(")/i, `$1${dims.h}$2`);
21631
21297
  }
21632
21298
  async function stampCompositionDims(compositionDir, dims) {
21633
- const metaPath = path21.join(compositionDir, "meta.json");
21634
- const rawMeta = await readFile15(metaPath, "utf8");
21635
- await writeFile8(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
21636
- const htmlPath = path21.join(compositionDir, "index.html");
21637
- const rawHtml = await readFile15(htmlPath, "utf8");
21638
- await writeFile8(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
21299
+ const metaPath = path20.join(compositionDir, "meta.json");
21300
+ const rawMeta = await readFile14(metaPath, "utf8");
21301
+ await writeFile7(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
21302
+ const htmlPath = path20.join(compositionDir, "index.html");
21303
+ const rawHtml = await readFile14(htmlPath, "utf8");
21304
+ await writeFile7(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
21639
21305
  }
21640
21306
  function parseElements2(raw) {
21641
21307
  const parsed = JSON.parse(raw);
@@ -21670,7 +21336,7 @@ async function detectShotCutsBestEffort(videoPath, threshold) {
21670
21336
  return void 0;
21671
21337
  }
21672
21338
  }
21673
- function fail4(code, message) {
21339
+ function fail3(code, message) {
21674
21340
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code, message } }, null, 2)}
21675
21341
  `);
21676
21342
  process.exit(2);
@@ -21682,7 +21348,7 @@ var VIDEO_EXT_BY_MIME = {
21682
21348
  "video/x-matroska": ".mkv"
21683
21349
  };
21684
21350
  function referenceVideoExt(url, contentType) {
21685
- const fromPath = path21.extname(new URL(url).pathname).toLowerCase();
21351
+ const fromPath = path20.extname(new URL(url).pathname).toLowerCase();
21686
21352
  if (fromPath && fromPath.length <= 5) return fromPath;
21687
21353
  const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase();
21688
21354
  return mime && VIDEO_EXT_BY_MIME[mime] || ".mp4";
@@ -21708,7 +21374,7 @@ function videoDefinitionDescription(blueprint) {
21708
21374
  return typeof product === "string" && product.trim() ? product.trim() : void 0;
21709
21375
  }
21710
21376
  async function materializeReferenceVideo(fileArg2) {
21711
- if (!/^https?:\/\//i.test(fileArg2)) return path21.resolve(fileArg2);
21377
+ if (!/^https?:\/\//i.test(fileArg2)) return path20.resolve(fileArg2);
21712
21378
  let res;
21713
21379
  try {
21714
21380
  res = await fetch(fileArg2);
@@ -21718,11 +21384,11 @@ async function materializeReferenceVideo(fileArg2) {
21718
21384
  if (!res.ok) throw new Error(`failed to download reference video (${res.status} ${res.statusText})`);
21719
21385
  const bytes = Buffer.from(await res.arrayBuffer());
21720
21386
  if (bytes.length === 0) throw new Error("reference video download was empty");
21721
- const dest = path21.join(
21387
+ const dest = path20.join(
21722
21388
  tmpdir2(),
21723
21389
  `baker-ref-${sha256Hex(bytes).slice(0, 16)}${referenceVideoExt(fileArg2, res.headers.get("content-type"))}`
21724
21390
  );
21725
- await writeFile8(dest, bytes);
21391
+ await writeFile7(dest, bytes);
21726
21392
  return dest;
21727
21393
  }
21728
21394
  function resolveSeamDedup(raw) {
@@ -21830,9 +21496,9 @@ async function runAnalysisPasses(deconstructCanvas, selectModel) {
21830
21496
  blueprint = JSON.parse(await loadAssetText2(r1.outputs_by_node.deconstruct?.analysis, "deconstruct output"));
21831
21497
  transcript = await loadTranscriptBestEffort(r1.outputs_by_node.deconstruct?.transcript);
21832
21498
  } catch (e) {
21833
- if (e instanceof ValidationError) return fail4("validation", JSON.stringify(e.issues));
21834
- if (e instanceof SyntaxError) return fail4("read_outputs", e.message);
21835
- return fail4("deconstruct", e instanceof Error ? e.message : String(e));
21499
+ if (e instanceof ValidationError) return fail3("validation", JSON.stringify(e.issues));
21500
+ if (e instanceof SyntaxError) return fail3("read_outputs", e.message);
21501
+ return fail3("deconstruct", e instanceof Error ? e.message : String(e));
21836
21502
  }
21837
21503
  const slimJson = JSON.stringify(slimBlueprintForSelection(blueprint));
21838
21504
  try {
@@ -21841,12 +21507,12 @@ async function runAnalysisPasses(deconstructCanvas, selectModel) {
21841
21507
  const elements = parseElements2(await loadAssetText2(r2.outputs_by_node.select?.text, "selection output"));
21842
21508
  return { blueprint, elements, transcript, creditsSpent: sawCredits ? credits : void 0 };
21843
21509
  } catch (e) {
21844
- if (e instanceof ValidationError) return fail4("validation", JSON.stringify(e.issues));
21845
- if (e instanceof SyntaxError) return fail4("read_outputs", e.message);
21846
- return fail4("deconstruct", e instanceof Error ? e.message : String(e));
21510
+ if (e instanceof ValidationError) return fail3("validation", JSON.stringify(e.issues));
21511
+ if (e instanceof SyntaxError) return fail3("read_outputs", e.message);
21512
+ return fail3("deconstruct", e instanceof Error ? e.message : String(e));
21847
21513
  }
21848
21514
  }
21849
- var scaffoldVideoCommand = defineCommand94({
21515
+ var scaffoldVideoCommand = defineCommand92({
21850
21516
  meta: {
21851
21517
  name: "scaffold-video",
21852
21518
  description: "Turn a reference video into a runnable reproduction canvas in one command. Runs billed passes \u2014 video_deconstruct (the full scene-by-scene blueprint + transcript, baked to a split, editable blueprint: a global prompt.json plus one small scenes/sNN.json per scene) and an AI selection of the video's RECURRING identity elements (person/animal/product/logo) \u2014 then scaffolds a pipeline where every scene boundary is a static-ad-grade frame (the blueprint as target_blueprint, a reference legend, the real frame as anchor) and each recurring element gets ONE shared [TODO] ingest slot wired into every frame it appears in. The clips feed Seedance an ultra-detailed motion brief (action, camera, dialogue, transcript). Edit a scene's scenes/sNN.json (or prompt.json for global cast/palette/brand), drop the real source images, then `baker canvas run`."
@@ -21927,7 +21593,7 @@ var scaffoldVideoCommand = defineCommand94({
21927
21593
  }
21928
21594
  const isUrl = /^https?:\/\//i.test(fileArg2);
21929
21595
  if (isUrl && !slug && !args.out) {
21930
- return fail4(
21596
+ return fail3(
21931
21597
  "missing_output_target",
21932
21598
  "When the reference is a URL, pass --slug (writes src/creatives/<slug>/) or --out <path> so the scaffolded canvas has a home in the repo."
21933
21599
  );
@@ -21936,13 +21602,13 @@ var scaffoldVideoCommand = defineCommand94({
21936
21602
  try {
21937
21603
  videoPath = await materializeReferenceVideo(fileArg2);
21938
21604
  } catch (e) {
21939
- return fail4("download", e instanceof Error ? e.message : String(e));
21605
+ return fail3("download", e instanceof Error ? e.message : String(e));
21940
21606
  }
21941
- const base = path21.basename(videoPath, path21.extname(videoPath));
21942
- const outPath = args.out ? path21.resolve(String(args.out)) : slug ? path21.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`) : path21.join(path21.dirname(videoPath), `${base}.video.canvas.json`);
21943
- const outDir = path21.dirname(outPath);
21944
- const blueprintPath = path21.join(outDir, "prompt.json");
21945
- const blueprintStylePath = path21.join(outDir, "prompt.style.json");
21607
+ const base = path20.basename(videoPath, path20.extname(videoPath));
21608
+ const outPath = args.out ? path20.resolve(String(args.out)) : slug ? path20.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`) : path20.join(path20.dirname(videoPath), `${base}.video.canvas.json`);
21609
+ const outDir = path20.dirname(outPath);
21610
+ const blueprintPath = path20.join(outDir, "prompt.json");
21611
+ const blueprintStylePath = path20.join(outDir, "prompt.style.json");
21946
21612
  const frames = args.frames === "reuse" ? "reuse" : "generate";
21947
21613
  const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
21948
21614
  if (Number.isFinite(maxScenes)) {
@@ -21966,10 +21632,10 @@ var scaffoldVideoCommand = defineCommand94({
21966
21632
  process.stderr.write(`\u{1F3AC} Photoreal on-camera cast detected \u2192 generating clips on ${videoModel} (dodges Seedance's real-person filter).
21967
21633
  `);
21968
21634
  }
21969
- await mkdir7(outDir, { recursive: true });
21635
+ await mkdir6(outDir, { recursive: true });
21970
21636
  const annotated = annotateBlueprintWithElements(blueprint, elements);
21971
21637
  await writeSceneFiles(outDir, annotated);
21972
- await writeFile8(blueprintStylePath, renderStyleProjectionFromValue(annotated), "utf8");
21638
+ await writeFile7(blueprintStylePath, renderStyleProjectionFromValue(annotated), "utf8");
21973
21639
  let aspect;
21974
21640
  try {
21975
21641
  aspect = resolveAspect(
@@ -21978,7 +21644,7 @@ var scaffoldVideoCommand = defineCommand94({
21978
21644
  genAspectsFor(videoModel)
21979
21645
  );
21980
21646
  } catch (e) {
21981
- return fail4("aspect", e instanceof Error ? e.message : String(e));
21647
+ return fail3("aspect", e instanceof Error ? e.message : String(e));
21982
21648
  }
21983
21649
  const outDims = canvasDims(aspect.outAr);
21984
21650
  if (aspect.remapped) {
@@ -21987,29 +21653,29 @@ var scaffoldVideoCommand = defineCommand94({
21987
21653
  `
21988
21654
  );
21989
21655
  }
21990
- const compositionDest = path21.join(outDir, "video-overlay-composition");
21656
+ const compositionDest = path20.join(outDir, "video-overlay-composition");
21991
21657
  await cp(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
21992
21658
  await stampCompositionDims(compositionDest, outDims);
21993
- const indexPath = path21.join(compositionDest, "index.html");
21659
+ const indexPath = path20.join(compositionDest, "index.html");
21994
21660
  const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript) });
21995
- const indexHtml = await readFile15(indexPath, "utf8");
21661
+ const indexHtml = await readFile14(indexPath, "utf8");
21996
21662
  const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
21997
21663
  if (injected === indexHtml && overlayHtml.trim()) {
21998
- fail4(
21664
+ fail3(
21999
21665
  "composition_marker_missing",
22000
21666
  `video-overlay-composition/index.html is missing the <!--OVERLAYS--> marker \u2014 cannot inject the overlay layer`
22001
21667
  );
22002
21668
  }
22003
- await writeFile8(indexPath, injected, "utf8");
21669
+ await writeFile7(indexPath, injected, "utf8");
22004
21670
  const captions = await stageCaptions(outDir, transcript);
22005
21671
  if (captions.compositionPath) await stampCompositionDims(captions.compositionPath, outDims);
22006
21672
  const opts = {
22007
21673
  imageModel,
22008
21674
  videoModel,
22009
- overlayCompositionPath: path21.relative(outDir, compositionDest),
22010
- captionsCompositionPath: captions.compositionPath ? path21.relative(outDir, captions.compositionPath) : void 0,
22011
- blueprintPath: path21.relative(outDir, blueprintPath),
22012
- blueprintStylePath: path21.relative(outDir, blueprintStylePath),
21675
+ overlayCompositionPath: path20.relative(outDir, compositionDest),
21676
+ captionsCompositionPath: captions.compositionPath ? path20.relative(outDir, captions.compositionPath) : void 0,
21677
+ blueprintPath: path20.relative(outDir, blueprintPath),
21678
+ blueprintStylePath: path20.relative(outDir, blueprintStylePath),
22013
21679
  frames,
22014
21680
  ambient: Boolean(args.ambient),
22015
21681
  seamDedup: resolveSeamDedup(args["seam-dedup"]),
@@ -22022,7 +21688,7 @@ var scaffoldVideoCommand = defineCommand94({
22022
21688
  canvas = scaffoldVideoCanvas(blueprint, elements, opts);
22023
21689
  report = videoReport(blueprint, elements);
22024
21690
  } catch (e) {
22025
- return fail4("scaffold", e instanceof Error ? e.message : String(e));
21691
+ return fail3("scaffold", e instanceof Error ? e.message : String(e));
22026
21692
  }
22027
21693
  if (captions.compositionPath && !canvas.nodes.some((n) => n.id === "captions")) {
22028
21694
  await rm6(captions.compositionPath, { recursive: true, force: true });
@@ -22034,10 +21700,10 @@ var scaffoldVideoCommand = defineCommand94({
22034
21700
  todo.blocking_validation_issues = validation.issues;
22035
21701
  meta.todo = todo;
22036
21702
  }
22037
- await writeFile8(outPath, `${JSON.stringify(canvas, null, 2)}
21703
+ await writeFile7(outPath, `${JSON.stringify(canvas, null, 2)}
22038
21704
  `, "utf8");
22039
- await writeFile8(
22040
- path21.join(outDir, REBUILD_FILE),
21705
+ await writeFile7(
21706
+ path20.join(outDir, REBUILD_FILE),
22041
21707
  `${JSON.stringify({ elements, opts }, null, 2)}
22042
21708
  `,
22043
21709
  "utf8"
@@ -22062,9 +21728,9 @@ var scaffoldVideoCommand = defineCommand94({
22062
21728
  await ensureGitignore(process.cwd(), ["canvas/", ".context/"]);
22063
21729
  const sourceRef = videoSourceReference(blueprint, fileArg2);
22064
21730
  if (slug) {
22065
- const definitionPath = path21.join(outDir, "_definition.md");
21731
+ const definitionPath = path20.join(outDir, "_definition.md");
22066
21732
  if (!await fileExists2(definitionPath)) {
22067
- await writeFile8(
21733
+ await writeFile7(
22068
21734
  definitionPath,
22069
21735
  buildCreativeDefinition({
22070
21736
  title: titleFromSlug(slug),
@@ -22117,7 +21783,7 @@ var scaffoldVideoCommand = defineCommand94({
22117
21783
  graph: canvas.metadata?.video?.graph_stats
22118
21784
  },
22119
21785
  checklist: {
22120
- edit_prompt: `The blueprint is split so you edit ONE small file at a time \u2014 never a giant one. Per-scene content (a scene's dialogue, action, frame prompts, overlays) lives in \`scenes/sNN.json\` \u2014 edit the single scene you want to change. Global cast/palette/brand/copy lives in \`${path21.basename(blueprintPath)}\`. \`baker canvas validate\`/\`run\` re-assemble the blueprint and re-flow every edited scene back into the render (and regenerate ${path21.basename(blueprintStylePath)}, the projection each frame's target_blueprint reads) \u2014 so your scene edits reach the render automatically. Never hand-edit the inlined node prompts in the canvas or the derived ${path21.basename(blueprintStylePath)}; both are regenerated.`,
21786
+ edit_prompt: `The blueprint is split so you edit ONE small file at a time \u2014 never a giant one. Per-scene content (a scene's dialogue, action, frame prompts, overlays) lives in \`scenes/sNN.json\` \u2014 edit the single scene you want to change. Global cast/palette/brand/copy lives in \`${path20.basename(blueprintPath)}\`. \`baker canvas validate\`/\`run\` re-assemble the blueprint and re-flow every edited scene back into the render (and regenerate ${path20.basename(blueprintStylePath)}, the projection each frame's target_blueprint reads) \u2014 so your scene edits reach the render automatically. Never hand-edit the inlined node prompts in the canvas or the derived ${path20.basename(blueprintStylePath)}; both are regenerated.`,
22121
21787
  recurring_elements_to_supply: report.elements,
22122
21788
  voices_to_confirm: report.dialogue.map((d) => ({
22123
21789
  scene: d.scene,
@@ -22154,9 +21820,9 @@ var scaffoldVideoCommand = defineCommand94({
22154
21820
  });
22155
21821
 
22156
21822
  // src/commands/canvas/set-prompt.ts
22157
- import { readFile as readFile16, writeFile as writeFile9 } from "fs/promises";
22158
- import path22 from "path";
22159
- import { defineCommand as defineCommand95 } from "citty";
21823
+ import { readFile as readFile15, writeFile as writeFile8 } from "fs/promises";
21824
+ import path21 from "path";
21825
+ import { defineCommand as defineCommand93 } from "citty";
22160
21826
  function setNodePrompt(canvas, nodeId, text) {
22161
21827
  const nodes = canvas?.nodes;
22162
21828
  if (!Array.isArray(nodes)) throw new Error("canvas has no nodes array");
@@ -22171,7 +21837,7 @@ function setNodePrompt(canvas, nodeId, text) {
22171
21837
  newNodes[idx] = newNode;
22172
21838
  return { ...canvas, nodes: newNodes };
22173
21839
  }
22174
- var setPromptCommand = defineCommand95({
21840
+ var setPromptCommand = defineCommand93({
22175
21841
  meta: {
22176
21842
  name: "set-prompt",
22177
21843
  description: "Safely set a node's params.prompt (a frame description, motion prompt, etc.) without hand-editing the JSON. Prefer --text-file for multi-line/accented copy \u2014 it preserves UTF-8 exactly, unlike shell-quoted jq."
@@ -22183,17 +21849,17 @@ var setPromptCommand = defineCommand95({
22183
21849
  "text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
22184
21850
  },
22185
21851
  async run({ args }) {
22186
- const filePath = path22.resolve(String(args.file));
21852
+ const filePath = path21.resolve(String(args.file));
22187
21853
  let canvas;
22188
21854
  try {
22189
- canvas = JSON.parse(await readFile16(filePath, "utf8"));
21855
+ canvas = JSON.parse(await readFile15(filePath, "utf8"));
22190
21856
  } catch (e) {
22191
21857
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "parse", message: String(e) } }, null, 2)}
22192
21858
  `);
22193
21859
  process.exit(2);
22194
21860
  }
22195
21861
  let text;
22196
- if (args["text-file"]) text = await readFile16(path22.resolve(String(args["text-file"])), "utf8");
21862
+ if (args["text-file"]) text = await readFile15(path21.resolve(String(args["text-file"])), "utf8");
22197
21863
  else if (args.text !== void 0) text = String(args.text);
22198
21864
  else {
22199
21865
  process.stderr.write(
@@ -22214,14 +21880,14 @@ var setPromptCommand = defineCommand95({
22214
21880
  process.exit(2);
22215
21881
  return;
22216
21882
  }
22217
- const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path22.dirname(filePath)), defaultRegistry());
21883
+ const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path21.dirname(filePath)), defaultRegistry());
22218
21884
  if (!validation.ok) {
22219
21885
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
22220
21886
  `);
22221
21887
  process.exit(2);
22222
21888
  return;
22223
21889
  }
22224
- await writeFile9(filePath, `${JSON.stringify(updated, null, 2)}
21890
+ await writeFile8(filePath, `${JSON.stringify(updated, null, 2)}
22225
21891
  `, "utf8");
22226
21892
  process.stdout.write(`${JSON.stringify({ ok: true, node: String(args.node), bytes: text.length }, null, 2)}
22227
21893
  `);
@@ -22229,18 +21895,18 @@ var setPromptCommand = defineCommand95({
22229
21895
  });
22230
21896
 
22231
21897
  // src/commands/canvas/validate.ts
22232
- import { readFile as readFile17 } from "fs/promises";
22233
- import path23 from "path";
22234
- import { defineCommand as defineCommand96 } from "citty";
22235
- var validateCommand = defineCommand96({
21898
+ import { readFile as readFile16 } from "fs/promises";
21899
+ import path22 from "path";
21900
+ import { defineCommand as defineCommand94 } from "citty";
21901
+ var validateCommand = defineCommand94({
22236
21902
  meta: {
22237
21903
  name: "validate",
22238
21904
  description: "Validate a canvas JSON file (no execution). Includes a per-node cost preview and runs each node's deep validators (composition meta checks for hyperframe_render/_snapshot)."
22239
21905
  },
22240
21906
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
22241
21907
  async run({ args }) {
22242
- const filePath = path23.resolve(String(args.file));
22243
- const raw = await readFile17(filePath, "utf8");
21908
+ const filePath = path22.resolve(String(args.file));
21909
+ const raw = await readFile16(filePath, "utf8");
22244
21910
  let parsed;
22245
21911
  try {
22246
21912
  parsed = JSON.parse(raw);
@@ -22250,7 +21916,7 @@ var validateCommand = defineCommand96({
22250
21916
  `);
22251
21917
  process.exit(2);
22252
21918
  }
22253
- parsed = resolveRelativeCanvasPaths(parsed, path23.dirname(filePath));
21919
+ parsed = resolveRelativeCanvasPaths(parsed, path22.dirname(filePath));
22254
21920
  let styleProjection = "not_applicable";
22255
21921
  try {
22256
21922
  styleProjection = await syncStyleProjection(parsed, (line) => process.stderr.write(`${line}
@@ -22302,7 +21968,7 @@ var validateCommand = defineCommand96({
22302
21968
  });
22303
21969
 
22304
21970
  // src/commands/canvas/index.ts
22305
- var canvasCommand = defineCommand97({
21971
+ var canvasCommand = defineCommand95({
22306
21972
  meta: {
22307
21973
  name: "canvas",
22308
21974
  description: `Run Baker creative canvas JSON files locally. Local nodes execute in-process; remote nodes POST to the Convex backend gateway.
@@ -22336,7 +22002,7 @@ Full guide: __tooling__/docs/tools/baker/canvas.md`
22336
22002
  });
22337
22003
 
22338
22004
  // src/commands/chats/index.ts
22339
- import { defineCommand as defineCommand98 } from "citty";
22005
+ import { defineCommand as defineCommand96 } from "citty";
22340
22006
  var STATUS_GROUPS = ["active", "archived", "all"];
22341
22007
  var REPO_SURFACES = ["knowledge", "company", "brand", "landings", "flows", "creatives"];
22342
22008
  function parseBoundedInt(raw, name, min, max) {
@@ -22358,7 +22024,7 @@ registerSchema({
22358
22024
  full: { type: "boolean", description: "Include each Session's full change list", required: false, default: false }
22359
22025
  }
22360
22026
  });
22361
- var listCommand5 = defineCommand98({
22027
+ var listCommand5 = defineCommand96({
22362
22028
  meta: { name: "list", description: "List other Sessions on this account, newest first." },
22363
22029
  args: {
22364
22030
  status: { type: "string", description: "Filter: active|archived|all (default: all)", required: false },
@@ -22413,7 +22079,7 @@ registerSchema({
22413
22079
  }
22414
22080
  }
22415
22081
  });
22416
- var viewCommand = defineCommand98({
22082
+ var viewCommand = defineCommand96({
22417
22083
  meta: {
22418
22084
  name: "view",
22419
22085
  description: "Inspect one Session's full effects \u2014 git content + actions/tags/ads, kickoff, commits."
@@ -22457,7 +22123,7 @@ registerSchema({
22457
22123
  }
22458
22124
  }
22459
22125
  });
22460
- var transcriptCommand = defineCommand98({
22126
+ var transcriptCommand = defineCommand96({
22461
22127
  meta: { name: "transcript", description: "Read another Session's conversation." },
22462
22128
  args: {
22463
22129
  id: { type: "positional", description: "The Session id", required: true },
@@ -22509,7 +22175,7 @@ registerSchema({
22509
22175
  }
22510
22176
  }
22511
22177
  });
22512
- var diffCommand = defineCommand98({
22178
+ var diffCommand = defineCommand96({
22513
22179
  meta: { name: "diff", description: "See a published Session's real file-level changes." },
22514
22180
  args: {
22515
22181
  id: { type: "positional", description: "The Session id", required: true },
@@ -22553,7 +22219,7 @@ var diffCommand = defineCommand98({
22553
22219
  }
22554
22220
  }
22555
22221
  });
22556
- var chatsCommand = defineCommand98({
22222
+ var chatsCommand = defineCommand96({
22557
22223
  meta: {
22558
22224
  name: "chats",
22559
22225
  description: `Inspect other Sessions on this account (read-only): list them, view what they produced, read their conversation, and see their real file changes \u2014 so you can reuse past work for a new goal.
@@ -22568,13 +22234,13 @@ Full guide: __tooling__/docs/tools/baker/chats.md`
22568
22234
  });
22569
22235
 
22570
22236
  // src/commands/creatives/index.ts
22571
- import { defineCommand as defineCommand100 } from "citty";
22237
+ import { defineCommand as defineCommand98 } from "citty";
22572
22238
 
22573
22239
  // src/commands/creatives/publish.ts
22574
- import { defineCommand as defineCommand99 } from "citty";
22240
+ import { defineCommand as defineCommand97 } from "citty";
22575
22241
 
22576
22242
  // src/commands/images/api.ts
22577
- import { readFile as readFile18 } from "fs/promises";
22243
+ import { readFile as readFile17 } from "fs/promises";
22578
22244
  import { extname } from "path";
22579
22245
  var imageProcessingTimeoutMs = 18e4;
22580
22246
  var imageReadyPollIntervalMs = 2e3;
@@ -22588,7 +22254,7 @@ var mimeMap = {
22588
22254
  ".avif": "image/avif"
22589
22255
  };
22590
22256
  var defaultImageApiDeps = {
22591
- readFile: readFile18,
22257
+ readFile: readFile17,
22592
22258
  post: apiPost,
22593
22259
  get: apiGet,
22594
22260
  sleep: (ms) => new Promise((resolve5) => setTimeout(resolve5, ms))
@@ -22715,7 +22381,7 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
22715
22381
  chatId: chatIdFromEnv()
22716
22382
  });
22717
22383
  }
22718
- var publishCommand = defineCommand99({
22384
+ var publishCommand = defineCommand97({
22719
22385
  meta: {
22720
22386
  name: "publish",
22721
22387
  description: "Publish a final static creative image to Baker Creatives and print the creative reference JSON."
@@ -22773,7 +22439,7 @@ var publishCommand = defineCommand99({
22773
22439
  });
22774
22440
 
22775
22441
  // src/commands/creatives/index.ts
22776
- var creativesCommand3 = defineCommand100({
22442
+ var creativesCommand3 = defineCommand98({
22777
22443
  meta: {
22778
22444
  name: "creatives",
22779
22445
  description: `Publish static ad creatives as first-class Baker outputs.
@@ -22790,7 +22456,7 @@ Full guide: __tooling__/docs/tools/baker/creatives.md`
22790
22456
  });
22791
22457
 
22792
22458
  // src/commands/flows/index.ts
22793
- import { defineCommand as defineCommand101 } from "citty";
22459
+ import { defineCommand as defineCommand99 } from "citty";
22794
22460
 
22795
22461
  // src/commands/flows/shared.ts
22796
22462
  import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync9 } from "fs";
@@ -22823,12 +22489,12 @@ function listFlowSlugs() {
22823
22489
  return readdirSync2(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith("_") && entry.name !== ".gitkeep").map((entry) => entry.name).sort();
22824
22490
  }
22825
22491
  function readFlowTree(slug) {
22826
- const path28 = join3(flowsDir(), slug, "_data.json");
22827
- if (!existsSync4(path28)) {
22492
+ const path27 = join3(flowsDir(), slug, "_data.json");
22493
+ if (!existsSync4(path27)) {
22828
22494
  failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
22829
22495
  }
22830
22496
  try {
22831
- return JSON.parse(readFileSync9(path28, "utf-8"));
22497
+ return JSON.parse(readFileSync9(path27, "utf-8"));
22832
22498
  } catch (error) {
22833
22499
  failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
22834
22500
  }
@@ -22945,7 +22611,7 @@ function displayName(slug) {
22945
22611
  const name = tree.displayName;
22946
22612
  return typeof name === "string" && name.trim() ? name.trim() : slug;
22947
22613
  }
22948
- var listCommand6 = defineCommand101({
22614
+ var listCommand6 = defineCommand99({
22949
22615
  meta: {
22950
22616
  name: "list",
22951
22617
  description: "List Forms in this workspace with the count of confidential fields still needing setup. Example: baker flows list"
@@ -22959,7 +22625,7 @@ var listCommand6 = defineCommand101({
22959
22625
  writeJson({ ok: true, data: { flows } });
22960
22626
  }
22961
22627
  });
22962
- var showCommand2 = defineCommand101({
22628
+ var showCommand2 = defineCommand99({
22963
22629
  meta: {
22964
22630
  name: "show",
22965
22631
  description: "Show a Form's confidential fields and their configuration status (never secret values). Example: baker flows show contact"
@@ -22980,7 +22646,7 @@ var showCommand2 = defineCommand101({
22980
22646
  writeJson({ ok: true, data: response });
22981
22647
  }
22982
22648
  });
22983
- var flowsCommand = defineCommand101({
22649
+ var flowsCommand = defineCommand99({
22984
22650
  meta: {
22985
22651
  name: "flows",
22986
22652
  description: `Read this workspace's Forms (flows) and the configuration status of their confidential fields \u2014 connection secrets, OAuth connections, and third-party field definitions (HubSpot, Calendly, HighLevel, SavvyCal).
@@ -23008,10 +22674,10 @@ Full guide: __tooling__/docs/tools/baker/flows.md`
23008
22674
  });
23009
22675
 
23010
22676
  // src/commands/ga4/index.ts
23011
- import { defineCommand as defineCommand105 } from "citty";
22677
+ import { defineCommand as defineCommand103 } from "citty";
23012
22678
 
23013
22679
  // src/commands/ga4/audit.ts
23014
- import { defineCommand as defineCommand102 } from "citty";
22680
+ import { defineCommand as defineCommand100 } from "citty";
23015
22681
 
23016
22682
  // src/commands/ga4/resolve.ts
23017
22683
  async function fetchProperties(useCache = true) {
@@ -23074,7 +22740,7 @@ registerSchema({
23074
22740
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
23075
22741
  }
23076
22742
  });
23077
- var auditCommand2 = defineCommand102({
22743
+ var auditCommand2 = defineCommand100({
23078
22744
  meta: {
23079
22745
  name: "audit",
23080
22746
  description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
@@ -23126,7 +22792,7 @@ Examples:
23126
22792
  });
23127
22793
 
23128
22794
  // src/commands/ga4/properties.ts
23129
- import { defineCommand as defineCommand103 } from "citty";
22795
+ import { defineCommand as defineCommand101 } from "citty";
23130
22796
  registerSchema({
23131
22797
  command: "ga4.properties",
23132
22798
  description: "List all accessible GA4 properties. Returns property IDs needed for query and audit commands. Run this first to find property IDs.",
@@ -23134,7 +22800,7 @@ registerSchema({
23134
22800
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
23135
22801
  }
23136
22802
  });
23137
- var propertiesCommand = defineCommand103({
22803
+ var propertiesCommand = defineCommand101({
23138
22804
  meta: {
23139
22805
  name: "properties",
23140
22806
  description: `List accessible GA4 properties.
@@ -23184,7 +22850,7 @@ Examples:
23184
22850
  // src/commands/ga4/query.ts
23185
22851
  import { appendFileSync as appendFileSync2, existsSync as existsSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "fs";
23186
22852
  import { resolve as resolve2 } from "path";
23187
- import { defineCommand as defineCommand104 } from "citty";
22853
+ import { defineCommand as defineCommand102 } from "citty";
23188
22854
 
23189
22855
  // src/commands/ga4/presets.ts
23190
22856
  var GA4_PRESETS = [
@@ -23316,7 +22982,7 @@ function handleError(err) {
23316
22982
  });
23317
22983
  process.exit(1);
23318
22984
  }
23319
- var queryCommand2 = defineCommand104({
22985
+ var queryCommand2 = defineCommand102({
23320
22986
  meta: {
23321
22987
  name: "query",
23322
22988
  description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
@@ -23387,7 +23053,7 @@ Free-form (escape hatch):
23387
23053
  });
23388
23054
 
23389
23055
  // src/commands/ga4/index.ts
23390
- var ga4Command = defineCommand105({
23056
+ var ga4Command = defineCommand103({
23391
23057
  meta: {
23392
23058
  name: "ga4",
23393
23059
  description: `Google Analytics 4 commands. Audit property config, run playbook-aligned reports.
@@ -23411,12 +23077,12 @@ Full guide: __tooling__/docs/tools/baker/ga4.md`
23411
23077
  });
23412
23078
 
23413
23079
  // src/commands/gsc/index.ts
23414
- import { defineCommand as defineCommand109 } from "citty";
23080
+ import { defineCommand as defineCommand107 } from "citty";
23415
23081
 
23416
23082
  // src/commands/gsc/query.ts
23417
23083
  import { appendFileSync as appendFileSync3, existsSync as existsSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync4 } from "fs";
23418
23084
  import { resolve as resolve3 } from "path";
23419
- import { defineCommand as defineCommand106 } from "citty";
23085
+ import { defineCommand as defineCommand104 } from "citty";
23420
23086
 
23421
23087
  // src/commands/gsc/presets.ts
23422
23088
  var GSC_PRESETS = [
@@ -23604,7 +23270,7 @@ function handleError2(err) {
23604
23270
  });
23605
23271
  process.exit(1);
23606
23272
  }
23607
- var queryCommand3 = defineCommand106({
23273
+ var queryCommand3 = defineCommand104({
23608
23274
  meta: {
23609
23275
  name: "query",
23610
23276
  description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
@@ -23682,7 +23348,7 @@ Free-form (escape hatch):
23682
23348
  });
23683
23349
 
23684
23350
  // src/commands/gsc/sitemaps.ts
23685
- import { defineCommand as defineCommand107 } from "citty";
23351
+ import { defineCommand as defineCommand105 } from "citty";
23686
23352
  registerSchema({
23687
23353
  command: "gsc.sitemaps",
23688
23354
  description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
@@ -23691,7 +23357,7 @@ registerSchema({
23691
23357
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
23692
23358
  }
23693
23359
  });
23694
- var sitemapsCommand = defineCommand107({
23360
+ var sitemapsCommand = defineCommand105({
23695
23361
  meta: {
23696
23362
  name: "sitemaps",
23697
23363
  description: `List sitemaps for a site. Check health and errors.
@@ -23741,7 +23407,7 @@ Examples:
23741
23407
  });
23742
23408
 
23743
23409
  // src/commands/gsc/sites.ts
23744
- import { defineCommand as defineCommand108 } from "citty";
23410
+ import { defineCommand as defineCommand106 } from "citty";
23745
23411
  registerSchema({
23746
23412
  command: "gsc.sites",
23747
23413
  description: "List all verified Google Search Console sites. Returns site URLs needed for query and sitemaps commands.",
@@ -23749,7 +23415,7 @@ registerSchema({
23749
23415
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
23750
23416
  }
23751
23417
  });
23752
- var sitesCommand = defineCommand108({
23418
+ var sitesCommand = defineCommand106({
23753
23419
  meta: {
23754
23420
  name: "sites",
23755
23421
  description: `List verified Search Console sites.
@@ -23797,7 +23463,7 @@ Examples:
23797
23463
  });
23798
23464
 
23799
23465
  // src/commands/gsc/index.ts
23800
- var gscCommand = defineCommand109({
23466
+ var gscCommand = defineCommand107({
23801
23467
  meta: {
23802
23468
  name: "gsc",
23803
23469
  description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
@@ -23821,7 +23487,7 @@ Full guide: __tooling__/docs/tools/baker/gsc.md`
23821
23487
  });
23822
23488
 
23823
23489
  // src/commands/history/index.ts
23824
- import { defineCommand as defineCommand110 } from "citty";
23490
+ import { defineCommand as defineCommand108 } from "citty";
23825
23491
  registerSchema({
23826
23492
  command: "history.list",
23827
23493
  description: "Start here: unified account history (audit log) \u2014 everything that changed on this account, newest first: publishes, chat lifecycle, backlog actions, team changes, setup links, tags, schedules, ad-platform writes, followed advertisers, media, creatives, reports, domains, and integrations. Use it to see what happened recently before planning work. Compact by default; add --full for raw metadata per entry.",
@@ -23876,7 +23542,7 @@ function parseBoundedInt2(raw, name, min, max) {
23876
23542
  }
23877
23543
  return value;
23878
23544
  }
23879
- var listCommand7 = defineCommand110({
23545
+ var listCommand7 = defineCommand108({
23880
23546
  meta: {
23881
23547
  name: "list",
23882
23548
  description: "List recent account changes (unified audit log), newest first."
@@ -23922,7 +23588,7 @@ var listCommand7 = defineCommand110({
23922
23588
  }
23923
23589
  }
23924
23590
  });
23925
- var historyCommand = defineCommand110({
23591
+ var historyCommand = defineCommand108({
23926
23592
  meta: {
23927
23593
  name: "history",
23928
23594
  description: `Unified account history (audit log): what changed, who did it, and when.
@@ -23932,10 +23598,10 @@ Full guide: __tooling__/docs/tools/baker/history.md`
23932
23598
  });
23933
23599
 
23934
23600
  // src/commands/images/index.ts
23935
- import { defineCommand as defineCommand134 } from "citty";
23601
+ import { defineCommand as defineCommand132 } from "citty";
23936
23602
 
23937
23603
  // src/commands/images/crop.ts
23938
- import { defineCommand as defineCommand111 } from "citty";
23604
+ import { defineCommand as defineCommand109 } from "citty";
23939
23605
 
23940
23606
  // src/lib/image/crop-sprite.ts
23941
23607
  import sharp from "sharp";
@@ -23950,7 +23616,7 @@ function cropSprite(input, region) {
23950
23616
 
23951
23617
  // src/lib/image/io.ts
23952
23618
  import { randomBytes } from "crypto";
23953
- import { glob as fsGlob, readFile as readFile19, rename, stat as stat4, writeFile as writeFile10 } from "fs/promises";
23619
+ import { glob as fsGlob, readFile as readFile18, rename, stat as stat4, writeFile as writeFile9 } from "fs/promises";
23954
23620
  import { dirname as dirname2, extname as extname2, join as join4, resolve as resolve4 } from "path";
23955
23621
  var REMOTE_RE = /^https?:\/\//i;
23956
23622
  var GLOB_RE = /[*?[\]{}]/;
@@ -23986,11 +23652,11 @@ async function readImageBuffer(pathOrUrl) {
23986
23652
  }
23987
23653
  return Buffer.from(await response.arrayBuffer());
23988
23654
  }
23989
- return readFile19(pathOrUrl);
23655
+ return readFile18(pathOrUrl);
23990
23656
  }
23991
- async function isDirectory(path28) {
23657
+ async function isDirectory(path27) {
23992
23658
  try {
23993
- const s = await stat4(path28);
23659
+ const s = await stat4(path27);
23994
23660
  return s.isDirectory();
23995
23661
  } catch {
23996
23662
  return false;
@@ -24009,7 +23675,7 @@ async function atomicWrite(targetPath, data) {
24009
23675
  const absolute = resolve4(targetPath);
24010
23676
  const dir = dirname2(absolute);
24011
23677
  const tmp = join4(dir, `.baker-image-${randomBytes(8).toString("hex")}.tmp`);
24012
- await writeFile10(tmp, data);
23678
+ await writeFile9(tmp, data);
24013
23679
  await rename(tmp, absolute);
24014
23680
  }
24015
23681
 
@@ -24060,7 +23726,7 @@ function emitError2(err) {
24060
23726
  }
24061
23727
  process.exit(1);
24062
23728
  }
24063
- var cropCommand = defineCommand111({
23729
+ var cropCommand = defineCommand109({
24064
23730
  meta: {
24065
23731
  name: "crop",
24066
23732
  description: "Crop a rectangular region from an image.\n\nExample: baker images crop sprite.png --x 0 --y 0 --width 64 --height 64 --output icon.png"
@@ -24096,7 +23762,7 @@ var cropCommand = defineCommand111({
24096
23762
  });
24097
23763
 
24098
23764
  // src/commands/images/delete.ts
24099
- import { defineCommand as defineCommand112 } from "citty";
23765
+ import { defineCommand as defineCommand110 } from "citty";
24100
23766
  registerSchema({
24101
23767
  command: "images.delete",
24102
23768
  description: "Delete an image by ID",
@@ -24110,7 +23776,7 @@ registerSchema({
24110
23776
  }
24111
23777
  }
24112
23778
  });
24113
- var deleteCommand = defineCommand112({
23779
+ var deleteCommand = defineCommand110({
24114
23780
  meta: {
24115
23781
  name: "delete",
24116
23782
  description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
@@ -24151,7 +23817,7 @@ var deleteCommand = defineCommand112({
24151
23817
  });
24152
23818
 
24153
23819
  // src/commands/images/dimensions.ts
24154
- import { defineCommand as defineCommand113 } from "citty";
23820
+ import { defineCommand as defineCommand111 } from "citty";
24155
23821
 
24156
23822
  // src/lib/image/dimensions.ts
24157
23823
  import { imageSize } from "image-size";
@@ -24174,7 +23840,7 @@ registerSchema({
24174
23840
  target: { type: "string", description: "Local file path or remote http(s) URL", required: true }
24175
23841
  }
24176
23842
  });
24177
- var dimensionsCommand = defineCommand113({
23843
+ var dimensionsCommand = defineCommand111({
24178
23844
  meta: {
24179
23845
  name: "dimensions",
24180
23846
  description: "Read image dimensions without decoding the full file.\n\nExample: baker images dimensions ./logo.png\nExample: baker images dimensions https://acme.com/hero.png"
@@ -24218,7 +23884,7 @@ var dimensionsCommand = defineCommand113({
24218
23884
  });
24219
23885
 
24220
23886
  // src/commands/images/extract.ts
24221
- import { defineCommand as defineCommand114 } from "citty";
23887
+ import { defineCommand as defineCommand112 } from "citty";
24222
23888
  registerSchema({
24223
23889
  command: "images.extract",
24224
23890
  description: "Extract images from a URL via Firecrawl (formats: images).",
@@ -24234,7 +23900,7 @@ registerSchema({
24234
23900
  }
24235
23901
  }
24236
23902
  });
24237
- var extractCommand = defineCommand114({
23903
+ var extractCommand = defineCommand112({
24238
23904
  meta: {
24239
23905
  name: "extract",
24240
23906
  description: "Pull every image from a single URL via Firecrawl. ~$0.001/scrape. Cap auto-ingest at 20.\n\nExample: baker images extract https://stripe.com --auto-ingest 5"
@@ -24272,7 +23938,7 @@ var extractCommand = defineCommand114({
24272
23938
  });
24273
23939
 
24274
23940
  // src/commands/images/find.ts
24275
- import { defineCommand as defineCommand115 } from "citty";
23941
+ import { defineCommand as defineCommand113 } from "citty";
24276
23942
  registerSchema({
24277
23943
  command: "images.find",
24278
23944
  description: "Fanout image search: library first, then opted-in external providers.",
@@ -24304,7 +23970,7 @@ registerSchema({
24304
23970
  }
24305
23971
  }
24306
23972
  });
24307
- var findCommand = defineCommand115({
23973
+ var findCommand = defineCommand113({
24308
23974
  meta: {
24309
23975
  name: "find",
24310
23976
  description: "Library-first fanout image search. Opt in to providers with --sources. `--fallback` short-circuits to externals only when library is thin. With --auto-ingest, ingested external hits return Baker-owned URLs.\n\nExample: baker images find 'office' --sources library,magnific --limit 20"
@@ -24352,8 +24018,8 @@ var findCommand = defineCommand115({
24352
24018
  });
24353
24019
 
24354
24020
  // src/commands/images/generate.ts
24355
- import { readFile as readFile20 } from "fs/promises";
24356
- import { defineCommand as defineCommand116 } from "citty";
24021
+ import { readFile as readFile19 } from "fs/promises";
24022
+ import { defineCommand as defineCommand114 } from "citty";
24357
24023
  import sharp2 from "sharp";
24358
24024
  var GENERATE_TIMEOUT_MS = 18e4;
24359
24025
  var REFERENCE_MAX_EDGE = 1536;
@@ -24442,7 +24108,7 @@ async function resolveReferences(spec) {
24442
24108
  }
24443
24109
  let raw;
24444
24110
  try {
24445
- raw = await readFile20(entry);
24111
+ raw = await readFile19(entry);
24446
24112
  } catch {
24447
24113
  throw new ApiError("VALIDATION_ERROR", `Reference file not found: ${entry}`);
24448
24114
  }
@@ -24456,7 +24122,7 @@ async function resolveReferences(spec) {
24456
24122
  }
24457
24123
  return out;
24458
24124
  }
24459
- var generateCommand = defineCommand116({
24125
+ var generateCommand = defineCommand114({
24460
24126
  meta: {
24461
24127
  name: "generate",
24462
24128
  description: "Generate an image with AI and store it in the library (cost-tracked per request via OpenRouter usage). Models mirror the canvas: google/gemini-3.1-flash-image-preview (Nano Banana flash \u2014 default, fast, extreme aspect ratios), google/gemini-3-pro-image-preview (Nano Banana Pro \u2014 highest fidelity), openai/gpt-image-2 (photoreal, cleanest in-image text, best for ad/landing reproduction \u2014 no --image-size, and no 4:5 / 5:4), recraft/recraft-v4.1-pro-vector (vector/SVG-style with palette control). The result is auto-ingested (describe + embed), so the next `baker images library` query finds it. Pass --reference with image URLs and/or local file paths (Pinterest, stock, brand assets, sandbox files) to ground generation in reality.\n\nExamples:\n baker images generate 'a friendly golden retriever sitting in a bright modern living room' --aspect-ratio 16:9\n baker images generate 'hero shot of a matte black water bottle on marble' --model openai/gpt-image-2 --aspect-ratio 3:2\n baker images generate 'lifestyle photo matching this mood' --reference 'https://\u2026/ref1.jpg,https://\u2026/ref2.jpg'\n baker images generate 'put this product on a marble countertop, soft daylight' --reference './src/brand/logos/product.png,./refs/kitchen-mood.jpg'\n baker images generate 'flat geometric mascot, brand palette' --model recraft/recraft-v4.1-pro-vector --rgb-colors '[[10,10,10],[255,80,0]]'"
@@ -24508,7 +24174,7 @@ var generateCommand = defineCommand116({
24508
24174
  });
24509
24175
 
24510
24176
  // src/commands/images/get.ts
24511
- import { defineCommand as defineCommand117 } from "citty";
24177
+ import { defineCommand as defineCommand115 } from "citty";
24512
24178
  registerSchema({
24513
24179
  command: "images.get",
24514
24180
  description: "Get a single image by ID",
@@ -24516,7 +24182,7 @@ registerSchema({
24516
24182
  id: { type: "string", description: "Image ID", required: true }
24517
24183
  }
24518
24184
  });
24519
- var getCommand2 = defineCommand117({
24185
+ var getCommand2 = defineCommand115({
24520
24186
  meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
24521
24187
  args: {
24522
24188
  id: { type: "positional", description: "Image ID", required: false },
@@ -24552,7 +24218,7 @@ var getCommand2 = defineCommand117({
24552
24218
  });
24553
24219
 
24554
24220
  // src/commands/images/gif.ts
24555
- import { defineCommand as defineCommand118 } from "citty";
24221
+ import { defineCommand as defineCommand116 } from "citty";
24556
24222
  registerSchema({
24557
24223
  command: "images.gif",
24558
24224
  description: "Search Giphy for GIFs / reaction memes (paid social creative).",
@@ -24584,7 +24250,7 @@ registerSchema({
24584
24250
  }
24585
24251
  }
24586
24252
  });
24587
- var gifCommand = defineCommand118({
24253
+ var gifCommand = defineCommand116({
24588
24254
  meta: {
24589
24255
  name: "gif",
24590
24256
  description: "Search Giphy for GIFs / reaction memes \u2014 built for paid-social creative (Meta, TikTok, LinkedIn, X). Free API. Each hit carries WebP + GIF + MP4 URLs in providerMeta so you can pick the right format per platform.\n\nExample: baker images gif 'this is fine' --limit 10\nExample: baker images gif 'office reaction' --rating pg --auto-ingest 2\nExample: baker images gif --trending --limit 25"
@@ -24631,7 +24297,7 @@ var gifCommand = defineCommand118({
24631
24297
  });
24632
24298
 
24633
24299
  // src/commands/images/google.ts
24634
- import { defineCommand as defineCommand119 } from "citty";
24300
+ import { defineCommand as defineCommand117 } from "citty";
24635
24301
 
24636
24302
  // src/commands/images/searchHints.ts
24637
24303
  var FALLBACK = {
@@ -24695,7 +24361,7 @@ registerSchema({
24695
24361
  }
24696
24362
  }
24697
24363
  });
24698
- var googleCommand2 = defineCommand119({
24364
+ var googleCommand2 = defineCommand117({
24699
24365
  meta: {
24700
24366
  name: "google",
24701
24367
  description: "Google Images via the official Custom Search JSON API ($0.005/query, free 100/day). \u26A0 Source unverified \u2014 watermarks, low-res, mislabeled results are common. Use as last resort. With --auto-ingest, ingested hits return Baker-owned URLs.\n\nExample: baker images google 'industrial workshop' --type photo --size large --limit 20"
@@ -24751,7 +24417,7 @@ var googleCommand2 = defineCommand119({
24751
24417
  });
24752
24418
 
24753
24419
  // src/commands/images/icon.ts
24754
- import { defineCommand as defineCommand120 } from "citty";
24420
+ import { defineCommand as defineCommand118 } from "citty";
24755
24421
  registerSchema({
24756
24422
  command: "images.icon",
24757
24423
  description: "Icon lookup via Iconify (200+ icon sets, free CDN).",
@@ -24777,7 +24443,7 @@ registerSchema({
24777
24443
  }
24778
24444
  }
24779
24445
  });
24780
- var iconCommand = defineCommand120({
24446
+ var iconCommand = defineCommand118({
24781
24447
  meta: {
24782
24448
  name: "icon",
24783
24449
  description: "Icon via Iconify (simple-icons, logos, lucide, devicon, heroicons, tabler, phosphor, material-symbols, \u2026). Free CDN, no API key.\n\nExample: baker images icon react --set devicon\nExample: baker images icon lucide:check --color '#0a0a0a'"
@@ -24817,7 +24483,7 @@ var iconCommand = defineCommand120({
24817
24483
  });
24818
24484
 
24819
24485
  // src/commands/images/ingest.ts
24820
- import { defineCommand as defineCommand121 } from "citty";
24486
+ import { defineCommand as defineCommand119 } from "citty";
24821
24487
  registerSchema({
24822
24488
  command: "images.ingest",
24823
24489
  description: "Ingest a remote image URL into the library (full describe + embed).",
@@ -24829,7 +24495,7 @@ registerSchema({
24829
24495
  context: { type: "string", description: "Description context hint", required: false }
24830
24496
  }
24831
24497
  });
24832
- var ingestCommand = defineCommand121({
24498
+ var ingestCommand = defineCommand119({
24833
24499
  meta: {
24834
24500
  name: "ingest",
24835
24501
  description: "Download a remote URL and store it in the library. Hash-deduped on bytes + externalId.\n\nExample: baker images ingest https://img.freepik.com/free-photo/xyz.jpg --source magnific --external-id 12345"
@@ -24871,7 +24537,7 @@ var ingestCommand = defineCommand121({
24871
24537
  });
24872
24538
 
24873
24539
  // src/commands/images/library.ts
24874
- import { defineCommand as defineCommand122 } from "citty";
24540
+ import { defineCommand as defineCommand120 } from "citty";
24875
24541
  registerSchema({
24876
24542
  command: "images.library",
24877
24543
  description: "Search the company image library. Returns only ready images.",
@@ -24897,7 +24563,7 @@ registerSchema({
24897
24563
  }
24898
24564
  }
24899
24565
  });
24900
- var libraryCommand = defineCommand122({
24566
+ var libraryCommand = defineCommand120({
24901
24567
  meta: {
24902
24568
  name: "library",
24903
24569
  description: "Search the company image library (hybrid BM25 + vector + Cohere rerank). Use this BEFORE any external provider.\n\nExample: baker images library 'hero banner' --aspect-ratio 16:9 --source magnific"
@@ -24954,7 +24620,7 @@ var libraryCommand = defineCommand122({
24954
24620
  });
24955
24621
 
24956
24622
  // src/commands/images/logo.ts
24957
- import { defineCommand as defineCommand123 } from "citty";
24623
+ import { defineCommand as defineCommand121 } from "citty";
24958
24624
  registerSchema({
24959
24625
  command: "images.logo",
24960
24626
  description: "Brand logo lookup via Brandfetch CDN (fallback/404). Auto-ingests by default.",
@@ -24979,7 +24645,7 @@ registerSchema({
24979
24645
  }
24980
24646
  }
24981
24647
  });
24982
- var logoCommand = defineCommand123({
24648
+ var logoCommand = defineCommand121({
24983
24649
  meta: {
24984
24650
  name: "logo",
24985
24651
  description: "Brand logo via Brandfetch CDN. Returns up to 5 variants (icon, light/dark logo, light/dark symbol). Auto-ingests the first variant.\n\nExample: baker images logo stripe.com --variant logo"
@@ -25017,7 +24683,7 @@ var logoCommand = defineCommand123({
25017
24683
  });
25018
24684
 
25019
24685
  // src/commands/images/normalize.ts
25020
- import { defineCommand as defineCommand124 } from "citty";
24686
+ import { defineCommand as defineCommand122 } from "citty";
25021
24687
 
25022
24688
  // src/lib/image/color-changer.ts
25023
24689
  import quantize from "quantize";
@@ -25749,7 +25415,7 @@ function coerceRawArgs(args) {
25749
25415
  "dry-run": bool(args["dry-run"])
25750
25416
  };
25751
25417
  }
25752
- var normalizeCommand = defineCommand124({
25418
+ var normalizeCommand = defineCommand122({
25753
25419
  meta: {
25754
25420
  name: "normalize",
25755
25421
  description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
@@ -25804,7 +25470,7 @@ Examples:
25804
25470
  });
25805
25471
 
25806
25472
  // src/commands/images/pinterest.ts
25807
- import { defineCommand as defineCommand125 } from "citty";
25473
+ import { defineCommand as defineCommand123 } from "citty";
25808
25474
  registerSchema({
25809
25475
  command: "images.pinterest",
25810
25476
  description: "Pinterest image search via ScrapeCreators. Reference-grade real-world photography, product styling, interiors, fashion, food, and aesthetic mood boards. Inspect before placing \u2014 Pinterest is unverified, trademark-bearing web content.",
@@ -25824,7 +25490,7 @@ registerSchema({
25824
25490
  }
25825
25491
  }
25826
25492
  });
25827
- var pinterestCommand = defineCommand125({
25493
+ var pinterestCommand = defineCommand123({
25828
25494
  meta: {
25829
25495
  name: "pinterest",
25830
25496
  description: "Pinterest image search via ScrapeCreators ($0.00188/request). Best for photo-realistic reference imagery \u2014 lifestyle, interiors, fashion, food, product styling, and mood boards to brief AI generation against. \u26A0 Unverified, trademark-bearing web content \u2014 inspect and respect rights before placing on a customer page. Browse first; auto-ingest only the pins you commit to.\n\nExamples:\n baker images pinterest 'scandinavian living room'\n baker images pinterest 'minimalist skincare product photography' --limit 20\n baker images pinterest 'cozy coffee shop interior' --auto-ingest 2 --context 'Mood reference for hero photography'"
@@ -25864,7 +25530,7 @@ var pinterestCommand = defineCommand125({
25864
25530
  });
25865
25531
 
25866
25532
  // src/commands/images/screenshot.ts
25867
- import { defineCommand as defineCommand126 } from "citty";
25533
+ import { defineCommand as defineCommand124 } from "citty";
25868
25534
  registerSchema({
25869
25535
  command: "images.screenshot",
25870
25536
  description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
@@ -25880,7 +25546,7 @@ registerSchema({
25880
25546
  }
25881
25547
  }
25882
25548
  });
25883
- var screenshotCommand = defineCommand126({
25549
+ var screenshotCommand = defineCommand124({
25884
25550
  meta: {
25885
25551
  name: "screenshot",
25886
25552
  description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
@@ -25943,7 +25609,7 @@ var screenshotCommand = defineCommand126({
25943
25609
  });
25944
25610
 
25945
25611
  // src/commands/images/search.ts
25946
- import { defineCommand as defineCommand127 } from "citty";
25612
+ import { defineCommand as defineCommand125 } from "citty";
25947
25613
  registerSchema({
25948
25614
  command: "images.search",
25949
25615
  description: "Search images by text query. Only returns ready images.",
@@ -25959,7 +25625,7 @@ registerSchema({
25959
25625
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
25960
25626
  }
25961
25627
  });
25962
- var searchCommand = defineCommand127({
25628
+ var searchCommand = defineCommand125({
25963
25629
  meta: {
25964
25630
  name: "search",
25965
25631
  description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
@@ -26019,7 +25685,7 @@ var searchCommand = defineCommand127({
26019
25685
  });
26020
25686
 
26021
25687
  // src/commands/images/sticker.ts
26022
- import { defineCommand as defineCommand128 } from "citty";
25688
+ import { defineCommand as defineCommand126 } from "citty";
26023
25689
  registerSchema({
26024
25690
  command: "images.sticker",
26025
25691
  description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
@@ -26051,7 +25717,7 @@ registerSchema({
26051
25717
  }
26052
25718
  }
26053
25719
  });
26054
- var stickerCommand = defineCommand128({
25720
+ var stickerCommand = defineCommand126({
26055
25721
  meta: {
26056
25722
  name: "sticker",
26057
25723
  description: "Search Giphy's sticker corpus \u2014 transparent-background WebPs / GIFs ideal for overlaying on ad creative (Meta, TikTok, Stories). Same Giphy free API as `baker images gif`; results carry WebP + GIF + MP4 URLs in providerMeta.\n\nExample: baker images sticker 'thumbs up' --limit 10\nExample: baker images sticker celebration --rating g --auto-ingest 3\nExample: baker images sticker --trending --limit 25"
@@ -26098,7 +25764,7 @@ var stickerCommand = defineCommand128({
26098
25764
  });
26099
25765
 
26100
25766
  // src/commands/images/stock.ts
26101
- import { defineCommand as defineCommand129 } from "citty";
25767
+ import { defineCommand as defineCommand127 } from "citty";
26102
25768
  var STOCK_ERROR_FIX = {
26103
25769
  action: "use_different_resource",
26104
25770
  explanation: "Switch provider instead of retrying stock search. Stock search is one of several image sources. Run `baker images find <query> --sources library,pinterest,google` (`--sources` is required \u2014 `find` alone searches the library only) or `baker images generate` to make the asset. Never sleep-and-retry this command \u2014 the CLI already backs off on rate limits. If no image can be sourced, continue the rest of the task with a placeholder rather than aborting it."
@@ -26175,7 +25841,7 @@ function buildStockRequest(query, args) {
26175
25841
  if (args.context) body.descriptionContext = args.context;
26176
25842
  return body;
26177
25843
  }
26178
- var stockCommand = defineCommand129({
25844
+ var stockCommand = defineCommand127({
26179
25845
  meta: {
26180
25846
  name: "stock",
26181
25847
  description: "Stock search via Magnific \u2014 Freepik's developer API (~250M assets: photos, vectors, illustrations, icons, PSDs). $0.002/req. With --auto-ingest, ingested hits return Baker-owned URLs.\n\nExamples:\n baker images stock 'minimalist office'\n baker images stock 'flat office workers' --type vector\n baker images stock 'hero photo of a kitchen' --type photo --orientation landscape --ai exclude\n baker images stock 'brand pattern' --color '#0a0a0a' --license freemium --auto-ingest 2"
@@ -26231,7 +25897,7 @@ var stockCommand = defineCommand129({
26231
25897
  });
26232
25898
 
26233
25899
  // src/lib/tags-command.ts
26234
- import { defineCommand as defineCommand130 } from "citty";
25900
+ import { defineCommand as defineCommand128 } from "citty";
26235
25901
  function makeTagsCommand(command, label, endpoint) {
26236
25902
  registerSchema({
26237
25903
  command: `${command}.tags`,
@@ -26240,7 +25906,7 @@ function makeTagsCommand(command, label, endpoint) {
26240
25906
  output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
26241
25907
  }
26242
25908
  });
26243
- return defineCommand130({
25909
+ return defineCommand128({
26244
25910
  meta: {
26245
25911
  name: "tags",
26246
25912
  description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
@@ -26276,7 +25942,7 @@ function makeTagsCommand(command, label, endpoint) {
26276
25942
  var tagsCommand2 = makeTagsCommand("images", "image", "/api/images/tags");
26277
25943
 
26278
25944
  // src/commands/images/upload.ts
26279
- import { defineCommand as defineCommand131 } from "citty";
25945
+ import { defineCommand as defineCommand129 } from "citty";
26280
25946
  registerSchema({
26281
25947
  command: "images.upload",
26282
25948
  description: "Upload an image to the library \u2014 local file path or remote http(s) URL.",
@@ -26314,7 +25980,7 @@ registerSchema({
26314
25980
  function isRemoteUrl2(value) {
26315
25981
  return /^https?:\/\//i.test(value);
26316
25982
  }
26317
- var uploadCommand = defineCommand131({
25983
+ var uploadCommand = defineCommand129({
26318
25984
  meta: {
26319
25985
  name: "upload",
26320
25986
  description: "Upload an image to the library \u2014 accepts a local file path OR a remote http(s) URL.\n\nLocal: reads bytes, sends to /api/images/upload, content-type auto-detected from extension.\nRemote: dispatches to /api/images/ingest with hash-dedup on bytes + externalId.\n\nExamples:\n baker images upload ./logo.png --source uploaded\n baker images upload ./cert.png --context 'ISO 27001 badge \u2014 enterprise tier'\n baker images upload https://acme.com/hero.png --source firecrawl --context 'Acme competitor pricing hero'"
@@ -26407,7 +26073,7 @@ async function uploadLocal(target, args) {
26407
26073
  }
26408
26074
 
26409
26075
  // src/commands/images/upscale.ts
26410
- import { defineCommand as defineCommand132 } from "citty";
26076
+ import { defineCommand as defineCommand130 } from "citty";
26411
26077
  registerSchema({
26412
26078
  command: "images.upscale",
26413
26079
  description: "Upscale a library image via the backend (Replicate, cost-tracked). Waits for completion by default. The image must be status 'ready' and raster (not SVG/AVIF).",
@@ -26422,7 +26088,7 @@ registerSchema({
26422
26088
  }
26423
26089
  });
26424
26090
  var POLL_INTERVAL_MS3 = 1500;
26425
- var upscaleCommand = defineCommand132({
26091
+ var upscaleCommand = defineCommand130({
26426
26092
  meta: {
26427
26093
  name: "upscale",
26428
26094
  description: "Upscale a library image via the Convex backend (Replicate, cost-tracked at $0.05/image). Waits for completion by default.\n\nExample: baker images upscale j571abc123def\nExample: baker images upscale j571abc123def --max-wait 0 # fire-and-forget"
@@ -26477,7 +26143,7 @@ var upscaleCommand = defineCommand132({
26477
26143
  });
26478
26144
 
26479
26145
  // src/commands/images/use.ts
26480
- import { defineCommand as defineCommand133 } from "citty";
26146
+ import { defineCommand as defineCommand131 } from "citty";
26481
26147
  registerSchema({
26482
26148
  command: "images.use",
26483
26149
  description: "Ingest a URL and wait for the library record to be ready.",
@@ -26493,7 +26159,7 @@ registerSchema({
26493
26159
  }
26494
26160
  });
26495
26161
  var POLL_INTERVAL_MS4 = 1500;
26496
- var useCommand = defineCommand133({
26162
+ var useCommand = defineCommand131({
26497
26163
  meta: {
26498
26164
  name: "use",
26499
26165
  description: "Sugar over `ingest`: download \u2192 store \u2192 wait until describe + embed complete \u2192 return ready library record.\n\nExample: baker images use https://cdn.example.com/hero.png --source uploaded"
@@ -26539,7 +26205,7 @@ var useCommand = defineCommand133({
26539
26205
  });
26540
26206
 
26541
26207
  // src/commands/images/index.ts
26542
- var imagesCommand = defineCommand134({
26208
+ var imagesCommand = defineCommand132({
26543
26209
  meta: {
26544
26210
  name: "images",
26545
26211
  description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
@@ -26610,16 +26276,16 @@ Full guide: __tooling__/docs/tools/baker/images.md`
26610
26276
  });
26611
26277
 
26612
26278
  // src/commands/landing/index.ts
26613
- import { defineCommand as defineCommand136 } from "citty";
26279
+ import { defineCommand as defineCommand134 } from "citty";
26614
26280
 
26615
26281
  // src/commands/landing/critique.ts
26616
26282
  import { readdir as readdir8, stat as stat6 } from "fs/promises";
26617
- import path27 from "path";
26618
- import { defineCommand as defineCommand135 } from "citty";
26283
+ import path26 from "path";
26284
+ import { defineCommand as defineCommand133 } from "citty";
26619
26285
 
26620
26286
  // src/engine/landing/lib/brand-tokens.ts
26621
- import { readFile as readFile21 } from "fs/promises";
26622
- import path24 from "path";
26287
+ import { readFile as readFile20 } from "fs/promises";
26288
+ import path23 from "path";
26623
26289
 
26624
26290
  // src/engine/landing/lib/color.ts
26625
26291
  var NEUTRAL_COLOR_KEYWORDS = /* @__PURE__ */ new Set([
@@ -26781,14 +26447,14 @@ function parseBrandMd(brandMd, fonts, colors) {
26781
26447
  }
26782
26448
  }
26783
26449
  async function loadBrandTokens(projectRoot) {
26784
- const globalCss = await safeRead(path24.join(projectRoot, "src", "styles", "global.css"));
26785
- const brandMd = await safeRead(path24.join(projectRoot, "src", "brand", "BRAND.md"));
26450
+ const globalCss = await safeRead(path23.join(projectRoot, "src", "styles", "global.css"));
26451
+ const brandMd = await safeRead(path23.join(projectRoot, "src", "brand", "BRAND.md"));
26786
26452
  if (!globalCss && !brandMd) return EMPTY;
26787
26453
  return parseBrandTokens(globalCss, brandMd);
26788
26454
  }
26789
26455
  async function safeRead(file) {
26790
26456
  try {
26791
- return await readFile21(file, "utf8");
26457
+ return await readFile20(file, "utf8");
26792
26458
  } catch {
26793
26459
  return "";
26794
26460
  }
@@ -27574,40 +27240,40 @@ function describeCounts(findings) {
27574
27240
  }
27575
27241
 
27576
27242
  // src/commands/landing/snapshot.ts
27577
- import { mkdir as mkdir8, rename as rename2, writeFile as writeFile11 } from "fs/promises";
27578
- import path25 from "path";
27243
+ import { mkdir as mkdir7, rename as rename2, writeFile as writeFile10 } from "fs/promises";
27244
+ import path24 from "path";
27579
27245
  var CRITIC_VERSION = "1";
27580
27246
  function critiqueCacheDir(projectRoot) {
27581
- return path25.join(projectRoot, ".cache", "landing-critique");
27247
+ return path24.join(projectRoot, ".cache", "landing-critique");
27582
27248
  }
27583
27249
  function snapshotPath(projectRoot, slug) {
27584
- return path25.join(critiqueCacheDir(projectRoot), `${slug}.json`);
27250
+ return path24.join(critiqueCacheDir(projectRoot), `${slug}.json`);
27585
27251
  }
27586
27252
  async function writeCritiqueSnapshot(projectRoot, snapshot) {
27587
- await mkdir8(critiqueCacheDir(projectRoot), { recursive: true });
27253
+ await mkdir7(critiqueCacheDir(projectRoot), { recursive: true });
27588
27254
  const dest = snapshotPath(projectRoot, snapshot.slug);
27589
27255
  const tmp = `${dest}.tmp`;
27590
- await writeFile11(tmp, `${JSON.stringify(snapshot, null, 2)}
27256
+ await writeFile10(tmp, `${JSON.stringify(snapshot, null, 2)}
27591
27257
  `, "utf8");
27592
27258
  await rename2(tmp, dest);
27593
27259
  }
27594
27260
 
27595
27261
  // src/commands/landing/source-version.ts
27596
- import { readdir as readdir7, readFile as readFile22, stat as stat5 } from "fs/promises";
27597
- import path26 from "path";
27262
+ import { readdir as readdir7, readFile as readFile21, stat as stat5 } from "fs/promises";
27263
+ import path25 from "path";
27598
27264
  async function landingSourceRelPaths(landingDir) {
27599
27265
  const rel = [];
27600
- if (await isFile(path26.join(landingDir, "index.astro"))) rel.push("index.astro");
27601
- const componentsDir = path26.join(landingDir, "_components");
27266
+ if (await isFile(path25.join(landingDir, "index.astro"))) rel.push("index.astro");
27267
+ const componentsDir = path25.join(landingDir, "_components");
27602
27268
  for (const abs of await walkAstro(componentsDir)) {
27603
- rel.push(path26.relative(landingDir, abs).split(path26.sep).join("/"));
27269
+ rel.push(path25.relative(landingDir, abs).split(path25.sep).join("/"));
27604
27270
  }
27605
27271
  return rel.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
27606
27272
  }
27607
27273
  async function readLandingSources(landingDir) {
27608
27274
  const rel = await landingSourceRelPaths(landingDir);
27609
27275
  const out = [];
27610
- for (const r of rel) out.push({ path: r, text: await readFile22(path26.join(landingDir, r), "utf8") });
27276
+ for (const r of rel) out.push({ path: r, text: await readFile21(path25.join(landingDir, r), "utf8") });
27611
27277
  return out;
27612
27278
  }
27613
27279
  async function computeLandingSourceSha(landingDir) {
@@ -27616,7 +27282,7 @@ async function computeLandingSourceSha(landingDir) {
27616
27282
  for (const r of rel) {
27617
27283
  let bytes;
27618
27284
  try {
27619
- bytes = await readFile22(path26.join(landingDir, r));
27285
+ bytes = await readFile21(path25.join(landingDir, r));
27620
27286
  } catch {
27621
27287
  bytes = Buffer.alloc(0);
27622
27288
  }
@@ -27640,7 +27306,7 @@ async function walkAstro(dir) {
27640
27306
  }
27641
27307
  const out = [];
27642
27308
  for (const entry of entries) {
27643
- const abs = path26.join(dir, entry.name);
27309
+ const abs = path25.join(dir, entry.name);
27644
27310
  if (entry.isDirectory()) out.push(...await walkAstro(abs));
27645
27311
  else if (entry.isFile() && entry.name.endsWith(".astro")) out.push(abs);
27646
27312
  }
@@ -27661,14 +27327,14 @@ registerSchema({
27661
27327
  }
27662
27328
  });
27663
27329
  var SLUG_RE = /^[a-z0-9][a-z0-9._-]*$/i;
27664
- function fail5(code, message, fix) {
27330
+ function fail4(code, message, fix) {
27665
27331
  process.stderr.write(
27666
27332
  `${JSON.stringify({ ok: false, error: { code, message, ...fix ? { fix } : {} } }, null, 2)}
27667
27333
  `
27668
27334
  );
27669
27335
  process.exit(2);
27670
27336
  }
27671
- var critiqueCommand2 = defineCommand135({
27337
+ var critiqueCommand2 = defineCommand133({
27672
27338
  meta: {
27673
27339
  name: "critique",
27674
27340
  description: "Start here: `baker landing critique <slug>` after building or editing a landing. Deterministic design-quality critic (ADVISORY \u2014 findings never fail it). Flags the known AI design tells (gradient text, overused fonts, side-tab borders, cream palettes, buzzword copy, broken images) tiered block/warn/advisory, respecting the client's BRAND.md as the allowlist. Also records the critique that publishing requires \u2014 run it before finishing a landing."
@@ -27681,15 +27347,15 @@ var critiqueCommand2 = defineCommand135({
27681
27347
  const slug = String(args.slug);
27682
27348
  const projectRoot = process.cwd();
27683
27349
  if (!SLUG_RE.test(slug) || slug.includes("..")) {
27684
- fail5(
27350
+ fail4(
27685
27351
  "INVALID_SLUG",
27686
27352
  `"${slug}" is not a landing slug \u2014 use the folder name directly under src/pages/ (letters, digits, dashes; not a path, not a _-private folder).`,
27687
27353
  { availableSlugs: await listLandingSlugs(projectRoot) }
27688
27354
  );
27689
27355
  }
27690
- const landingDir = path27.resolve(projectRoot, "src", "pages", slug);
27356
+ const landingDir = path26.resolve(projectRoot, "src", "pages", slug);
27691
27357
  if (!await isDir(landingDir)) {
27692
- fail5("NOT_FOUND", `No landing at src/pages/${slug}/`, {
27358
+ fail4("NOT_FOUND", `No landing at src/pages/${slug}/`, {
27693
27359
  availableSlugs: await listLandingSlugs(projectRoot)
27694
27360
  });
27695
27361
  }
@@ -27742,7 +27408,7 @@ var critiqueCommand2 = defineCommand135({
27742
27408
  });
27743
27409
  async function listLandingSlugs(projectRoot) {
27744
27410
  try {
27745
- const entries = await readdir8(path27.join(projectRoot, "src", "pages"), { withFileTypes: true });
27411
+ const entries = await readdir8(path26.join(projectRoot, "src", "pages"), { withFileTypes: true });
27746
27412
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
27747
27413
  } catch {
27748
27414
  return [];
@@ -27768,7 +27434,7 @@ async function isDir(p) {
27768
27434
  }
27769
27435
 
27770
27436
  // src/commands/landing/index.ts
27771
- var landingCommand = defineCommand136({
27437
+ var landingCommand = defineCommand134({
27772
27438
  meta: {
27773
27439
  name: "landing",
27774
27440
  description: `Design-quality tools for landing pages (src/pages/<slug>/).
@@ -27784,7 +27450,7 @@ Subcommands:
27784
27450
  });
27785
27451
 
27786
27452
  // src/commands/mcp/index.ts
27787
- import { defineCommand as defineCommand137 } from "citty";
27453
+ import { defineCommand as defineCommand135 } from "citty";
27788
27454
  var SCOPES = ["user", "user_org", "company", "org"];
27789
27455
  function parseScope(raw) {
27790
27456
  const scope = raw === void 0 ? "company" : String(raw);
@@ -27810,7 +27476,7 @@ function parseHeaders(raw) {
27810
27476
  }
27811
27477
  return Object.keys(headers).length > 0 ? headers : void 0;
27812
27478
  }
27813
- function fail6(err) {
27479
+ function fail5(err) {
27814
27480
  if (err instanceof ApiError) {
27815
27481
  writeJson({ ok: false, error: { code: err.code, message: err.message } });
27816
27482
  process.exit(1);
@@ -27823,7 +27489,7 @@ registerSchema({
27823
27489
  description: "List every third-party tool this chat can reach: managed integrations (Attio, Slack, Gmail, Google Sheets, \u2026) plus custom MCP servers. Start here when the user mentions an external tool.",
27824
27490
  args: {}
27825
27491
  });
27826
- var connectedCommand = defineCommand137({
27492
+ var connectedCommand = defineCommand135({
27827
27493
  meta: {
27828
27494
  name: "connected",
27829
27495
  description: `List all connected third-party tools \u2014 managed integrations plus custom MCP servers.
@@ -27861,7 +27527,7 @@ A tool the user names that is NOT listed here is simply not connected yet.`
27861
27527
  hints
27862
27528
  });
27863
27529
  } catch (err) {
27864
- fail6(err);
27530
+ fail5(err);
27865
27531
  }
27866
27532
  }
27867
27533
  });
@@ -27870,7 +27536,7 @@ registerSchema({
27870
27536
  description: "List the custom MCP servers this company's chats see (org + company + your own user scope).",
27871
27537
  args: {}
27872
27538
  });
27873
- var listCommand8 = defineCommand137({
27539
+ var listCommand8 = defineCommand135({
27874
27540
  meta: { name: "list", description: "List custom MCP servers visible to this company's chats." },
27875
27541
  run: async () => {
27876
27542
  try {
@@ -27881,7 +27547,7 @@ var listCommand8 = defineCommand137({
27881
27547
  );
27882
27548
  writeJson({ ok: true, data: data.servers });
27883
27549
  } catch (err) {
27884
- fail6(err);
27550
+ fail5(err);
27885
27551
  }
27886
27552
  }
27887
27553
  });
@@ -27895,7 +27561,7 @@ registerSchema({
27895
27561
  header: { type: "string", description: 'Auth header "Key: Value" (repeatable)', required: false }
27896
27562
  }
27897
27563
  });
27898
- var addCommand = defineCommand137({
27564
+ var addCommand = defineCommand135({
27899
27565
  meta: {
27900
27566
  name: "add",
27901
27567
  description: `Register a custom MCP server. Tools appear as mcp__<name>__* on the NEXT message.
@@ -27927,7 +27593,7 @@ Examples:
27927
27593
  });
27928
27594
  writeJson({ ok: true, data });
27929
27595
  } catch (err) {
27930
- fail6(err);
27596
+ fail5(err);
27931
27597
  }
27932
27598
  }
27933
27599
  });
@@ -27936,7 +27602,7 @@ registerSchema({
27936
27602
  description: "Remove a company custom MCP server by name.",
27937
27603
  args: { name: { type: "string", description: "Server name to remove", required: true } }
27938
27604
  });
27939
- var removeCommand4 = defineCommand137({
27605
+ var removeCommand4 = defineCommand135({
27940
27606
  meta: {
27941
27607
  name: "remove",
27942
27608
  description: `Remove a company custom MCP server by name.
@@ -27954,11 +27620,11 @@ Example:
27954
27620
  });
27955
27621
  writeJson({ ok: true, data });
27956
27622
  } catch (err) {
27957
- fail6(err);
27623
+ fail5(err);
27958
27624
  }
27959
27625
  }
27960
27626
  });
27961
- var mcpCommand = defineCommand137({
27627
+ var mcpCommand = defineCommand135({
27962
27628
  meta: {
27963
27629
  name: "mcp",
27964
27630
  description: `Third-party tools for this company \u2014 see what's connected, register custom HTTPS MCP endpoints.
@@ -27984,10 +27650,10 @@ Full guide: __tooling__/docs/tools/baker/mcp.md`
27984
27650
  });
27985
27651
 
27986
27652
  // src/commands/research/index.ts
27987
- import { defineCommand as defineCommand148 } from "citty";
27653
+ import { defineCommand as defineCommand146 } from "citty";
27988
27654
 
27989
27655
  // src/commands/research/advertisers.ts
27990
- import { defineCommand as defineCommand138 } from "citty";
27656
+ import { defineCommand as defineCommand136 } from "citty";
27991
27657
 
27992
27658
  // src/commands/research/output.ts
27993
27659
  var RESEARCH_DATA_NOTE = "Estimates based on third-party SERP data \u2014 not exact figures. Use for directional insights, not precise measurement.";
@@ -28100,7 +27766,7 @@ var FIELDS3 = {
28100
27766
  etv: "Estimated traffic value (USD)",
28101
27767
  visibility: "SERP visibility score (0-1)"
28102
27768
  };
28103
- var advertisersCommand = defineCommand138({
27769
+ var advertisersCommand = defineCommand136({
28104
27770
  meta: {
28105
27771
  name: "advertisers",
28106
27772
  description: `Find domains competing for a keyword in Google SERPs.
@@ -28147,7 +27813,7 @@ Examples:
28147
27813
  });
28148
27814
 
28149
27815
  // src/commands/research/autocomplete.ts
28150
- import { defineCommand as defineCommand139 } from "citty";
27816
+ import { defineCommand as defineCommand137 } from "citty";
28151
27817
  registerSchema({
28152
27818
  command: "research.autocomplete",
28153
27819
  description: "Get Google Autocomplete suggestions for a seed keyword. Useful for keyword expansion and discovering what people actually search for. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en).",
@@ -28170,7 +27836,7 @@ registerSchema({
28170
27836
  var FIELDS4 = {
28171
27837
  suggestion: "Autocomplete suggestion from Google"
28172
27838
  };
28173
- var autocompleteCommand = defineCommand139({
27839
+ var autocompleteCommand = defineCommand137({
28174
27840
  meta: {
28175
27841
  name: "autocomplete",
28176
27842
  description: `Get Google Autocomplete suggestions for keyword expansion.
@@ -28216,7 +27882,7 @@ Examples:
28216
27882
  });
28217
27883
 
28218
27884
  // src/commands/research/countries.ts
28219
- import { defineCommand as defineCommand140 } from "citty";
27885
+ import { defineCommand as defineCommand138 } from "citty";
28220
27886
  registerSchema({
28221
27887
  command: "research.countries",
28222
27888
  description: "List all supported country codes for --location flag in research commands.",
@@ -28273,7 +27939,7 @@ var FIELDS5 = {
28273
27939
  code: "Country code to pass as --location",
28274
27940
  name: "Country name"
28275
27941
  };
28276
- var countriesCommand = defineCommand140({
27942
+ var countriesCommand = defineCommand138({
28277
27943
  meta: {
28278
27944
  name: "countries",
28279
27945
  description: "List all supported country codes for --location flag."
@@ -28284,7 +27950,7 @@ var countriesCommand = defineCommand140({
28284
27950
  });
28285
27951
 
28286
27952
  // src/commands/research/intent.ts
28287
- import { defineCommand as defineCommand141 } from "citty";
27953
+ import { defineCommand as defineCommand139 } from "citty";
28288
27954
  registerSchema({
28289
27955
  command: "research.intent",
28290
27956
  description: "Classify Google Search intent for keywords. Determines if someone searching is looking to buy, research, or navigate. IMPORTANT: If --language is omitted, defaults to English (en). The response includes a query_context object showing which language was used.",
@@ -28307,7 +27973,7 @@ var FIELDS6 = {
28307
27973
  intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
28308
27974
  probability: "Confidence score 0.0-1.0"
28309
27975
  };
28310
- var intentCommand = defineCommand141({
27976
+ var intentCommand = defineCommand139({
28311
27977
  meta: {
28312
27978
  name: "intent",
28313
27979
  description: `Classify Google Search intent for keywords. Returns intent type and confidence.
@@ -28355,7 +28021,7 @@ Examples:
28355
28021
  });
28356
28022
 
28357
28023
  // src/commands/research/keyword-gap.ts
28358
- import { defineCommand as defineCommand142 } from "citty";
28024
+ import { defineCommand as defineCommand140 } from "citty";
28359
28025
  registerSchema({
28360
28026
  command: "research.keyword-gap",
28361
28027
  description: "Find keywords a competitor ranks for (organic or paid) that you don't. Discovers expansion opportunities. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
@@ -28384,7 +28050,7 @@ var FIELDS7 = {
28384
28050
  cpc: "Cost per click USD",
28385
28051
  their_position: "Competitor's ranking position"
28386
28052
  };
28387
- var keywordGapCommand = defineCommand142({
28053
+ var keywordGapCommand = defineCommand140({
28388
28054
  meta: {
28389
28055
  name: "keyword-gap",
28390
28056
  description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
@@ -28458,7 +28124,7 @@ Examples:
28458
28124
  });
28459
28125
 
28460
28126
  // src/commands/research/keywords-for-site.ts
28461
- import { defineCommand as defineCommand143 } from "citty";
28127
+ import { defineCommand as defineCommand141 } from "citty";
28462
28128
  registerSchema({
28463
28129
  command: "research.keywords-for-site",
28464
28130
  description: "Get keywords a competitor targets in Google. Use --type paid to see only paid keywords, --type organic for organic only. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
@@ -28491,7 +28157,7 @@ var FIELDS8 = {
28491
28157
  competition: "LOW, MEDIUM, or HIGH",
28492
28158
  competition_index: "Competition score 0-100"
28493
28159
  };
28494
- var keywordsForSiteCommand = defineCommand143({
28160
+ var keywordsForSiteCommand = defineCommand141({
28495
28161
  meta: {
28496
28162
  name: "keywords-for-site",
28497
28163
  description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
@@ -28544,7 +28210,7 @@ Examples:
28544
28210
  });
28545
28211
 
28546
28212
  // src/commands/research/languages.ts
28547
- import { defineCommand as defineCommand144 } from "citty";
28213
+ import { defineCommand as defineCommand142 } from "citty";
28548
28214
  registerSchema({
28549
28215
  command: "research.languages",
28550
28216
  description: "List all supported language codes for --language flag in research commands.",
@@ -28574,7 +28240,7 @@ var FIELDS9 = {
28574
28240
  code: "Language code to pass as --language",
28575
28241
  name: "Language name (also accepted by --language)"
28576
28242
  };
28577
- var languagesCommand2 = defineCommand144({
28243
+ var languagesCommand2 = defineCommand142({
28578
28244
  meta: {
28579
28245
  name: "languages",
28580
28246
  description: "List all supported language codes for --language flag."
@@ -28585,7 +28251,7 @@ var languagesCommand2 = defineCommand144({
28585
28251
  });
28586
28252
 
28587
28253
  // src/commands/research/lighthouse.ts
28588
- import { defineCommand as defineCommand145 } from "citty";
28254
+ import { defineCommand as defineCommand143 } from "citty";
28589
28255
  registerSchema({
28590
28256
  command: "research.lighthouse",
28591
28257
  description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
@@ -28604,7 +28270,7 @@ var FIELDS10 = {
28604
28270
  speed_index_ms: "Speed Index in ms (good: < 3400)",
28605
28271
  interactive_ms: "Time to Interactive in ms (good: < 3800)"
28606
28272
  };
28607
- var lighthouseCommand = defineCommand145({
28273
+ var lighthouseCommand = defineCommand143({
28608
28274
  meta: {
28609
28275
  name: "lighthouse",
28610
28276
  description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
@@ -28642,7 +28308,7 @@ Examples:
28642
28308
  });
28643
28309
 
28644
28310
  // src/commands/research/relevant-pages.ts
28645
- import { defineCommand as defineCommand146 } from "citty";
28311
+ import { defineCommand as defineCommand144 } from "citty";
28646
28312
  registerSchema({
28647
28313
  command: "research.relevant-pages",
28648
28314
  description: "Get the top pages of a competitor domain with organic traffic and ranking data. Shows which pages drive the most traffic. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en).",
@@ -28668,7 +28334,7 @@ var FIELDS11 = {
28668
28334
  keywords: "Total organic keywords the page ranks for",
28669
28335
  top_10: "Keywords in positions 1-10"
28670
28336
  };
28671
- var relevantPagesCommand = defineCommand146({
28337
+ var relevantPagesCommand = defineCommand144({
28672
28338
  meta: {
28673
28339
  name: "relevant-pages",
28674
28340
  description: `Get the top pages of a competitor domain with traffic data.
@@ -28714,7 +28380,7 @@ Examples:
28714
28380
  });
28715
28381
 
28716
28382
  // src/commands/research/web.ts
28717
- import { defineCommand as defineCommand147 } from "citty";
28383
+ import { defineCommand as defineCommand145 } from "citty";
28718
28384
  registerSchema({
28719
28385
  command: "research.web",
28720
28386
  description: "Search the web with AI to answer marketing questions \u2014 competitors, ICP, pricing, pain points, market trends. Three depth levels: medium (quick, default), high (thorough), xhigh (exhaustive deep research).",
@@ -28765,7 +28431,7 @@ async function runDeepResearch(question) {
28765
28431
  }
28766
28432
  throw new Error("Deep research timed out");
28767
28433
  }
28768
- var webCommand = defineCommand147({
28434
+ var webCommand = defineCommand145({
28769
28435
  meta: {
28770
28436
  name: "web",
28771
28437
  description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
@@ -28825,7 +28491,7 @@ Examples:
28825
28491
  });
28826
28492
 
28827
28493
  // src/commands/research/index.ts
28828
- var researchCommand = defineCommand148({
28494
+ var researchCommand = defineCommand146({
28829
28495
  meta: {
28830
28496
  name: "research",
28831
28497
  description: `Competitive intelligence and AI-powered research commands.
@@ -28866,10 +28532,10 @@ Full guide: __tooling__/docs/tools/baker/research.md`
28866
28532
  });
28867
28533
 
28868
28534
  // src/commands/scheduled-actions/index.ts
28869
- import { defineCommand as defineCommand155 } from "citty";
28535
+ import { defineCommand as defineCommand153 } from "citty";
28870
28536
 
28871
28537
  // src/commands/scheduled-actions/create.ts
28872
- import { defineCommand as defineCommand149 } from "citty";
28538
+ import { defineCommand as defineCommand147 } from "citty";
28873
28539
 
28874
28540
  // src/commands/scheduled-actions/shared.ts
28875
28541
  var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
@@ -28984,7 +28650,7 @@ registerSchema({
28984
28650
  prompt: { type: "string", description: "Additional prompt instructions for the spawned agent", required: false }
28985
28651
  }
28986
28652
  });
28987
- var createCommand2 = defineCommand149({
28653
+ var createCommand2 = defineCommand147({
28988
28654
  meta: {
28989
28655
  name: "create",
28990
28656
  description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
@@ -29033,7 +28699,7 @@ var createCommand2 = defineCommand149({
29033
28699
  });
29034
28700
 
29035
28701
  // src/commands/scheduled-actions/delete.ts
29036
- import { defineCommand as defineCommand150 } from "citty";
28702
+ import { defineCommand as defineCommand148 } from "citty";
29037
28703
  registerSchema({
29038
28704
  command: "scheduled-actions.delete",
29039
28705
  description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
@@ -29041,7 +28707,7 @@ registerSchema({
29041
28707
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
29042
28708
  }
29043
28709
  });
29044
- var deleteCommand2 = defineCommand150({
28710
+ var deleteCommand2 = defineCommand148({
29045
28711
  meta: {
29046
28712
  name: "delete",
29047
28713
  description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
@@ -29070,7 +28736,7 @@ var deleteCommand2 = defineCommand150({
29070
28736
  });
29071
28737
 
29072
28738
  // src/commands/scheduled-actions/get.ts
29073
- import { defineCommand as defineCommand151 } from "citty";
28739
+ import { defineCommand as defineCommand149 } from "citty";
29074
28740
  registerSchema({
29075
28741
  command: "scheduled-actions.get",
29076
28742
  description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
@@ -29078,7 +28744,7 @@ registerSchema({
29078
28744
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
29079
28745
  }
29080
28746
  });
29081
- var getCommand3 = defineCommand151({
28747
+ var getCommand3 = defineCommand149({
29082
28748
  meta: {
29083
28749
  name: "get",
29084
28750
  description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
@@ -29115,13 +28781,13 @@ var getCommand3 = defineCommand151({
29115
28781
  });
29116
28782
 
29117
28783
  // src/commands/scheduled-actions/list.ts
29118
- import { defineCommand as defineCommand152 } from "citty";
28784
+ import { defineCommand as defineCommand150 } from "citty";
29119
28785
  registerSchema({
29120
28786
  command: "scheduled-actions.list",
29121
28787
  description: "List published scheduled actions. Includes draft state when BAKER_CHAT_ID is set.",
29122
28788
  args: {}
29123
28789
  });
29124
- var listCommand9 = defineCommand152({
28790
+ var listCommand9 = defineCommand150({
29125
28791
  meta: {
29126
28792
  name: "list",
29127
28793
  description: "List scheduled actions. Includes staged draft ops when BAKER_CHAT_ID is set."
@@ -29142,7 +28808,7 @@ var listCommand9 = defineCommand152({
29142
28808
  });
29143
28809
 
29144
28810
  // src/commands/scheduled-actions/trigger.ts
29145
- import { defineCommand as defineCommand153 } from "citty";
28811
+ import { defineCommand as defineCommand151 } from "citty";
29146
28812
  registerSchema({
29147
28813
  command: "scheduled-actions.trigger",
29148
28814
  description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
@@ -29150,7 +28816,7 @@ registerSchema({
29150
28816
  id: { type: "string", description: "Published scheduled action ID", required: true }
29151
28817
  }
29152
28818
  });
29153
- var triggerCommand = defineCommand153({
28819
+ var triggerCommand = defineCommand151({
29154
28820
  meta: {
29155
28821
  name: "trigger",
29156
28822
  description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
@@ -29187,7 +28853,7 @@ var triggerCommand = defineCommand153({
29187
28853
  });
29188
28854
 
29189
28855
  // src/commands/scheduled-actions/update.ts
29190
- import { defineCommand as defineCommand154 } from "citty";
28856
+ import { defineCommand as defineCommand152 } from "citty";
29191
28857
  registerSchema({
29192
28858
  command: "scheduled-actions.update",
29193
28859
  description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
@@ -29212,7 +28878,7 @@ registerSchema({
29212
28878
  prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
29213
28879
  }
29214
28880
  });
29215
- var updateCommand2 = defineCommand154({
28881
+ var updateCommand2 = defineCommand152({
29216
28882
  meta: {
29217
28883
  name: "update",
29218
28884
  description: "Stage a scheduled action update. Example: baker scheduled-actions update <id> --enabled false"
@@ -29283,7 +28949,7 @@ var updateCommand2 = defineCommand154({
29283
28949
  });
29284
28950
 
29285
28951
  // src/commands/scheduled-actions/index.ts
29286
- var scheduledActionsCommand = defineCommand155({
28952
+ var scheduledActionsCommand = defineCommand153({
29287
28953
  meta: {
29288
28954
  name: "scheduled-actions",
29289
28955
  description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger.
@@ -29310,8 +28976,8 @@ Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
29310
28976
  });
29311
28977
 
29312
28978
  // src/commands/schema.ts
29313
- import { defineCommand as defineCommand156 } from "citty";
29314
- var schemaCommand = defineCommand156({
28979
+ import { defineCommand as defineCommand154 } from "citty";
28980
+ var schemaCommand = defineCommand154({
29315
28981
  meta: {
29316
28982
  name: "schema",
29317
28983
  description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
@@ -29353,7 +29019,7 @@ var schemaCommand = defineCommand156({
29353
29019
  });
29354
29020
 
29355
29021
  // src/commands/tags/index.ts
29356
- import { defineCommand as defineCommand157 } from "citty";
29022
+ import { defineCommand as defineCommand155 } from "citty";
29357
29023
 
29358
29024
  // src/commands/tags/shared.ts
29359
29025
  function failApi3(err) {
@@ -29419,7 +29085,7 @@ async function listTags(json) {
29419
29085
  failApi3(err);
29420
29086
  }
29421
29087
  }
29422
- var listCommand10 = defineCommand157({
29088
+ var listCommand10 = defineCommand155({
29423
29089
  meta: {
29424
29090
  name: "list",
29425
29091
  description: "Effective tags for this chat (production + staged), with each tag's full readable config (secrets excluded) \u2014 reuse a stored value to pre-fill a change rather than asking the user. Refs printed here are what flow side-effect tagIds should use. Example: baker tags list"
@@ -29438,7 +29104,7 @@ async function listDraft3() {
29438
29104
  failApi3(err);
29439
29105
  }
29440
29106
  }
29441
- var draftCommand3 = defineCommand157({
29107
+ var draftCommand3 = defineCommand155({
29442
29108
  meta: {
29443
29109
  name: "draft",
29444
29110
  description: "Review the tag changes staged in this chat (read-only). Staged changes were approved via request_tag_input and apply when the chat is published; to amend or drop one, propose a follow-up change through the same tool (a delete on a tag_temp_* ref drops the staged create)."
@@ -29447,7 +29113,7 @@ var draftCommand3 = defineCommand157({
29447
29113
  await listDraft3();
29448
29114
  }
29449
29115
  });
29450
- var tagsCommand3 = defineCommand157({
29116
+ var tagsCommand3 = defineCommand155({
29451
29117
  meta: {
29452
29118
  name: "tags",
29453
29119
  description: `Read the client's marketing/analytics tags (Meta pixel, GA4, Google Ads, GTM, Clarity, Hotjar, \u2026) \u2014 production tags plus the changes staged in this chat.
@@ -29473,10 +29139,10 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
29473
29139
  });
29474
29140
 
29475
29141
  // src/commands/testimonials/index.ts
29476
- import { defineCommand as defineCommand161 } from "citty";
29142
+ import { defineCommand as defineCommand159 } from "citty";
29477
29143
 
29478
29144
  // src/commands/testimonials/get.ts
29479
- import { defineCommand as defineCommand158 } from "citty";
29145
+ import { defineCommand as defineCommand156 } from "citty";
29480
29146
  registerSchema({
29481
29147
  command: "testimonials.get",
29482
29148
  description: "Get a single testimonial by ID",
@@ -29484,7 +29150,7 @@ registerSchema({
29484
29150
  id: { type: "string", description: "Testimonial ID", required: true }
29485
29151
  }
29486
29152
  });
29487
- var getCommand4 = defineCommand158({
29153
+ var getCommand4 = defineCommand156({
29488
29154
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
29489
29155
  args: {
29490
29156
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -29521,7 +29187,7 @@ var getCommand4 = defineCommand158({
29521
29187
  });
29522
29188
 
29523
29189
  // src/commands/testimonials/list.ts
29524
- import { defineCommand as defineCommand159 } from "citty";
29190
+ import { defineCommand as defineCommand157 } from "citty";
29525
29191
  registerSchema({
29526
29192
  command: "testimonials.list",
29527
29193
  description: "List testimonials with optional filters.",
@@ -29551,7 +29217,7 @@ registerSchema({
29551
29217
  limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
29552
29218
  }
29553
29219
  });
29554
- var listCommand11 = defineCommand159({
29220
+ var listCommand11 = defineCommand157({
29555
29221
  meta: {
29556
29222
  name: "list",
29557
29223
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -29600,7 +29266,7 @@ var listCommand11 = defineCommand159({
29600
29266
  });
29601
29267
 
29602
29268
  // src/commands/testimonials/search.ts
29603
- import { defineCommand as defineCommand160 } from "citty";
29269
+ import { defineCommand as defineCommand158 } from "citty";
29604
29270
  function languageBiasHint(results, requestedLanguage) {
29605
29271
  if (requestedLanguage) {
29606
29272
  return null;
@@ -29678,7 +29344,7 @@ function buildSearchRequest(query, args) {
29678
29344
  }
29679
29345
  return body;
29680
29346
  }
29681
- var searchCommand2 = defineCommand160({
29347
+ var searchCommand2 = defineCommand158({
29682
29348
  meta: {
29683
29349
  name: "search",
29684
29350
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -29734,7 +29400,7 @@ var searchCommand2 = defineCommand160({
29734
29400
  var tagsCommand4 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
29735
29401
 
29736
29402
  // src/commands/testimonials/index.ts
29737
- var testimonialsCommand = defineCommand161({
29403
+ var testimonialsCommand = defineCommand159({
29738
29404
  meta: {
29739
29405
  name: "testimonials",
29740
29406
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -29756,10 +29422,10 @@ Full guide: __tooling__/docs/tools/baker/testimonials.md`
29756
29422
  });
29757
29423
 
29758
29424
  // src/commands/videos/index.ts
29759
- import { defineCommand as defineCommand166 } from "citty";
29425
+ import { defineCommand as defineCommand164 } from "citty";
29760
29426
 
29761
29427
  // src/commands/videos/delete.ts
29762
- import { defineCommand as defineCommand162 } from "citty";
29428
+ import { defineCommand as defineCommand160 } from "citty";
29763
29429
  registerSchema({
29764
29430
  command: "videos.delete",
29765
29431
  description: "Delete a video by ID",
@@ -29773,7 +29439,7 @@ registerSchema({
29773
29439
  }
29774
29440
  }
29775
29441
  });
29776
- var deleteCommand3 = defineCommand162({
29442
+ var deleteCommand3 = defineCommand160({
29777
29443
  meta: {
29778
29444
  name: "delete",
29779
29445
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -29814,7 +29480,7 @@ var deleteCommand3 = defineCommand162({
29814
29480
  });
29815
29481
 
29816
29482
  // src/commands/videos/get.ts
29817
- import { defineCommand as defineCommand163 } from "citty";
29483
+ import { defineCommand as defineCommand161 } from "citty";
29818
29484
  registerSchema({
29819
29485
  command: "videos.get",
29820
29486
  description: "Get a single video by ID",
@@ -29822,7 +29488,7 @@ registerSchema({
29822
29488
  id: { type: "string", description: "Video ID", required: true }
29823
29489
  }
29824
29490
  });
29825
- var getCommand5 = defineCommand163({
29491
+ var getCommand5 = defineCommand161({
29826
29492
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
29827
29493
  args: {
29828
29494
  id: { type: "positional", description: "Video ID", required: false },
@@ -29859,7 +29525,7 @@ var getCommand5 = defineCommand163({
29859
29525
  });
29860
29526
 
29861
29527
  // src/commands/videos/search.ts
29862
- import { defineCommand as defineCommand164 } from "citty";
29528
+ import { defineCommand as defineCommand162 } from "citty";
29863
29529
  registerSchema({
29864
29530
  command: "videos.search",
29865
29531
  description: "Search videos by text query. Only returns ready videos.",
@@ -29869,7 +29535,7 @@ registerSchema({
29869
29535
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
29870
29536
  }
29871
29537
  });
29872
- var searchCommand3 = defineCommand164({
29538
+ var searchCommand3 = defineCommand162({
29873
29539
  meta: {
29874
29540
  name: "search",
29875
29541
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -29919,9 +29585,9 @@ var searchCommand3 = defineCommand164({
29919
29585
  var tagsCommand5 = makeTagsCommand("videos", "video", "/api/videos/tags");
29920
29586
 
29921
29587
  // src/commands/videos/upload.ts
29922
- import { readFile as readFile23, stat as stat7 } from "fs/promises";
29588
+ import { readFile as readFile22, stat as stat7 } from "fs/promises";
29923
29589
  import { extname as extname3 } from "path";
29924
- import { defineCommand as defineCommand165 } from "citty";
29590
+ import { defineCommand as defineCommand163 } from "citty";
29925
29591
  var MIME_MAP = {
29926
29592
  ".mp4": "video/mp4",
29927
29593
  ".mov": "video/quicktime",
@@ -29955,7 +29621,7 @@ function detectContentType(filePath) {
29955
29621
  }
29956
29622
  return mime;
29957
29623
  }
29958
- var uploadCommand2 = defineCommand165({
29624
+ var uploadCommand2 = defineCommand163({
29959
29625
  meta: {
29960
29626
  name: "upload",
29961
29627
  description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
@@ -29984,7 +29650,7 @@ var uploadCommand2 = defineCommand165({
29984
29650
  return;
29985
29651
  }
29986
29652
  const { uploadUrl, videoId } = await apiPost("/api/videos/upload", {});
29987
- const fileBuffer = await readFile23(filePath);
29653
+ const fileBuffer = await readFile22(filePath);
29988
29654
  const uploadResponse = await fetch(uploadUrl, {
29989
29655
  method: "PUT",
29990
29656
  headers: { "Content-Type": contentType },
@@ -30009,7 +29675,7 @@ var uploadCommand2 = defineCommand165({
30009
29675
  });
30010
29676
 
30011
29677
  // src/commands/videos/index.ts
30012
- var videosCommand = defineCommand166({
29678
+ var videosCommand = defineCommand164({
30013
29679
  meta: {
30014
29680
  name: "videos",
30015
29681
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
@@ -30033,10 +29699,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
30033
29699
  });
30034
29700
 
30035
29701
  // src/commands/winning-ads/index.ts
30036
- import { defineCommand as defineCommand179 } from "citty";
29702
+ import { defineCommand as defineCommand177 } from "citty";
30037
29703
 
30038
29704
  // src/commands/winning-ads/advertisers.ts
30039
- import { defineCommand as defineCommand167 } from "citty";
29705
+ import { defineCommand as defineCommand165 } from "citty";
30040
29706
 
30041
29707
  // src/commands/winning-ads/shared.ts
30042
29708
  function splitList(value) {
@@ -30089,7 +29755,7 @@ function advertiserNormalizer(record, full) {
30089
29755
  last_synced_at: record.last_synced_at ?? null
30090
29756
  };
30091
29757
  }
30092
- var advertisersCommand2 = defineCommand167({
29758
+ var advertisersCommand2 = defineCommand165({
30093
29759
  meta: {
30094
29760
  name: "advertisers",
30095
29761
  description: 'List corpus advertisers by name or domain. Find your own advertiser for --exclude-advertiser, or a competitor for --advertiser-id / winners. Example: baker winning-ads advertisers "Deel" --output md'
@@ -30147,7 +29813,7 @@ var advertisersCommand2 = defineCommand167({
30147
29813
  });
30148
29814
 
30149
29815
  // src/commands/winning-ads/brief.ts
30150
- import { defineCommand as defineCommand168 } from "citty";
29816
+ import { defineCommand as defineCommand166 } from "citty";
30151
29817
  registerSchema({
30152
29818
  command: "winning-ads.brief",
30153
29819
  description: "Generate a creative brief grounded in strategically-similar winning ads. Optionally describe the target creative with --dna (JSON) and steer with --notes.",
@@ -30193,7 +29859,7 @@ function parseDna(raw) {
30193
29859
  }
30194
29860
  return parsed;
30195
29861
  }
30196
- var briefCommand = defineCommand168({
29862
+ var briefCommand = defineCommand166({
30197
29863
  meta: {
30198
29864
  name: "brief",
30199
29865
  description: `Generate a creative brief from winning references. Example: baker winning-ads brief --dna '{"angle":"cost savings"}' --notes "B2B, LinkedIn video" --k 8`
@@ -30229,7 +29895,7 @@ var briefCommand = defineCommand168({
30229
29895
  });
30230
29896
 
30231
29897
  // src/commands/winning-ads/content.ts
30232
- import { defineCommand as defineCommand169 } from "citty";
29898
+ import { defineCommand as defineCommand167 } from "citty";
30233
29899
  registerSchema({
30234
29900
  command: "winning-ads.content",
30235
29901
  description: "Read what's INSIDE one winning ad: the spoken transcript, the on-screen text, and the ad copy. Use this after `search`/`winners`/`feed` return a shortlist \u2014 pass an ad_id to understand a reference before reproducing it. Add --full for speech, pacing, and soundtrack detail. Video ads carry the transcript/on-screen text; static ads carry only the copy.",
@@ -30242,7 +29908,7 @@ registerSchema({
30242
29908
  }
30243
29909
  }
30244
29910
  });
30245
- var contentCommand = defineCommand169({
29911
+ var contentCommand = defineCommand167({
30246
29912
  meta: {
30247
29913
  name: "content",
30248
29914
  description: "Read the transcript + on-screen text + copy of one winning ad. Example: baker winning-ads content adg_123 --platform meta --full --output md"
@@ -30291,7 +29957,7 @@ var contentCommand = defineCommand169({
30291
29957
  });
30292
29958
 
30293
29959
  // src/commands/winning-ads/feed.ts
30294
- import { defineCommand as defineCommand170 } from "citty";
29960
+ import { defineCommand as defineCommand168 } from "citty";
30295
29961
  function buildFeedParams(input) {
30296
29962
  const params = {};
30297
29963
  const advertiser = splitList(input.advertiser);
@@ -30343,7 +30009,7 @@ registerSchema({
30343
30009
  format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
30344
30010
  }
30345
30011
  });
30346
- var feedCommand = defineCommand170({
30012
+ var feedCommand = defineCommand168({
30347
30013
  meta: {
30348
30014
  name: "feed",
30349
30015
  description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
@@ -30428,7 +30094,7 @@ var feedCommand = defineCommand170({
30428
30094
  });
30429
30095
 
30430
30096
  // src/commands/winning-ads/follow.ts
30431
- import { defineCommand as defineCommand171 } from "citty";
30097
+ import { defineCommand as defineCommand169 } from "citty";
30432
30098
  var PLATFORMS = ["meta", "linkedin"];
30433
30099
  registerSchema({
30434
30100
  command: "winning-ads.follow",
@@ -30443,7 +30109,7 @@ registerSchema({
30443
30109
  label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
30444
30110
  }
30445
30111
  });
30446
- var followCommand = defineCommand171({
30112
+ var followCommand = defineCommand169({
30447
30113
  meta: {
30448
30114
  name: "follow",
30449
30115
  description: 'Follow a brand to track ALL its ads \u2014 every platform and country. --platform is how we read your input, not a limit. A domain tracks both Meta + LinkedIn. Example: baker winning-ads follow "deel.com" --platform meta'
@@ -30490,7 +30156,7 @@ var followCommand = defineCommand171({
30490
30156
  });
30491
30157
 
30492
30158
  // src/commands/winning-ads/follow-competitors.ts
30493
- import { defineCommand as defineCommand172 } from "citty";
30159
+ import { defineCommand as defineCommand170 } from "citty";
30494
30160
  var PLATFORMS2 = ["meta", "linkedin"];
30495
30161
  var BATCH_TIMEOUT_MS = 3e5;
30496
30162
  function buildFollowBatchBody(input) {
@@ -30523,7 +30189,7 @@ registerSchema({
30523
30189
  }
30524
30190
  }
30525
30191
  });
30526
- var followCompetitorsCommand = defineCommand172({
30192
+ var followCompetitorsCommand = defineCommand170({
30527
30193
  meta: {
30528
30194
  name: "follow-competitors",
30529
30195
  description: 'Follow many brands at once by domain \u2014 add every competitor in one call. Example: baker winning-ads follow-competitors "deel.com,notion.so,hubspot.com"'
@@ -30598,7 +30264,7 @@ var followCompetitorsCommand = defineCommand172({
30598
30264
  });
30599
30265
 
30600
30266
  // src/commands/winning-ads/following.ts
30601
- import { defineCommand as defineCommand173 } from "citty";
30267
+ import { defineCommand as defineCommand171 } from "citty";
30602
30268
  registerSchema({
30603
30269
  command: "winning-ads.following",
30604
30270
  description: "List the brands you follow in your ad-dna library, with each one's status (ready vs still adding) and cached ad counts.",
@@ -30631,7 +30297,7 @@ function followingNormalizer(record, full) {
30631
30297
  platforms: Array.isArray(record.platforms) ? record.platforms : []
30632
30298
  };
30633
30299
  }
30634
- var followingCommand = defineCommand173({
30300
+ var followingCommand = defineCommand171({
30635
30301
  meta: {
30636
30302
  name: "following",
30637
30303
  description: "List brands you follow, with status (ready / adding\u2026) and cached counts. Example: baker winning-ads following --output md"
@@ -30666,7 +30332,7 @@ var followingCommand = defineCommand173({
30666
30332
  });
30667
30333
 
30668
30334
  // src/commands/winning-ads/patterns.ts
30669
- import { defineCommand as defineCommand174 } from "citty";
30335
+ import { defineCommand as defineCommand172 } from "citty";
30670
30336
  registerSchema({
30671
30337
  command: "winning-ads.patterns",
30672
30338
  description: "Mine what separates two cohorts of ads: pass a comma-list of winning ad ids (--winners) and a comma-list of weaker ad ids (--duds). Returns the discriminating DNA fields.",
@@ -30705,7 +30371,7 @@ function discriminatorRow(record) {
30705
30371
  top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
30706
30372
  };
30707
30373
  }
30708
- var patternsCommand = defineCommand174({
30374
+ var patternsCommand = defineCommand172({
30709
30375
  meta: {
30710
30376
  name: "patterns",
30711
30377
  description: "Discover what separates winning ads from weak ones. Example: baker winning-ads patterns --winners a_1,a_2,a_3 --duds a_9,a_8 --output md"
@@ -30761,7 +30427,7 @@ var patternsCommand = defineCommand174({
30761
30427
  });
30762
30428
 
30763
30429
  // src/commands/winning-ads/search.ts
30764
- import { defineCommand as defineCommand175 } from "citty";
30430
+ import { defineCommand as defineCommand173 } from "citty";
30765
30431
  registerSchema({
30766
30432
  command: "winning-ads.search",
30767
30433
  description: "Search the ad-dna corpus of scored winning ads. Returns a lean shortlist (advertiser, summary, scores, media_url) to pick a reference to reproduce.",
@@ -30869,7 +30535,7 @@ function buildSearchBody(args) {
30869
30535
  }
30870
30536
  return body;
30871
30537
  }
30872
- var searchCommand4 = defineCommand175({
30538
+ var searchCommand4 = defineCommand173({
30873
30539
  meta: {
30874
30540
  name: "search",
30875
30541
  description: "Search winning reference ads. Example: baker winning-ads search 'B2B SaaS before/after AI automation' --platform meta --format static --winner-category winner --exclude-advertiser adv_123 --output md"
@@ -30984,7 +30650,7 @@ var searchCommand4 = defineCommand175({
30984
30650
  });
30985
30651
 
30986
30652
  // src/commands/winning-ads/seeds.ts
30987
- import { defineCommand as defineCommand176 } from "citty";
30653
+ import { defineCommand as defineCommand174 } from "citty";
30988
30654
  function leanRow(r) {
30989
30655
  return {
30990
30656
  key: r.key,
@@ -31012,7 +30678,7 @@ function makeSeedCommand(opts) {
31012
30678
  limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
31013
30679
  }
31014
30680
  });
31015
- return defineCommand176({
30681
+ return defineCommand174({
31016
30682
  meta: { name: opts.name, description: opts.description },
31017
30683
  args: {
31018
30684
  platform: { type: "string", description: "Single platform to segment on", required: false },
@@ -31061,7 +30727,7 @@ var formatsCommand = makeSeedCommand({
31061
30727
  });
31062
30728
 
31063
30729
  // src/commands/winning-ads/unfollow.ts
31064
- import { defineCommand as defineCommand177 } from "citty";
30730
+ import { defineCommand as defineCommand175 } from "citty";
31065
30731
  registerSchema({
31066
30732
  command: "winning-ads.unfollow",
31067
30733
  description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
@@ -31069,7 +30735,7 @@ registerSchema({
31069
30735
  advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
31070
30736
  }
31071
30737
  });
31072
- var unfollowCommand = defineCommand177({
30738
+ var unfollowCommand = defineCommand175({
31073
30739
  meta: {
31074
30740
  name: "unfollow",
31075
30741
  description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
@@ -31090,7 +30756,7 @@ var unfollowCommand = defineCommand177({
31090
30756
  });
31091
30757
 
31092
30758
  // src/commands/winning-ads/winners.ts
31093
- import { defineCommand as defineCommand178 } from "citty";
30759
+ import { defineCommand as defineCommand176 } from "citty";
31094
30760
  registerSchema({
31095
30761
  command: "winning-ads.winners",
31096
30762
  description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
@@ -31100,7 +30766,7 @@ registerSchema({
31100
30766
  platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false }
31101
30767
  }
31102
30768
  });
31103
- var winnersCommand = defineCommand178({
30769
+ var winnersCommand = defineCommand176({
31104
30770
  meta: {
31105
30771
  name: "winners",
31106
30772
  description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
@@ -31150,7 +30816,7 @@ var winnersCommand = defineCommand178({
31150
30816
  });
31151
30817
 
31152
30818
  // src/commands/winning-ads/index.ts
31153
- var winningAdsCommand = defineCommand179({
30819
+ var winningAdsCommand = defineCommand177({
31154
30820
  meta: {
31155
30821
  name: "winning-ads",
31156
30822
  description: `Search the ad-dna corpus of scored "winning" ads for reference creatives to reproduce, and manage the brands your library tracks. Proxied through the Baker backend (BAKER_API_KEY) \u2014 no separate token needed.
@@ -31222,7 +30888,7 @@ function getCliVersion() {
31222
30888
  }
31223
30889
 
31224
30890
  // src/cli.ts
31225
- var main = defineCommand180({
30891
+ var main = defineCommand178({
31226
30892
  meta: {
31227
30893
  name: "baker",
31228
30894
  version: getCliVersion(),
@@ -31238,7 +30904,6 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
31238
30904
  actions: actionsCommand,
31239
30905
  "scheduled-actions": scheduledActionsCommand,
31240
30906
  ads: adsCommand2,
31241
- brand: brandCommand,
31242
30907
  ga4: ga4Command,
31243
30908
  gsc: gscCommand,
31244
30909
  research: researchCommand,