@koda-sl/baker-cli 0.393.0 → 0.394.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -34387,16 +34387,16 @@ async function runChatgptRead(reference, read, hintsFor4) {
34387
34387
  }
34388
34388
  }
34389
34389
  var TRUNCATED_HINT = "These rows are the first 2,000, not the whole account \u2014 narrow the read (--campaign-id, --ad-group-id) before counting them or concluding something is missing.";
34390
- async function getChatgptList(path56, params) {
34391
- const { data, headers } = await apiGetWithHeaders(path56, params);
34390
+ async function getChatgptList(path57, params) {
34391
+ const { data, headers } = await apiGetWithHeaders(path57, params);
34392
34392
  return { data, truncated: headers.get(CHATGPT_ADS_TRUNCATED_HEADER) === "true" };
34393
34393
  }
34394
- async function runChatgptListRead(reference, path56, params, hintsFor4) {
34394
+ async function runChatgptListRead(reference, path57, params, hintsFor4) {
34395
34395
  let truncated = false;
34396
34396
  await runChatgptRead(
34397
34397
  reference,
34398
34398
  async () => {
34399
- const read = await getChatgptList(path56, params);
34399
+ const read = await getChatgptList(path57, params);
34400
34400
  truncated = read.truncated;
34401
34401
  return read.data;
34402
34402
  },
@@ -35201,7 +35201,7 @@ var MEMBER_ARGS = {
35201
35201
  },
35202
35202
  country: { type: "string", description: "Country of phones written without a +code, e.g. ES" }
35203
35203
  };
35204
- function membersFromArgs(args8, readFile42 = (path56) => readFileSync2(path56, "utf8")) {
35204
+ function membersFromArgs(args8, readFile42 = (path57) => readFileSync2(path57, "utf8")) {
35205
35205
  const fromFile = typeof args8.file === "string" && args8.file ? membersFromFile(readFile42(args8.file)) : { emails: [], phones: [] };
35206
35206
  const given = [...csvArg(args8.emails) ?? [], ...fromFile.emails];
35207
35207
  const givenPhones = [...csvArg(args8.phones) ?? [], ...fromFile.phones];
@@ -38576,9 +38576,9 @@ var COPY_LIST_FLAG = {
38576
38576
  descriptions: "--descriptions",
38577
38577
  longHeadlines: "--long-headlines"
38578
38578
  };
38579
- function valueAt(root, path56) {
38579
+ function valueAt(root, path57) {
38580
38580
  let node = root;
38581
- for (const key of path56) {
38581
+ for (const key of path57) {
38582
38582
  if (node === null || typeof node !== "object") return void 0;
38583
38583
  node = node[key];
38584
38584
  }
@@ -38811,11 +38811,11 @@ function parseKeywordEntry(raw, defaultMatch) {
38811
38811
  function rawTextEntries(value2, rawArgs) {
38812
38812
  return repeatedValues(rawArgs, "text", value2).flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
38813
38813
  }
38814
- function rawFileEntries(path56) {
38815
- if (typeof path56 !== "string" || path56.length === 0) {
38814
+ function rawFileEntries(path57) {
38815
+ if (typeof path57 !== "string" || path57.length === 0) {
38816
38816
  return [];
38817
38817
  }
38818
- return readFileSync4(path56, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
38818
+ return readFileSync4(path57, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
38819
38819
  }
38820
38820
  function keywordEntries(args8, rawArgs) {
38821
38821
  const defaultMatch = typeof args8["match-type"] === "string" ? args8["match-type"].toUpperCase() : void 0;
@@ -38838,14 +38838,14 @@ function keywordEntries(args8, rawArgs) {
38838
38838
  }
38839
38839
  return entries;
38840
38840
  }
38841
- function loadJsonFileArg(path56) {
38842
- if (typeof path56 !== "string" || path56.length === 0) {
38841
+ function loadJsonFileArg(path57) {
38842
+ if (typeof path57 !== "string" || path57.length === 0) {
38843
38843
  return {};
38844
38844
  }
38845
- const inline = path56.trimStart().startsWith("{");
38846
- const source = inline ? "inline JSON" : path56;
38845
+ const inline = path57.trimStart().startsWith("{");
38846
+ const source = inline ? "inline JSON" : path57;
38847
38847
  try {
38848
- const parsed = JSON.parse(inline ? path56 : readFileSync4(path56, "utf8"));
38848
+ const parsed = JSON.parse(inline ? path57 : readFileSync4(path57, "utf8"));
38849
38849
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
38850
38850
  failWriteValidation2(`${source} must contain a JSON object`);
38851
38851
  }
@@ -38982,10 +38982,10 @@ async function stageUpdate(kind, customerId, target2, payload, hints2) {
38982
38982
  async function stageTarget(kind, customerId, target2, hints2) {
38983
38983
  await stageGoogleOp({ kind, customerId, target: target2 }, hints2);
38984
38984
  }
38985
- async function draftAction(path56, body, chat) {
38985
+ async function draftAction(path57, body, chat) {
38986
38986
  try {
38987
38987
  const chatId = resolveChatId(chat);
38988
- const response = await apiPost(path56, { chatId, ...body });
38988
+ const response = await apiPost(path57, { chatId, ...body });
38989
38989
  writeJsonEnvelope(response);
38990
38990
  } catch (err) {
38991
38991
  handleGoogleError(err);
@@ -41403,14 +41403,14 @@ function mappingRowProblem(row) {
41403
41403
 
41404
41404
  // ../api/src/event-sources/template.ts
41405
41405
  var MENTION = /\{\{\s*([^{}]+?)\s*\}\}/g;
41406
- function mentionOf(path56) {
41407
- return `{{${path56}}}`;
41406
+ function mentionOf(path57) {
41407
+ return `{{${path57}}}`;
41408
41408
  }
41409
41409
  function templateMentions(template) {
41410
41410
  const seen = [];
41411
41411
  for (const match of template.matchAll(MENTION)) {
41412
- const path56 = (match[1] ?? "").trim();
41413
- if (path56 !== "" && !seen.includes(path56)) seen.push(path56);
41412
+ const path57 = (match[1] ?? "").trim();
41413
+ if (path57 !== "" && !seen.includes(path57)) seen.push(path57);
41414
41414
  }
41415
41415
  return seen;
41416
41416
  }
@@ -44765,17 +44765,17 @@ function ignoredColumnHints(columns) {
44765
44765
  `Ignored ${columns.length} column(s) that are not part of a conversion: ${columns.join(", ")}. A conversion carries an order id, a date, and something to match on: a click id (gclid / gbraid / wbraid), an email, a phone, or all four of givenName + familyName + country + postalCode. Optionally a value + currency, conversionCount, and eventSource (WEB / APP / IN_STORE / PHONE / OTHER). A column named just \`Name\` is ignored on purpose \u2014 Google needs the first and last name separately, so split it before re-running.`
44766
44766
  ];
44767
44767
  }
44768
- function readRowsFile(path56) {
44769
- const inline = path56.trimStart().startsWith("[") || path56.trimStart().startsWith("{");
44768
+ function readRowsFile(path57) {
44769
+ const inline = path57.trimStart().startsWith("[") || path57.trimStart().startsWith("{");
44770
44770
  let text2;
44771
44771
  try {
44772
- text2 = inline ? path56 : readFileSync6(path56, "utf8");
44772
+ text2 = inline ? path57 : readFileSync6(path57, "utf8");
44773
44773
  } catch (err) {
44774
- failWriteValidation2(`could not read ${path56}: ${err instanceof Error ? err.message : String(err)}`);
44774
+ failWriteValidation2(`could not read ${path57}: ${err instanceof Error ? err.message : String(err)}`);
44775
44775
  }
44776
44776
  const parsed = parseConversionRowsText(text2);
44777
44777
  if (!parsed.ok) {
44778
- failWriteValidation2(`${inline ? "the conversions passed inline" : path56}: ${parsed.error}`);
44778
+ failWriteValidation2(`${inline ? "the conversions passed inline" : path57}: ${parsed.error}`);
44779
44779
  }
44780
44780
  return { rows: parsed.rows, ignoredColumns: parsed.ignoredColumns };
44781
44781
  }
@@ -46676,19 +46676,19 @@ function failWriteValidation3(message) {
46676
46676
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
46677
46677
  process.exit(1);
46678
46678
  }
46679
- function loadJsonFileArg2(path56) {
46680
- if (typeof path56 !== "string" || path56.length === 0) {
46679
+ function loadJsonFileArg2(path57) {
46680
+ if (typeof path57 !== "string" || path57.length === 0) {
46681
46681
  return {};
46682
46682
  }
46683
46683
  try {
46684
- const parsed = JSON.parse(readFileSync7(path56, "utf8"));
46684
+ const parsed = JSON.parse(readFileSync7(path57, "utf8"));
46685
46685
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
46686
- failWriteValidation3(`${path56} must contain a JSON object`);
46686
+ failWriteValidation3(`${path57} must contain a JSON object`);
46687
46687
  }
46688
46688
  return parsed;
46689
46689
  } catch (err) {
46690
46690
  if (err instanceof SyntaxError) {
46691
- failWriteValidation3(`${path56} is not valid JSON: ${err.message}`);
46691
+ failWriteValidation3(`${path57} is not valid JSON: ${err.message}`);
46692
46692
  }
46693
46693
  throw err;
46694
46694
  }
@@ -46773,15 +46773,15 @@ function parseLocaleFlag(value2) {
46773
46773
  }
46774
46774
  return { language: match[1], country: match[2].toUpperCase() };
46775
46775
  }
46776
- function loadTargetingFileArg(path56) {
46777
- if (typeof path56 !== "string" || path56.length === 0) {
46776
+ function loadTargetingFileArg(path57) {
46777
+ if (typeof path57 !== "string" || path57.length === 0) {
46778
46778
  return void 0;
46779
46779
  }
46780
- const parsed = loadJsonFileArg2(path56);
46780
+ const parsed = loadJsonFileArg2(path57);
46781
46781
  const criteria = parsed.targetingCriteria ?? parsed;
46782
46782
  if (!criteria.include) {
46783
46783
  failWriteValidation3(
46784
- `${path56} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
46784
+ `${path57} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
46785
46785
  );
46786
46786
  }
46787
46787
  return criteria;
@@ -46816,14 +46816,14 @@ function parseCsvLine(line) {
46816
46816
  cells.push(current);
46817
46817
  return cells.map((cell3) => cell3.trim());
46818
46818
  }
46819
- function parseListFileArg(path56, maxRows) {
46820
- if (typeof path56 !== "string" || path56.length === 0) {
46819
+ function parseListFileArg(path57, maxRows) {
46820
+ if (typeof path57 !== "string" || path57.length === 0) {
46821
46821
  return void 0;
46822
46822
  }
46823
- const raw = readFileSync7(path56, "utf8");
46823
+ const raw = readFileSync7(path57, "utf8");
46824
46824
  const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
46825
46825
  if (lines.length < 2) {
46826
- failWriteValidation3(`${path56} needs a header row and at least one data row`);
46826
+ failWriteValidation3(`${path57} needs a header row and at least one data row`);
46827
46827
  }
46828
46828
  const columns = parseCsvLine(lines[0]).map((column) => column.trim());
46829
46829
  const rows = [];
@@ -46842,7 +46842,7 @@ function parseListFileArg(path56, maxRows) {
46842
46842
  }
46843
46843
  }
46844
46844
  if (rows.length > maxRows) {
46845
- failWriteValidation3(`${path56} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
46845
+ failWriteValidation3(`${path57} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
46846
46846
  }
46847
46847
  return { columns, rows };
46848
46848
  }
@@ -46938,11 +46938,11 @@ function readPositionals(args8) {
46938
46938
  function splitIdList(raw) {
46939
46939
  return raw.split(",").map((id) => id.trim()).filter(Boolean);
46940
46940
  }
46941
- function idsFileEntries(path56) {
46942
- if (typeof path56 !== "string" || path56.length === 0) {
46941
+ function idsFileEntries(path57) {
46942
+ if (typeof path57 !== "string" || path57.length === 0) {
46943
46943
  return [];
46944
46944
  }
46945
- return readFileSync7(path56, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
46945
+ return readFileSync7(path57, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
46946
46946
  }
46947
46947
  function requireTargets2(args8, entity) {
46948
46948
  const positionals = readPositionals(args8);
@@ -49703,9 +49703,9 @@ import { defineCommand as defineCommand64 } from "citty";
49703
49703
  function asRecord(value2) {
49704
49704
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) ? value2 : void 0;
49705
49705
  }
49706
- function readPath2(row, path56) {
49706
+ function readPath2(row, path57) {
49707
49707
  let current = row;
49708
- for (const segment of path56.split(".")) {
49708
+ for (const segment of path57.split(".")) {
49709
49709
  const record = asRecord(current);
49710
49710
  if (!record) return void 0;
49711
49711
  current = record[segment];
@@ -49715,10 +49715,10 @@ function readPath2(row, path56) {
49715
49715
  function projectFields(rows, paths) {
49716
49716
  return rows.map((row) => {
49717
49717
  const projected = {};
49718
- for (const path56 of paths) {
49719
- const value2 = readPath2(row, path56);
49718
+ for (const path57 of paths) {
49719
+ const value2 = readPath2(row, path57);
49720
49720
  if (value2 !== void 0) {
49721
- projected[path56] = value2;
49721
+ projected[path57] = value2;
49722
49722
  }
49723
49723
  }
49724
49724
  return projected;
@@ -49731,16 +49731,16 @@ function shapeListRows(rows, args8, compact5) {
49731
49731
  const paths = fields.split(",").map((field) => field.trim()).filter((field) => field.length > 0);
49732
49732
  if (paths.length > 0) {
49733
49733
  const projected = projectFields(raw, paths).map((row, i) => {
49734
- const missing = paths.filter((path56) => row[path56] === void 0);
49734
+ const missing = paths.filter((path57) => row[path57] === void 0);
49735
49735
  const source = rows[i];
49736
49736
  if (missing.length === 0 || source === void 0) return row;
49737
49737
  const compactRow3 = compact5.row(source);
49738
- for (const path56 of missing) {
49739
- if (compactRow3[path56] !== void 0) row[path56] = compactRow3[path56];
49738
+ for (const path57 of missing) {
49739
+ if (compactRow3[path57] !== void 0) row[path57] = compactRow3[path57];
49740
49740
  }
49741
49741
  return row;
49742
49742
  });
49743
- const unmatched = paths.filter((path56) => projected.every((row) => row[path56] === void 0));
49743
+ const unmatched = paths.filter((path57) => projected.every((row) => row[path57] === void 0));
49744
49744
  if (projected.length === 0 || unmatched.length === 0) return { rows: projected, fields: paths };
49745
49745
  const carried = /* @__PURE__ */ new Set([...compact5.columns, ...raw.flatMap((row) => Object.keys(row))]);
49746
49746
  return {
@@ -51100,54 +51100,54 @@ function ruleFields(node) {
51100
51100
  ([key, value2]) => (key === "and" || key === "or") && Array.isArray(value2) ? value2.flatMap(ruleFields) : [key]
51101
51101
  );
51102
51102
  }
51103
- function branchRefusal(key, value2, path56) {
51103
+ function branchRefusal(key, value2, path57) {
51104
51104
  if (!Array.isArray(value2) || value2.length === 0) {
51105
- return `${path56}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
51105
+ return `${path57}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
51106
51106
  }
51107
51107
  for (const [index, child] of value2.entries()) {
51108
- const refusal = ruleNodeRefusal(child, `${path56}.${key}[${index}]`);
51108
+ const refusal = ruleNodeRefusal(child, `${path57}.${key}[${index}]`);
51109
51109
  if (refusal) {
51110
51110
  return refusal;
51111
51111
  }
51112
51112
  }
51113
51113
  return void 0;
51114
51114
  }
51115
- function conditionRefusal(key, value2, path56) {
51116
- return key === "and" || key === "or" ? branchRefusal(key, value2, path56) : leafRefusal(key, value2, path56);
51115
+ function conditionRefusal(key, value2, path57) {
51116
+ return key === "and" || key === "or" ? branchRefusal(key, value2, path57) : leafRefusal(key, value2, path57);
51117
51117
  }
51118
- function ruleNodeRefusal(node, path56) {
51118
+ function ruleNodeRefusal(node, path57) {
51119
51119
  if (!isRecord2(node)) {
51120
- return `${path56} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
51120
+ return `${path57} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
51121
51121
  }
51122
51122
  const entries = Object.entries(node);
51123
51123
  if (entries.length === 0) {
51124
- return `${path56} is empty \u2014 a rule with no condition counts every event the pixel sends`;
51124
+ return `${path57} is empty \u2014 a rule with no condition counts every event the pixel sends`;
51125
51125
  }
51126
51126
  if (entries.length > 1) {
51127
- return `${path56} names ${entries.length} conditions side by side (${entries.map(([key]) => key).join(", ")}) \u2014 Meta reads one branch or one field test per object, so combine them with {"and":[\u2026]}`;
51127
+ return `${path57} names ${entries.length} conditions side by side (${entries.map(([key]) => key).join(", ")}) \u2014 Meta reads one branch or one field test per object, so combine them with {"and":[\u2026]}`;
51128
51128
  }
51129
51129
  for (const [key, value2] of entries) {
51130
- const refusal = conditionRefusal(key, value2, path56);
51130
+ const refusal = conditionRefusal(key, value2, path57);
51131
51131
  if (refusal) {
51132
51132
  return refusal;
51133
51133
  }
51134
51134
  }
51135
51135
  return void 0;
51136
51136
  }
51137
- function leafRefusal(field, condition, path56) {
51137
+ function leafRefusal(field, condition, path57) {
51138
51138
  if (!isRecord2(condition)) {
51139
- return `${path56}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
51139
+ return `${path57}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
51140
51140
  }
51141
51141
  const tests = Object.entries(condition);
51142
51142
  if (tests.length === 0) {
51143
- return `${path56}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
51143
+ return `${path57}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
51144
51144
  }
51145
51145
  if (tests.length > 1) {
51146
- return `${path56}.${field} names ${tests.length} operators at once (${tests.map(([operator]) => operator).join(", ")}) \u2014 test a field once per condition and combine them with {"and":[\u2026]}`;
51146
+ return `${path57}.${field} names ${tests.length} operators at once (${tests.map(([operator]) => operator).join(", ")}) \u2014 test a field once per condition and combine them with {"and":[\u2026]}`;
51147
51147
  }
51148
51148
  for (const [operator] of tests) {
51149
51149
  if (!RULE_OPERATORS[operator]) {
51150
- return `${path56}.${field} uses "${operator}", which is not a Meta rule operator \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")} (URL matching is i_contains, not contains or includes)`;
51150
+ return `${path57}.${field} uses "${operator}", which is not a Meta rule operator \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")} (URL matching is i_contains, not contains or includes)`;
51151
51151
  }
51152
51152
  }
51153
51153
  return void 0;
@@ -51863,11 +51863,11 @@ var updateStatusSchema2 = z45.enum(UPDATE_STATUSES);
51863
51863
  function currencyMinimums2(currencyCode) {
51864
51864
  return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
51865
51865
  }
51866
- function validateDailyBudgetFloor(money, ctx, path56) {
51866
+ function validateDailyBudgetFloor(money, ctx, path57) {
51867
51867
  if (money?.currencyCode) {
51868
51868
  const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
51869
51869
  if (Number(money.amount) < min) {
51870
- ctx.addIssue({ code: "custom", path: path56, message: `below the ${min} ${money.currencyCode} daily minimum` });
51870
+ ctx.addIssue({ code: "custom", path: path57, message: `below the ${min} ${money.currencyCode} daily minimum` });
51871
51871
  }
51872
51872
  }
51873
51873
  }
@@ -52785,19 +52785,19 @@ function refuseDeleteByUpdate(payload, group) {
52785
52785
  );
52786
52786
  }
52787
52787
  }
52788
- function loadJsonFileArg3(path56) {
52789
- if (typeof path56 !== "string" || path56.length === 0) {
52788
+ function loadJsonFileArg3(path57) {
52789
+ if (typeof path57 !== "string" || path57.length === 0) {
52790
52790
  return {};
52791
52791
  }
52792
52792
  try {
52793
- const parsed = JSON.parse(readFileSync11(path56, "utf8"));
52793
+ const parsed = JSON.parse(readFileSync11(path57, "utf8"));
52794
52794
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
52795
- failWriteValidation4(`${path56} must contain a JSON object`);
52795
+ failWriteValidation4(`${path57} must contain a JSON object`);
52796
52796
  }
52797
52797
  return parsed;
52798
52798
  } catch (err) {
52799
52799
  if (err instanceof SyntaxError) {
52800
- failWriteValidation4(`${path56} is not valid JSON: ${err.message}`);
52800
+ failWriteValidation4(`${path57} is not valid JSON: ${err.message}`);
52801
52801
  }
52802
52802
  throw err;
52803
52803
  }
@@ -58568,12 +58568,12 @@ function flowExists(slug) {
58568
58568
  return existsSync3(join2(flowsDir(), slug, "_data.json"));
58569
58569
  }
58570
58570
  function readFlowTree(slug) {
58571
- const path56 = join2(flowsDir(), slug, "_data.json");
58572
- if (!existsSync3(path56)) {
58571
+ const path57 = join2(flowsDir(), slug, "_data.json");
58572
+ if (!existsSync3(path57)) {
58573
58573
  failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
58574
58574
  }
58575
58575
  try {
58576
- return JSON.parse(readFileSync13(path56, "utf-8"));
58576
+ return JSON.parse(readFileSync13(path57, "utf-8"));
58577
58577
  } catch (error) {
58578
58578
  failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
58579
58579
  }
@@ -59533,12 +59533,12 @@ function readPeopleFile(args8) {
59533
59533
  }
59534
59534
  function unreadablePeopleFile(args8) {
59535
59535
  if (!args8["people-file"]) return void 0;
59536
- const path56 = String(args8["people-file"]);
59536
+ const path57 = String(args8["people-file"]);
59537
59537
  try {
59538
- readFileSync14(path56, "utf8");
59538
+ readFileSync14(path57, "utf8");
59539
59539
  return void 0;
59540
59540
  } catch {
59541
- return `Couldn't read --people-file ${path56}. Check the path, or pass the people inline with --person.`;
59541
+ return `Couldn't read --people-file ${path57}. Check the path, or pass the people inline with --person.`;
59542
59542
  }
59543
59543
  }
59544
59544
  function peopleLimitError(args8) {
@@ -60510,11 +60510,11 @@ function parseFieldArgs(argv) {
60510
60510
  for (const pair of parseRepeated(argv, "--field")) {
60511
60511
  const eq = pair.indexOf("=");
60512
60512
  const field = eq === -1 ? pair : pair.slice(0, eq);
60513
- const path56 = eq === -1 ? "" : pair.slice(eq + 1).trim();
60513
+ const path57 = eq === -1 ? "" : pair.slice(eq + 1).trim();
60514
60514
  const problem = mappingRowProblem(field);
60515
60515
  if (problem !== null) throw new ConversionArgsError(problem);
60516
- if (path56 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
60517
- mapping[field] = path56;
60516
+ if (path57 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
60517
+ mapping[field] = path57;
60518
60518
  }
60519
60519
  return mapping;
60520
60520
  }
@@ -62116,11 +62116,11 @@ function unwrap(response) {
62116
62116
  }
62117
62117
  return response.data;
62118
62118
  }
62119
- async function readAvatars(path56, params) {
62120
- return unwrap(await apiGet(path56, params));
62119
+ async function readAvatars(path57, params) {
62120
+ return unwrap(await apiGet(path57, params));
62121
62121
  }
62122
- async function writeAvatars(path56, body) {
62123
- return unwrap(await apiPost(path56, body));
62122
+ async function writeAvatars(path57, body) {
62123
+ return unwrap(await apiPost(path57, body));
62124
62124
  }
62125
62125
 
62126
62126
  // src/commands/avatars/create.ts
@@ -63029,12 +63029,12 @@ function missingFontFiles(urls, available) {
63029
63029
  function planFontAdoption(sources, families) {
63030
63030
  const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
63031
63031
  const byFamily = /* @__PURE__ */ new Map();
63032
- for (const { path: path56, source } of sources) {
63033
- const dir = posix.dirname(path56);
63032
+ for (const { path: path57, source } of sources) {
63033
+ const dir = posix.dirname(path57);
63034
63034
  for (const face of declaredFontFaces(source)) {
63035
63035
  if (!wanted.has(face.family)) continue;
63036
63036
  const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
63037
- perFile.set(path56, [...perFile.get(path56) ?? [], rebaseFontFaceSrc(face.block, dir)]);
63037
+ perFile.set(path57, [...perFile.get(path57) ?? [], rebaseFontFaceSrc(face.block, dir)]);
63038
63038
  byFamily.set(face.family, perFile);
63039
63039
  }
63040
63040
  }
@@ -69560,10 +69560,10 @@ function runDirsToPrune(entries, keep, currentRunId) {
69560
69560
  return runs.slice(0, Math.max(0, runs.length - keep));
69561
69561
  }
69562
69562
  async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
69563
- const { readdir: readdir18 } = await import("fs/promises");
69563
+ const { readdir: readdir19 } = await import("fs/promises");
69564
69564
  let entries;
69565
69565
  try {
69566
- entries = await readdir18(outputsDir);
69566
+ entries = await readdir19(outputsDir);
69567
69567
  } catch {
69568
69568
  return;
69569
69569
  }
@@ -71388,10 +71388,63 @@ var rerunCommand = defineCommand132({
71388
71388
  });
71389
71389
 
71390
71390
  // src/commands/canvas/scaffold-static-ad.ts
71391
- import { mkdir as mkdir7, readFile as readFile23, writeFile as writeFile12 } from "fs/promises";
71392
- import path29 from "path";
71391
+ import { mkdir as mkdir8, readFile as readFile23, writeFile as writeFile13 } from "fs/promises";
71392
+ import path30 from "path";
71393
71393
  import { defineCommand as defineCommand134 } from "citty";
71394
71394
 
71395
+ // src/commands/canvas/creative-limit.ts
71396
+ import { existsSync as existsSync7 } from "fs";
71397
+ import { mkdir as mkdir7, readdir as readdir10, writeFile as writeFile12 } from "fs/promises";
71398
+ import path25 from "path";
71399
+ var NEW_CREATIVES_PER_CHAT = 10;
71400
+ function claimNewCreative(made, slug) {
71401
+ if (made.includes(slug)) return { allowed: true, count: made.length };
71402
+ if (made.length >= NEW_CREATIVES_PER_CHAT) return { allowed: false, count: made.length };
71403
+ return { allowed: true, count: made.length + 1 };
71404
+ }
71405
+ function chatDir(canvasRoot, chatId) {
71406
+ return path25.join(canvasRoot, ".creative-limit", (chatId ?? "no-chat").replace(/[^A-Za-z0-9_-]/g, "_"));
71407
+ }
71408
+ async function madeInChat(dir) {
71409
+ return readdir10(dir).catch(() => []);
71410
+ }
71411
+ async function claimNewCreativeInWorkspace(canvasRoot, slug, chatId, definitionPath, exists3 = existsSync7) {
71412
+ const dir = chatDir(canvasRoot, chatId);
71413
+ const made = await madeInChat(dir);
71414
+ if (!made.includes(slug) && exists3(definitionPath)) return { allowed: true, count: made.length };
71415
+ const claim = claimNewCreative(made, slug);
71416
+ if (claim.allowed && !made.includes(slug)) {
71417
+ try {
71418
+ await mkdir7(dir, { recursive: true });
71419
+ await writeFile12(path25.join(dir, slug), "", { flag: "wx" });
71420
+ } catch {
71421
+ }
71422
+ }
71423
+ return claim;
71424
+ }
71425
+ function creativeLimitRefusal(slug) {
71426
+ return {
71427
+ ok: false,
71428
+ error: {
71429
+ code: "CREATIVE_LIMIT",
71430
+ message: `${slug} would be new creative number ${NEW_CREATIVES_PER_CHAT + 1} in this chat. A chat makes at most ${NEW_CREATIVES_PER_CHAT} new creatives.`,
71431
+ fix: `Build nothing more. Finish and show the ${NEW_CREATIVES_PER_CHAT} you have, and tell the person in one line that a chat makes up to ${NEW_CREATIVES_PER_CHAT} new creatives, so the rest go in a new chat. Editing or resizing the ones already made still works here. Working as a subagent: return now and say the limit was reached.`
71432
+ }
71433
+ };
71434
+ }
71435
+ async function enforceNewCreativeLimit(slug, canvasPath) {
71436
+ const claim = await claimNewCreativeInWorkspace(
71437
+ canvasOutputsRoot(canvasPath),
71438
+ slug,
71439
+ optionalChatId() ?? null,
71440
+ path25.join(path25.dirname(path25.resolve(canvasPath)), "_definition.md")
71441
+ );
71442
+ if (claim.allowed) return;
71443
+ process.stderr.write(`${JSON.stringify(creativeLimitRefusal(slug), null, 2)}
71444
+ `);
71445
+ process.exit(2);
71446
+ }
71447
+
71395
71448
  // src/engine/scaffold/staticAd.ts
71396
71449
  import { z as z57 } from "zod";
71397
71450
 
@@ -71567,8 +71620,8 @@ function extensionPrompt(format, legend, hasElementRefs) {
71567
71620
  "{{plate_spec}}"
71568
71621
  ].join("\n");
71569
71622
  }
71570
- function ingestNode(id, path56, expect) {
71571
- return { id, type: "ingest", params: { source: "path", path: path56, expect } };
71623
+ function ingestNode(id, path57, expect) {
71624
+ return { id, type: "ingest", params: { source: "path", path: path57, expect } };
71572
71625
  }
71573
71626
  function annotateBlueprintWithLabels(blueprintInput, elementsInput) {
71574
71627
  if (!blueprintInput || typeof blueprintInput !== "object") return blueprintInput;
@@ -71968,19 +72021,19 @@ function staticAdReport(input, elementsInput, opts) {
71968
72021
  import { access, readFile as readFile22 } from "fs/promises";
71969
72022
 
71970
72023
  // src/commands/canvas/composition-path.ts
71971
- import { existsSync as existsSync7 } from "fs";
71972
- import path25 from "path";
71973
- function resolveShippedCanvasDir(name, startDir, exists3 = existsSync7, maxDepth = 8) {
71974
- const rel = path25.join("canvas", name);
72024
+ import { existsSync as existsSync8 } from "fs";
72025
+ import path26 from "path";
72026
+ function resolveShippedCanvasDir(name, startDir, exists3 = existsSync8, maxDepth = 8) {
72027
+ const rel = path26.join("canvas", name);
71975
72028
  let dir = startDir;
71976
72029
  for (let i = 0; i < maxDepth; i++) {
71977
- const candidate = path25.join(dir, rel);
71978
- if (exists3(path25.join(candidate, "meta.json"))) return candidate;
71979
- const parent = path25.dirname(dir);
72030
+ const candidate = path26.join(dir, rel);
72031
+ if (exists3(path26.join(candidate, "meta.json"))) return candidate;
72032
+ const parent = path26.dirname(dir);
71980
72033
  if (parent === dir) break;
71981
72034
  dir = parent;
71982
72035
  }
71983
- return path25.resolve(startDir, "../../../", rel);
72036
+ return path26.resolve(startDir, "../../../", rel);
71984
72037
  }
71985
72038
 
71986
72039
  // src/commands/canvas/scaffold-common.ts
@@ -72027,7 +72080,7 @@ function fileExists(target2) {
72027
72080
  }
72028
72081
 
72029
72082
  // src/commands/canvas/creative-definition.ts
72030
- import path26 from "path";
72083
+ import path27 from "path";
72031
72084
  var PLATFORM_VALUES = ["meta", "google", "linkedin", "tiktok", "youtube", "x", "other"];
72032
72085
  var FORMAT_VALUES = ["1:1", "4:5", "9:16", "16:9", "1.91:1"];
72033
72086
  function titleFromSlug(slug) {
@@ -72075,16 +72128,16 @@ function buildCreativeDefinition(input) {
72075
72128
  }
72076
72129
 
72077
72130
  // src/commands/canvas/scaffold-static-ad-paths.ts
72078
- import path27 from "path";
72131
+ import path28 from "path";
72079
72132
  function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
72080
72133
  const file = rawFile.trim();
72081
72134
  const imageIsUrl = /^https?:\/\//i.test(file);
72082
- const imageSource = imageIsUrl ? file : path27.resolve(cwd, file);
72083
- const outPath = out ? path27.resolve(cwd, out) : slug ? path27.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path27.join(cwd, "static-ad.canvas.json") : path27.join(path27.dirname(imageSource), "static-ad.canvas.json");
72084
- const blueprintPath2 = path27.join(path27.dirname(outPath), "prompt.json");
72085
- const creativeDir = slug ? path27.dirname(outPath) : null;
72086
- const definitionPath = creativeDir ? path27.join(creativeDir, "_definition.md") : null;
72087
- const referencesDir = creativeDir ? path27.join(creativeDir, "references") : null;
72135
+ const imageSource = imageIsUrl ? file : path28.resolve(cwd, file);
72136
+ const outPath = out ? path28.resolve(cwd, out) : slug ? path28.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path28.join(cwd, "static-ad.canvas.json") : path28.join(path28.dirname(imageSource), "static-ad.canvas.json");
72137
+ const blueprintPath2 = path28.join(path28.dirname(outPath), "prompt.json");
72138
+ const creativeDir = slug ? path28.dirname(outPath) : null;
72139
+ const definitionPath = creativeDir ? path28.join(creativeDir, "_definition.md") : null;
72140
+ const referencesDir = creativeDir ? path28.join(creativeDir, "references") : null;
72088
72141
  return { imageIsUrl, imageSource, outPath, blueprintPath: blueprintPath2, creativeDir, definitionPath, referencesDir };
72089
72142
  }
72090
72143
  var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
@@ -72094,8 +72147,8 @@ function isValidScaffoldSlug(slug) {
72094
72147
  }
72095
72148
 
72096
72149
  // src/commands/canvas/sync-definition.ts
72097
- import { readdir as readdir10, stat as stat4 } from "fs/promises";
72098
- import path28 from "path";
72150
+ import { readdir as readdir11, stat as stat4 } from "fs/promises";
72151
+ import path29 from "path";
72099
72152
  import { defineCommand as defineCommand133 } from "citty";
72100
72153
 
72101
72154
  // src/commands/canvas/definition-graph.ts
@@ -72169,26 +72222,26 @@ async function syncCreativeDefinitionBestEffort(input) {
72169
72222
  }
72170
72223
  }
72171
72224
  async function resolveCanvasPath(inputPath) {
72172
- const resolved = path28.resolve(inputPath);
72225
+ const resolved = path29.resolve(inputPath);
72173
72226
  let dir = resolved;
72174
72227
  try {
72175
72228
  if ((await stat4(resolved)).isFile()) {
72176
72229
  if (resolved.endsWith(".canvas.json")) return resolved;
72177
- dir = path28.dirname(resolved);
72230
+ dir = path29.dirname(resolved);
72178
72231
  }
72179
72232
  } catch {
72180
- dir = resolved.endsWith(".canvas.json") ? path28.dirname(resolved) : resolved;
72233
+ dir = resolved.endsWith(".canvas.json") ? path29.dirname(resolved) : resolved;
72181
72234
  }
72182
72235
  let entries;
72183
72236
  try {
72184
- entries = await readdir10(dir);
72237
+ entries = await readdir11(dir);
72185
72238
  } catch {
72186
72239
  return null;
72187
72240
  }
72188
72241
  const canvases = entries.filter((name) => name.endsWith(".canvas.json"));
72189
72242
  const slug = creativeSlugFromCanvasPath(`${dir}/x/`);
72190
72243
  const chosen = (slug ? canvases.find((name) => name === `${slug}.canvas.json`) : void 0) ?? canvases[0];
72191
- return chosen ? path28.join(dir, chosen) : null;
72244
+ return chosen ? path29.join(dir, chosen) : null;
72192
72245
  }
72193
72246
  var syncDefinitionCommand = defineCommand133({
72194
72247
  meta: {
@@ -72253,19 +72306,19 @@ async function resolveCastAvatars(flag) {
72253
72306
 
72254
72307
  // src/commands/canvas/scaffold-static-ad.ts
72255
72308
  async function writeStaticComposition(dir, width, height) {
72256
- await mkdir7(dir, { recursive: true });
72257
- const html = await readFile23(path29.join(SHIPPED_STATIC_COMPOSITION_DIR, "index.html"), "utf8");
72258
- await writeFile12(
72259
- path29.join(dir, "index.html"),
72309
+ await mkdir8(dir, { recursive: true });
72310
+ const html = await readFile23(path30.join(SHIPPED_STATIC_COMPOSITION_DIR, "index.html"), "utf8");
72311
+ await writeFile13(
72312
+ path30.join(dir, "index.html"),
72260
72313
  html.replaceAll("__WIDTH__", String(width)).replaceAll("__HEIGHT__", String(height)),
72261
72314
  "utf8"
72262
72315
  );
72263
- const meta = JSON.parse(await readFile23(path29.join(SHIPPED_STATIC_COMPOSITION_DIR, "meta.json"), "utf8"));
72264
- await writeFile12(path29.join(dir, "meta.json"), `${JSON.stringify({ ...meta, width, height }, null, 2)}
72316
+ const meta = JSON.parse(await readFile23(path30.join(SHIPPED_STATIC_COMPOSITION_DIR, "meta.json"), "utf8"));
72317
+ await writeFile13(path30.join(dir, "meta.json"), `${JSON.stringify({ ...meta, width, height }, null, 2)}
72265
72318
  `, "utf8");
72266
72319
  }
72267
72320
  function toCanvasRelative2(canvasDir, file) {
72268
- const rel = path29.relative(canvasDir, file).split(path29.sep).join("/");
72321
+ const rel = path30.relative(canvasDir, file).split(path30.sep).join("/");
72269
72322
  return rel.startsWith(".") ? rel : `./${rel}`;
72270
72323
  }
72271
72324
  async function uploadSourceAsReference(source, isUrl, client) {
@@ -72547,7 +72600,8 @@ var scaffoldStaticAdCommand = defineCommand134({
72547
72600
  process.cwd(),
72548
72601
  slug
72549
72602
  );
72550
- await mkdir7(path29.dirname(outPath), { recursive: true });
72603
+ if (slug) await enforceNewCreativeLimit(slug, outPath);
72604
+ await mkdir8(path30.dirname(outPath), { recursive: true });
72551
72605
  let models;
72552
72606
  try {
72553
72607
  models = resolveModels(args8);
@@ -72584,7 +72638,7 @@ var scaffoldStaticAdCommand = defineCommand134({
72584
72638
  if (layout && annotated && typeof annotated === "object") {
72585
72639
  annotated.layout = layout;
72586
72640
  }
72587
- await writeFile12(blueprintPath2, `${JSON.stringify(annotated, null, 2)}
72641
+ await writeFile13(blueprintPath2, `${JSON.stringify(annotated, null, 2)}
72588
72642
  `, "utf8");
72589
72643
  let canvasImagePath = imageSource;
72590
72644
  let canvasImageIsUrl = imageIsUrl;
@@ -72603,7 +72657,7 @@ var scaffoldStaticAdCommand = defineCommand134({
72603
72657
  );
72604
72658
  if (!placementsResult.ok) return fail4("invalid_placements", placementsResult.message);
72605
72659
  const placements = placementsResult.placements;
72606
- const canvasDir = path29.dirname(outPath);
72660
+ const canvasDir = path30.dirname(outPath);
72607
72661
  const workspaceRoot = await findBrandRoot(canvasDir) ?? process.cwd();
72608
72662
  const kit = await readStaticBrandKit(workspaceRoot);
72609
72663
  const relative = (file) => file ? toCanvasRelative2(canvasDir, file) : void 0;
@@ -72634,12 +72688,12 @@ var scaffoldStaticAdCommand = defineCommand134({
72634
72688
  return fail4("scaffold", e instanceof Error ? e.message : String(e));
72635
72689
  }
72636
72690
  for (const layout2 of staticAdCompositions(blueprint, opts)) {
72637
- await writeStaticComposition(path29.resolve(canvasDir, layout2.dir), layout2.width, layout2.height);
72691
+ await writeStaticComposition(path30.resolve(canvasDir, layout2.dir), layout2.width, layout2.height);
72638
72692
  }
72639
72693
  const specOptions = composeOptionsFor(canvas, annotated);
72640
- await writeFile12(path29.resolve(canvasDir, PLATE_SPEC_PATH), renderPlateSpec(annotated, specOptions), "utf8");
72641
- await writeFile12(path29.resolve(canvasDir, COMPOSE_SPEC_PATH), renderComposeSpec(annotated, kit, specOptions), "utf8");
72642
- const validation = await validateScaffoldedStaticAd(canvas, path29.dirname(outPath));
72694
+ await writeFile13(path30.resolve(canvasDir, PLATE_SPEC_PATH), renderPlateSpec(annotated, specOptions), "utf8");
72695
+ await writeFile13(path30.resolve(canvasDir, COMPOSE_SPEC_PATH), renderComposeSpec(annotated, kit, specOptions), "utf8");
72696
+ const validation = await validateScaffoldedStaticAd(canvas, path30.dirname(outPath));
72643
72697
  if (validation.blocking.length > 0) {
72644
72698
  process.stderr.write(
72645
72699
  `${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.blocking } }, null, 2)}
@@ -72647,10 +72701,10 @@ var scaffoldStaticAdCommand = defineCommand134({
72647
72701
  );
72648
72702
  process.exit(2);
72649
72703
  }
72650
- await writeFile12(outPath, `${JSON.stringify(canvas, null, 2)}
72704
+ await writeFile13(outPath, `${JSON.stringify(canvas, null, 2)}
72651
72705
  `, "utf8");
72652
72706
  if (definitionPath && !await fileExists(definitionPath)) {
72653
- await writeFile12(
72707
+ await writeFile13(
72654
72708
  definitionPath,
72655
72709
  buildCreativeDefinition({
72656
72710
  title: args8.title ? String(args8.title) : titleFromSlug(slug ?? ""),
@@ -72706,7 +72760,7 @@ var scaffoldStaticAdCommand = defineCommand134({
72706
72760
  run_estimated_credits: validation.estimatedCredits
72707
72761
  },
72708
72762
  checklist: {
72709
- edit_prompt: `Edit ${path29.basename(blueprintPath2)} \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.`,
72763
+ edit_prompt: `Edit ${path30.basename(blueprintPath2)} \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.`,
72710
72764
  winning_mechanisms: report.winning_mechanisms,
72711
72765
  rebuild_the_mechanism: "`winning_mechanisms` is WHY the source ad works. Rewrite each one for our brand in prompt.json (a rhyme stays a rhyme in our words, a before/after stays a before/after of our product); never copy the source's literal copy.",
72712
72766
  assets_to_supply: report.elements,
@@ -72768,8 +72822,8 @@ function clientLogoMissNote(decision, domain) {
72768
72822
  }
72769
72823
 
72770
72824
  // src/commands/canvas/scaffold-ad.ts
72771
- import { copyFile, cp, mkdir as mkdir8, readFile as readFile25, stat as stat5, writeFile as writeFile14 } from "fs/promises";
72772
- import path31 from "path";
72825
+ import { copyFile, cp, mkdir as mkdir9, readFile as readFile25, stat as stat5, writeFile as writeFile15 } from "fs/promises";
72826
+ import path32 from "path";
72773
72827
  import { defineCommand as defineCommand135 } from "citty";
72774
72828
 
72775
72829
  // src/engine/scaffold/ad-spec.ts
@@ -73483,8 +73537,8 @@ function injectAdBrandOverlay(indexHtml, overlayHtml, style = {}) {
73483
73537
  }
73484
73538
 
73485
73539
  // src/commands/canvas/composition-dims.ts
73486
- import { readFile as readFile24, writeFile as writeFile13 } from "fs/promises";
73487
- import path30 from "path";
73540
+ import { readFile as readFile24, writeFile as writeFile14 } from "fs/promises";
73541
+ import path31 from "path";
73488
73542
  function patchCompositionMeta(metaJson, dims) {
73489
73543
  try {
73490
73544
  const meta = JSON.parse(metaJson);
@@ -73499,12 +73553,12 @@ function patchCompositionHtml(html, dims) {
73499
73553
  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`);
73500
73554
  }
73501
73555
  async function stampCompositionDims(compositionDir, dims) {
73502
- const metaPath = path30.join(compositionDir, "meta.json");
73556
+ const metaPath = path31.join(compositionDir, "meta.json");
73503
73557
  const rawMeta = await readFile24(metaPath, "utf8");
73504
- await writeFile13(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
73505
- const htmlPath = path30.join(compositionDir, "index.html");
73558
+ await writeFile14(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
73559
+ const htmlPath = path31.join(compositionDir, "index.html");
73506
73560
  const rawHtml = await readFile24(htmlPath, "utf8");
73507
- await writeFile13(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
73561
+ await writeFile14(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
73508
73562
  }
73509
73563
 
73510
73564
  // src/commands/canvas/scaffold-ad.ts
@@ -73799,8 +73853,9 @@ var scaffoldAdCommand = defineCommand135({
73799
73853
  videoModel: chosenVideoModel,
73800
73854
  ...avatarVoice ? { avatarVoice } : {}
73801
73855
  });
73802
- const slug = args8.slug ?? path31.basename(specPath).replace(/\.[^.]+$/, "");
73803
- const outPath = args8.out ?? (args8.slug ? path31.join("src/creatives", slug, `${slug}.canvas.json`) : path31.join(path31.dirname(specPath), `${slug}.canvas.json`));
73856
+ const slug = args8.slug ?? path32.basename(specPath).replace(/\.[^.]+$/, "");
73857
+ const outPath = args8.out ?? (args8.slug ? path32.join("src/creatives", slug, `${slug}.canvas.json`) : path32.join(path32.dirname(specPath), `${slug}.canvas.json`));
73858
+ if (args8.slug) await enforceNewCreativeLimit(slug, outPath);
73804
73859
  let outAr;
73805
73860
  try {
73806
73861
  outAr = resolveAspect(void 0, spec.data.format.aspect_ratio, genAspectsFor(chosenVideoModel)).outAr;
@@ -73817,30 +73872,30 @@ var scaffoldAdCommand = defineCommand135({
73817
73872
  return;
73818
73873
  }
73819
73874
  const outDims = canvasDims(outAr);
73820
- const outDir = path31.dirname(outPath);
73821
- await mkdir8(outDir, { recursive: true });
73822
- const compositionDest = path31.join(outDir, "video-overlay-composition");
73823
- const captionsDest = path31.join(outDir, "tiktok-captions-composition");
73875
+ const outDir = path32.dirname(outPath);
73876
+ await mkdir9(outDir, { recursive: true });
73877
+ const compositionDest = path32.join(outDir, "video-overlay-composition");
73878
+ const captionsDest = path32.join(outDir, "tiktok-captions-composition");
73824
73879
  await cp(SHIPPED_OVERLAY_COMPOSITION_DIR, compositionDest, { recursive: true });
73825
73880
  await cp(SHIPPED_CAPTIONS_DIR, captionsDest, { recursive: true });
73826
73881
  await stampCompositionDims(compositionDest, outDims);
73827
73882
  await stampCompositionDims(captionsDest, outDims);
73828
- const captionsIndex = path31.join(captionsDest, "index.html");
73829
- await writeFile14(captionsIndex, injectAdCaptionPlacement(await readFile25(captionsIndex, "utf-8"), outAr), "utf-8");
73883
+ const captionsIndex = path32.join(captionsDest, "index.html");
73884
+ await writeFile15(captionsIndex, injectAdCaptionPlacement(await readFile25(captionsIndex, "utf-8"), outAr), "utf-8");
73830
73885
  const face = await stageBrandDisplayFace(outDir, captionsDest);
73831
73886
  if (face) {
73832
- await writeFile14(captionsIndex, injectAdDisplayFace(await readFile25(captionsIndex, "utf-8"), face.file), "utf-8");
73887
+ await writeFile15(captionsIndex, injectAdDisplayFace(await readFile25(captionsIndex, "utf-8"), face.file), "utf-8");
73833
73888
  }
73834
- const blueprintPath2 = path31.join(outDir, "prompt.json");
73835
- const blueprintStylePath = path31.join(outDir, "prompt.style.json");
73889
+ const blueprintPath2 = path32.join(outDir, "prompt.json");
73890
+ const blueprintStylePath = path32.join(outDir, "prompt.style.json");
73836
73891
  await writeSceneFiles(outDir, blueprint);
73837
- await writeFile14(blueprintStylePath, renderStyleProjectionFromValue(blueprint), "utf8");
73838
- await writeFile14(path31.join(outDir, AD_SPEC_FILE), `${JSON.stringify(specArtifact, null, 2)}
73892
+ await writeFile15(blueprintStylePath, renderStyleProjectionFromValue(blueprint), "utf8");
73893
+ await writeFile15(path32.join(outDir, AD_SPEC_FILE), `${JSON.stringify(specArtifact, null, 2)}
73839
73894
  `, "utf8");
73840
73895
  const logoPath = noBrand ? void 0 : spec.data.brand?.logo?.trim();
73841
- const transcriptPath = path31.join(outDir, "transcript.json");
73896
+ const transcriptPath = path32.join(outDir, "transcript.json");
73842
73897
  if (spec.data.voiceover === false) {
73843
- await writeFile14(transcriptPath, `${JSON.stringify(staticTranscript(spec.data, chosenVideoModel), null, 2)}
73898
+ await writeFile15(transcriptPath, `${JSON.stringify(staticTranscript(spec.data, chosenVideoModel), null, 2)}
73844
73899
  `, "utf-8");
73845
73900
  }
73846
73901
  const opts = {
@@ -73850,10 +73905,10 @@ var scaffoldAdCommand = defineCommand135({
73850
73905
  // that stops the whole canvas. The same sheet model every other scaffold uses.
73851
73906
  sheetModel: ACTOR_SHEET_MODEL,
73852
73907
  videoModel: chosenVideoModel,
73853
- overlayCompositionPath: path31.relative(outDir, compositionDest),
73854
- captionsCompositionPath: path31.relative(outDir, captionsDest),
73855
- blueprintPath: path31.relative(outDir, blueprintPath2),
73856
- blueprintStylePath: path31.relative(outDir, blueprintStylePath),
73908
+ overlayCompositionPath: path32.relative(outDir, compositionDest),
73909
+ captionsCompositionPath: path32.relative(outDir, captionsDest),
73910
+ blueprintPath: path32.relative(outDir, blueprintPath2),
73911
+ blueprintStylePath: path32.relative(outDir, blueprintStylePath),
73857
73912
  aspect: spec.data.format.aspect_ratio,
73858
73913
  resolution: spec.data.format.resolution,
73859
73914
  // A beat is one clause and one card, so the cap has to clear a whole clause.
@@ -73892,17 +73947,17 @@ var scaffoldAdCommand = defineCommand135({
73892
73947
  // the stock voice this exists to avoid. It is to convert the LATER extracts onto the
73893
73948
  // first beat of the same speaker, which keeps a voice the clip really produced.
73894
73949
  ...avatar ? { keepRenderedVoice: true } : {},
73895
- ...spec.data.voiceover === false ? { staticTranscriptPath: path31.relative(outDir, transcriptPath) } : {}
73950
+ ...spec.data.voiceover === false ? { staticTranscriptPath: path32.relative(outDir, transcriptPath) } : {}
73896
73951
  };
73897
73952
  const canvas = scaffoldVideoCanvas(blueprint, adSpecCastElements(spec.data, avatar), opts);
73898
73953
  const renderNode5 = canvas.nodes.find((n) => n.type === "hyperframe_render");
73899
- const renderedDir = renderNode5 ? path31.join(outDir, String(renderNode5.params?.composition ?? "")) : null;
73954
+ const renderedDir = renderNode5 ? path32.join(outDir, String(renderNode5.params?.composition ?? "")) : null;
73900
73955
  let staged = null;
73901
73956
  let markIsLight = false;
73902
73957
  if (logoPath && renderedDir) {
73903
- const ext = path31.extname(logoPath) || ".png";
73958
+ const ext = path32.extname(logoPath) || ".png";
73904
73959
  try {
73905
- await copyFile(logoPath, path31.join(renderedDir, `brand-mark${ext}`));
73960
+ await copyFile(logoPath, path32.join(renderedDir, `brand-mark${ext}`));
73906
73961
  staged = { file: `brand-mark${ext}`, alt: spec.data.brand?.name ?? "brand" };
73907
73962
  markIsLight = await markInkIsLight(logoPath);
73908
73963
  } catch {
@@ -73921,12 +73976,12 @@ var scaffoldAdCommand = defineCommand135({
73921
73976
  plateIsDark: plateIsDark(spec.data.brand?.palette)
73922
73977
  }) : "";
73923
73978
  if (overlayHtml && renderedDir) {
73924
- const indexPath = path31.join(renderedDir, "index.html");
73979
+ const indexPath = path32.join(renderedDir, "index.html");
73925
73980
  const html = await readFile25(indexPath, "utf-8");
73926
- await writeFile14(indexPath, injectAdBrandOverlay(html, overlayHtml, { aspect: outAr, ...face ? { face: AD_DISPLAY_FAMILY } : {} }), "utf-8");
73981
+ await writeFile15(indexPath, injectAdBrandOverlay(html, overlayHtml, { aspect: outAr, ...face ? { face: AD_DISPLAY_FAMILY } : {} }), "utf-8");
73927
73982
  }
73928
- await writeFile14(
73929
- path31.join(outDir, REBUILD_FILE),
73983
+ await writeFile15(
73984
+ path32.join(outDir, REBUILD_FILE),
73930
73985
  `${JSON.stringify({ elements: adSpecCastElements(spec.data, avatar), opts }, null, 2)}
73931
73986
  `,
73932
73987
  "utf8"
@@ -73936,7 +73991,7 @@ var scaffoldAdCommand = defineCommand135({
73936
73991
  const meta = canvas.metadata;
73937
73992
  meta.todo = { ...meta.todo ?? {}, blocking_validation_issues: validation.issues };
73938
73993
  }
73939
- await writeFile14(outPath, `${JSON.stringify(canvas, null, 2)}
73994
+ await writeFile15(outPath, `${JSON.stringify(canvas, null, 2)}
73940
73995
  `, "utf-8");
73941
73996
  if (!validation.ok) {
73942
73997
  process.stderr.write(
@@ -73956,10 +74011,10 @@ var scaffoldAdCommand = defineCommand135({
73956
74011
  return;
73957
74012
  }
73958
74013
  if (args8.slug) {
73959
- const definitionPath = path31.join(outDir, "_definition.md");
74014
+ const definitionPath = path32.join(outDir, "_definition.md");
73960
74015
  const definitionExists = await stat5(definitionPath).then(() => true, () => false);
73961
74016
  if (!definitionExists) {
73962
- await writeFile14(
74017
+ await writeFile15(
73963
74018
  definitionPath,
73964
74019
  buildCreativeDefinition({
73965
74020
  title: titleFromSlug(slug),
@@ -74074,10 +74129,10 @@ async function fetchClientLogo() {
74074
74129
  if (!response.ok) return { ok: false, reason: clientLogoMissNote({ use: false, reason: "no_hits" }, domain) };
74075
74130
  const bytes = Buffer.from(await response.arrayBuffer());
74076
74131
  const extension = /\.(svg|png|jpg|jpeg|webp)(?:\?|$)/i.exec(decision.url)?.[1]?.toLowerCase() ?? "svg";
74077
- const dir = path31.join(BRAND_DIR, "logos");
74078
- await mkdir8(dir, { recursive: true });
74079
- const file = path31.join(dir, `brand-mark.${extension}`);
74080
- await writeFile14(file, bytes);
74132
+ const dir = path32.join(BRAND_DIR, "logos");
74133
+ await mkdir9(dir, { recursive: true });
74134
+ const file = path32.join(dir, `brand-mark.${extension}`);
74135
+ await writeFile15(file, bytes);
74081
74136
  return { ok: true, path: file };
74082
74137
  } catch {
74083
74138
  return { ok: false, reason: clientLogoMissNote({ use: false, reason: "no_hits" }, domain) };
@@ -74095,14 +74150,14 @@ async function stageBrandDisplayFace(outDir, compositionDir) {
74095
74150
  if (!face) return null;
74096
74151
  try {
74097
74152
  if ("path" in face.slot) {
74098
- const file2 = `brand-face${path31.extname(face.slot.path).toLowerCase()}`;
74099
- await copyFile(face.slot.path, path31.join(compositionDir, file2));
74100
- return { file: file2, label: `the font file \`${path31.relative(root, face.slot.path)}\`` };
74153
+ const file2 = `brand-face${path32.extname(face.slot.path).toLowerCase()}`;
74154
+ await copyFile(face.slot.path, path32.join(compositionDir, file2));
74155
+ return { file: file2, label: `the font file \`${path32.relative(root, face.slot.path)}\`` };
74101
74156
  }
74102
74157
  const { buffer } = await fetchExternalBytes(face.slot.url, { maxBytes: MAX_FONT_BYTES });
74103
74158
  const extension = /\.(woff2|woff|ttf|otf)(?:\?|$)/i.exec(face.slot.url)?.[1]?.toLowerCase() ?? "woff2";
74104
74159
  const file = `brand-face.${extension}`;
74105
- await writeFile14(path31.join(compositionDir, file), buffer);
74160
+ await writeFile15(path32.join(compositionDir, file), buffer);
74106
74161
  return { file, label: `${face.family ?? "the brand's typeface"}, loaded as a web font` };
74107
74162
  } catch {
74108
74163
  return null;
@@ -74110,9 +74165,9 @@ async function stageBrandDisplayFace(outDir, compositionDir) {
74110
74165
  }
74111
74166
 
74112
74167
  // src/commands/canvas/scaffold-video.ts
74113
- import { cp as cp2, mkdir as mkdir9, readFile as readFile28, rm as rm8, writeFile as writeFile15 } from "fs/promises";
74168
+ import { cp as cp2, mkdir as mkdir10, readFile as readFile28, rm as rm8, writeFile as writeFile16 } from "fs/promises";
74114
74169
  import { tmpdir as tmpdir3 } from "os";
74115
- import path33 from "path";
74170
+ import path34 from "path";
74116
74171
  import { defineCommand as defineCommand136 } from "citty";
74117
74172
 
74118
74173
  // src/engine/scaffold/lib/model-router.ts
@@ -74152,7 +74207,7 @@ function routeVideoModel(input) {
74152
74207
 
74153
74208
  // src/engine/nodes/local/lib/sceneDetect.ts
74154
74209
  import { execFile as execFile3 } from "child_process";
74155
- import { mkdtemp as mkdtemp2, readdir as readdir11, readFile as readFile26, rm as rm7 } from "fs/promises";
74210
+ import { mkdtemp as mkdtemp2, readdir as readdir12, readFile as readFile26, rm as rm7 } from "fs/promises";
74156
74211
  import { tmpdir as tmpdir2 } from "os";
74157
74212
  import { join as join3 } from "path";
74158
74213
  import { promisify as promisify3 } from "util";
@@ -74226,7 +74281,7 @@ async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs)
74226
74281
  ],
74227
74282
  { encoding: "utf-8", maxBuffer: 32 * 1024 * 1024, timeout: timeoutMs }
74228
74283
  );
74229
- const csvName = (await readdir11(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
74284
+ const csvName = (await readdir12(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
74230
74285
  if (!csvName) return [];
74231
74286
  return parsePySceneDetectCsvCuts(await readFile26(join3(outDir, csvName), "utf-8"));
74232
74287
  } finally {
@@ -74253,7 +74308,7 @@ async function detectSceneCutsPySceneDetect(filePath, opts = {}) {
74253
74308
 
74254
74309
  // src/commands/canvas/gitignore.ts
74255
74310
  import { appendFile, readFile as readFile27 } from "fs/promises";
74256
- import path32 from "path";
74311
+ import path33 from "path";
74257
74312
  function missingGitignoreEntries(existing, entries) {
74258
74313
  const present2 = new Set(
74259
74314
  existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
@@ -74261,7 +74316,7 @@ function missingGitignoreEntries(existing, entries) {
74261
74316
  return entries.filter((e) => !present2.has(e.trim().replace(/\/+$/, "")));
74262
74317
  }
74263
74318
  async function ensureGitignore(dir, entries) {
74264
- const file = path32.join(dir, ".gitignore");
74319
+ const file = path33.join(dir, ".gitignore");
74265
74320
  let existing;
74266
74321
  try {
74267
74322
  existing = await readFile27(file, "utf8");
@@ -74306,7 +74361,7 @@ async function loadTranscriptBestEffort(ref2) {
74306
74361
  async function stageCaptions(outDir, transcript) {
74307
74362
  const text2 = transcript?.trim();
74308
74363
  if (!text2 || text2 === "[]") return {};
74309
- const compositionPath = path33.join(outDir, "tiktok-captions-composition");
74364
+ const compositionPath = path34.join(outDir, "tiktok-captions-composition");
74310
74365
  await cp2(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
74311
74366
  return { compositionPath };
74312
74367
  }
@@ -74342,7 +74397,7 @@ var VIDEO_EXT_BY_MIME = {
74342
74397
  "video/x-matroska": ".mkv"
74343
74398
  };
74344
74399
  function referenceVideoExt(url, contentType) {
74345
- const fromPath = path33.extname(new URL(url).pathname).toLowerCase();
74400
+ const fromPath = path34.extname(new URL(url).pathname).toLowerCase();
74346
74401
  if (fromPath && fromPath.length <= 5) return fromPath;
74347
74402
  const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase();
74348
74403
  return mime && VIDEO_EXT_BY_MIME[mime] || ".mp4";
@@ -74368,7 +74423,7 @@ function framesModeReport(canvas, requested) {
74368
74423
  return { frames_mode: mode, ...refused ? { frames_reuse_refused: refused } : {} };
74369
74424
  }
74370
74425
  async function materializeReferenceVideo(fileArg2) {
74371
- if (!/^https?:\/\//i.test(fileArg2)) return path33.resolve(fileArg2);
74426
+ if (!/^https?:\/\//i.test(fileArg2)) return path34.resolve(fileArg2);
74372
74427
  let bytes;
74373
74428
  let contentType;
74374
74429
  try {
@@ -74380,11 +74435,11 @@ async function materializeReferenceVideo(fileArg2) {
74380
74435
  throw new Error(`failed to download reference video: ${e instanceof Error ? e.message : String(e)}`);
74381
74436
  }
74382
74437
  if (bytes.length === 0) throw new Error("reference video download was empty");
74383
- const dest = path33.join(
74438
+ const dest = path34.join(
74384
74439
  tmpdir3(),
74385
74440
  `baker-ref-${sha256Hex(bytes).slice(0, 16)}${referenceVideoExt(fileArg2, contentType)}`
74386
74441
  );
74387
- await writeFile15(dest, bytes);
74442
+ await writeFile16(dest, bytes);
74388
74443
  return dest;
74389
74444
  }
74390
74445
  function resolveSeamDedup(raw) {
@@ -74607,11 +74662,12 @@ var scaffoldVideoCommand = defineCommand136({
74607
74662
  } catch (e) {
74608
74663
  return fail4("download", e instanceof Error ? e.message : String(e));
74609
74664
  }
74610
- const base = path33.basename(videoPath, path33.extname(videoPath));
74611
- const outPath = args8.out ? path33.resolve(String(args8.out)) : slug ? path33.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`) : path33.join(path33.dirname(videoPath), `${base}.video.canvas.json`);
74612
- const outDir = path33.dirname(outPath);
74613
- const blueprintPath2 = path33.join(outDir, "prompt.json");
74614
- const blueprintStylePath = path33.join(outDir, "prompt.style.json");
74665
+ const base = path34.basename(videoPath, path34.extname(videoPath));
74666
+ const outPath = args8.out ? path34.resolve(String(args8.out)) : slug ? path34.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`) : path34.join(path34.dirname(videoPath), `${base}.video.canvas.json`);
74667
+ if (slug) await enforceNewCreativeLimit(slug, outPath);
74668
+ const outDir = path34.dirname(outPath);
74669
+ const blueprintPath2 = path34.join(outDir, "prompt.json");
74670
+ const blueprintStylePath = path34.join(outDir, "prompt.style.json");
74615
74671
  const frames = args8.frames === "reuse" ? "reuse" : "generate";
74616
74672
  const maxScenes = args8["max-scenes"] ? Number(args8["max-scenes"]) : void 0;
74617
74673
  if (Number.isFinite(maxScenes)) {
@@ -74659,10 +74715,10 @@ var scaffoldVideoCommand = defineCommand136({
74659
74715
  process.stderr.write(`\u{1F3AC} Photoreal on-camera cast detected \u2192 generating clips on ${videoModel} (dodges Seedance's real-person filter).
74660
74716
  `);
74661
74717
  }
74662
- await mkdir9(outDir, { recursive: true });
74718
+ await mkdir10(outDir, { recursive: true });
74663
74719
  const annotated = annotateBlueprintWithElements(blueprint, elements);
74664
74720
  await writeSceneFiles(outDir, annotated);
74665
- await writeFile15(blueprintStylePath, renderStyleProjectionFromValue(annotated), "utf8");
74721
+ await writeFile16(blueprintStylePath, renderStyleProjectionFromValue(annotated), "utf8");
74666
74722
  let aspect;
74667
74723
  try {
74668
74724
  aspect = resolveAspect(
@@ -74680,10 +74736,10 @@ var scaffoldVideoCommand = defineCommand136({
74680
74736
  `
74681
74737
  );
74682
74738
  }
74683
- const compositionDest = path33.join(outDir, "video-overlay-composition");
74739
+ const compositionDest = path34.join(outDir, "video-overlay-composition");
74684
74740
  await cp2(SHIPPED_OVERLAY_COMPOSITION_DIR, compositionDest, { recursive: true });
74685
74741
  await stampCompositionDims(compositionDest, outDims);
74686
- const indexPath = path33.join(compositionDest, "index.html");
74742
+ const indexPath = path34.join(compositionDest, "index.html");
74687
74743
  const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript), videoModel });
74688
74744
  const indexHtml = await readFile28(indexPath, "utf8");
74689
74745
  const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
@@ -74693,16 +74749,16 @@ var scaffoldVideoCommand = defineCommand136({
74693
74749
  `video-overlay-composition/index.html is missing the <!--OVERLAYS--> marker \u2014 cannot inject the overlay layer`
74694
74750
  );
74695
74751
  }
74696
- await writeFile15(indexPath, injected, "utf8");
74752
+ await writeFile16(indexPath, injected, "utf8");
74697
74753
  const captions = await stageCaptions(outDir, transcript);
74698
74754
  if (captions.compositionPath) await stampCompositionDims(captions.compositionPath, outDims);
74699
74755
  const opts = {
74700
74756
  imageModel,
74701
74757
  videoModel,
74702
- overlayCompositionPath: path33.relative(outDir, compositionDest),
74703
- captionsCompositionPath: captions.compositionPath ? path33.relative(outDir, captions.compositionPath) : void 0,
74704
- blueprintPath: path33.relative(outDir, blueprintPath2),
74705
- blueprintStylePath: path33.relative(outDir, blueprintStylePath),
74758
+ overlayCompositionPath: path34.relative(outDir, compositionDest),
74759
+ captionsCompositionPath: captions.compositionPath ? path34.relative(outDir, captions.compositionPath) : void 0,
74760
+ blueprintPath: path34.relative(outDir, blueprintPath2),
74761
+ blueprintStylePath: path34.relative(outDir, blueprintStylePath),
74706
74762
  frames,
74707
74763
  ambient: Boolean(args8.ambient),
74708
74764
  seamDedup: resolveSeamDedup(args8["seam-dedup"]),
@@ -74727,10 +74783,10 @@ var scaffoldVideoCommand = defineCommand136({
74727
74783
  todo.blocking_validation_issues = validation.issues;
74728
74784
  meta.todo = todo;
74729
74785
  }
74730
- await writeFile15(outPath, `${JSON.stringify(canvas, null, 2)}
74786
+ await writeFile16(outPath, `${JSON.stringify(canvas, null, 2)}
74731
74787
  `, "utf8");
74732
- await writeFile15(
74733
- path33.join(outDir, REBUILD_FILE),
74788
+ await writeFile16(
74789
+ path34.join(outDir, REBUILD_FILE),
74734
74790
  `${JSON.stringify({ elements, opts }, null, 2)}
74735
74791
  `,
74736
74792
  "utf8"
@@ -74757,9 +74813,9 @@ var scaffoldVideoCommand = defineCommand136({
74757
74813
  await ensureGitignore(process.cwd(), ["canvas/", ".context/"]);
74758
74814
  const sourceRef = videoSourceReference(blueprint, fileArg2);
74759
74815
  if (slug) {
74760
- const definitionPath = path33.join(outDir, "_definition.md");
74816
+ const definitionPath = path34.join(outDir, "_definition.md");
74761
74817
  if (!await fileExists(definitionPath)) {
74762
- await writeFile15(
74818
+ await writeFile16(
74763
74819
  definitionPath,
74764
74820
  buildCreativeDefinition({
74765
74821
  title: titleFromSlug(slug),
@@ -74813,7 +74869,7 @@ var scaffoldVideoCommand = defineCommand136({
74813
74869
  graph: canvas.metadata?.video?.graph_stats
74814
74870
  },
74815
74871
  checklist: {
74816
- 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 \`${path33.basename(blueprintPath2)}\`. \`baker canvas validate\`/\`run\` re-assemble the blueprint and re-flow every edited scene back into the render (and regenerate ${path33.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 ${path33.basename(blueprintStylePath)}; both are regenerated.`,
74872
+ 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 \`${path34.basename(blueprintPath2)}\`. \`baker canvas validate\`/\`run\` re-assemble the blueprint and re-flow every edited scene back into the render (and regenerate ${path34.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 ${path34.basename(blueprintStylePath)}; both are regenerated.`,
74817
74873
  recurring_elements_to_supply: report.elements,
74818
74874
  voices_to_confirm: report.dialogue.map((d) => ({
74819
74875
  scene: d.scene,
@@ -74850,8 +74906,8 @@ var scaffoldVideoCommand = defineCommand136({
74850
74906
  });
74851
74907
 
74852
74908
  // src/commands/canvas/set-prompt.ts
74853
- import { readFile as readFile29, writeFile as writeFile16 } from "fs/promises";
74854
- import path34 from "path";
74909
+ import { readFile as readFile29, writeFile as writeFile17 } from "fs/promises";
74910
+ import path35 from "path";
74855
74911
  import { defineCommand as defineCommand137 } from "citty";
74856
74912
  function setNodePrompt(canvas, nodeId, text2) {
74857
74913
  const nodes = canvas?.nodes;
@@ -74880,7 +74936,7 @@ var SetPromptError = class extends Error {
74880
74936
  }
74881
74937
  };
74882
74938
  async function setPromptInCanvasFile(canvasPath, nodeId, text2) {
74883
- const filePath = path34.resolve(canvasPath);
74939
+ const filePath = path35.resolve(canvasPath);
74884
74940
  const original = await readFile29(filePath, "utf8");
74885
74941
  let canvas;
74886
74942
  try {
@@ -74904,9 +74960,9 @@ async function setPromptInCanvasFile(canvasPath, nodeId, text2) {
74904
74960
  } catch (e) {
74905
74961
  throw new SetPromptError("node_not_found", e instanceof Error ? e.message : String(e));
74906
74962
  }
74907
- await writeFile16(filePath, `${JSON.stringify(updated, null, 2)}
74963
+ await writeFile17(filePath, `${JSON.stringify(updated, null, 2)}
74908
74964
  `, "utf8");
74909
- const restore = () => writeFile16(filePath, original, "utf8");
74965
+ const restore = () => writeFile17(filePath, original, "utf8");
74910
74966
  try {
74911
74967
  const prepared = await prepareCanvas(filePath);
74912
74968
  const validation = await validateCanvasDeep(prepared.canvas, defaultRegistry());
@@ -74948,7 +75004,7 @@ var setPromptCommand = defineCommand137({
74948
75004
  },
74949
75005
  async run({ args: args8 }) {
74950
75006
  let text2;
74951
- if (args8["text-file"]) text2 = await readFile29(path34.resolve(String(args8["text-file"])), "utf8");
75007
+ if (args8["text-file"]) text2 = await readFile29(path35.resolve(String(args8["text-file"])), "utf8");
74952
75008
  else if (args8.text !== void 0) text2 = String(args8.text);
74953
75009
  else {
74954
75010
  process.stderr.write(
@@ -75005,7 +75061,7 @@ var staleCommand = defineCommand138({
75005
75061
  });
75006
75062
 
75007
75063
  // src/commands/canvas/validate.ts
75008
- import path35 from "path";
75064
+ import path36 from "path";
75009
75065
  import { defineCommand as defineCommand139 } from "citty";
75010
75066
  var validateCommand = defineCommand139({
75011
75067
  meta: {
@@ -75014,7 +75070,7 @@ var validateCommand = defineCommand139({
75014
75070
  },
75015
75071
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
75016
75072
  async run({ args: args8 }) {
75017
- const filePath = path35.resolve(String(args8.file));
75073
+ const filePath = path36.resolve(String(args8.file));
75018
75074
  let prepared;
75019
75075
  try {
75020
75076
  prepared = await prepareCanvas(filePath, { log: (line) => process.stderr.write(`${line}
@@ -75576,7 +75632,7 @@ var feedbackCommand = defineCommand144({
75576
75632
 
75577
75633
  // src/commands/creatives/performance.ts
75578
75634
  import { readFileSync as readFileSync16 } from "fs";
75579
- import path36 from "path";
75635
+ import path37 from "path";
75580
75636
  import { defineCommand as defineCommand145 } from "citty";
75581
75637
  import { parse as parseYaml2 } from "yaml";
75582
75638
  var DESCRIPTION4 = `How each Baker creative is doing in the live Meta ads that show it: spend, impressions, CTR, CPC, results, cost per result, frequency and a fatigue verdict, next to the angle, hook, mechanism and dominant slot its definition set out to test. Video creatives add hookRate (percent of impressions that watched 3 seconds) and holdRate (percent of those that reached a ThruPlay). Use it before briefing new creatives, to learn which angle and mechanism to make next and which creatives to replace.
@@ -75629,7 +75685,7 @@ function definitionInsights(markdown) {
75629
75685
  }
75630
75686
  function readLocalDefinition(slug) {
75631
75687
  try {
75632
- return readFileSync16(path36.join(process.cwd(), "src", "creatives", slug, "_definition.md"), "utf8");
75688
+ return readFileSync16(path37.join(process.cwd(), "src", "creatives", slug, "_definition.md"), "utf8");
75633
75689
  } catch {
75634
75690
  return null;
75635
75691
  }
@@ -76188,12 +76244,12 @@ Full guide: __tooling__/docs/tools/baker/creatives.md`
76188
76244
  import { defineCommand as defineCommand149 } from "citty";
76189
76245
 
76190
76246
  // src/commands/experiment/composition.ts
76191
- import { readdir as readdir13, readFile as readFile33 } from "fs/promises";
76192
- import path38 from "path";
76247
+ import { readdir as readdir14, readFile as readFile33 } from "fs/promises";
76248
+ import path39 from "path";
76193
76249
 
76194
76250
  // src/commands/landing/import-graph.ts
76195
- import { readdir as readdir12, readFile as readFile32, stat as stat6 } from "fs/promises";
76196
- import path37 from "path";
76251
+ import { readdir as readdir13, readFile as readFile32, stat as stat6 } from "fs/promises";
76252
+ import path38 from "path";
76197
76253
  var SOURCE_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
76198
76254
  var RESOLVE_CANDIDATES = [
76199
76255
  "",
@@ -76220,13 +76276,13 @@ async function isFile(p) {
76220
76276
  async function walkFiles(dir) {
76221
76277
  let entries;
76222
76278
  try {
76223
- entries = await readdir12(dir, { withFileTypes: true });
76279
+ entries = await readdir13(dir, { withFileTypes: true });
76224
76280
  } catch {
76225
76281
  return [];
76226
76282
  }
76227
76283
  const out = [];
76228
76284
  for (const entry of entries) {
76229
- const full = path37.join(dir, entry.name);
76285
+ const full = path38.join(dir, entry.name);
76230
76286
  if (entry.isDirectory()) {
76231
76287
  if (entry.name === "node_modules" || entry.name === "dist") continue;
76232
76288
  out.push(...await walkFiles(full));
@@ -76240,8 +76296,8 @@ async function resolveSpecifier(specifier, fromFile, root) {
76240
76296
  const bare = specifier.split("?")[0] ?? "";
76241
76297
  if (bare.includes("*")) return null;
76242
76298
  let base;
76243
- if (bare.startsWith("/")) base = path37.join(root, bare.slice(1));
76244
- else if (bare.startsWith(".")) base = path37.resolve(path37.dirname(fromFile), bare);
76299
+ if (bare.startsWith("/")) base = path38.join(root, bare.slice(1));
76300
+ else if (bare.startsWith(".")) base = path38.resolve(path38.dirname(fromFile), bare);
76245
76301
  else return null;
76246
76302
  for (const suffix of RESOLVE_CANDIDATES) {
76247
76303
  const candidate = base + suffix;
@@ -76263,7 +76319,7 @@ async function importedFiles(text2, file, root) {
76263
76319
  }
76264
76320
  async function landingGraphFiles(root, slug) {
76265
76321
  const seen = /* @__PURE__ */ new Set();
76266
- const queue = await walkFiles(path37.join(root, "src/pages", slug));
76322
+ const queue = await walkFiles(path38.join(root, "src/pages", slug));
76267
76323
  while (queue.length > 0) {
76268
76324
  const file = queue.pop();
76269
76325
  if (file === void 0 || seen.has(file)) continue;
@@ -76278,7 +76334,7 @@ async function landingGraphFiles(root, slug) {
76278
76334
  if (!seen.has(target2)) queue.push(target2);
76279
76335
  }
76280
76336
  }
76281
- return new Set([...seen].map((abs) => path37.relative(root, abs).split(path37.sep).join("/")));
76337
+ return new Set([...seen].map((abs) => path38.relative(root, abs).split(path38.sep).join("/")));
76282
76338
  }
76283
76339
 
76284
76340
  // src/commands/experiment/composition.ts
@@ -76323,7 +76379,7 @@ function formsOnlyIn(these, those) {
76323
76379
  }
76324
76380
  async function knownFlows(root) {
76325
76381
  try {
76326
- const entries = await readdir13(path38.join(root, "src/lib/flow-engine/flows"), { withFileTypes: true });
76382
+ const entries = await readdir14(path39.join(root, "src/lib/flow-engine/flows"), { withFileTypes: true });
76327
76383
  return new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name));
76328
76384
  } catch {
76329
76385
  return /* @__PURE__ */ new Set();
@@ -76334,7 +76390,7 @@ async function readForms(root, slug) {
76334
76390
  const [files, flows] = await Promise.all([landingGraphFiles(root, slug), knownFlows(root)]);
76335
76391
  if (flows.size === 0) return [];
76336
76392
  const texts = await Promise.all(
76337
- [...files].filter((file) => /\.(astro|ts|tsx|js|mjs)$/.test(file)).map((file) => readFile33(path38.join(root, file), "utf8"))
76393
+ [...files].filter((file) => /\.(astro|ts|tsx|js|mjs)$/.test(file)).map((file) => readFile33(path39.join(root, file), "utf8"))
76338
76394
  );
76339
76395
  return formsReferenced(texts, flows);
76340
76396
  } catch {
@@ -76344,8 +76400,8 @@ async function readForms(root, slug) {
76344
76400
 
76345
76401
  // src/commands/experiment/fold.ts
76346
76402
  import { statSync } from "fs";
76347
- import { cp as cp3, mkdir as mkdir10, readdir as readdir14, readFile as readFile34, rm as rm9, stat as stat7, writeFile as writeFile17 } from "fs/promises";
76348
- import path40 from "path";
76403
+ import { cp as cp3, mkdir as mkdir11, readdir as readdir15, readFile as readFile34, rm as rm9, stat as stat7, writeFile as writeFile18 } from "fs/promises";
76404
+ import path41 from "path";
76349
76405
 
76350
76406
  // ../api/src/experiments/variants.ts
76351
76407
  var VARIANT_SEPARATOR = "--";
@@ -76370,21 +76426,21 @@ function nextVariantNumber(page, existingSlugs, archived) {
76370
76426
  }
76371
76427
 
76372
76428
  // src/commands/landing/repoint.ts
76373
- import path39 from "path";
76429
+ import path40 from "path";
76374
76430
  var QUOTED_RELATIVE = /(['"])(\.\.?\/[^'"]*)\1/g;
76375
76431
  function isInside3(abs, dir) {
76376
- return abs === dir || abs.startsWith(dir + path39.sep);
76432
+ return abs === dir || abs.startsWith(dir + path40.sep);
76377
76433
  }
76378
76434
  function toSpecifier(from, to) {
76379
- const rel = path39.relative(from, to).split(path39.sep).join("/");
76435
+ const rel = path40.relative(from, to).split(path40.sep).join("/");
76380
76436
  return rel.startsWith(".") ? rel : `./${rel}`;
76381
76437
  }
76382
76438
  function repointSpecifier(spec, opts) {
76383
76439
  if (!spec.startsWith(".")) return spec;
76384
- const abs = path39.resolve(opts.fromDir, spec);
76440
+ const abs = path40.resolve(opts.fromDir, spec);
76385
76441
  if (opts.forkedTargets?.has(abs)) {
76386
- const withinControl = path39.relative(opts.controlDir, abs);
76387
- return toSpecifier(opts.toDir, path39.resolve(opts.variantDir, withinControl));
76442
+ const withinControl = path40.relative(opts.controlDir, abs);
76443
+ return toSpecifier(opts.toDir, path40.resolve(opts.variantDir, withinControl));
76388
76444
  }
76389
76445
  if (!isInside3(abs, opts.controlDir)) return spec;
76390
76446
  return toSpecifier(opts.toDir, abs);
@@ -76396,9 +76452,9 @@ function repointFile(text2, opts) {
76396
76452
  }
76397
76453
  function repointMoved(text2, opts) {
76398
76454
  return text2.replace(QUOTED_RELATIVE, (_match, quote, spec) => {
76399
- const abs = path39.resolve(opts.fromDir, spec);
76400
- const within = path39.relative(opts.movedFrom, abs);
76401
- const target2 = within.startsWith("..") || path39.isAbsolute(within) ? abs : path39.resolve(opts.movedTo, within);
76455
+ const abs = path40.resolve(opts.fromDir, spec);
76456
+ const within = path40.relative(opts.movedFrom, abs);
76457
+ const target2 = within.startsWith("..") || path40.isAbsolute(within) ? abs : path40.resolve(opts.movedTo, within);
76402
76458
  return `${quote}${toSpecifier(opts.toDir, target2)}${quote}`;
76403
76459
  });
76404
76460
  }
@@ -76407,7 +76463,7 @@ function repointMoved(text2, opts) {
76407
76463
  var ARCHIVE_ROOT = "src/_variants";
76408
76464
  var QUOTED_RELATIVE2 = /(['"])(\.\.?\/[^'"]*)\1/g;
76409
76465
  function posix2(p) {
76410
- return p.split(path40.sep).join("/");
76466
+ return p.split(path41.sep).join("/");
76411
76467
  }
76412
76468
  async function isDir(p) {
76413
76469
  try {
@@ -76419,46 +76475,46 @@ async function isDir(p) {
76419
76475
  async function filesUnder(dir, prefix = "") {
76420
76476
  let entries;
76421
76477
  try {
76422
- entries = await readdir14(dir, { withFileTypes: true });
76478
+ entries = await readdir15(dir, { withFileTypes: true });
76423
76479
  } catch {
76424
76480
  return [];
76425
76481
  }
76426
76482
  const out = [];
76427
76483
  for (const entry of entries) {
76428
76484
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
76429
- if (entry.isDirectory()) out.push(...await filesUnder(path40.join(dir, entry.name), rel));
76485
+ if (entry.isDirectory()) out.push(...await filesUnder(path41.join(dir, entry.name), rel));
76430
76486
  else out.push(rel);
76431
76487
  }
76432
76488
  return out.sort();
76433
76489
  }
76434
76490
  var TEXT_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte|md|json|css)$/;
76435
76491
  function archiveRelPath(abs, base) {
76436
- if (!abs.startsWith(base + path40.sep)) return null;
76437
- return posix2(path40.relative(base, abs));
76492
+ if (!abs.startsWith(base + path41.sep)) return null;
76493
+ return posix2(path41.relative(base, abs));
76438
76494
  }
76439
76495
  async function archiveArm(opts) {
76440
76496
  const { root, armDir, pageDir, archiveDir, armSlug } = opts;
76441
76497
  const targets = await archiveContents({ root, armDir, pageDir, armSlug });
76442
- const archivedBySource = new Map([...targets].map(([rel, abs]) => [abs, path40.join(archiveDir, rel)]));
76498
+ const archivedBySource = new Map([...targets].map(([rel, abs]) => [abs, path41.join(archiveDir, rel)]));
76443
76499
  const written = [];
76444
76500
  for (const [rel, abs] of [...targets].sort()) {
76445
- const dest = path40.join(archiveDir, rel);
76446
- await mkdir10(path40.dirname(dest), { recursive: true });
76501
+ const dest = path41.join(archiveDir, rel);
76502
+ await mkdir11(path41.dirname(dest), { recursive: true });
76447
76503
  if (!TEXT_EXT.test(rel)) {
76448
76504
  await cp3(abs, dest);
76449
76505
  } else {
76450
76506
  const text2 = await readFile34(abs, "utf8");
76451
- await writeFile17(dest, repointIntoArchive(text2, abs, dest, archivedBySource), "utf8");
76507
+ await writeFile18(dest, repointIntoArchive(text2, abs, dest, archivedBySource), "utf8");
76452
76508
  }
76453
- written.push(posix2(path40.relative(root, dest)));
76509
+ written.push(posix2(path41.relative(root, dest)));
76454
76510
  }
76455
76511
  return written;
76456
76512
  }
76457
76513
  async function archiveContents(opts) {
76458
76514
  const { root, armDir, pageDir, armSlug } = opts;
76459
76515
  const graph = await landingGraphFiles(root, armSlug);
76460
- const reachable = new Set([...graph].map((rel) => path40.resolve(root, rel)));
76461
- for (const rel of await filesUnder(armDir)) reachable.add(path40.join(armDir, rel));
76516
+ const reachable = new Set([...graph].map((rel) => path41.resolve(root, rel)));
76517
+ for (const rel of await filesUnder(armDir)) reachable.add(path41.join(armDir, rel));
76462
76518
  const sorted = [...reachable].sort();
76463
76519
  const targets = /* @__PURE__ */ new Map();
76464
76520
  for (const base of [pageDir, armDir]) {
@@ -76471,14 +76527,14 @@ async function archiveContents(opts) {
76471
76527
  return targets;
76472
76528
  }
76473
76529
  function repointIntoArchive(text2, sourceAbs, destAbs, archivedBySource) {
76474
- const fromDir = path40.dirname(sourceAbs);
76475
- const toDir = path40.dirname(destAbs);
76530
+ const fromDir = path41.dirname(sourceAbs);
76531
+ const toDir = path41.dirname(destAbs);
76476
76532
  return text2.replace(QUOTED_RELATIVE2, (match, quote, spec, offset) => {
76477
76533
  const [specPath, suffix] = splitSuffix(spec);
76478
- const target2 = path40.resolve(fromDir, specPath);
76534
+ const target2 = path41.resolve(fromDir, specPath);
76479
76535
  const resolved = resolveInArchive(target2, archivedBySource) ?? resolveOnDisk(target2, isImportPosition(text2, offset));
76480
76536
  if (resolved === null) return match;
76481
- const rel = posix2(path40.relative(toDir, resolved));
76537
+ const rel = posix2(path41.relative(toDir, resolved));
76482
76538
  return `${quote}${rel.startsWith(".") ? rel : `./${rel}`}${suffix}${quote}`;
76483
76539
  });
76484
76540
  }
@@ -76512,25 +76568,25 @@ async function promoteVariantFiles(opts) {
76512
76568
  const written = [];
76513
76569
  for (const rel of await filesUnder(variantDir)) {
76514
76570
  if (rel === "_definition.md") continue;
76515
- const from = path40.join(variantDir, rel);
76516
- const to = path40.join(pageDir, rel);
76517
- await mkdir10(path40.dirname(to), { recursive: true });
76571
+ const from = path41.join(variantDir, rel);
76572
+ const to = path41.join(pageDir, rel);
76573
+ await mkdir11(path41.dirname(to), { recursive: true });
76518
76574
  if (!TEXT_EXT.test(rel)) {
76519
76575
  await cp3(from, to);
76520
76576
  } else {
76521
76577
  const text2 = await readFile34(from, "utf8");
76522
- await writeFile17(
76578
+ await writeFile18(
76523
76579
  to,
76524
76580
  repointMoved(text2, {
76525
- fromDir: path40.dirname(from),
76526
- toDir: path40.dirname(to),
76581
+ fromDir: path41.dirname(from),
76582
+ toDir: path41.dirname(to),
76527
76583
  movedFrom: variantDir,
76528
76584
  movedTo: pageDir
76529
76585
  }),
76530
76586
  "utf8"
76531
76587
  );
76532
76588
  }
76533
- written.push(posix2(path40.relative(root, to)));
76589
+ written.push(posix2(path41.relative(root, to)));
76534
76590
  }
76535
76591
  return written;
76536
76592
  }
@@ -76554,8 +76610,8 @@ function archiveRecord(target2, variantNumber) {
76554
76610
  `;
76555
76611
  }
76556
76612
  async function foldExperiment(root, target2) {
76557
- const pageDir = path40.resolve(root, "src/pages", target2.landingSlug);
76558
- const variantDir = path40.resolve(root, "src/pages", target2.variantSlug);
76613
+ const pageDir = path41.resolve(root, "src/pages", target2.landingSlug);
76614
+ const variantDir = path41.resolve(root, "src/pages", target2.variantSlug);
76559
76615
  const variantNumber = variantNumberOf(target2.variantSlug);
76560
76616
  if (variantNumber === null) {
76561
76617
  return {
@@ -76569,9 +76625,9 @@ async function foldExperiment(root, target2) {
76569
76625
  return { error: `src/pages/${target2.variantSlug}/ is already gone \u2014 this test looks folded in already` };
76570
76626
  }
76571
76627
  const archiveKey = target2.landingInternalId ?? target2.landingSlug;
76572
- const archiveDir = path40.resolve(root, ARCHIVE_ROOT, archiveKey, String(variantNumber));
76628
+ const archiveDir = path41.resolve(root, ARCHIVE_ROOT, archiveKey, String(variantNumber));
76573
76629
  await rm9(archiveDir, { recursive: true, force: true });
76574
- await mkdir10(archiveDir, { recursive: true });
76630
+ await mkdir11(archiveDir, { recursive: true });
76575
76631
  const written = await archiveArm({
76576
76632
  root,
76577
76633
  armDir: target2.survivor === "variant" ? pageDir : variantDir,
@@ -76579,8 +76635,8 @@ async function foldExperiment(root, target2) {
76579
76635
  archiveDir,
76580
76636
  armSlug: target2.survivor === "variant" ? target2.landingSlug : target2.variantSlug
76581
76637
  });
76582
- await writeFile17(path40.join(archiveDir, "_variant.json"), archiveRecord(target2, variantNumber), "utf8");
76583
- written.push(posix2(path40.join(ARCHIVE_ROOT, archiveKey, String(variantNumber), "_variant.json")));
76638
+ await writeFile18(path41.join(archiveDir, "_variant.json"), archiveRecord(target2, variantNumber), "utf8");
76639
+ written.push(posix2(path41.join(ARCHIVE_ROOT, archiveKey, String(variantNumber), "_variant.json")));
76584
76640
  if (target2.survivor === "variant") {
76585
76641
  written.push(...await promoteVariantFiles({ root, pageDir, variantDir }));
76586
76642
  }
@@ -76588,7 +76644,7 @@ async function foldExperiment(root, target2) {
76588
76644
  return {
76589
76645
  experimentId: target2.experimentId,
76590
76646
  page: target2.landingSlug,
76591
- archivedTo: posix2(path40.join(ARCHIVE_ROOT, archiveKey, String(variantNumber))),
76647
+ archivedTo: posix2(path41.join(ARCHIVE_ROOT, archiveKey, String(variantNumber))),
76592
76648
  written,
76593
76649
  removed: [`src/pages/${target2.variantSlug}`]
76594
76650
  };
@@ -77361,10 +77417,10 @@ function parseEvidence(raw, rawArgs) {
77361
77417
 
77362
77418
  // src/commands/experiment/identity.ts
77363
77419
  import { readFile as readFile35 } from "fs/promises";
77364
- import path41 from "path";
77420
+ import path42 from "path";
77365
77421
  async function readPageInternalId(root, slug) {
77366
77422
  try {
77367
- const text2 = await readFile35(path41.resolve(root, "src", "pages", slug, "_definition.md"), "utf8");
77423
+ const text2 = await readFile35(path42.resolve(root, "src", "pages", slug, "_definition.md"), "utf8");
77368
77424
  return /^internalId:\s*"?([^"\s]+)"?\s*$/m.exec(text2)?.[1];
77369
77425
  } catch {
77370
77426
  return void 0;
@@ -77373,7 +77429,7 @@ async function readPageInternalId(root, slug) {
77373
77429
 
77374
77430
  // src/commands/experiment/measurement.ts
77375
77431
  import { readFile as readFile36 } from "fs/promises";
77376
- import path42 from "path";
77432
+ import path43 from "path";
77377
77433
  function eventDeclarationsIn(source) {
77378
77434
  const found = [];
77379
77435
  const pattern = /\b(data-baker-(?:view|event))\s*=\s*["']([^"']+)["']/g;
@@ -77433,7 +77489,7 @@ function sectionsOf(files, slug) {
77433
77489
  return files.filter((file) => file.startsWith(prefix) && !file.slice(prefix.length).startsWith("index."));
77434
77490
  }
77435
77491
  async function declarationsOf(root, files) {
77436
- const sources = await Promise.all(files.map((file) => readFile36(path42.join(root, file), "utf8").catch(() => "")));
77492
+ const sources = await Promise.all(files.map((file) => readFile36(path43.join(root, file), "utf8").catch(() => "")));
77437
77493
  return sources.flatMap(eventDeclarationsIn);
77438
77494
  }
77439
77495
 
@@ -78401,7 +78457,7 @@ import { readFileSync as readFileSync18 } from "fs";
78401
78457
  import { defineCommand as defineCommand151 } from "citty";
78402
78458
 
78403
78459
  // src/commands/flows/value-expression.ts
78404
- import { existsSync as existsSync8, readFileSync as readFileSync17 } from "fs";
78460
+ import { existsSync as existsSync9, readFileSync as readFileSync17 } from "fs";
78405
78461
  import { join as join4 } from "path";
78406
78462
  var PREFIXES2 = ["field", "tracking", "global", "code"];
78407
78463
  function splitParts(raw) {
@@ -78485,10 +78541,10 @@ function parseValueExpression(raw) {
78485
78541
  return parts.map(parsePart);
78486
78542
  }
78487
78543
  function trackingFieldIds() {
78488
- const path56 = join4(flowsDir(), "..", "tracking.ts");
78489
- if (!existsSync8(path56)) return null;
78544
+ const path57 = join4(flowsDir(), "..", "tracking.ts");
78545
+ if (!existsSync9(path57)) return null;
78490
78546
  try {
78491
- const source = readFileSync17(path56, "utf-8");
78547
+ const source = readFileSync17(path57, "utf-8");
78492
78548
  const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
78493
78549
  if (!block2) return null;
78494
78550
  const ids2 = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
@@ -79062,13 +79118,13 @@ function specsFromFile(parsed) {
79062
79118
  return `${destField}${type}=${entry?.value ?? ""}`;
79063
79119
  });
79064
79120
  }
79065
- function readSpecFile(path56) {
79121
+ function readSpecFile(path57) {
79066
79122
  let raw;
79067
79123
  try {
79068
- raw = path56 === "-" ? readFileSync18(0, "utf-8") : readFileSync18(path56, "utf-8");
79124
+ raw = path57 === "-" ? readFileSync18(0, "utf-8") : readFileSync18(path57, "utf-8");
79069
79125
  } catch (error) {
79070
79126
  refuse(
79071
- `Could not read ${path56 === "-" ? "the mapping from stdin" : `"${path56}"`}: ${error instanceof Error ? error.message : String(error)}`
79127
+ `Could not read ${path57 === "-" ? "the mapping from stdin" : `"${path57}"`}: ${error instanceof Error ? error.message : String(error)}`
79072
79128
  );
79073
79129
  }
79074
79130
  let parsed;
@@ -79076,7 +79132,7 @@ function readSpecFile(path56) {
79076
79132
  parsed = JSON.parse(raw);
79077
79133
  } catch (error) {
79078
79134
  refuse(
79079
- `${path56 === "-" ? "stdin" : `"${path56}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
79135
+ `${path57 === "-" ? "stdin" : `"${path57}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
79080
79136
  'Expected { "map": { "<destField>": "<value>", \u2026 } }'
79081
79137
  );
79082
79138
  }
@@ -79375,21 +79431,21 @@ var ARRAY_FIELDS = [
79375
79431
  "tagIds"
79376
79432
  ];
79377
79433
  var ARRAY_OWNERS = ["", "body"];
79378
- function dropUnsetOptionals(sideEffect, path56) {
79434
+ function dropUnsetOptionals(sideEffect, path57) {
79379
79435
  return OPTIONAL_STRINGS.flatMap((key) => {
79380
79436
  if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
79381
79437
  delete sideEffect[key];
79382
- return [{ path: path56, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
79438
+ return [{ path: path57, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
79383
79439
  });
79384
79440
  }
79385
- function fillNulledArrays(target2, prefix, path56) {
79441
+ function fillNulledArrays(target2, prefix, path57) {
79386
79442
  return ARRAY_FIELDS.flatMap((key) => {
79387
79443
  if (!(key in target2) || target2[key] !== null) return [];
79388
79444
  target2[key] = [];
79389
- return [{ path: path56, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
79445
+ return [{ path: path57, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
79390
79446
  });
79391
79447
  }
79392
- function tidyEmailRecipients(sideEffect, path56) {
79448
+ function tidyEmailRecipients(sideEffect, path57) {
79393
79449
  if (sideEffect.type !== "email") return [];
79394
79450
  const config = sideEffect.encryptedConfig;
79395
79451
  if (!config || typeof config !== "object" || Array.isArray(config)) return [];
@@ -79400,7 +79456,7 @@ function tidyEmailRecipients(sideEffect, path56) {
79400
79456
  const tidied = to.join(", ");
79401
79457
  if (tidied === raw) return [];
79402
79458
  config.email = tidied;
79403
- return [{ path: path56, change: "tidied the recipient list's spacing and separators" }];
79459
+ return [{ path: path57, change: "tidied the recipient list's spacing and separators" }];
79404
79460
  }
79405
79461
  function sideEffectsOf(node) {
79406
79462
  if (!Array.isArray(node.sideEffects)) return [];
@@ -79409,13 +79465,13 @@ function sideEffectsOf(node) {
79409
79465
  );
79410
79466
  }
79411
79467
  function normalizeSideEffect(sideEffect, where) {
79412
- const path56 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
79468
+ const path57 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
79413
79469
  const arrays = ARRAY_OWNERS.flatMap((owner) => {
79414
79470
  const target2 = owner ? sideEffect[owner] : sideEffect;
79415
79471
  if (!target2 || typeof target2 !== "object") return [];
79416
- return fillNulledArrays(target2, owner ? `${owner}.` : "", path56);
79472
+ return fillNulledArrays(target2, owner ? `${owner}.` : "", path57);
79417
79473
  });
79418
- return [...dropUnsetOptionals(sideEffect, path56), ...arrays, ...tidyEmailRecipients(sideEffect, path56)];
79474
+ return [...dropUnsetOptionals(sideEffect, path57), ...arrays, ...tidyEmailRecipients(sideEffect, path57)];
79419
79475
  }
79420
79476
  function normalizeFlowTree(tree) {
79421
79477
  const changes = [];
@@ -80807,10 +80863,10 @@ async function stageOps(ops) {
80807
80863
  handleError5(err);
80808
80864
  }
80809
80865
  }
80810
- async function draftAction2(path56, body, chat) {
80866
+ async function draftAction2(path57, body, chat) {
80811
80867
  const chatId = resolveChatId(chat);
80812
80868
  try {
80813
- const { data, hints: hints2 } = splitHints(await apiPost(path56, { chatId, ...body }));
80869
+ const { data, hints: hints2 } = splitHints(await apiPost(path57, { chatId, ...body }));
80814
80870
  writeJsonEnvelope({ ok: true, data, ...hints2.length > 0 ? { hints: hints2 } : {} });
80815
80871
  return data;
80816
80872
  } catch (err) {
@@ -81065,7 +81121,7 @@ Examples:
81065
81121
  });
81066
81122
 
81067
81123
  // src/commands/ga4/query.ts
81068
- import { appendFileSync as appendFileSync2, existsSync as existsSync9, readFileSync as readFileSync21, writeFileSync as writeFileSync4 } from "fs";
81124
+ import { appendFileSync as appendFileSync2, existsSync as existsSync10, readFileSync as readFileSync21, writeFileSync as writeFileSync4 } from "fs";
81069
81125
  import { resolve as resolve2 } from "path";
81070
81126
  import { defineCommand as defineCommand160 } from "citty";
81071
81127
 
@@ -81139,7 +81195,7 @@ function writeRowsToFile2(filePath, rows, append) {
81139
81195
  const fields = extractFields2(rows);
81140
81196
  const ext = filePath.split(".").pop()?.toLowerCase();
81141
81197
  if (ext === "csv") {
81142
- if (!append || !existsSync9(filePath)) {
81198
+ if (!append || !existsSync10(filePath)) {
81143
81199
  writeFileSync4(filePath, `${toCsvRow(fields)}
81144
81200
  `, "utf-8");
81145
81201
  }
@@ -81150,12 +81206,12 @@ function writeRowsToFile2(filePath, rows, append) {
81150
81206
  const lines = rows.map((row) => JSON.stringify(row));
81151
81207
  const content = `${lines.join("\n")}
81152
81208
  `;
81153
- if (append && existsSync9(filePath)) {
81209
+ if (append && existsSync10(filePath)) {
81154
81210
  appendFileSync2(filePath, content, "utf-8");
81155
81211
  } else {
81156
81212
  writeFileSync4(filePath, content, "utf-8");
81157
81213
  }
81158
- } else if (append && existsSync9(filePath)) {
81214
+ } else if (append && existsSync10(filePath)) {
81159
81215
  const existing = JSON.parse(readFileSync21(filePath, "utf-8"));
81160
81216
  writeFileSync4(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
81161
81217
  } else {
@@ -82008,7 +82064,7 @@ Full guide: __tooling__/docs/tools/baker/ga4.md`
82008
82064
  import { defineCommand as defineCommand166 } from "citty";
82009
82065
 
82010
82066
  // src/commands/gsc/query.ts
82011
- import { appendFileSync as appendFileSync3, existsSync as existsSync10, readFileSync as readFileSync22, writeFileSync as writeFileSync5 } from "fs";
82067
+ import { appendFileSync as appendFileSync3, existsSync as existsSync11, readFileSync as readFileSync22, writeFileSync as writeFileSync5 } from "fs";
82012
82068
  import { resolve as resolve3 } from "path";
82013
82069
  import { defineCommand as defineCommand163 } from "citty";
82014
82070
 
@@ -82140,7 +82196,7 @@ function writeRowsToFile3(filePath, rows, append) {
82140
82196
  const fields = extractFields3(rows);
82141
82197
  const ext = filePath.split(".").pop()?.toLowerCase();
82142
82198
  if (ext === "csv") {
82143
- if (!append || !existsSync10(filePath)) {
82199
+ if (!append || !existsSync11(filePath)) {
82144
82200
  writeFileSync5(filePath, `${toCsvRow(fields)}
82145
82201
  `, "utf-8");
82146
82202
  }
@@ -82150,12 +82206,12 @@ function writeRowsToFile3(filePath, rows, append) {
82150
82206
  } else if (ext === "jsonl") {
82151
82207
  const content = `${rows.map((row) => JSON.stringify(row)).join("\n")}
82152
82208
  `;
82153
- if (append && existsSync10(filePath)) {
82209
+ if (append && existsSync11(filePath)) {
82154
82210
  appendFileSync3(filePath, content, "utf-8");
82155
82211
  } else {
82156
82212
  writeFileSync5(filePath, content, "utf-8");
82157
82213
  }
82158
- } else if (append && existsSync10(filePath)) {
82214
+ } else if (append && existsSync11(filePath)) {
82159
82215
  const existing = JSON.parse(readFileSync22(filePath, "utf-8"));
82160
82216
  writeFileSync5(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
82161
82217
  } else {
@@ -83305,7 +83361,7 @@ function cropSprite(input, region) {
83305
83361
 
83306
83362
  // src/lib/image/io.ts
83307
83363
  import { randomBytes } from "crypto";
83308
- import { glob as fsGlob, readFile as readFile37, rename, stat as stat8, writeFile as writeFile18 } from "fs/promises";
83364
+ import { glob as fsGlob, readFile as readFile37, rename, stat as stat8, writeFile as writeFile19 } from "fs/promises";
83309
83365
  import { dirname as dirname2, extname as extname3, join as join5, resolve as resolve4 } from "path";
83310
83366
  var REMOTE_RE = /^https?:\/\//i;
83311
83367
  var GLOB_RE = /[*?[\]{}]/;
@@ -83340,9 +83396,9 @@ async function readImageBuffer(pathOrUrl) {
83340
83396
  }
83341
83397
  return readFile37(pathOrUrl);
83342
83398
  }
83343
- async function isDirectory(path56) {
83399
+ async function isDirectory(path57) {
83344
83400
  try {
83345
- const s = await stat8(path56);
83401
+ const s = await stat8(path57);
83346
83402
  return s.isDirectory();
83347
83403
  } catch {
83348
83404
  return false;
@@ -83361,7 +83417,7 @@ async function atomicWrite(targetPath, data) {
83361
83417
  const absolute = resolve4(targetPath);
83362
83418
  const dir = dirname2(absolute);
83363
83419
  const tmp = join5(dir, `.baker-image-${randomBytes(8).toString("hex")}.tmp`);
83364
- await writeFile18(tmp, data);
83420
+ await writeFile19(tmp, data);
83365
83421
  await rename(tmp, absolute);
83366
83422
  }
83367
83423
 
@@ -83770,13 +83826,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
83770
83826
  }
83771
83827
  function disambiguate(paths) {
83772
83828
  const taken = /* @__PURE__ */ new Set();
83773
- return paths.map((path56) => {
83774
- if (!taken.has(path56)) {
83775
- taken.add(path56);
83776
- return path56;
83829
+ return paths.map((path57) => {
83830
+ if (!taken.has(path57)) {
83831
+ taken.add(path57);
83832
+ return path57;
83777
83833
  }
83778
- const ext = extname4(path56);
83779
- const stem = path56.slice(0, path56.length - ext.length);
83834
+ const ext = extname4(path57);
83835
+ const stem = path57.slice(0, path57.length - ext.length);
83780
83836
  let n = 2;
83781
83837
  while (taken.has(`${stem}-${n}${ext}`)) n += 1;
83782
83838
  const unique = `${stem}-${n}${ext}`;
@@ -83902,10 +83958,10 @@ async function runDownloads(plan) {
83902
83958
  const paths = disambiguate(fetched.map((item) => item.path));
83903
83959
  const downloaded = [];
83904
83960
  for (const [index, item] of fetched.entries()) {
83905
- const path56 = paths[index] ?? item.path;
83961
+ const path57 = paths[index] ?? item.path;
83906
83962
  try {
83907
- await atomicWrite(path56, item.buffer);
83908
- downloaded.push({ input: item.input, output: path56, bytes: item.buffer.length, contentType: item.contentType });
83963
+ await atomicWrite(path57, item.buffer);
83964
+ downloaded.push({ input: item.input, output: path57, bytes: item.buffer.length, contentType: item.contentType });
83909
83965
  } catch (err) {
83910
83966
  failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
83911
83967
  }
@@ -86887,8 +86943,8 @@ Full guide: __tooling__/docs/tools/baker/images.md`
86887
86943
  import { defineCommand as defineCommand207 } from "citty";
86888
86944
 
86889
86945
  // src/commands/landing/critique.ts
86890
- import { readdir as readdir16, readFile as readFile39, stat as stat10 } from "fs/promises";
86891
- import path45 from "path";
86946
+ import { readdir as readdir17, readFile as readFile39, stat as stat10 } from "fs/promises";
86947
+ import path46 from "path";
86892
86948
  import { defineCommand as defineCommand196 } from "citty";
86893
86949
 
86894
86950
  // src/engine/landing/lib/constants.ts
@@ -88079,27 +88135,27 @@ function describeCounts(findings) {
88079
88135
  }
88080
88136
 
88081
88137
  // src/commands/landing/snapshot.ts
88082
- import { mkdir as mkdir11, rename as rename2, writeFile as writeFile19 } from "fs/promises";
88083
- import path43 from "path";
88138
+ import { mkdir as mkdir12, rename as rename2, writeFile as writeFile20 } from "fs/promises";
88139
+ import path44 from "path";
88084
88140
  var CRITIC_VERSION = "4";
88085
88141
  function critiqueCacheDir(projectRoot) {
88086
- return path43.join(projectRoot, ".cache", "landing-critique");
88142
+ return path44.join(projectRoot, ".cache", "landing-critique");
88087
88143
  }
88088
88144
  function snapshotPath(projectRoot, slug) {
88089
- return path43.join(critiqueCacheDir(projectRoot), `${slug}.json`);
88145
+ return path44.join(critiqueCacheDir(projectRoot), `${slug}.json`);
88090
88146
  }
88091
88147
  async function writeCritiqueSnapshot(projectRoot, snapshot) {
88092
- await mkdir11(critiqueCacheDir(projectRoot), { recursive: true });
88148
+ await mkdir12(critiqueCacheDir(projectRoot), { recursive: true });
88093
88149
  const dest = snapshotPath(projectRoot, snapshot.slug);
88094
88150
  const tmp = `${dest}.tmp`;
88095
- await writeFile19(tmp, `${JSON.stringify(snapshot, null, 2)}
88151
+ await writeFile20(tmp, `${JSON.stringify(snapshot, null, 2)}
88096
88152
  `, "utf8");
88097
88153
  await rename2(tmp, dest);
88098
88154
  }
88099
88155
 
88100
88156
  // src/commands/landing/source-version.ts
88101
- import { readdir as readdir15, readFile as readFile38, stat as stat9 } from "fs/promises";
88102
- import path44 from "path";
88157
+ import { readdir as readdir16, readFile as readFile38, stat as stat9 } from "fs/promises";
88158
+ import path45 from "path";
88103
88159
  var CRITIQUED_ROOTS = ["src/pages/", "src/components/"];
88104
88160
  async function landingSourceRelPaths(root, slug) {
88105
88161
  const files = await landingGraphFiles(root, slug);
@@ -88108,7 +88164,7 @@ async function landingSourceRelPaths(root, slug) {
88108
88164
  async function readLandingSources(root, slug) {
88109
88165
  const rel = await landingSourceRelPaths(root, slug);
88110
88166
  const out = [];
88111
- for (const r of rel) out.push({ path: r, text: await readFile38(path44.join(root, r), "utf8") });
88167
+ for (const r of rel) out.push({ path: r, text: await readFile38(path45.join(root, r), "utf8") });
88112
88168
  return out;
88113
88169
  }
88114
88170
  async function computeLandingSourceSha(root, slug) {
@@ -88117,7 +88173,7 @@ async function computeLandingSourceSha(root, slug) {
88117
88173
  for (const r of rel) {
88118
88174
  let bytes;
88119
88175
  try {
88120
- bytes = await readFile38(path44.join(root, r));
88176
+ bytes = await readFile38(path45.join(root, r));
88121
88177
  } catch {
88122
88178
  bytes = Buffer.alloc(0);
88123
88179
  }
@@ -88127,16 +88183,16 @@ async function computeLandingSourceSha(root, slug) {
88127
88183
  }
88128
88184
  async function computeLegacyLandingSourceSha(landingDir) {
88129
88185
  const rel = [];
88130
- if (await isFile2(path44.join(landingDir, "index.astro"))) rel.push("index.astro");
88131
- for (const abs of await walkAstro(path44.join(landingDir, "_components"))) {
88132
- rel.push(path44.relative(landingDir, abs).split(path44.sep).join("/"));
88186
+ if (await isFile2(path45.join(landingDir, "index.astro"))) rel.push("index.astro");
88187
+ for (const abs of await walkAstro(path45.join(landingDir, "_components"))) {
88188
+ rel.push(path45.relative(landingDir, abs).split(path45.sep).join("/"));
88133
88189
  }
88134
88190
  rel.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
88135
88191
  const parts = [];
88136
88192
  for (const r of rel) {
88137
88193
  let bytes;
88138
88194
  try {
88139
- bytes = await readFile38(path44.join(landingDir, r));
88195
+ bytes = await readFile38(path45.join(landingDir, r));
88140
88196
  } catch {
88141
88197
  bytes = Buffer.alloc(0);
88142
88198
  }
@@ -88154,13 +88210,13 @@ async function isFile2(p) {
88154
88210
  async function walkAstro(dir) {
88155
88211
  let entries;
88156
88212
  try {
88157
- entries = await readdir15(dir, { withFileTypes: true });
88213
+ entries = await readdir16(dir, { withFileTypes: true });
88158
88214
  } catch {
88159
88215
  return [];
88160
88216
  }
88161
88217
  const out = [];
88162
88218
  for (const entry of entries) {
88163
- const abs = path44.join(dir, entry.name);
88219
+ const abs = path45.join(dir, entry.name);
88164
88220
  if (entry.isDirectory()) out.push(...await walkAstro(abs));
88165
88221
  else if (entry.isFile() && entry.name.endsWith(".astro")) out.push(abs);
88166
88222
  }
@@ -88221,7 +88277,7 @@ var critiqueCommand2 = defineCommand196({
88221
88277
  { availableSlugs: await listLandingSlugs(projectRoot) }
88222
88278
  );
88223
88279
  }
88224
- if (!await isDir2(path45.resolve(projectRoot, "src", "pages", slug))) {
88280
+ if (!await isDir2(path46.resolve(projectRoot, "src", "pages", slug))) {
88225
88281
  fail8("NOT_FOUND", `No landing at src/pages/${slug}/`, {
88226
88282
  availableSlugs: await listLandingSlugs(projectRoot)
88227
88283
  });
@@ -88264,7 +88320,7 @@ async function critiqueOne(projectRoot, slug, brand, competitors) {
88264
88320
  const [sources, compositionSha, sourceSha] = await Promise.all([
88265
88321
  readLandingSources(projectRoot, slug),
88266
88322
  computeLandingSourceSha(projectRoot, slug),
88267
- computeLegacyLandingSourceSha(path45.resolve(projectRoot, "src", "pages", slug))
88323
+ computeLegacyLandingSourceSha(path46.resolve(projectRoot, "src", "pages", slug))
88268
88324
  ]);
88269
88325
  const report = critiqueLanding({ slug, sources, brand, competitors });
88270
88326
  let snapshotFailed = false;
@@ -88284,18 +88340,18 @@ async function critiqueOne(projectRoot, slug, brand, competitors) {
88284
88340
  return { slug, report, snapshotFailed };
88285
88341
  }
88286
88342
  async function readCompetitorNames(projectRoot) {
88287
- const dir = path45.join(projectRoot, "src", "content", "competitors");
88343
+ const dir = path46.join(projectRoot, "src", "content", "competitors");
88288
88344
  let entries;
88289
88345
  try {
88290
- entries = (await readdir16(dir)).filter((f) => f.endsWith(".md"));
88346
+ entries = (await readdir17(dir)).filter((f) => f.endsWith(".md"));
88291
88347
  } catch {
88292
88348
  return [];
88293
88349
  }
88294
88350
  const names = [];
88295
88351
  for (const entry of entries) {
88296
- names.push(path45.basename(entry, ".md").replace(/[-_]+/g, " "));
88352
+ names.push(path46.basename(entry, ".md").replace(/[-_]+/g, " "));
88297
88353
  try {
88298
- const head = (await readFile39(path45.join(dir, entry), "utf8")).slice(0, 2e3);
88354
+ const head = (await readFile39(path46.join(dir, entry), "utf8")).slice(0, 2e3);
88299
88355
  const titled = /^\s*(?:title|name)\s*:\s*["']?([^"'\n]+)["']?\s*$/im.exec(head);
88300
88356
  if (titled?.[1]) names.push(titled[1].trim());
88301
88357
  } catch {
@@ -88305,7 +88361,7 @@ async function readCompetitorNames(projectRoot) {
88305
88361
  }
88306
88362
  async function listLandingSlugs(projectRoot) {
88307
88363
  try {
88308
- const entries = await readdir16(path45.join(projectRoot, "src", "pages"), { withFileTypes: true });
88364
+ const entries = await readdir17(path46.join(projectRoot, "src", "pages"), { withFileTypes: true });
88309
88365
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
88310
88366
  } catch {
88311
88367
  return [];
@@ -88456,8 +88512,8 @@ var addCommand = defineCommand197({
88456
88512
  });
88457
88513
 
88458
88514
  // src/commands/landing/inspiration/code.ts
88459
- import { mkdir as mkdir12, writeFile as writeFile20 } from "fs/promises";
88460
- import path46 from "path";
88515
+ import { mkdir as mkdir13, writeFile as writeFile21 } from "fs/promises";
88516
+ import path47 from "path";
88461
88517
  import { defineCommand as defineCommand198 } from "citty";
88462
88518
  registerSchema({
88463
88519
  command: "landing.inspiration.code",
@@ -88480,10 +88536,10 @@ var codeCommand = defineCommand198({
88480
88536
  try {
88481
88537
  const id = args8.id;
88482
88538
  const data = await apiGet("/api/landing-inspiration/section-code", { id });
88483
- const dir = path46.join(process.cwd(), ".baker", "inspiration", id);
88484
- await mkdir12(dir, { recursive: true });
88485
- const file = path46.join(dir, "section.html");
88486
- await writeFile20(file, data.html);
88539
+ const dir = path47.join(process.cwd(), ".baker", "inspiration", id);
88540
+ await mkdir13(dir, { recursive: true });
88541
+ const file = path47.join(dir, "section.html");
88542
+ await writeFile21(file, data.html);
88487
88543
  const hints2 = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
88488
88544
  const fidelity = fidelityHint(data.fidelity);
88489
88545
  if (fidelity) hints2.push(fidelity);
@@ -88492,7 +88548,7 @@ var codeCommand = defineCommand198({
88492
88548
  ok: true,
88493
88549
  data: {
88494
88550
  id,
88495
- file: path46.relative(process.cwd(), file),
88551
+ file: path47.relative(process.cwd(), file),
88496
88552
  bytes: data.html.length,
88497
88553
  fidelity: data.fidelity,
88498
88554
  reproduction_notes: data.reproductionNotes,
@@ -88923,8 +88979,8 @@ function classifyCaptureFailure(error) {
88923
88979
  }
88924
88980
 
88925
88981
  // src/engine/landing-library/run.ts
88926
- import { mkdir as mkdir13, writeFile as writeFile22 } from "fs/promises";
88927
- import path48 from "path";
88982
+ import { mkdir as mkdir14, writeFile as writeFile23 } from "fs/promises";
88983
+ import path49 from "path";
88928
88984
 
88929
88985
  // ../proxy/src/preflight.ts
88930
88986
  import http from "http";
@@ -90339,11 +90395,11 @@ async function renderBundleToPng(browser, html, viewportWidth, options = {}) {
90339
90395
  }
90340
90396
 
90341
90397
  // src/engine/landing-library/report.ts
90342
- import { writeFile as writeFile21 } from "fs/promises";
90343
- import path47 from "path";
90398
+ import { writeFile as writeFile22 } from "fs/promises";
90399
+ import path48 from "path";
90344
90400
  async function writeCaptureReport(manifest, outDir) {
90345
- const file = path47.join(outDir, "report.html");
90346
- await writeFile21(file, renderReport(manifest));
90401
+ const file = path48.join(outDir, "report.html");
90402
+ await writeFile22(file, renderReport(manifest));
90347
90403
  return file;
90348
90404
  }
90349
90405
  function escapeHtml3(value2) {
@@ -90521,32 +90577,32 @@ async function reproducePage(args8) {
90521
90577
  const { browser, page, outDir, pageUrl, livePageShot } = args8;
90522
90578
  const built = await buildSectionBundle(page, "body", pageUrl).catch(() => null);
90523
90579
  if (!built) return { bundle: null, fidelity: null };
90524
- await writeFile22(path48.join(outDir, "page.html"), built.html);
90580
+ await writeFile23(path49.join(outDir, "page.html"), built.html);
90525
90581
  const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width, {
90526
90582
  wholePage: true,
90527
90583
  timeoutMs: 6e4
90528
90584
  });
90529
90585
  if (!rendered || !livePageShot) return { bundle: "page.html", fidelity: null };
90530
- await writeFile22(path48.join(outDir, "page-rendered.png"), rendered);
90586
+ await writeFile23(path49.join(outDir, "page-rendered.png"), rendered);
90531
90587
  const { score, note } = await scoreFidelity(livePageShot, rendered);
90532
90588
  return { bundle: "page.html", fidelity: score, ...note ? { fidelityNote: note } : {} };
90533
90589
  }
90534
90590
  async function captureOneSection(args8) {
90535
90591
  const { browser, page, candidate, sectionsDir, outDir, pageUrl, withCode } = args8;
90536
- const dir = path48.join(sectionsDir, String(candidate.index).padStart(2, "0"));
90537
- await mkdir13(dir, { recursive: true });
90592
+ const dir = path49.join(sectionsDir, String(candidate.index).padStart(2, "0"));
90593
+ await mkdir14(dir, { recursive: true });
90538
90594
  const desktop = await captureSection(page, candidate);
90539
- if (desktop) await writeFile22(path48.join(dir, "desktop.png"), desktop);
90595
+ if (desktop) await writeFile23(path49.join(dir, "desktop.png"), desktop);
90540
90596
  const visualHash = desktop ? await perceptualHash(desktop) : null;
90541
90597
  const motion = await collectMotion(page, candidate.selector);
90542
90598
  const built = withCode ? await buildSectionBundle(page, candidate.selector, pageUrl) : null;
90543
90599
  let fidelity = null;
90544
90600
  let fidelityNote;
90545
90601
  if (built) {
90546
- await writeFile22(path48.join(dir, "section.html"), built.html);
90602
+ await writeFile23(path49.join(dir, "section.html"), built.html);
90547
90603
  const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width);
90548
90604
  if (rendered && desktop) {
90549
- await writeFile22(path48.join(dir, "section-rendered.png"), rendered);
90605
+ await writeFile23(path49.join(dir, "section-rendered.png"), rendered);
90550
90606
  const result = await scoreFidelity(desktop, rendered);
90551
90607
  fidelity = result.score;
90552
90608
  fidelityNote = result.note;
@@ -90554,9 +90610,9 @@ async function captureOneSection(args8) {
90554
90610
  }
90555
90611
  return {
90556
90612
  ...candidate,
90557
- desktopShot: desktop ? path48.relative(outDir, path48.join(dir, "desktop.png")) : null,
90613
+ desktopShot: desktop ? path49.relative(outDir, path49.join(dir, "desktop.png")) : null,
90558
90614
  mobileShot: null,
90559
- bundle: built ? path48.relative(outDir, path48.join(dir, "section.html")) : null,
90615
+ bundle: built ? path49.relative(outDir, path49.join(dir, "section.html")) : null,
90560
90616
  fidelity,
90561
90617
  ...fidelityNote ? { fidelityNote } : {},
90562
90618
  ...built ? { cssStats: built.stats } : {},
@@ -90575,9 +90631,9 @@ async function captureMobileShots(args8) {
90575
90631
  for (const section of sections) {
90576
90632
  const shot = await captureSectionOnMobile(mobile.page, section);
90577
90633
  if (!shot) continue;
90578
- const file = path48.join(sectionsDir, String(section.index).padStart(2, "0"), "mobile.png");
90579
- await writeFile22(file, shot);
90580
- section.mobileShot = path48.relative(outDir, file);
90634
+ const file = path49.join(sectionsDir, String(section.index).padStart(2, "0"), "mobile.png");
90635
+ await writeFile23(file, shot);
90636
+ section.mobileShot = path49.relative(outDir, file);
90581
90637
  }
90582
90638
  } finally {
90583
90639
  await mobile.context.close();
@@ -90592,10 +90648,10 @@ async function captureMotionTakes(args8) {
90592
90648
  const filmOne = async (section) => {
90593
90649
  const take = await captureMotionTake(browser, pageUrl, section.selector).catch(() => null);
90594
90650
  if (!take) return;
90595
- const dir = path48.join(sectionsDir, String(section.index).padStart(2, "0"));
90596
- const file = path48.join(dir, "motion-filmstrip.png");
90597
- await writeFile22(file, take.filmstrip);
90598
- section.motionFilmstrip = path48.relative(outDir, file);
90651
+ const dir = path49.join(sectionsDir, String(section.index).padStart(2, "0"));
90652
+ const file = path49.join(dir, "motion-filmstrip.png");
90653
+ await writeFile23(file, take.filmstrip);
90654
+ section.motionFilmstrip = path49.relative(outDir, file);
90599
90655
  log(` [${section.index}] ${section.motion.summary}`);
90600
90656
  };
90601
90657
  const queue = [...moving];
@@ -90652,7 +90708,7 @@ async function captureAlternateViews(args8) {
90652
90708
  async function reproduceWholePage(args8) {
90653
90709
  const { browser, page, outDir, pageUrl, withCode, log } = args8;
90654
90710
  const fullPage = await page.screenshot({ type: "png", fullPage: true }).catch(() => null);
90655
- if (fullPage) await writeFile22(path48.join(outDir, "full-page.png"), fullPage);
90711
+ if (fullPage) await writeFile23(path49.join(outDir, "full-page.png"), fullPage);
90656
90712
  if (!withCode) return { bundle: null, fidelity: null };
90657
90713
  const reproduction = await reproducePage({ browser, page, outDir, pageUrl, livePageShot: fullPage });
90658
90714
  log(`page reproduction: ${reproduction.fidelity === null ? "unavailable" : reproduction.fidelity.toFixed(2)}`);
@@ -90723,7 +90779,7 @@ async function openViaLadder(args8) {
90723
90779
  async function scrapeLanding(options) {
90724
90780
  const timeoutMs = options.timeoutMs ?? 45e3;
90725
90781
  const log = options.onProgress ?? (() => void 0);
90726
- const sectionsDir = path48.join(options.outDir, "sections");
90782
+ const sectionsDir = path49.join(options.outDir, "sections");
90727
90783
  const nonPublic = refuseNonPublicUrl(options.url);
90728
90784
  if (nonPublic) {
90729
90785
  throw new BlockedPageError({
@@ -90743,7 +90799,7 @@ async function scrapeLanding(options) {
90743
90799
  const withMotion = options.motion !== false && !escalated;
90744
90800
  const renderBrowser = options.code === false ? null : await launchBrowser();
90745
90801
  try {
90746
- await mkdir13(sectionsDir, { recursive: true });
90802
+ await mkdir14(sectionsDir, { recursive: true });
90747
90803
  const sections = await captureSections({
90748
90804
  browser: renderBrowser ?? browser,
90749
90805
  page,
@@ -90785,7 +90841,7 @@ async function scrapeLanding(options) {
90785
90841
  security: prepared.security,
90786
90842
  captureTier: tier
90787
90843
  };
90788
- await writeFile22(path48.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
90844
+ await writeFile23(path49.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
90789
90845
  `);
90790
90846
  if (options.report !== false) {
90791
90847
  const reportPath = await writeCaptureReport(manifest, options.outDir);
@@ -90799,29 +90855,29 @@ async function scrapeLanding(options) {
90799
90855
  }
90800
90856
 
90801
90857
  // src/commands/landing/inspiration/captureOut.ts
90802
- import { existsSync as existsSync11 } from "fs";
90803
- import path49 from "path";
90858
+ import { existsSync as existsSync12 } from "fs";
90859
+ import path50 from "path";
90804
90860
  var SCRATCH_DIR = ".baker";
90805
90861
  function isWithin(parent, target2) {
90806
- const relative = path49.relative(parent, target2);
90807
- return relative === "" || !relative.startsWith("..") && !path49.isAbsolute(relative);
90862
+ const relative = path50.relative(parent, target2);
90863
+ return relative === "" || !relative.startsWith("..") && !path50.isAbsolute(relative);
90808
90864
  }
90809
90865
  function findRepoRoot(from) {
90810
- let dir = path49.resolve(from);
90866
+ let dir = path50.resolve(from);
90811
90867
  for (; ; ) {
90812
- if (existsSync11(path49.join(dir, ".git"))) return dir;
90813
- const parent = path49.dirname(dir);
90868
+ if (existsSync12(path50.join(dir, ".git"))) return dir;
90869
+ const parent = path50.dirname(dir);
90814
90870
  if (parent === dir) return null;
90815
90871
  dir = parent;
90816
90872
  }
90817
90873
  }
90818
90874
  function checkCaptureOut(out, options) {
90819
90875
  const { cwd, repoRoot } = options;
90820
- const resolved = path49.resolve(cwd, out);
90876
+ const resolved = path50.resolve(cwd, out);
90821
90877
  if (repoRoot === null || !isWithin(repoRoot, resolved)) return { ok: true };
90822
- const scratch = path49.join(repoRoot, SCRATCH_DIR);
90878
+ const scratch = path50.join(repoRoot, SCRATCH_DIR);
90823
90879
  if (isWithin(scratch, resolved)) return { ok: true };
90824
- const suggestion = path49.posix.join(SCRATCH_DIR, "teardowns", path49.basename(resolved) || "capture");
90880
+ const suggestion = path50.posix.join(SCRATCH_DIR, "teardowns", path50.basename(resolved) || "capture");
90825
90881
  return {
90826
90882
  ok: false,
90827
90883
  error: {
@@ -90995,12 +91051,12 @@ var scrapeCommand = defineCommand201({
90995
91051
  });
90996
91052
 
90997
91053
  // src/commands/landing/inspiration/search.ts
90998
- import path51 from "path";
91054
+ import path52 from "path";
90999
91055
  import { defineCommand as defineCommand202 } from "citty";
91000
91056
 
91001
91057
  // src/commands/landing/inspiration/shot.ts
91002
- import { mkdir as mkdir14, writeFile as writeFile23 } from "fs/promises";
91003
- import path50 from "path";
91058
+ import { mkdir as mkdir15, writeFile as writeFile24 } from "fs/promises";
91059
+ import path51 from "path";
91004
91060
  import sharp8 from "sharp";
91005
91061
  var READABLE_SHOT = {
91006
91062
  maxWidth: 1440,
@@ -91026,9 +91082,9 @@ async function downloadReadableShot(url, file) {
91026
91082
  const response = await fetch(url);
91027
91083
  if (!response.ok) return null;
91028
91084
  const shot = await toReadableShot(Buffer.from(await response.arrayBuffer()));
91029
- await mkdir14(path50.dirname(file), { recursive: true });
91030
- await writeFile23(file, shot);
91031
- return path50.relative(process.cwd(), file);
91085
+ await mkdir15(path51.dirname(file), { recursive: true });
91086
+ await writeFile24(file, shot);
91087
+ return path51.relative(process.cwd(), file);
91032
91088
  } catch {
91033
91089
  return null;
91034
91090
  }
@@ -91120,13 +91176,13 @@ function buildSearchBody(args8) {
91120
91176
  return body;
91121
91177
  }
91122
91178
  async function downloadShots(results) {
91123
- const dir = path51.join(process.cwd(), ".baker", "inspiration");
91179
+ const dir = path52.join(process.cwd(), ".baker", "inspiration");
91124
91180
  const saved = /* @__PURE__ */ new Map();
91125
91181
  await Promise.all(
91126
91182
  results.map(async (result) => {
91127
91183
  const file = await downloadReadableShot(
91128
91184
  result.desktopShotUrl,
91129
- path51.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
91185
+ path52.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
91130
91186
  );
91131
91187
  if (file) saved.set(result.id, file);
91132
91188
  })
@@ -91354,7 +91410,7 @@ var sequencesCommand = defineCommand203({
91354
91410
  });
91355
91411
 
91356
91412
  // src/commands/landing/inspiration/view.ts
91357
- import path52 from "path";
91413
+ import path53 from "path";
91358
91414
  import { defineCommand as defineCommand204 } from "citty";
91359
91415
  registerSchema({
91360
91416
  command: "landing.inspiration.view",
@@ -91387,12 +91443,12 @@ var viewCommand2 = defineCommand204({
91387
91443
  const id = args8.id;
91388
91444
  const data = await apiGet("/api/landing-inspiration/section", { id });
91389
91445
  const section = data.section;
91390
- const dir = path52.join(process.cwd(), ".baker", "inspiration", id);
91446
+ const dir = path53.join(process.cwd(), ".baker", "inspiration", id);
91391
91447
  const ext = READABLE_SHOT.extension;
91392
91448
  const [desktop, mobile, filmstrip] = await Promise.all([
91393
- downloadReadableShot(section.desktopShotUrl, path52.join(dir, `desktop.${ext}`)),
91394
- downloadReadableShot(section.mobileShotUrl, path52.join(dir, `mobile.${ext}`)),
91395
- downloadReadableShot(section.motionFilmstripUrl, path52.join(dir, `motion-filmstrip.${ext}`))
91449
+ downloadReadableShot(section.desktopShotUrl, path53.join(dir, `desktop.${ext}`)),
91450
+ downloadReadableShot(section.mobileShotUrl, path53.join(dir, `mobile.${ext}`)),
91451
+ downloadReadableShot(section.motionFilmstripUrl, path53.join(dir, `motion-filmstrip.${ext}`))
91396
91452
  ]);
91397
91453
  const full = args8.full;
91398
91454
  const hints2 = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
@@ -91498,8 +91554,8 @@ Full guide: __tooling__/docs/tools/baker/landing.md`
91498
91554
 
91499
91555
  // src/commands/landing/variant.ts
91500
91556
  import { randomUUID as randomUUID3 } from "crypto";
91501
- import { mkdir as mkdir15, readdir as readdir17, readFile as readFile40, stat as stat11, writeFile as writeFile24 } from "fs/promises";
91502
- import path53 from "path";
91557
+ import { mkdir as mkdir16, readdir as readdir18, readFile as readFile40, stat as stat11, writeFile as writeFile25 } from "fs/promises";
91558
+ import path54 from "path";
91503
91559
  import { defineCommand as defineCommand206 } from "citty";
91504
91560
  registerSchema({
91505
91561
  command: "landing.variant",
@@ -91535,7 +91591,7 @@ async function readInternalId(definitionPath) {
91535
91591
  async function archivedVariantNumbers(root, internalId) {
91536
91592
  if (!internalId) return [];
91537
91593
  try {
91538
- const entries = await readdir17(path53.resolve(root, "src/_variants", internalId), { withFileTypes: true });
91594
+ const entries = await readdir18(path54.resolve(root, "src/_variants", internalId), { withFileTypes: true });
91539
91595
  return entries.filter((entry) => entry.isDirectory()).map((entry) => Number(entry.name)).filter((n) => Number.isInteger(n) && n > 0);
91540
91596
  } catch {
91541
91597
  return [];
@@ -91565,7 +91621,7 @@ async function exists2(p) {
91565
91621
  }
91566
91622
  async function listLandingSlugs2(root) {
91567
91623
  try {
91568
- const entries = await readdir17(path53.resolve(root, "src", "pages"), { withFileTypes: true });
91624
+ const entries = await readdir18(path54.resolve(root, "src", "pages"), { withFileTypes: true });
91569
91625
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
91570
91626
  } catch {
91571
91627
  return [];
@@ -91574,14 +91630,14 @@ async function listLandingSlugs2(root) {
91574
91630
  async function listComponents(componentsDir, prefix = "") {
91575
91631
  let entries;
91576
91632
  try {
91577
- entries = await readdir17(componentsDir, { withFileTypes: true });
91633
+ entries = await readdir18(componentsDir, { withFileTypes: true });
91578
91634
  } catch {
91579
91635
  return [];
91580
91636
  }
91581
91637
  const out = [];
91582
91638
  for (const entry of entries) {
91583
91639
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
91584
- if (entry.isDirectory()) out.push(...await listComponents(path53.join(componentsDir, entry.name), rel));
91640
+ if (entry.isDirectory()) out.push(...await listComponents(path54.join(componentsDir, entry.name), rel));
91585
91641
  else if (entry.name.endsWith(".astro")) out.push(rel);
91586
91642
  }
91587
91643
  return out.sort();
@@ -91648,16 +91704,16 @@ async function resolveTargets(projectRoot, opts) {
91648
91704
  `"${controlSlug}" is already a variant of "${variantOfSlug(controlSlug)}". Make the next variant of the page itself: \`baker landing variant ${variantOfSlug(controlSlug)}\`.`
91649
91705
  );
91650
91706
  }
91651
- const controlDir = path53.resolve(projectRoot, "src", "pages", controlSlug);
91707
+ const controlDir = path54.resolve(projectRoot, "src", "pages", controlSlug);
91652
91708
  if (!await isDir3(controlDir)) {
91653
91709
  fail9("NOT_FOUND", `No page at src/pages/${controlSlug}/`, {
91654
91710
  availableSlugs: await listLandingSlugs2(projectRoot)
91655
91711
  });
91656
91712
  }
91657
- if (!await exists2(path53.join(controlDir, "index.astro"))) {
91713
+ if (!await exists2(path54.join(controlDir, "index.astro"))) {
91658
91714
  fail9("NOT_FOUND", `src/pages/${controlSlug}/index.astro is missing, so there is no page to make a variant of.`);
91659
91715
  }
91660
- const internalId = await readInternalId(path53.join(controlDir, "_definition.md"));
91716
+ const internalId = await readInternalId(path54.join(controlDir, "_definition.md"));
91661
91717
  const variantSlugValue = variantSlug(
91662
91718
  controlSlug,
91663
91719
  nextVariantNumber(
@@ -91666,8 +91722,8 @@ async function resolveTargets(projectRoot, opts) {
91666
91722
  await archivedVariantNumbers(projectRoot, internalId)
91667
91723
  )
91668
91724
  );
91669
- const variantDir = path53.resolve(projectRoot, "src", "pages", variantSlugValue);
91670
- const available = await listComponents(path53.join(controlDir, "_components"));
91725
+ const variantDir = path54.resolve(projectRoot, "src", "pages", variantSlugValue);
91726
+ const available = await listComponents(path54.join(controlDir, "_components"));
91671
91727
  const forks = [];
91672
91728
  for (const name of parseForks(opts.fork, opts.rawArgs)) {
91673
91729
  const resolved = resolveForkName(name, available);
@@ -91683,26 +91739,26 @@ async function resolveTargets(projectRoot, opts) {
91683
91739
  }
91684
91740
  async function writeVariant(opts) {
91685
91741
  const { controlDir, variantDir, controlSlug, variantSlug: variantSlug2, forks } = opts;
91686
- const forkedTargets = new Set(forks.map((f) => path53.join(controlDir, "_components", f)));
91742
+ const forkedTargets = new Set(forks.map((f) => path54.join(controlDir, "_components", f)));
91687
91743
  const written = [];
91688
- const indexText = await readFile40(path53.join(controlDir, "index.astro"), "utf8");
91689
- await mkdir15(variantDir, { recursive: true });
91690
- await writeFile24(
91691
- path53.join(variantDir, "index.astro"),
91744
+ const indexText = await readFile40(path54.join(controlDir, "index.astro"), "utf8");
91745
+ await mkdir16(variantDir, { recursive: true });
91746
+ await writeFile25(
91747
+ path54.join(variantDir, "index.astro"),
91692
91748
  repointFile(indexText, { fromDir: controlDir, toDir: variantDir, controlDir, variantDir, forkedTargets }),
91693
91749
  "utf8"
91694
91750
  );
91695
91751
  written.push(`src/pages/${variantSlug2}/index.astro`);
91696
91752
  for (const fork of forks) {
91697
- const fromFile = path53.join(controlDir, "_components", fork);
91698
- const toFile = path53.join(variantDir, "_components", fork);
91753
+ const fromFile = path54.join(controlDir, "_components", fork);
91754
+ const toFile = path54.join(variantDir, "_components", fork);
91699
91755
  const text2 = await readFile40(fromFile, "utf8");
91700
- await mkdir15(path53.dirname(toFile), { recursive: true });
91701
- await writeFile24(
91756
+ await mkdir16(path54.dirname(toFile), { recursive: true });
91757
+ await writeFile25(
91702
91758
  toFile,
91703
91759
  repointFile(text2, {
91704
- fromDir: path53.dirname(fromFile),
91705
- toDir: path53.dirname(toFile),
91760
+ fromDir: path54.dirname(fromFile),
91761
+ toDir: path54.dirname(toFile),
91706
91762
  controlDir,
91707
91763
  variantDir,
91708
91764
  forkedTargets
@@ -91711,7 +91767,7 @@ async function writeVariant(opts) {
91711
91767
  );
91712
91768
  written.push(`src/pages/${variantSlug2}/_components/${fork}`);
91713
91769
  }
91714
- const controlDefinitionPath = path53.join(controlDir, "_definition.md");
91770
+ const controlDefinitionPath = path54.join(controlDir, "_definition.md");
91715
91771
  if (await exists2(controlDefinitionPath)) {
91716
91772
  const definition = buildVariantDefinition(await readFile40(controlDefinitionPath, "utf8"), {
91717
91773
  internalId: randomUUID3().replace(/-/g, "").slice(0, 8),
@@ -91721,11 +91777,11 @@ async function writeVariant(opts) {
91721
91777
  ...opts.because ? { because: opts.because } : {},
91722
91778
  ...opts.change ? { change: opts.change } : {}
91723
91779
  });
91724
- await writeFile24(path53.join(variantDir, "_definition.md"), definition, "utf8");
91780
+ await writeFile25(path54.join(variantDir, "_definition.md"), definition, "utf8");
91725
91781
  written.push(`src/pages/${variantSlug2}/_definition.md`);
91726
91782
  }
91727
- await mkdir15(path53.join(variantDir, "_images"), { recursive: true });
91728
- await writeFile24(path53.join(variantDir, "_images", ".gitkeep"), "", "utf8");
91783
+ await mkdir16(path54.join(variantDir, "_images"), { recursive: true });
91784
+ await writeFile25(path54.join(variantDir, "_images", ".gitkeep"), "", "utf8");
91729
91785
  return written;
91730
91786
  }
91731
91787
  var variantCommand = defineCommand206({
@@ -94077,7 +94133,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
94077
94133
 
94078
94134
  // src/commands/scheduled-agents/templates.ts
94079
94135
  import { readFile as readFile41 } from "fs/promises";
94080
- import path54 from "path";
94136
+ import path55 from "path";
94081
94137
  import { defineCommand as defineCommand228 } from "citty";
94082
94138
  registerSchema({
94083
94139
  command: "scheduled-agents.templates",
@@ -94184,7 +94240,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
94184
94240
  }
94185
94241
  if (save.length > 0) {
94186
94242
  const briefFile = flag("brief-file");
94187
- const brief2 = briefFile.length > 0 ? await readFile41(path54.resolve(briefFile), "utf8") : flag("brief");
94243
+ const brief2 = briefFile.length > 0 ? await readFile41(path55.resolve(briefFile), "utf8") : flag("brief");
94188
94244
  if (brief2.trim().length === 0) {
94189
94245
  failValidation4("--brief-file (preferred) or --brief is required: the brief is the recipe.");
94190
94246
  }
@@ -94824,7 +94880,7 @@ function parseImageRefs(spec) {
94824
94880
  }
94825
94881
  var defaultDeps = {
94826
94882
  ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
94827
- upload: (path56) => uploadLocalImage({ file: path56, contentType: detectImageContentType(path56), source: "uploaded" })
94883
+ upload: (path57) => uploadLocalImage({ file: path57, contentType: detectImageContentType(path57), source: "uploaded" })
94828
94884
  };
94829
94885
  async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
94830
94886
  const refs = parseImageRefs(spec);
@@ -94844,10 +94900,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
94844
94900
  }
94845
94901
  return { imageIds, added };
94846
94902
  }
94847
- function uploadFailure(path56) {
94903
+ function uploadFailure(path57) {
94848
94904
  return (error) => {
94849
94905
  if (error instanceof ApiError) throw error;
94850
- throw new ApiError("VALIDATION_ERROR", `Could not read "${path56}" as an image.`);
94906
+ throw new ApiError("VALIDATION_ERROR", `Could not read "${path57}" as an image.`);
94851
94907
  };
94852
94908
  }
94853
94909
 
@@ -95947,10 +96003,10 @@ async function stageOp4(op) {
95947
96003
  handleError8(err);
95948
96004
  }
95949
96005
  }
95950
- async function draftAction3(path56, body, chat) {
96006
+ async function draftAction3(path57, body, chat) {
95951
96007
  const chatId = resolveChatId(chat);
95952
96008
  try {
95953
- const { data, hints: hints2 } = splitHints(await apiPost(path56, { chatId, ...body }));
96009
+ const { data, hints: hints2 } = splitHints(await apiPost(path57, { chatId, ...body }));
95954
96010
  writeJsonEnvelope({ ok: true, data, ...hints2.length > 0 ? { hints: hints2 } : {} });
95955
96011
  return data;
95956
96012
  } catch (err) {
@@ -97181,7 +97237,7 @@ var groupCommand2 = defineCommand255({
97181
97237
  // src/commands/videos/ingest.ts
97182
97238
  import { mkdtemp as mkdtemp3, rm as rm10, stat as stat12 } from "fs/promises";
97183
97239
  import { tmpdir as tmpdir4 } from "os";
97184
- import path55 from "path";
97240
+ import path56 from "path";
97185
97241
  import { defineCommand as defineCommand256 } from "citty";
97186
97242
 
97187
97243
  // src/lib/streamUpload.ts
@@ -97532,7 +97588,7 @@ function ingestUrl(args8) {
97532
97588
  }
97533
97589
  async function downloadThenIngest(args8, country) {
97534
97590
  const vimeoCookie = captureVimeoCookie();
97535
- const workDir = await mkdtemp3(path55.join(tmpdir4(), "videos-ingest-"));
97591
+ const workDir = await mkdtemp3(path56.join(tmpdir4(), "videos-ingest-"));
97536
97592
  try {
97537
97593
  const probe = await probeYtDlp({ url: args8.url, country, vimeoCookie, cookieDir: workDir });
97538
97594
  if (isAudioOnly(probe.info)) {