@koda-sl/baker-cli 0.455.0-dev.0e869aae7 → 0.457.0-dev.f1df1f4e9

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
@@ -201,7 +201,7 @@ import {
201
201
  withoutCastName,
202
202
  wordCount,
203
203
  ytDlpBlockSignal
204
- } from "./chunk-EIFW4274.js";
204
+ } from "./chunk-ZAQIZ4KZ.js";
205
205
  import {
206
206
  NAME_CONTAINS_ARG,
207
207
  csvOrJson,
@@ -35514,16 +35514,16 @@ async function runChatgptRead(reference, read, hintsFor4) {
35514
35514
  }
35515
35515
  }
35516
35516
  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.";
35517
- async function getChatgptList(path69, params) {
35518
- const { data, headers } = await apiGetWithHeaders(path69, params);
35517
+ async function getChatgptList(path70, params) {
35518
+ const { data, headers } = await apiGetWithHeaders(path70, params);
35519
35519
  return { data, truncated: headers.get(CHATGPT_ADS_TRUNCATED_HEADER) === "true" };
35520
35520
  }
35521
- async function runChatgptListRead(reference, path69, params, hintsFor4) {
35521
+ async function runChatgptListRead(reference, path70, params, hintsFor4) {
35522
35522
  let truncated = false;
35523
35523
  await runChatgptRead(
35524
35524
  reference,
35525
35525
  async () => {
35526
- const read = await getChatgptList(path69, params);
35526
+ const read = await getChatgptList(path70, params);
35527
35527
  truncated = read.truncated;
35528
35528
  return read.data;
35529
35529
  },
@@ -36328,7 +36328,7 @@ var MEMBER_ARGS = {
36328
36328
  },
36329
36329
  country: { type: "string", description: "Country of phones written without a +code, e.g. ES" }
36330
36330
  };
36331
- function membersFromArgs(args8, readFile52 = (path69) => readFileSync2(path69, "utf8")) {
36331
+ function membersFromArgs(args8, readFile52 = (path70) => readFileSync2(path70, "utf8")) {
36332
36332
  const fromFile = typeof args8.file === "string" && args8.file ? membersFromFile(readFile52(args8.file)) : { emails: [], phones: [] };
36333
36333
  const given = [...csvArg(args8.emails) ?? [], ...fromFile.emails];
36334
36334
  const givenPhones = [...csvArg(args8.phones) ?? [], ...fromFile.phones];
@@ -39721,9 +39721,9 @@ var COPY_LIST_FLAG = {
39721
39721
  descriptions: "--descriptions",
39722
39722
  longHeadlines: "--long-headlines"
39723
39723
  };
39724
- function valueAt(root, path69) {
39724
+ function valueAt(root, path70) {
39725
39725
  let node = root;
39726
- for (const key of path69) {
39726
+ for (const key of path70) {
39727
39727
  if (node === null || typeof node !== "object") return void 0;
39728
39728
  node = node[key];
39729
39729
  }
@@ -39956,11 +39956,11 @@ function parseKeywordEntry(raw, defaultMatch) {
39956
39956
  function rawTextEntries(value2, rawArgs) {
39957
39957
  return repeatedValues(rawArgs, "text", value2).flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
39958
39958
  }
39959
- function rawFileEntries(path69) {
39960
- if (typeof path69 !== "string" || path69.length === 0) {
39959
+ function rawFileEntries(path70) {
39960
+ if (typeof path70 !== "string" || path70.length === 0) {
39961
39961
  return [];
39962
39962
  }
39963
- return readFileSync4(path69, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
39963
+ return readFileSync4(path70, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
39964
39964
  }
39965
39965
  function keywordEntries(args8, rawArgs) {
39966
39966
  const defaultMatch = typeof args8["match-type"] === "string" ? args8["match-type"].toUpperCase() : void 0;
@@ -39983,14 +39983,14 @@ function keywordEntries(args8, rawArgs) {
39983
39983
  }
39984
39984
  return entries;
39985
39985
  }
39986
- function loadJsonFileArg(path69) {
39987
- if (typeof path69 !== "string" || path69.length === 0) {
39986
+ function loadJsonFileArg(path70) {
39987
+ if (typeof path70 !== "string" || path70.length === 0) {
39988
39988
  return {};
39989
39989
  }
39990
- const inline = path69.trimStart().startsWith("{");
39991
- const source = inline ? "inline JSON" : path69;
39990
+ const inline = path70.trimStart().startsWith("{");
39991
+ const source = inline ? "inline JSON" : path70;
39992
39992
  try {
39993
- const parsed = JSON.parse(inline ? path69 : readFileSync4(path69, "utf8"));
39993
+ const parsed = JSON.parse(inline ? path70 : readFileSync4(path70, "utf8"));
39994
39994
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
39995
39995
  failWriteValidation2(`${source} must contain a JSON object`);
39996
39996
  }
@@ -40127,10 +40127,10 @@ async function stageUpdate(kind, customerId, target2, payload, hints2) {
40127
40127
  async function stageTarget(kind, customerId, target2, hints2) {
40128
40128
  await stageGoogleOp({ kind, customerId, target: target2 }, hints2);
40129
40129
  }
40130
- async function draftAction(path69, body, chat) {
40130
+ async function draftAction(path70, body, chat) {
40131
40131
  try {
40132
40132
  const chatId = resolveChatId(chat);
40133
- const response = await apiPost(path69, { chatId, ...body });
40133
+ const response = await apiPost(path70, { chatId, ...body });
40134
40134
  writeJsonEnvelope(response);
40135
40135
  } catch (err) {
40136
40136
  handleGoogleError(err);
@@ -42550,14 +42550,14 @@ function mappingRowProblem(row2) {
42550
42550
 
42551
42551
  // ../api/src/event-sources/template.ts
42552
42552
  var MENTION = /\{\{\s*([^{}]+?)\s*\}\}/g;
42553
- function mentionOf(path69) {
42554
- return `{{${path69}}}`;
42553
+ function mentionOf(path70) {
42554
+ return `{{${path70}}}`;
42555
42555
  }
42556
42556
  function templateMentions(template) {
42557
42557
  const seen = [];
42558
42558
  for (const match of template.matchAll(MENTION)) {
42559
- const path69 = (match[1] ?? "").trim();
42560
- if (path69 !== "" && !seen.includes(path69)) seen.push(path69);
42559
+ const path70 = (match[1] ?? "").trim();
42560
+ if (path70 !== "" && !seen.includes(path70)) seen.push(path70);
42561
42561
  }
42562
42562
  return seen;
42563
42563
  }
@@ -45954,17 +45954,17 @@ function ignoredColumnHints(columns) {
45954
45954
  `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.`
45955
45955
  ];
45956
45956
  }
45957
- function readRowsFile(path69) {
45958
- const inline = path69.trimStart().startsWith("[") || path69.trimStart().startsWith("{");
45957
+ function readRowsFile(path70) {
45958
+ const inline = path70.trimStart().startsWith("[") || path70.trimStart().startsWith("{");
45959
45959
  let text3;
45960
45960
  try {
45961
- text3 = inline ? path69 : readFileSync6(path69, "utf8");
45961
+ text3 = inline ? path70 : readFileSync6(path70, "utf8");
45962
45962
  } catch (err) {
45963
- failWriteValidation2(`could not read ${path69}: ${err instanceof Error ? err.message : String(err)}`);
45963
+ failWriteValidation2(`could not read ${path70}: ${err instanceof Error ? err.message : String(err)}`);
45964
45964
  }
45965
45965
  const parsed = parseConversionRowsText(text3);
45966
45966
  if (!parsed.ok) {
45967
- failWriteValidation2(`${inline ? "the conversions passed inline" : path69}: ${parsed.error}`);
45967
+ failWriteValidation2(`${inline ? "the conversions passed inline" : path70}: ${parsed.error}`);
45968
45968
  }
45969
45969
  return { rows: parsed.rows, ignoredColumns: parsed.ignoredColumns };
45970
45970
  }
@@ -47865,19 +47865,19 @@ function failWriteValidation3(message) {
47865
47865
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
47866
47866
  process.exit(1);
47867
47867
  }
47868
- function loadJsonFileArg2(path69) {
47869
- if (typeof path69 !== "string" || path69.length === 0) {
47868
+ function loadJsonFileArg2(path70) {
47869
+ if (typeof path70 !== "string" || path70.length === 0) {
47870
47870
  return {};
47871
47871
  }
47872
47872
  try {
47873
- const parsed = JSON.parse(readFileSync7(path69, "utf8"));
47873
+ const parsed = JSON.parse(readFileSync7(path70, "utf8"));
47874
47874
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
47875
- failWriteValidation3(`${path69} must contain a JSON object`);
47875
+ failWriteValidation3(`${path70} must contain a JSON object`);
47876
47876
  }
47877
47877
  return parsed;
47878
47878
  } catch (err) {
47879
47879
  if (err instanceof SyntaxError) {
47880
- failWriteValidation3(`${path69} is not valid JSON: ${err.message}`);
47880
+ failWriteValidation3(`${path70} is not valid JSON: ${err.message}`);
47881
47881
  }
47882
47882
  throw err;
47883
47883
  }
@@ -47962,15 +47962,15 @@ function parseLocaleFlag(value2) {
47962
47962
  }
47963
47963
  return { language: match[1], country: match[2].toUpperCase() };
47964
47964
  }
47965
- function loadTargetingFileArg(path69) {
47966
- if (typeof path69 !== "string" || path69.length === 0) {
47965
+ function loadTargetingFileArg(path70) {
47966
+ if (typeof path70 !== "string" || path70.length === 0) {
47967
47967
  return void 0;
47968
47968
  }
47969
- const parsed = loadJsonFileArg2(path69);
47969
+ const parsed = loadJsonFileArg2(path70);
47970
47970
  const criteria = parsed.targetingCriteria ?? parsed;
47971
47971
  if (!criteria.include) {
47972
47972
  failWriteValidation3(
47973
- `${path69} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
47973
+ `${path70} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
47974
47974
  );
47975
47975
  }
47976
47976
  return criteria;
@@ -48005,14 +48005,14 @@ function parseCsvLine(line) {
48005
48005
  cells.push(current);
48006
48006
  return cells.map((cell3) => cell3.trim());
48007
48007
  }
48008
- function parseListFileArg(path69, maxRows) {
48009
- if (typeof path69 !== "string" || path69.length === 0) {
48008
+ function parseListFileArg(path70, maxRows) {
48009
+ if (typeof path70 !== "string" || path70.length === 0) {
48010
48010
  return void 0;
48011
48011
  }
48012
- const raw = readFileSync7(path69, "utf8");
48012
+ const raw = readFileSync7(path70, "utf8");
48013
48013
  const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
48014
48014
  if (lines.length < 2) {
48015
- failWriteValidation3(`${path69} needs a header row and at least one data row`);
48015
+ failWriteValidation3(`${path70} needs a header row and at least one data row`);
48016
48016
  }
48017
48017
  const columns = parseCsvLine(lines[0]).map((column) => column.trim());
48018
48018
  const rows = [];
@@ -48031,7 +48031,7 @@ function parseListFileArg(path69, maxRows) {
48031
48031
  }
48032
48032
  }
48033
48033
  if (rows.length > maxRows) {
48034
- failWriteValidation3(`${path69} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
48034
+ failWriteValidation3(`${path70} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
48035
48035
  }
48036
48036
  return { columns, rows };
48037
48037
  }
@@ -48127,11 +48127,11 @@ function readPositionals(args8) {
48127
48127
  function splitIdList(raw) {
48128
48128
  return raw.split(",").map((id) => id.trim()).filter(Boolean);
48129
48129
  }
48130
- function idsFileEntries(path69) {
48131
- if (typeof path69 !== "string" || path69.length === 0) {
48130
+ function idsFileEntries(path70) {
48131
+ if (typeof path70 !== "string" || path70.length === 0) {
48132
48132
  return [];
48133
48133
  }
48134
- return readFileSync7(path69, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
48134
+ return readFileSync7(path70, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
48135
48135
  }
48136
48136
  function requireTargets2(args8, entity) {
48137
48137
  const positionals = readPositionals(args8);
@@ -52233,54 +52233,54 @@ function ruleFields(node) {
52233
52233
  ([key, value2]) => (key === "and" || key === "or") && Array.isArray(value2) ? value2.flatMap(ruleFields) : [key]
52234
52234
  );
52235
52235
  }
52236
- function branchRefusal(key, value2, path69) {
52236
+ function branchRefusal(key, value2, path70) {
52237
52237
  if (!Array.isArray(value2) || value2.length === 0) {
52238
- return `${path69}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
52238
+ return `${path70}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
52239
52239
  }
52240
52240
  for (const [index, child] of value2.entries()) {
52241
- const refusal = ruleNodeRefusal(child, `${path69}.${key}[${index}]`);
52241
+ const refusal = ruleNodeRefusal(child, `${path70}.${key}[${index}]`);
52242
52242
  if (refusal) {
52243
52243
  return refusal;
52244
52244
  }
52245
52245
  }
52246
52246
  return void 0;
52247
52247
  }
52248
- function conditionRefusal(key, value2, path69) {
52249
- return key === "and" || key === "or" ? branchRefusal(key, value2, path69) : leafRefusal(key, value2, path69);
52248
+ function conditionRefusal(key, value2, path70) {
52249
+ return key === "and" || key === "or" ? branchRefusal(key, value2, path70) : leafRefusal(key, value2, path70);
52250
52250
  }
52251
- function ruleNodeRefusal(node, path69) {
52251
+ function ruleNodeRefusal(node, path70) {
52252
52252
  if (!isRecord2(node)) {
52253
- return `${path69} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
52253
+ return `${path70} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
52254
52254
  }
52255
52255
  const entries = Object.entries(node);
52256
52256
  if (entries.length === 0) {
52257
- return `${path69} is empty \u2014 a rule with no condition counts every event the pixel sends`;
52257
+ return `${path70} is empty \u2014 a rule with no condition counts every event the pixel sends`;
52258
52258
  }
52259
52259
  if (entries.length > 1) {
52260
- return `${path69} 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]}`;
52260
+ return `${path70} 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]}`;
52261
52261
  }
52262
52262
  for (const [key, value2] of entries) {
52263
- const refusal = conditionRefusal(key, value2, path69);
52263
+ const refusal = conditionRefusal(key, value2, path70);
52264
52264
  if (refusal) {
52265
52265
  return refusal;
52266
52266
  }
52267
52267
  }
52268
52268
  return void 0;
52269
52269
  }
52270
- function leafRefusal(field, condition, path69) {
52270
+ function leafRefusal(field, condition, path70) {
52271
52271
  if (!isRecord2(condition)) {
52272
- return `${path69}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
52272
+ return `${path70}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
52273
52273
  }
52274
52274
  const tests = Object.entries(condition);
52275
52275
  if (tests.length === 0) {
52276
- return `${path69}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
52276
+ return `${path70}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
52277
52277
  }
52278
52278
  if (tests.length > 1) {
52279
- return `${path69}.${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]}`;
52279
+ return `${path70}.${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]}`;
52280
52280
  }
52281
52281
  for (const [operator] of tests) {
52282
52282
  if (!RULE_OPERATORS[operator]) {
52283
- return `${path69}.${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)`;
52283
+ return `${path70}.${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)`;
52284
52284
  }
52285
52285
  }
52286
52286
  return void 0;
@@ -52996,11 +52996,11 @@ var updateStatusSchema2 = z52.enum(UPDATE_STATUSES);
52996
52996
  function currencyMinimums2(currencyCode) {
52997
52997
  return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
52998
52998
  }
52999
- function validateDailyBudgetFloor(money, ctx, path69) {
52999
+ function validateDailyBudgetFloor(money, ctx, path70) {
53000
53000
  if (money?.currencyCode) {
53001
53001
  const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
53002
53002
  if (Number(money.amount) < min) {
53003
- ctx.addIssue({ code: "custom", path: path69, message: `below the ${min} ${money.currencyCode} daily minimum` });
53003
+ ctx.addIssue({ code: "custom", path: path70, message: `below the ${min} ${money.currencyCode} daily minimum` });
53004
53004
  }
53005
53005
  }
53006
53006
  }
@@ -53918,19 +53918,19 @@ function refuseDeleteByUpdate(payload, group) {
53918
53918
  );
53919
53919
  }
53920
53920
  }
53921
- function loadJsonFileArg3(path69) {
53922
- if (typeof path69 !== "string" || path69.length === 0) {
53921
+ function loadJsonFileArg3(path70) {
53922
+ if (typeof path70 !== "string" || path70.length === 0) {
53923
53923
  return {};
53924
53924
  }
53925
53925
  try {
53926
- const parsed = JSON.parse(readFileSync11(path69, "utf8"));
53926
+ const parsed = JSON.parse(readFileSync11(path70, "utf8"));
53927
53927
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
53928
- failWriteValidation4(`${path69} must contain a JSON object`);
53928
+ failWriteValidation4(`${path70} must contain a JSON object`);
53929
53929
  }
53930
53930
  return parsed;
53931
53931
  } catch (err) {
53932
53932
  if (err instanceof SyntaxError) {
53933
- failWriteValidation4(`${path69} is not valid JSON: ${err.message}`);
53933
+ failWriteValidation4(`${path70} is not valid JSON: ${err.message}`);
53934
53934
  }
53935
53935
  throw err;
53936
53936
  }
@@ -54832,9 +54832,9 @@ var listArgs6 = {
54832
54832
  },
54833
54833
  ...META_LIST_SHAPE_ARGS
54834
54834
  };
54835
- async function readOrEmpty(path69, params, label, hints2) {
54835
+ async function readOrEmpty(path70, params, label, hints2) {
54836
54836
  try {
54837
- return await apiGet(path69, params);
54837
+ return await apiGet(path70, params);
54838
54838
  } catch (err) {
54839
54839
  const message = err instanceof Error ? err.message : "unknown error";
54840
54840
  hints2.push(`Could not read the account's ${label} (${message}); the viewer was read without them.`);
@@ -59777,12 +59777,12 @@ function flowExists(slug) {
59777
59777
  return existsSync3(join2(flowsDir(), slug, "_data.json"));
59778
59778
  }
59779
59779
  function readFlowTree(slug) {
59780
- const path69 = join2(flowsDir(), slug, "_data.json");
59781
- if (!existsSync3(path69)) {
59780
+ const path70 = join2(flowsDir(), slug, "_data.json");
59781
+ if (!existsSync3(path70)) {
59782
59782
  failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
59783
59783
  }
59784
59784
  try {
59785
- return JSON.parse(readFileSync13(path69, "utf-8"));
59785
+ return JSON.parse(readFileSync13(path70, "utf-8"));
59786
59786
  } catch (error) {
59787
59787
  failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
59788
59788
  }
@@ -60759,12 +60759,12 @@ function readPeopleFile(args8) {
60759
60759
  }
60760
60760
  function unreadablePeopleFile(args8) {
60761
60761
  if (!args8["people-file"]) return void 0;
60762
- const path69 = String(args8["people-file"]);
60762
+ const path70 = String(args8["people-file"]);
60763
60763
  try {
60764
- readFileSync14(path69, "utf8");
60764
+ readFileSync14(path70, "utf8");
60765
60765
  return void 0;
60766
60766
  } catch {
60767
- return `Couldn't read --people-file ${path69}. Check the path, or pass the people inline with --person.`;
60767
+ return `Couldn't read --people-file ${path70}. Check the path, or pass the people inline with --person.`;
60768
60768
  }
60769
60769
  }
60770
60770
  function peopleLimitError(args8) {
@@ -61736,11 +61736,11 @@ function parseFieldArgs(argv) {
61736
61736
  for (const pair of parseRepeated(argv, "--field")) {
61737
61737
  const eq = pair.indexOf("=");
61738
61738
  const field = eq === -1 ? pair : pair.slice(0, eq);
61739
- const path69 = eq === -1 ? "" : pair.slice(eq + 1).trim();
61739
+ const path70 = eq === -1 ? "" : pair.slice(eq + 1).trim();
61740
61740
  const problem = mappingRowProblem(field);
61741
61741
  if (problem !== null) throw new ConversionArgsError(problem);
61742
- if (path69 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
61743
- mapping[field] = path69;
61742
+ if (path70 === "") throw new ConversionArgsError(`--field ${field} needs a path: --field ${field}=<dotted.path>.`);
61743
+ mapping[field] = path70;
61744
61744
  }
61745
61745
  return mapping;
61746
61746
  }
@@ -63413,11 +63413,11 @@ function unwrap(response) {
63413
63413
  }
63414
63414
  return response.data;
63415
63415
  }
63416
- async function readAvatars(path69, params) {
63417
- return unwrap(await apiGet(path69, params));
63416
+ async function readAvatars(path70, params) {
63417
+ return unwrap(await apiGet(path70, params));
63418
63418
  }
63419
- async function writeAvatars(path69, body, opts) {
63420
- return unwrap(await apiPost(path69, body, opts));
63419
+ async function writeAvatars(path70, body, opts) {
63420
+ return unwrap(await apiPost(path70, body, opts));
63421
63421
  }
63422
63422
 
63423
63423
  // src/commands/avatars/create.ts
@@ -64531,12 +64531,12 @@ function missingFontFiles(urls, available) {
64531
64531
  function planFontAdoption(sources, families) {
64532
64532
  const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
64533
64533
  const byFamily = /* @__PURE__ */ new Map();
64534
- for (const { path: path69, source } of sources) {
64535
- const dir = posix.dirname(path69);
64534
+ for (const { path: path70, source } of sources) {
64535
+ const dir = posix.dirname(path70);
64536
64536
  for (const face of declaredFontFaces(source)) {
64537
64537
  if (!wanted.has(face.family)) continue;
64538
64538
  const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
64539
- perFile.set(path69, [...perFile.get(path69) ?? [], rebaseFontFaceSrc(face.block, dir)]);
64539
+ perFile.set(path70, [...perFile.get(path70) ?? [], rebaseFontFaceSrc(face.block, dir)]);
64540
64540
  byFamily.set(face.family, perFile);
64541
64541
  }
64542
64542
  }
@@ -67205,8 +67205,8 @@ function logoComposited(opts) {
67205
67205
  }
67206
67206
  var MAX_TAKES = 3;
67207
67207
  var UNCOMPILED = "compiled from prompt.json";
67208
- function ingestNode(id, path69, expect) {
67209
- return { id, type: "ingest", params: { source: "path", path: path69, expect } };
67208
+ function ingestNode(id, path70, expect) {
67209
+ return { id, type: "ingest", params: { source: "path", path: path70, expect } };
67210
67210
  }
67211
67211
  function aspectRatio(blueprint, opts) {
67212
67212
  const requested = opts.aspectRatio ?? blueprint.meta?.estimated_aspect_ratio;
@@ -67709,6 +67709,30 @@ function unsourcedFigureLines(spec, knowledge2) {
67709
67709
  return claims.length > 0 ? [{ text: line.text, claims }] : [];
67710
67710
  });
67711
67711
  }
67712
+ var QUOTED_RUN = 5;
67713
+ var SIGNING_ROLE = /^(attribution|author|byline|name|reviewer|source|signature)$/i;
67714
+ var SIGNED2 = new RegExp("(?:^|\\s)[\u2014\u2013-]\\s*\\p{Lu}", "u");
67715
+ var quoteWords = (text3) => text3.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter(Boolean);
67716
+ function quotes(line, quote) {
67717
+ const said = ` ${quoteWords(line).join(" ")} `;
67718
+ const words2 = quoteWords(quote);
67719
+ for (let i = 0; i + QUOTED_RUN <= words2.length; i++) {
67720
+ if (said.includes(` ${words2.slice(i, i + QUOTED_RUN).join(" ")} `)) return true;
67721
+ }
67722
+ return false;
67723
+ }
67724
+ function unattributedQuotes(spec, said) {
67725
+ const signedApart = spec.copy.some((line) => SIGNING_ROLE.test(line.role ?? ""));
67726
+ return spec.copy.flatMap((line) => {
67727
+ if (signedApart || SIGNED2.test(line.text)) return [];
67728
+ const by = said.find((q) => quotes(line.text, q.quote));
67729
+ if (!by) return [];
67730
+ const name = by.author ? `"\u2014 ${by.author}"` : '"\u2014 <their first name and initial>"';
67731
+ return [
67732
+ `"${line.text}" sets a customer's words with no name on them: add ${name} to the line (or a line of its own with role "attribution"); the review blocks a quote nobody signed.`
67733
+ ];
67734
+ });
67735
+ }
67712
67736
  function claimsWithoutSource(spec, knowledge2) {
67713
67737
  return [...new Set(unsourcedFigureLines(spec, knowledge2).flatMap((l) => l.claims))];
67714
67738
  }
@@ -71142,6 +71166,7 @@ function parseInsight(id, markdown) {
71142
71166
  const force = text2(fm.force);
71143
71167
  const persona = text2(fm.persona);
71144
71168
  const sourceKind = text2(fm.sourceKind);
71169
+ const author = markdown.replace(/^---[\s\S]*?\n---/, "").match(/\bby ([\p{Lu}][\p{L}'’-]*\.?(?: [\p{Lu}][\p{L}'’-]*\.?)?)/u)?.[1]?.replace(new RegExp("(\\p{L}{2,})\\.$", "u"), "$1");
71145
71170
  return {
71146
71171
  id,
71147
71172
  type: text2(fm.type) ?? "other",
@@ -71150,7 +71175,8 @@ function parseInsight(id, markdown) {
71150
71175
  status: evidenceStatus(oneOf(EVIDENCE_LEVELS, fm.status) ?? "observed", quote, source),
71151
71176
  ...sourceKind ? { sourceKind } : {},
71152
71177
  ...force ? { force } : {},
71153
- ...persona ? { persona } : {}
71178
+ ...persona ? { persona } : {},
71179
+ ...author ? { author } : {}
71154
71180
  };
71155
71181
  }
71156
71182
  function evidenceList(value2) {
@@ -71339,7 +71365,9 @@ function warningsOf(idea, evidence, personas, insights) {
71339
71365
  );
71340
71366
  }
71341
71367
  if (sentencesOf(idea.message) > 1 || idea.message.split(/\s+/).length > 25) {
71342
- warnings.push("the message says more than one thing: keep one promise, the rest goes to the ad text");
71368
+ warnings.push(
71369
+ 'the message says more than one thing: keep one promise that still names what is offered ("a free roof survey that shows your real saving", never a slogan like "the numbers, explained"), the rest goes to the ad text'
71370
+ );
71343
71371
  }
71344
71372
  if (personas.length > 0 && !personas.includes(idea.who)) {
71345
71373
  warnings.push(`who "${idea.who}" is not a persona in the Knowledge (${personas.join(", ")})`);
@@ -71777,6 +71805,7 @@ async function staticSpecGate(canvas, canvasDir) {
71777
71805
  };
71778
71806
  const root = await findBrandRoot(canvasDir) ?? findWorkspaceRoot(canvasDir) ?? canvasDir;
71779
71807
  const records = await readRecords(root);
71808
+ const ours = (await readInsights(root)).filter(sourcesClaims);
71780
71809
  const gates = spec.native ? [
71781
71810
  concept,
71782
71811
  {
@@ -71795,7 +71824,7 @@ async function staticSpecGate(canvas, canvasDir) {
71795
71824
  concept,
71796
71825
  {
71797
71826
  code: "proof_without_source",
71798
- problems: proofProblems(spec, records),
71827
+ problems: [...proofProblems(spec, records), ...unattributedQuotes(spec, ours)],
71799
71828
  fix: proofFix(claimsWithoutSource(spec, records))
71800
71829
  }
71801
71830
  ];
@@ -71803,7 +71832,7 @@ async function staticSpecGate(canvas, canvasDir) {
71803
71832
  }
71804
71833
  function proofFix(claims) {
71805
71834
  const named = claims.length > 0 ? `drop ${claims.map((c) => `"${c}"`).join(", ")} or source it in the Knowledge, and ` : "";
71806
- return `In prompt.json, ${named}wire the badge or drop any other claim named above, everywhere it appears (copy and scene).`;
71835
+ return `In prompt.json, ${named}wire the badge or drop any other claim named above, everywhere it appears (copy and scene), and sign each customer quote named above with the name given.`;
71807
71836
  }
71808
71837
  function oneRefusal(gates) {
71809
71838
  const first = gates[0];
@@ -72194,7 +72223,7 @@ async function probeDuration(filePath) {
72194
72223
  import { defineCommand as defineCommand140 } from "citty";
72195
72224
 
72196
72225
  // src/commands/canvas/run.ts
72197
- import path30 from "path";
72226
+ import path31 from "path";
72198
72227
  import { defineCommand as defineCommand139 } from "citty";
72199
72228
 
72200
72229
  // src/commands/canvas/definition-status.ts
@@ -74086,6 +74115,7 @@ async function variantImage(canvasRoot, runId, sha2562, fetchRecord = fetchRunRe
74086
74115
 
74087
74116
  // src/commands/canvas/static-run-review.ts
74088
74117
  import { readFile as readFile24 } from "fs/promises";
74118
+ import path30 from "path";
74089
74119
 
74090
74120
  // src/commands/canvas/glance-check.ts
74091
74121
  import sharp2 from "sharp";
@@ -74290,6 +74320,15 @@ async function writeTurnRenders(cacheDir, ledger) {
74290
74320
  await writeFile13(ledgerPath(cacheDir), JSON.stringify(ledger), "utf8");
74291
74321
  }
74292
74322
 
74323
+ // src/commands/creatives/company-offer.ts
74324
+ var MARKET_QUERY_WORDS = 6;
74325
+ function marketQuery(companyDoc) {
74326
+ const first = companyDoc.split("\n").find((line) => line.trim() && !line.trim().startsWith("#")) ?? "";
74327
+ if (/^\s*TODO\b/.test(first)) return "";
74328
+ const what = first.replace(/^\s*[-*]\s+/, "").replace(/^\*\*[^*]+\*\*\s*[—–:-]?\s*/, "").split(/\s+for\s+|[,.;:(]|\s[—–-]\s/)[0];
74329
+ return (what ?? "").trim().split(/\s+/).filter(Boolean).slice(0, MARKET_QUERY_WORDS).join(" ");
74330
+ }
74331
+
74293
74332
  // src/commands/canvas/viewer-check.ts
74294
74333
  var VIEWER_QUESTIONS = ["offer", "for_whom", "next_step"];
74295
74334
  var VIEWER_CLARITY = ["clear", "guess", "unclear"];
@@ -74331,9 +74370,9 @@ function looksEnglish(text3) {
74331
74370
  return /^[\x20-\x7e]*$/.test(text3);
74332
74371
  }
74333
74372
  var writtenAsBelief = (text3) => wordsOf(text3).some((w) => ["i", "my", "me", "mine"].includes(w));
74334
- function misread(said, meant) {
74373
+ function misread(said, meant, sells) {
74335
74374
  if (!meant || !said.trim() || !looksEnglish(meant) || !looksEnglish(said) || writtenAsBelief(meant)) return false;
74336
- const meantStems = contentStems(meant);
74375
+ const meantStems = /* @__PURE__ */ new Set([...contentStems(meant), ...sells && looksEnglish(sells) ? contentStems(sells) : []]);
74337
74376
  if (meantStems.size === 0) return false;
74338
74377
  return ![...contentStems(said)].some((stem) => meantStems.has(stem));
74339
74378
  }
@@ -74350,7 +74389,7 @@ function judgeViewerAnswer(answer, intended, required = VIEWER_REQUIRED_CLARITY)
74350
74389
  viewerSaid: reply.answer,
74351
74390
  ...withIntended
74352
74391
  });
74353
- } else if (question === "offer" && misread(reply.answer, meant)) {
74392
+ } else if (question === "offer" && misread(reply.answer, meant, intended.sells)) {
74354
74393
  missed.push({ question, reason: "misread", viewerSaid: reply.answer, ...withIntended });
74355
74394
  }
74356
74395
  }
@@ -74571,6 +74610,7 @@ async function readCreativeForViewerCheck(creativeDir) {
74571
74610
  const offer = spec.message?.trim() || definition.angle?.trim();
74572
74611
  const persona = spec.viewer?.who.trim() || definition.persona?.trim();
74573
74612
  const brand = spec.brand?.name?.trim();
74613
+ const sells = marketQuery(await readFile23(path29.resolve(creativeDir, "../../../COMPANY.md"), "utf8").catch(() => ""));
74574
74614
  return {
74575
74615
  ad: {
74576
74616
  copy: spec.copy.map((line) => ({
@@ -74580,7 +74620,7 @@ async function readCreativeForViewerCheck(creativeDir) {
74580
74620
  })),
74581
74621
  scene: spec.scene.description,
74582
74622
  ...brand ? { brand } : {},
74583
- intended: { ...offer ? { offer } : {}, ...persona ? { persona } : {} },
74623
+ intended: { ...offer ? { offer } : {}, ...persona ? { persona } : {}, ...sells ? { sells } : {} },
74584
74624
  ...castPeople(spec)
74585
74625
  },
74586
74626
  sources: {
@@ -75086,10 +75126,14 @@ async function reviewStaticRun(opts) {
75086
75126
  palette = spec.native ? [] : brandPalette(spec.brand);
75087
75127
  mechanisms = spec.mechanism.map((m) => m.device);
75088
75128
  brand = spec.brand?.name ?? opts.brandName;
75129
+ const sells = marketQuery(
75130
+ await readFile24(path30.resolve(path30.dirname(targets.promptPath), "../../../COMPANY.md"), "utf8").catch(() => "")
75131
+ );
75089
75132
  intended = {
75090
75133
  ...spec.message?.trim() ? { offer: spec.message.trim() } : {},
75091
75134
  ...spec.viewer?.who.trim() ? { persona: spec.viewer.who.trim() } : {},
75092
- ...spec.recognition?.trim() ? { recognition: spec.recognition.trim() } : {}
75135
+ ...spec.recognition?.trim() ? { recognition: spec.recognition.trim() } : {},
75136
+ ...sells ? { sells } : {}
75093
75137
  };
75094
75138
  lockup = [.../* @__PURE__ */ new Set([...spec.brand?.lockup ?? [], ...lockup])];
75095
75139
  sceneText = [
@@ -75265,8 +75309,8 @@ var Answer = z67.object({
75265
75309
  changed: z67.string().min(1),
75266
75310
  set: z67.array(z67.object({ path: z67.string().min(1), value: z67.unknown() }))
75267
75311
  });
75268
- function withValueAt(root, path69, value2) {
75269
- const [key, ...rest] = path69;
75312
+ function withValueAt(root, path70, value2) {
75313
+ const [key, ...rest] = path70;
75270
75314
  if (key === void 0) return value2;
75271
75315
  if (Array.isArray(root)) {
75272
75316
  const at = Number(key);
@@ -75284,7 +75328,7 @@ function printedWords(spec) {
75284
75328
  function acceptRepair(before, answer) {
75285
75329
  const parsed = Answer.safeParse(answer);
75286
75330
  if (!parsed.success || !isAdSpec(before)) return null;
75287
- const spec = parsed.data.set.reduce((at, { path: path69, value: value2 }) => withValueAt(at, path69.split("."), value2), before);
75331
+ const spec = parsed.data.set.reduce((at, { path: path70, value: value2 }) => withValueAt(at, path70.split("."), value2), before);
75288
75332
  if (!isAdSpec(spec)) return null;
75289
75333
  const was = AdSpecSchema.safeParse(before);
75290
75334
  const now = AdSpecSchema.safeParse(spec);
@@ -75456,7 +75500,7 @@ function failPreflight3(code, message, fix) {
75456
75500
  process.exit(2);
75457
75501
  }
75458
75502
  async function canvasFileFor(opts) {
75459
- if (opts.file) return { canvasPath: path30.resolve(opts.file) };
75503
+ if (opts.file) return { canvasPath: path31.resolve(opts.file) };
75460
75504
  if (!opts.slug) failPreflight3("missing_canvas", "Pass the canvas file, or --slug <slug> to run a creative by name.");
75461
75505
  const cwd = process.cwd();
75462
75506
  try {
@@ -75479,7 +75523,7 @@ async function executeCanvasRun(opts) {
75479
75523
  const creativeSlug = creativeSlugFromCanvasPath(filePath) ?? void 0;
75480
75524
  if (creativeSlug) await clearLegacyDirtyMarker(canvasRoot, creativeSlug);
75481
75525
  const turnId = optionalTurnId();
75482
- const turnCache = opts.cacheDir ?? path30.join(canvasRoot, ".cache");
75526
+ const turnCache = opts.cacheDir ?? path31.join(canvasRoot, ".cache");
75483
75527
  if (creativeSlug && (opts.autoFixRound ?? 0) === 0) {
75484
75528
  const refusal = turnRenderRefusal(await readTurnRenders(turnCache), turnId, creativeSlug);
75485
75529
  if (refusal) {
@@ -75491,14 +75535,14 @@ async function executeCanvasRun(opts) {
75491
75535
  }
75492
75536
  }
75493
75537
  await wireProofBadges(
75494
- path30.join(path30.dirname(filePath), "prompt.json"),
75538
+ path31.join(path31.dirname(filePath), "prompt.json"),
75495
75539
  fetchBrandLogo,
75496
75540
  (line) => process.stderr.write(`${line}
75497
75541
  `)
75498
75542
  );
75499
75543
  if ((opts.autoFixRound ?? 0) === 0) {
75500
75544
  await wireNamedPeople(
75501
- path30.join(path30.dirname(filePath), "prompt.json"),
75545
+ path31.join(path31.dirname(filePath), "prompt.json"),
75502
75546
  avatarOfNamedPerson,
75503
75547
  (line) => process.stderr.write(`${line}
75504
75548
  `)
@@ -75592,8 +75636,8 @@ ${describeRewrites(prepared.rewrites)}
75592
75636
  });
75593
75637
  const last = Object.fromEntries(
75594
75638
  nodesWithRole(parsed, STATIC_ADAPT_FORMAT_ROLE).flatMap((n) => {
75595
- const path69 = delivered.find((d) => d.format === formatOfAdaptId(n.id))?.path;
75596
- return path69 ? [[n.id, path69]] : [];
75639
+ const path70 = delivered.find((d) => d.format === formatOfAdaptId(n.id))?.path;
75640
+ return path70 ? [[n.id, path70]] : [];
75597
75641
  })
75598
75642
  );
75599
75643
  parsed = withSizesFollowingFix(parsed, {
@@ -75696,7 +75740,7 @@ ${describeRewrites(prepared.rewrites)}
75696
75740
  process.stdout.write(`[extend] placing ${opts.extendSizes.join(", ")} clear of what covers or cuts it, its margins painted
75697
75741
  `);
75698
75742
  }
75699
- const cacheDir = opts.cacheDir ?? path30.join(canvasRoot, ".cache");
75743
+ const cacheDir = opts.cacheDir ?? path31.join(canvasRoot, ".cache");
75700
75744
  const engine = createEngineFromEnv({
75701
75745
  cacheDir,
75702
75746
  outputsDir: opts.outputsDir ?? canvasRoot,
@@ -75720,7 +75764,7 @@ ${describeRewrites(prepared.rewrites)}
75720
75764
  const canvasSha = sha256Hex(Buffer.from(canvasText));
75721
75765
  const sourceSha = prepared.sourceSha;
75722
75766
  const client = opts.record === false ? null : buildBackendClient();
75723
- const outputsDir = opts.outputsDir ? path30.resolve(opts.outputsDir) : canvasRoot;
75767
+ const outputsDir = opts.outputsDir ? path31.resolve(opts.outputsDir) : canvasRoot;
75724
75768
  const { runId, resumed, source, sameSource, concurrentRunId, rendering } = await resolveRunId({
75725
75769
  explicitRunId: opts.runId,
75726
75770
  adoptedRunId: adoptRunId,
@@ -75751,7 +75795,7 @@ ${describeRewrites(prepared.rewrites)}
75751
75795
  }
75752
75796
  const viewerUsage = [];
75753
75797
  const viewerCheck = creativeSlug && isStaticAdCanvas(parsed) ? await viewerCheckBeforeRender({
75754
- creativeDir: path30.dirname(filePath),
75798
+ creativeDir: path31.dirname(filePath),
75755
75799
  cacheDir,
75756
75800
  slug: creativeSlug,
75757
75801
  skip: viewerCheckSkip({
@@ -75763,7 +75807,7 @@ ${describeRewrites(prepared.rewrites)}
75763
75807
  asked: opts.skipViewerCheck === true
75764
75808
  }),
75765
75809
  spent: viewerChecksSpent(await readTurnRenders(turnCache), turnId, creativeSlug),
75766
- lookups: liveViewerLookups(path30.dirname(canvasRoot)),
75810
+ lookups: liveViewerLookups(path31.dirname(canvasRoot)),
75767
75811
  model: VIEWER_CHECK_MODEL,
75768
75812
  ask: gatewayViewerModel(VIEWER_CHECK_MODEL, (usage) => viewerUsage.push(usage))
75769
75813
  }) : null;
@@ -75820,7 +75864,7 @@ ${describeRewrites(prepared.rewrites)}
75820
75864
  if (snapshot && creativeSlug) await recordSnapshot(canvasRoot, creativeSlug, snapshot);
75821
75865
  const recordMeta = {
75822
75866
  creativeSlug,
75823
- canvasPath: path30.relative(path30.dirname(canvasRoot), filePath) || void 0,
75867
+ canvasPath: path31.relative(path31.dirname(canvasRoot), filePath) || void 0,
75824
75868
  canvasSha,
75825
75869
  // The fingerprint the dashboard compares against the current source to flag
75826
75870
  // "edited since last render": the same `computeSourceSha` the edit-sync posts,
@@ -75908,7 +75952,7 @@ ${describeRewrites(prepared.rewrites)}
75908
75952
  brief: opts.brief?.trim() || void 0,
75909
75953
  onSpend: (usage) => reviewUsage.push(usage)
75910
75954
  }) : null;
75911
- const brandKit = reviewable ? null : await readStaticBrandKit(await findBrandRoot(path30.dirname(filePath)) ?? process.cwd());
75955
+ const brandKit = reviewable ? null : await readStaticBrandKit(await findBrandRoot(path31.dirname(filePath)) ?? process.cwd());
75912
75956
  const runShape = {
75913
75957
  fix: fixInstruction !== void 0,
75914
75958
  useVariant: opts.useVariant !== void 0,
@@ -75961,7 +76005,7 @@ ${describeRewrites(prepared.rewrites)}
75961
76005
  ] : [];
75962
76006
  const findings = staticReview ? staticReview.review : review;
75963
76007
  const ready = staticReview ? staticReview.verdict === "ready" || staticReview.verdict === "ready_with_notes" : review !== null && !review.some((f) => f.severity === "blocking");
75964
- const definitionStatus = ready && creativeSlug ? await advanceDefinitionStatus(path30.join(path30.dirname(filePath), "_definition.md"), "rendered") : null;
76008
+ const definitionStatus = ready && creativeSlug ? await advanceDefinitionStatus(path31.join(path31.dirname(filePath), "_definition.md"), "rendered") : null;
75965
76009
  if (poster) {
75966
76010
  await flushBilled(
75967
76011
  poster,
@@ -76203,13 +76247,13 @@ var rerunCommand = defineCommand140({
76203
76247
 
76204
76248
  // src/commands/canvas/scaffold-static-ad.ts
76205
76249
  import { mkdir as mkdir12, readFile as readFile29, writeFile as writeFile18 } from "fs/promises";
76206
- import path36 from "path";
76250
+ import path37 from "path";
76207
76251
  import { defineCommand as defineCommand143 } from "citty";
76208
76252
 
76209
76253
  // src/commands/canvas/creative-limit.ts
76210
76254
  import { existsSync as existsSync7 } from "fs";
76211
76255
  import { mkdir as mkdir10, readdir as readdir13, writeFile as writeFile16 } from "fs/promises";
76212
- import path31 from "path";
76256
+ import path32 from "path";
76213
76257
  var NEW_CREATIVES_PER_CHAT = 10;
76214
76258
  function claimNewCreative(made, slug) {
76215
76259
  if (made.includes(slug)) return { allowed: true, count: made.length };
@@ -76217,7 +76261,7 @@ function claimNewCreative(made, slug) {
76217
76261
  return { allowed: true, count: made.length + 1 };
76218
76262
  }
76219
76263
  function chatDir(canvasRoot, chatId) {
76220
- return path31.join(canvasRoot, ".creative-limit", (chatId ?? "no-chat").replace(/[^A-Za-z0-9_-]/g, "_"));
76264
+ return path32.join(canvasRoot, ".creative-limit", (chatId ?? "no-chat").replace(/[^A-Za-z0-9_-]/g, "_"));
76221
76265
  }
76222
76266
  async function madeInChat(dir) {
76223
76267
  return readdir13(dir).catch(() => []);
@@ -76230,7 +76274,7 @@ async function claimNewCreativeInWorkspace(canvasRoot, slug, chatId, definitionP
76230
76274
  if (claim.allowed && !made.includes(slug)) {
76231
76275
  try {
76232
76276
  await mkdir10(dir, { recursive: true });
76233
- await writeFile16(path31.join(dir, slug), "", { flag: "wx" });
76277
+ await writeFile16(path32.join(dir, slug), "", { flag: "wx" });
76234
76278
  } catch {
76235
76279
  }
76236
76280
  }
@@ -76251,7 +76295,7 @@ async function enforceNewCreativeLimit(slug, canvasPath) {
76251
76295
  canvasOutputsRoot(canvasPath),
76252
76296
  slug,
76253
76297
  optionalChatId() ?? null,
76254
- path31.join(path31.dirname(path31.resolve(canvasPath)), "_definition.md")
76298
+ path32.join(path32.dirname(path32.resolve(canvasPath)), "_definition.md")
76255
76299
  );
76256
76300
  if (claim.allowed) return;
76257
76301
  process.stderr.write(`${JSON.stringify(creativeLimitRefusal(slug), null, 2)}
@@ -76264,18 +76308,18 @@ import { access, readFile as readFile26 } from "fs/promises";
76264
76308
 
76265
76309
  // src/commands/canvas/composition-path.ts
76266
76310
  import { existsSync as existsSync8 } from "fs";
76267
- import path32 from "path";
76311
+ import path33 from "path";
76268
76312
  function resolveShippedCanvasDir(name, startDir, exists3 = existsSync8, maxDepth = 8) {
76269
- const rel = path32.join("canvas", name);
76313
+ const rel = path33.join("canvas", name);
76270
76314
  let dir = startDir;
76271
76315
  for (let i = 0; i < maxDepth; i++) {
76272
- const candidate = path32.join(dir, rel);
76273
- if (exists3(path32.join(candidate, "meta.json"))) return candidate;
76274
- const parent = path32.dirname(dir);
76316
+ const candidate = path33.join(dir, rel);
76317
+ if (exists3(path33.join(candidate, "meta.json"))) return candidate;
76318
+ const parent = path33.dirname(dir);
76275
76319
  if (parent === dir) break;
76276
76320
  dir = parent;
76277
76321
  }
76278
- return path32.resolve(startDir, "../../../", rel);
76322
+ return path33.resolve(startDir, "../../../", rel);
76279
76323
  }
76280
76324
 
76281
76325
  // src/commands/canvas/scaffold-common.ts
@@ -76440,16 +76484,16 @@ ${doc.toString()}---${raw.slice(match[0].length)}`;
76440
76484
  }
76441
76485
 
76442
76486
  // src/commands/canvas/scaffold-static-ad-paths.ts
76443
- import path33 from "path";
76487
+ import path34 from "path";
76444
76488
  function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
76445
76489
  const file = rawFile.trim();
76446
76490
  const imageIsUrl = /^https?:\/\//i.test(file);
76447
- const imageSource = imageIsUrl ? file : path33.resolve(cwd, file);
76448
- const outPath = out ? path33.resolve(cwd, out) : slug ? path33.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path33.join(cwd, "static-ad.canvas.json") : path33.join(path33.dirname(imageSource), "static-ad.canvas.json");
76449
- const blueprintPath2 = path33.join(path33.dirname(outPath), "prompt.json");
76450
- const creativeDir = slug ? path33.dirname(outPath) : null;
76451
- const definitionPath = creativeDir ? path33.join(creativeDir, "_definition.md") : null;
76452
- const referencesDir = creativeDir ? path33.join(creativeDir, "references") : null;
76491
+ const imageSource = imageIsUrl ? file : path34.resolve(cwd, file);
76492
+ const outPath = out ? path34.resolve(cwd, out) : slug ? path34.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path34.join(cwd, "static-ad.canvas.json") : path34.join(path34.dirname(imageSource), "static-ad.canvas.json");
76493
+ const blueprintPath2 = path34.join(path34.dirname(outPath), "prompt.json");
76494
+ const creativeDir = slug ? path34.dirname(outPath) : null;
76495
+ const definitionPath = creativeDir ? path34.join(creativeDir, "_definition.md") : null;
76496
+ const referencesDir = creativeDir ? path34.join(creativeDir, "references") : null;
76453
76497
  return { imageIsUrl, imageSource, outPath, blueprintPath: blueprintPath2, creativeDir, definitionPath, referencesDir };
76454
76498
  }
76455
76499
  var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
@@ -76460,7 +76504,7 @@ function isValidScaffoldSlug(slug) {
76460
76504
 
76461
76505
  // src/commands/canvas/sync-definition.ts
76462
76506
  import { readdir as readdir14, readFile as readFile27, stat as stat5 } from "fs/promises";
76463
- import path34 from "path";
76507
+ import path35 from "path";
76464
76508
  import { defineCommand as defineCommand141 } from "citty";
76465
76509
 
76466
76510
  // src/commands/canvas/definition-graph.ts
@@ -76517,14 +76561,14 @@ function buildDefinitionSyncPayload(input, graph, chatId) {
76517
76561
  }
76518
76562
  async function readDefinitionSourceFields(canvasPath) {
76519
76563
  try {
76520
- return parseDefinitionSourceFields(await readFile27(path34.join(path34.dirname(canvasPath), "_definition.md"), "utf8"));
76564
+ return parseDefinitionSourceFields(await readFile27(path35.join(path35.dirname(canvasPath), "_definition.md"), "utf8"));
76521
76565
  } catch {
76522
76566
  return {};
76523
76567
  }
76524
76568
  }
76525
76569
  async function readDefinitionStrategyFields(canvasPath) {
76526
76570
  try {
76527
- return parseDefinitionStrategyFields(await readFile27(path34.join(path34.dirname(canvasPath), "_definition.md"), "utf8"));
76571
+ return parseDefinitionStrategyFields(await readFile27(path35.join(path35.dirname(canvasPath), "_definition.md"), "utf8"));
76528
76572
  } catch {
76529
76573
  return {};
76530
76574
  }
@@ -76547,15 +76591,15 @@ async function syncCreativeDefinitionBestEffort(input) {
76547
76591
  }
76548
76592
  }
76549
76593
  async function resolveCanvasPath(inputPath) {
76550
- const resolved = path34.resolve(inputPath);
76594
+ const resolved = path35.resolve(inputPath);
76551
76595
  let dir = resolved;
76552
76596
  try {
76553
76597
  if ((await stat5(resolved)).isFile()) {
76554
76598
  if (resolved.endsWith(".canvas.json")) return resolved;
76555
- dir = path34.dirname(resolved);
76599
+ dir = path35.dirname(resolved);
76556
76600
  }
76557
76601
  } catch {
76558
- dir = resolved.endsWith(".canvas.json") ? path34.dirname(resolved) : resolved;
76602
+ dir = resolved.endsWith(".canvas.json") ? path35.dirname(resolved) : resolved;
76559
76603
  }
76560
76604
  let entries;
76561
76605
  try {
@@ -76566,7 +76610,7 @@ async function resolveCanvasPath(inputPath) {
76566
76610
  const canvases = entries.filter((name) => name.endsWith(".canvas.json"));
76567
76611
  const slug = creativeSlugFromCanvasPath(`${dir}/x/`);
76568
76612
  const chosen = (slug ? canvases.find((name) => name === `${slug}.canvas.json`) : void 0) ?? canvases[0];
76569
- return chosen ? path34.join(dir, chosen) : null;
76613
+ return chosen ? path35.join(dir, chosen) : null;
76570
76614
  }
76571
76615
  var syncDefinitionCommand = defineCommand141({
76572
76616
  meta: {
@@ -76837,7 +76881,7 @@ function mergeReferenceIntoBlueprint(blueprint, reference) {
76837
76881
 
76838
76882
  // src/commands/winning-ads/fit.ts
76839
76883
  import { mkdir as mkdir11, readdir as readdir15, readFile as readFile28, writeFile as writeFile17 } from "fs/promises";
76840
- import path35 from "path";
76884
+ import path36 from "path";
76841
76885
  import { defineCommand as defineCommand142 } from "citty";
76842
76886
  import sharp4 from "sharp";
76843
76887
  import { z as z68 } from "zod";
@@ -76926,19 +76970,19 @@ function readText(file) {
76926
76970
  }
76927
76971
  async function readKnowledge(root) {
76928
76972
  const parts = [];
76929
- const company = await readText(path35.join(root, "COMPANY.md"));
76973
+ const company = await readText(path36.join(root, "COMPANY.md"));
76930
76974
  if (company) parts.push(`COMPANY.md:
76931
76975
  ${company.slice(0, MAX_DOC_CHARS)}`);
76932
- const brand = await readText(path35.join(root, "src", "brand", "BRAND.md"));
76976
+ const brand = await readText(path36.join(root, "src", "brand", "BRAND.md"));
76933
76977
  if (brand) parts.push(`BRAND.md (start):
76934
76978
  ${brand.slice(0, MAX_DOC_CHARS)}`);
76935
76979
  for (const collection of KNOWLEDGE_COLLECTIONS) {
76936
- const dir = path35.join(root, "src", "content", collection);
76980
+ const dir = path36.join(root, "src", "content", collection);
76937
76981
  const files = (await readdir15(dir, { recursive: true }).catch(() => [])).filter(
76938
76982
  (f) => f.endsWith(".md")
76939
76983
  );
76940
76984
  for (const file of files.sort().slice(0, 12)) {
76941
- const text3 = await readText(path35.join(dir, file));
76985
+ const text3 = await readText(path36.join(dir, file));
76942
76986
  if (text3) parts.push(`${collection}/${file}:
76943
76987
  ${text3.slice(0, MAX_ENTRY_CHARS)}`);
76944
76988
  }
@@ -76970,7 +77014,7 @@ async function readReviews() {
76970
77014
  }
76971
77015
  }
76972
77016
  function fitCachePath(root, platform, adId) {
76973
- return path35.join(root, "canvas", ".cache", "fit", `${platform}-${adId.replace(/[^a-zA-Z0-9_-]/g, "_")}.json`);
77017
+ return path36.join(root, "canvas", ".cache", "fit", `${platform}-${adId.replace(/[^a-zA-Z0-9_-]/g, "_")}.json`);
76974
77018
  }
76975
77019
  async function readCachedFit(root, platform, adId) {
76976
77020
  const raw = await readText(fitCachePath(root, platform, adId));
@@ -77025,7 +77069,7 @@ async function fitOnce(root, platform, adId, ask) {
77025
77069
  const fit = await ask();
77026
77070
  if (!fit) return null;
77027
77071
  const file = fitCachePath(root, platform, adId);
77028
- await mkdir11(path35.dirname(file), { recursive: true });
77072
+ await mkdir11(path36.dirname(file), { recursive: true });
77029
77073
  await writeFile17(file, `${JSON.stringify(fit, null, 2)}
77030
77074
  `, "utf8");
77031
77075
  return fit;
@@ -77064,7 +77108,7 @@ async function fitReference(root, platform, adId) {
77064
77108
  const prompt = buildFitPrompt({ library: libraryRead(ad), knowledge: knowledge2 });
77065
77109
  const spent = [];
77066
77110
  const answer = await askFit(jpeg, prompt, (u) => spent.push(u));
77067
- await holdUnbilledSpend(path35.join(root, "canvas", ".cache"), spent);
77111
+ await holdUnbilledSpend(path36.join(root, "canvas", ".cache"), spent);
77068
77112
  return answer;
77069
77113
  });
77070
77114
  if (fit) return { ok: true, fit };
@@ -77117,7 +77161,7 @@ var fitCommand = defineCommand142({
77117
77161
 
77118
77162
  // src/commands/canvas/scaffold-static-ad.ts
77119
77163
  function toCanvasRelative2(canvasDir, file) {
77120
- const rel = path36.relative(canvasDir, file).split(path36.sep).join("/");
77164
+ const rel = path37.relative(canvasDir, file).split(path37.sep).join("/");
77121
77165
  return rel.startsWith(".") ? rel : `./${rel}`;
77122
77166
  }
77123
77167
  async function uploadSourceAsReference(source, isUrl, client) {
@@ -77409,17 +77453,17 @@ async function lookupReference(args8) {
77409
77453
  }
77410
77454
  async function scaffoldFromSpec(args8, slug) {
77411
77455
  if (!slug) return fail4("missing_slug", "--spec needs --slug: an ad started from a spec is a creative.");
77412
- const specPath = path36.resolve(process.cwd(), String(args8.spec));
77456
+ const specPath = path37.resolve(process.cwd(), String(args8.spec));
77413
77457
  let started;
77414
77458
  try {
77415
77459
  started = readAdSpec(JSON.parse(await readFile29(specPath, "utf8")));
77416
77460
  } catch (e) {
77417
77461
  return fail4("invalid_spec", `${specPath} is not an ad spec: ${e instanceof Error ? e.message : String(e)}`);
77418
77462
  }
77419
- const outPath = path36.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`);
77420
- const dir = path36.dirname(outPath);
77421
- const blueprintPath2 = path36.join(dir, "prompt.json");
77422
- const definitionPath = path36.join(dir, "_definition.md");
77463
+ const outPath = path37.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`);
77464
+ const dir = path37.dirname(outPath);
77465
+ const blueprintPath2 = path37.join(dir, "prompt.json");
77466
+ const definitionPath = path37.join(dir, "_definition.md");
77423
77467
  await enforceNewCreativeLimit(slug, outPath);
77424
77468
  const existingDefinition = await fileExists(definitionPath) ? await readFile29(definitionPath, "utf8") : null;
77425
77469
  const who = await scaffoldViewer(args8, existingDefinition, liveViewerLookups(process.cwd()).adSetViewer);
@@ -77427,7 +77471,7 @@ async function scaffoldFromSpec(args8, slug) {
77427
77471
  await mkdir12(dir, { recursive: true });
77428
77472
  const workspaceRoot = await findBrandRoot(dir) ?? process.cwd();
77429
77473
  const kit = await readStaticBrandKit(workspaceRoot);
77430
- const market = who.viewer?.market ?? marketFromCompanyDoc(await readFile29(path36.join(workspaceRoot, "COMPANY.md"), "utf8").catch(() => null));
77474
+ const market = who.viewer?.market ?? marketFromCompanyDoc(await readFile29(path37.join(workspaceRoot, "COMPANY.md"), "utf8").catch(() => null));
77431
77475
  const brand = brandBlock(kit);
77432
77476
  const platform = resolvePlatform(args8.platform ? String(args8.platform) : void 0);
77433
77477
  const placementsResult = resolvePlacements(args8.placements ? String(args8.placements) : void 0, platform);
@@ -77581,7 +77625,7 @@ var scaffoldStaticAdCommand = defineCommand143({
77581
77625
  const fit = reference || lookup.status === "unavailable" ? await readCachedFit(fitRoot, reference?.platform ?? (lookup.status === "unavailable" ? lookup.platform : "meta"), reference?.ad_id ?? (lookup.status === "unavailable" ? lookup.adId : "")) : null;
77582
77626
  const fitProblems = fit ? fitHints(fit, reference?.ad_id ?? "").filter((h) => h.startsWith("Pick another reference")) : [];
77583
77627
  if (fitProblems.length > 0) return fail4("concept_does_not_fit", fitProblems.join(" "));
77584
- await mkdir12(path36.dirname(outPath), { recursive: true });
77628
+ await mkdir12(path37.dirname(outPath), { recursive: true });
77585
77629
  let models;
77586
77630
  try {
77587
77631
  models = resolveModels(args8);
@@ -77615,10 +77659,10 @@ var scaffoldStaticAdCommand = defineCommand143({
77615
77659
  const persona = existingDefinition?.match(/^persona:\s*"?([^"\n]+)"?\s*$/m)?.[1];
77616
77660
  const elements = castAvatarsOnStaticElements(vision.elements, cast.avatars, persona);
77617
77661
  const uncast = staticAvatarsNotCast(elements, cast.handles);
77618
- const canvasDir = path36.dirname(outPath);
77662
+ const canvasDir = path37.dirname(outPath);
77619
77663
  const workspaceRoot = await findBrandRoot(canvasDir) ?? process.cwd();
77620
77664
  const kit = await readStaticBrandKit(workspaceRoot);
77621
- const market = who.viewer?.market ?? marketFromCompanyDoc(await readFile29(path36.join(workspaceRoot, "COMPANY.md"), "utf8").catch(() => null));
77665
+ const market = who.viewer?.market ?? marketFromCompanyDoc(await readFile29(path37.join(workspaceRoot, "COMPANY.md"), "utf8").catch(() => null));
77622
77666
  const brand = brandBlock(kit);
77623
77667
  let canvasImagePath = imageSource;
77624
77668
  let canvasImageIsUrl = imageIsUrl;
@@ -77682,7 +77726,7 @@ var scaffoldStaticAdCommand = defineCommand143({
77682
77726
  } catch (e) {
77683
77727
  return fail4("scaffold", e instanceof Error ? e.message : String(e));
77684
77728
  }
77685
- const validation = await validateScaffoldedStaticAd(canvas, path36.dirname(outPath));
77729
+ const validation = await validateScaffoldedStaticAd(canvas, path37.dirname(outPath));
77686
77730
  if (validation.blocking.length > 0) {
77687
77731
  process.stderr.write(
77688
77732
  `${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.blocking } }, null, 2)}
@@ -77779,7 +77823,7 @@ var scaffoldStaticAdCommand = defineCommand143({
77779
77823
  run_estimated_credits: validation.estimatedCredits
77780
77824
  },
77781
77825
  checklist: {
77782
- edit_prompt: `Edit ${path36.basename(blueprintPath2)}: it is the ad spec, read from your image, to rewrite into the ad you want. \`viewer\` (who sees it and what they already know), \`message\` (the one thing it tells them), \`copy\` (each line, \`in_scene\` or \`designed\`), \`scene\`, \`references\` (one picture each, by role), \`colors\` (each tied to an object, from the brand) and an optional \`direction\`. You never write a model prompt: every render prompt is compiled from this file and shown on its node.${reference ? " Its `reference` block is the library's read of the source ad (container, layout, mechanism, offer, text blocks): keep it as the account of why the ad won, and rebuild it for our brand." : ""}`,
77826
+ edit_prompt: `Edit ${path37.basename(blueprintPath2)}: it is the ad spec, read from your image, to rewrite into the ad you want. \`viewer\` (who sees it and what they already know), \`message\` (the one thing it tells them), \`copy\` (each line, \`in_scene\` or \`designed\`), \`scene\`, \`references\` (one picture each, by role), \`colors\` (each tied to an object, from the brand) and an optional \`direction\`. You never write a model prompt: every render prompt is compiled from this file and shown on its node.${reference ? " Its `reference` block is the library's read of the source ad (container, layout, mechanism, offer, text blocks): keep it as the account of why the ad won, and rebuild it for our brand." : ""}`,
77783
77827
  mechanism: report.winning_mechanisms,
77784
77828
  rebuild_the_mechanism: "`mechanism` is WHY the source ad works. Rebuild each device for our brand in prompt.json's copy and scene (a rhyme stays a rhyme in our words, a before/after stays a before/after of our product); never copy the source's literal copy.",
77785
77829
  assets_to_supply: report.elements,
@@ -77842,7 +77886,7 @@ function clientLogoMissNote(decision, domain) {
77842
77886
 
77843
77887
  // src/commands/canvas/scaffold-ad.ts
77844
77888
  import { copyFile, cp, mkdir as mkdir13, readFile as readFile31, stat as stat6, writeFile as writeFile20 } from "fs/promises";
77845
- import path38 from "path";
77889
+ import path39 from "path";
77846
77890
  import { defineCommand as defineCommand144 } from "citty";
77847
77891
 
77848
77892
  // src/engine/scaffold/ad-spec.ts
@@ -78557,7 +78601,7 @@ function injectAdBrandOverlay(indexHtml, overlayHtml, style = {}) {
78557
78601
 
78558
78602
  // src/commands/canvas/composition-dims.ts
78559
78603
  import { readFile as readFile30, writeFile as writeFile19 } from "fs/promises";
78560
- import path37 from "path";
78604
+ import path38 from "path";
78561
78605
  function patchCompositionMeta(metaJson, dims) {
78562
78606
  try {
78563
78607
  const meta = JSON.parse(metaJson);
@@ -78572,10 +78616,10 @@ function patchCompositionHtml(html, dims) {
78572
78616
  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`);
78573
78617
  }
78574
78618
  async function stampCompositionDims(compositionDir, dims) {
78575
- const metaPath = path37.join(compositionDir, "meta.json");
78619
+ const metaPath = path38.join(compositionDir, "meta.json");
78576
78620
  const rawMeta = await readFile30(metaPath, "utf8");
78577
78621
  await writeFile19(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
78578
- const htmlPath = path37.join(compositionDir, "index.html");
78622
+ const htmlPath = path38.join(compositionDir, "index.html");
78579
78623
  const rawHtml = await readFile30(htmlPath, "utf8");
78580
78624
  await writeFile19(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
78581
78625
  }
@@ -78872,8 +78916,8 @@ var scaffoldAdCommand = defineCommand144({
78872
78916
  videoModel: chosenVideoModel,
78873
78917
  ...avatarVoice ? { avatarVoice } : {}
78874
78918
  });
78875
- const slug = args8.slug ?? path38.basename(specPath).replace(/\.[^.]+$/, "");
78876
- const outPath = args8.out ?? (args8.slug ? path38.join("src/creatives", slug, `${slug}.canvas.json`) : path38.join(path38.dirname(specPath), `${slug}.canvas.json`));
78919
+ const slug = args8.slug ?? path39.basename(specPath).replace(/\.[^.]+$/, "");
78920
+ const outPath = args8.out ?? (args8.slug ? path39.join("src/creatives", slug, `${slug}.canvas.json`) : path39.join(path39.dirname(specPath), `${slug}.canvas.json`));
78877
78921
  if (args8.slug) await enforceNewCreativeLimit(slug, outPath);
78878
78922
  let outAr;
78879
78923
  try {
@@ -78891,28 +78935,28 @@ var scaffoldAdCommand = defineCommand144({
78891
78935
  return;
78892
78936
  }
78893
78937
  const outDims = canvasDims(outAr);
78894
- const outDir = path38.dirname(outPath);
78938
+ const outDir = path39.dirname(outPath);
78895
78939
  await mkdir13(outDir, { recursive: true });
78896
- const compositionDest = path38.join(outDir, "video-overlay-composition");
78897
- const captionsDest = path38.join(outDir, "tiktok-captions-composition");
78940
+ const compositionDest = path39.join(outDir, "video-overlay-composition");
78941
+ const captionsDest = path39.join(outDir, "tiktok-captions-composition");
78898
78942
  await cp(SHIPPED_OVERLAY_COMPOSITION_DIR, compositionDest, { recursive: true });
78899
78943
  await cp(SHIPPED_CAPTIONS_DIR, captionsDest, { recursive: true });
78900
78944
  await stampCompositionDims(compositionDest, outDims);
78901
78945
  await stampCompositionDims(captionsDest, outDims);
78902
- const captionsIndex = path38.join(captionsDest, "index.html");
78946
+ const captionsIndex = path39.join(captionsDest, "index.html");
78903
78947
  await writeFile20(captionsIndex, injectAdCaptionPlacement(await readFile31(captionsIndex, "utf-8"), outAr), "utf-8");
78904
78948
  const face = await stageBrandDisplayFace(outDir, captionsDest);
78905
78949
  if (face) {
78906
78950
  await writeFile20(captionsIndex, injectAdDisplayFace(await readFile31(captionsIndex, "utf-8"), face.file), "utf-8");
78907
78951
  }
78908
- const blueprintPath2 = path38.join(outDir, "prompt.json");
78909
- const blueprintStylePath = path38.join(outDir, "prompt.style.json");
78952
+ const blueprintPath2 = path39.join(outDir, "prompt.json");
78953
+ const blueprintStylePath = path39.join(outDir, "prompt.style.json");
78910
78954
  await writeSceneFiles(outDir, blueprint);
78911
78955
  await writeFile20(blueprintStylePath, renderStyleProjectionFromValue(blueprint), "utf8");
78912
- await writeFile20(path38.join(outDir, AD_SPEC_FILE), `${JSON.stringify(specArtifact, null, 2)}
78956
+ await writeFile20(path39.join(outDir, AD_SPEC_FILE), `${JSON.stringify(specArtifact, null, 2)}
78913
78957
  `, "utf8");
78914
78958
  const logoPath = noBrand ? void 0 : spec.data.brand?.logo?.trim();
78915
- const transcriptPath = path38.join(outDir, "transcript.json");
78959
+ const transcriptPath = path39.join(outDir, "transcript.json");
78916
78960
  if (spec.data.voiceover === false) {
78917
78961
  await writeFile20(transcriptPath, `${JSON.stringify(staticTranscript(spec.data, chosenVideoModel), null, 2)}
78918
78962
  `, "utf-8");
@@ -78924,10 +78968,10 @@ var scaffoldAdCommand = defineCommand144({
78924
78968
  // that stops the whole canvas. The same sheet model every other scaffold uses.
78925
78969
  sheetModel: ACTOR_SHEET_MODEL,
78926
78970
  videoModel: chosenVideoModel,
78927
- overlayCompositionPath: path38.relative(outDir, compositionDest),
78928
- captionsCompositionPath: path38.relative(outDir, captionsDest),
78929
- blueprintPath: path38.relative(outDir, blueprintPath2),
78930
- blueprintStylePath: path38.relative(outDir, blueprintStylePath),
78971
+ overlayCompositionPath: path39.relative(outDir, compositionDest),
78972
+ captionsCompositionPath: path39.relative(outDir, captionsDest),
78973
+ blueprintPath: path39.relative(outDir, blueprintPath2),
78974
+ blueprintStylePath: path39.relative(outDir, blueprintStylePath),
78931
78975
  aspect: spec.data.format.aspect_ratio,
78932
78976
  resolution: spec.data.format.resolution,
78933
78977
  // A beat is one clause and one card, so the cap has to clear a whole clause.
@@ -78966,17 +79010,17 @@ var scaffoldAdCommand = defineCommand144({
78966
79010
  // the stock voice this exists to avoid. It is to convert the LATER extracts onto the
78967
79011
  // first beat of the same speaker, which keeps a voice the clip really produced.
78968
79012
  ...avatar ? { keepRenderedVoice: true } : {},
78969
- ...spec.data.voiceover === false ? { staticTranscriptPath: path38.relative(outDir, transcriptPath) } : {}
79013
+ ...spec.data.voiceover === false ? { staticTranscriptPath: path39.relative(outDir, transcriptPath) } : {}
78970
79014
  };
78971
79015
  const canvas = scaffoldVideoCanvas(blueprint, adSpecCastElements(spec.data, avatar), opts);
78972
79016
  const renderNode5 = canvas.nodes.find((n) => n.type === "hyperframe_render");
78973
- const renderedDir = renderNode5 ? path38.join(outDir, String(renderNode5.params?.composition ?? "")) : null;
79017
+ const renderedDir = renderNode5 ? path39.join(outDir, String(renderNode5.params?.composition ?? "")) : null;
78974
79018
  let staged = null;
78975
79019
  let markIsLight = false;
78976
79020
  if (logoPath && renderedDir) {
78977
- const ext = path38.extname(logoPath) || ".png";
79021
+ const ext = path39.extname(logoPath) || ".png";
78978
79022
  try {
78979
- await copyFile(logoPath, path38.join(renderedDir, `brand-mark${ext}`));
79023
+ await copyFile(logoPath, path39.join(renderedDir, `brand-mark${ext}`));
78980
79024
  staged = { file: `brand-mark${ext}`, alt: spec.data.brand?.name ?? "brand" };
78981
79025
  markIsLight = await markInkIsLight(logoPath);
78982
79026
  } catch {
@@ -78995,12 +79039,12 @@ var scaffoldAdCommand = defineCommand144({
78995
79039
  plateIsDark: plateIsDark(spec.data.brand?.palette)
78996
79040
  }) : "";
78997
79041
  if (overlayHtml && renderedDir) {
78998
- const indexPath = path38.join(renderedDir, "index.html");
79042
+ const indexPath = path39.join(renderedDir, "index.html");
78999
79043
  const html = await readFile31(indexPath, "utf-8");
79000
79044
  await writeFile20(indexPath, injectAdBrandOverlay(html, overlayHtml, { aspect: outAr, ...face ? { face: AD_DISPLAY_FAMILY } : {} }), "utf-8");
79001
79045
  }
79002
79046
  await writeFile20(
79003
- path38.join(outDir, REBUILD_FILE),
79047
+ path39.join(outDir, REBUILD_FILE),
79004
79048
  `${JSON.stringify({ elements: adSpecCastElements(spec.data, avatar), opts }, null, 2)}
79005
79049
  `,
79006
79050
  "utf8"
@@ -79030,7 +79074,7 @@ var scaffoldAdCommand = defineCommand144({
79030
79074
  return;
79031
79075
  }
79032
79076
  if (args8.slug) {
79033
- const definitionPath = path38.join(outDir, "_definition.md");
79077
+ const definitionPath = path39.join(outDir, "_definition.md");
79034
79078
  const definitionExists = await stat6(definitionPath).then(() => true, () => false);
79035
79079
  if (!definitionExists) {
79036
79080
  await writeFile20(
@@ -79148,9 +79192,9 @@ async function fetchClientLogo() {
79148
79192
  if (!response.ok) return { ok: false, reason: clientLogoMissNote({ use: false, reason: "no_hits" }, domain) };
79149
79193
  const bytes = Buffer.from(await response.arrayBuffer());
79150
79194
  const extension = /\.(svg|png|jpg|jpeg|webp)(?:\?|$)/i.exec(decision.url)?.[1]?.toLowerCase() ?? "svg";
79151
- const dir = path38.join(BRAND_DIR, "logos");
79195
+ const dir = path39.join(BRAND_DIR, "logos");
79152
79196
  await mkdir13(dir, { recursive: true });
79153
- const file = path38.join(dir, `brand-mark.${extension}`);
79197
+ const file = path39.join(dir, `brand-mark.${extension}`);
79154
79198
  await writeFile20(file, bytes);
79155
79199
  return { ok: true, path: file };
79156
79200
  } catch {
@@ -79169,14 +79213,14 @@ async function stageBrandDisplayFace(outDir, compositionDir) {
79169
79213
  if (!face) return null;
79170
79214
  try {
79171
79215
  if ("path" in face.slot) {
79172
- const file2 = `brand-face${path38.extname(face.slot.path).toLowerCase()}`;
79173
- await copyFile(face.slot.path, path38.join(compositionDir, file2));
79174
- return { file: file2, label: `the font file \`${path38.relative(root, face.slot.path)}\`` };
79216
+ const file2 = `brand-face${path39.extname(face.slot.path).toLowerCase()}`;
79217
+ await copyFile(face.slot.path, path39.join(compositionDir, file2));
79218
+ return { file: file2, label: `the font file \`${path39.relative(root, face.slot.path)}\`` };
79175
79219
  }
79176
79220
  const { buffer } = await fetchExternalBytes(face.slot.url, { maxBytes: MAX_FONT_BYTES });
79177
79221
  const extension = /\.(woff2|woff|ttf|otf)(?:\?|$)/i.exec(face.slot.url)?.[1]?.toLowerCase() ?? "woff2";
79178
79222
  const file = `brand-face.${extension}`;
79179
- await writeFile20(path38.join(compositionDir, file), buffer);
79223
+ await writeFile20(path39.join(compositionDir, file), buffer);
79180
79224
  return { file, label: `${face.family ?? "the brand's typeface"}, loaded as a web font` };
79181
79225
  } catch {
79182
79226
  return null;
@@ -79186,7 +79230,7 @@ async function stageBrandDisplayFace(outDir, compositionDir) {
79186
79230
  // src/commands/canvas/scaffold-video.ts
79187
79231
  import { cp as cp2, mkdir as mkdir14, readFile as readFile34, rm as rm6, writeFile as writeFile21 } from "fs/promises";
79188
79232
  import { tmpdir as tmpdir2 } from "os";
79189
- import path40 from "path";
79233
+ import path41 from "path";
79190
79234
  import { defineCommand as defineCommand145 } from "citty";
79191
79235
 
79192
79236
  // src/engine/scaffold/lib/model-router.ts
@@ -79327,7 +79371,7 @@ async function detectSceneCutsPySceneDetect(filePath, opts = {}) {
79327
79371
 
79328
79372
  // src/commands/canvas/gitignore.ts
79329
79373
  import { appendFile, readFile as readFile33 } from "fs/promises";
79330
- import path39 from "path";
79374
+ import path40 from "path";
79331
79375
  function missingGitignoreEntries(existing, entries) {
79332
79376
  const present2 = new Set(
79333
79377
  existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
@@ -79335,7 +79379,7 @@ function missingGitignoreEntries(existing, entries) {
79335
79379
  return entries.filter((e) => !present2.has(e.trim().replace(/\/+$/, "")));
79336
79380
  }
79337
79381
  async function ensureGitignore(dir, entries) {
79338
- const file = path39.join(dir, ".gitignore");
79382
+ const file = path40.join(dir, ".gitignore");
79339
79383
  let existing;
79340
79384
  try {
79341
79385
  existing = await readFile33(file, "utf8");
@@ -79380,7 +79424,7 @@ async function loadTranscriptBestEffort(ref2) {
79380
79424
  async function stageCaptions(outDir, transcript) {
79381
79425
  const text3 = transcript?.trim();
79382
79426
  if (!text3 || text3 === "[]") return {};
79383
- const compositionPath = path40.join(outDir, "tiktok-captions-composition");
79427
+ const compositionPath = path41.join(outDir, "tiktok-captions-composition");
79384
79428
  await cp2(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
79385
79429
  return { compositionPath };
79386
79430
  }
@@ -79416,7 +79460,7 @@ var VIDEO_EXT_BY_MIME = {
79416
79460
  "video/x-matroska": ".mkv"
79417
79461
  };
79418
79462
  function referenceVideoExt(url, contentType) {
79419
- const fromPath = path40.extname(new URL(url).pathname).toLowerCase();
79463
+ const fromPath = path41.extname(new URL(url).pathname).toLowerCase();
79420
79464
  if (fromPath && fromPath.length <= 5) return fromPath;
79421
79465
  const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase();
79422
79466
  return mime && VIDEO_EXT_BY_MIME[mime] || ".mp4";
@@ -79442,7 +79486,7 @@ function framesModeReport(canvas, requested) {
79442
79486
  return { frames_mode: mode, ...refused ? { frames_reuse_refused: refused } : {} };
79443
79487
  }
79444
79488
  async function materializeReferenceVideo(fileArg2) {
79445
- if (!/^https?:\/\//i.test(fileArg2)) return path40.resolve(fileArg2);
79489
+ if (!/^https?:\/\//i.test(fileArg2)) return path41.resolve(fileArg2);
79446
79490
  let bytes;
79447
79491
  let contentType;
79448
79492
  try {
@@ -79454,7 +79498,7 @@ async function materializeReferenceVideo(fileArg2) {
79454
79498
  throw new Error(`failed to download reference video: ${e instanceof Error ? e.message : String(e)}`);
79455
79499
  }
79456
79500
  if (bytes.length === 0) throw new Error("reference video download was empty");
79457
- const dest = path40.join(
79501
+ const dest = path41.join(
79458
79502
  tmpdir2(),
79459
79503
  `baker-ref-${sha256Hex(bytes).slice(0, 16)}${referenceVideoExt(fileArg2, contentType)}`
79460
79504
  );
@@ -79681,12 +79725,12 @@ var scaffoldVideoCommand = defineCommand145({
79681
79725
  } catch (e) {
79682
79726
  return fail4("download", e instanceof Error ? e.message : String(e));
79683
79727
  }
79684
- const base = path40.basename(videoPath, path40.extname(videoPath));
79685
- const outPath = args8.out ? path40.resolve(String(args8.out)) : slug ? path40.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`) : path40.join(path40.dirname(videoPath), `${base}.video.canvas.json`);
79728
+ const base = path41.basename(videoPath, path41.extname(videoPath));
79729
+ const outPath = args8.out ? path41.resolve(String(args8.out)) : slug ? path41.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`) : path41.join(path41.dirname(videoPath), `${base}.video.canvas.json`);
79686
79730
  if (slug) await enforceNewCreativeLimit(slug, outPath);
79687
- const outDir = path40.dirname(outPath);
79688
- const blueprintPath2 = path40.join(outDir, "prompt.json");
79689
- const blueprintStylePath = path40.join(outDir, "prompt.style.json");
79731
+ const outDir = path41.dirname(outPath);
79732
+ const blueprintPath2 = path41.join(outDir, "prompt.json");
79733
+ const blueprintStylePath = path41.join(outDir, "prompt.style.json");
79690
79734
  const frames = args8.frames === "reuse" ? "reuse" : "generate";
79691
79735
  const maxScenes = args8["max-scenes"] ? Number(args8["max-scenes"]) : void 0;
79692
79736
  if (Number.isFinite(maxScenes)) {
@@ -79755,10 +79799,10 @@ var scaffoldVideoCommand = defineCommand145({
79755
79799
  `
79756
79800
  );
79757
79801
  }
79758
- const compositionDest = path40.join(outDir, "video-overlay-composition");
79802
+ const compositionDest = path41.join(outDir, "video-overlay-composition");
79759
79803
  await cp2(SHIPPED_OVERLAY_COMPOSITION_DIR, compositionDest, { recursive: true });
79760
79804
  await stampCompositionDims(compositionDest, outDims);
79761
- const indexPath = path40.join(compositionDest, "index.html");
79805
+ const indexPath = path41.join(compositionDest, "index.html");
79762
79806
  const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript), videoModel });
79763
79807
  const indexHtml = await readFile34(indexPath, "utf8");
79764
79808
  const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
@@ -79774,10 +79818,10 @@ var scaffoldVideoCommand = defineCommand145({
79774
79818
  const opts = {
79775
79819
  imageModel,
79776
79820
  videoModel,
79777
- overlayCompositionPath: path40.relative(outDir, compositionDest),
79778
- captionsCompositionPath: captions.compositionPath ? path40.relative(outDir, captions.compositionPath) : void 0,
79779
- blueprintPath: path40.relative(outDir, blueprintPath2),
79780
- blueprintStylePath: path40.relative(outDir, blueprintStylePath),
79821
+ overlayCompositionPath: path41.relative(outDir, compositionDest),
79822
+ captionsCompositionPath: captions.compositionPath ? path41.relative(outDir, captions.compositionPath) : void 0,
79823
+ blueprintPath: path41.relative(outDir, blueprintPath2),
79824
+ blueprintStylePath: path41.relative(outDir, blueprintStylePath),
79781
79825
  frames,
79782
79826
  ambient: Boolean(args8.ambient),
79783
79827
  seamDedup: resolveSeamDedup(args8["seam-dedup"]),
@@ -79805,7 +79849,7 @@ var scaffoldVideoCommand = defineCommand145({
79805
79849
  await writeFile21(outPath, `${JSON.stringify(canvas, null, 2)}
79806
79850
  `, "utf8");
79807
79851
  await writeFile21(
79808
- path40.join(outDir, REBUILD_FILE),
79852
+ path41.join(outDir, REBUILD_FILE),
79809
79853
  `${JSON.stringify({ elements, opts }, null, 2)}
79810
79854
  `,
79811
79855
  "utf8"
@@ -79832,7 +79876,7 @@ var scaffoldVideoCommand = defineCommand145({
79832
79876
  await ensureGitignore(process.cwd(), ["canvas/", ".context/"]);
79833
79877
  const sourceRef = videoSourceReference(blueprint, fileArg2);
79834
79878
  if (slug) {
79835
- const definitionPath = path40.join(outDir, "_definition.md");
79879
+ const definitionPath = path41.join(outDir, "_definition.md");
79836
79880
  if (!await fileExists(definitionPath)) {
79837
79881
  await writeFile21(
79838
79882
  definitionPath,
@@ -79888,7 +79932,7 @@ var scaffoldVideoCommand = defineCommand145({
79888
79932
  graph: canvas.metadata?.video?.graph_stats
79889
79933
  },
79890
79934
  checklist: {
79891
- 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 \`${path40.basename(blueprintPath2)}\`. \`baker canvas validate\`/\`run\` re-assemble the blueprint and re-flow every edited scene back into the render (and regenerate ${path40.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 ${path40.basename(blueprintStylePath)}; both are regenerated.`,
79935
+ 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 \`${path41.basename(blueprintPath2)}\`. \`baker canvas validate\`/\`run\` re-assemble the blueprint and re-flow every edited scene back into the render (and regenerate ${path41.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 ${path41.basename(blueprintStylePath)}; both are regenerated.`,
79892
79936
  recurring_elements_to_supply: report.elements,
79893
79937
  voices_to_confirm: report.dialogue.map((d) => ({
79894
79938
  scene: d.scene,
@@ -79926,7 +79970,7 @@ var scaffoldVideoCommand = defineCommand145({
79926
79970
 
79927
79971
  // src/commands/canvas/set-prompt.ts
79928
79972
  import { readFile as readFile35, writeFile as writeFile22 } from "fs/promises";
79929
- import path41 from "path";
79973
+ import path42 from "path";
79930
79974
  import { defineCommand as defineCommand146 } from "citty";
79931
79975
  function setNodePrompt(canvas, nodeId, text3) {
79932
79976
  const nodes = canvas?.nodes;
@@ -79955,7 +79999,7 @@ var SetPromptError = class extends Error {
79955
79999
  }
79956
80000
  };
79957
80001
  async function setPromptInCanvasFile(canvasPath, nodeId, text3) {
79958
- const filePath = path41.resolve(canvasPath);
80002
+ const filePath = path42.resolve(canvasPath);
79959
80003
  const original = await readFile35(filePath, "utf8");
79960
80004
  let canvas;
79961
80005
  try {
@@ -79978,7 +80022,7 @@ async function setPromptInCanvasFile(canvasPath, nodeId, text3) {
79978
80022
  "projected_prompt",
79979
80023
  `The prompt of "${nodeId}" is compiled from prompt.json on every validate and run, so setting it in the canvas would be overwritten.`,
79980
80024
  {
79981
- fix: `Edit the ad in ${path41.join(path41.dirname(filePath), "prompt.json")} (its scene, copy, references or direction), then run \`baker canvas validate\` to see the compiled prompt on the node.`
80025
+ fix: `Edit the ad in ${path42.join(path42.dirname(filePath), "prompt.json")} (its scene, copy, references or direction), then run \`baker canvas validate\` to see the compiled prompt on the node.`
79982
80026
  }
79983
80027
  );
79984
80028
  }
@@ -80032,7 +80076,7 @@ var setPromptCommand = defineCommand146({
80032
80076
  },
80033
80077
  async run({ args: args8 }) {
80034
80078
  let text3;
80035
- if (args8["text-file"]) text3 = await readFile35(path41.resolve(String(args8["text-file"])), "utf8");
80079
+ if (args8["text-file"]) text3 = await readFile35(path42.resolve(String(args8["text-file"])), "utf8");
80036
80080
  else if (args8.text !== void 0) text3 = String(args8.text);
80037
80081
  else {
80038
80082
  process.stderr.write(
@@ -80089,7 +80133,7 @@ var staleCommand = defineCommand147({
80089
80133
  });
80090
80134
 
80091
80135
  // src/commands/canvas/validate.ts
80092
- import path42 from "path";
80136
+ import path43 from "path";
80093
80137
  import { defineCommand as defineCommand148 } from "citty";
80094
80138
  var validateCommand = defineCommand148({
80095
80139
  meta: {
@@ -80098,7 +80142,7 @@ var validateCommand = defineCommand148({
80098
80142
  },
80099
80143
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
80100
80144
  async run({ args: args8 }) {
80101
- const filePath = path42.resolve(String(args8.file));
80145
+ const filePath = path43.resolve(String(args8.file));
80102
80146
  let prepared;
80103
80147
  try {
80104
80148
  prepared = await prepareCanvas(filePath, { gate: true, log: (line) => process.stderr.write(`${line}
@@ -80535,7 +80579,7 @@ import { defineCommand as defineCommand162 } from "citty";
80535
80579
  // src/commands/creatives/brief.ts
80536
80580
  import { readFileSync as readFileSync17 } from "fs";
80537
80581
  import { readdir as readdir17, readFile as readFile36 } from "fs/promises";
80538
- import path44 from "path";
80582
+ import path45 from "path";
80539
80583
  import { defineCommand as defineCommand155 } from "citty";
80540
80584
 
80541
80585
  // src/commands/winning-ads/search.ts
@@ -80793,8 +80837,8 @@ var FLAG_FOR_FIELD = {
80793
80837
  first_seen_after: "--first-seen-after",
80794
80838
  first_seen_before: "--first-seen-before"
80795
80839
  };
80796
- function flagFor(path69) {
80797
- const field = String(path69[0] === "hard_filters" ? path69[1] : path69[0]);
80840
+ function flagFor(path70) {
80841
+ const field = String(path70[0] === "hard_filters" ? path70[1] : path70[0]);
80798
80842
  return FLAG_FOR_FIELD[field] ?? field;
80799
80843
  }
80800
80844
  function schemaRejection(body) {
@@ -81108,17 +81152,17 @@ function customerTruth(insights) {
81108
81152
  for (const insight of insights) byType[insight.type] = (byType[insight.type] ?? 0) + 1;
81109
81153
  const observed = insights.filter((i) => i.status === "observed");
81110
81154
  const seen = /* @__PURE__ */ new Set();
81111
- const quotes = [];
81155
+ const quotes2 = [];
81112
81156
  for (const insight of observed) {
81113
- if (seen.has(insight.type) || quotes.length >= MAX_QUOTES) continue;
81157
+ if (seen.has(insight.type) || quotes2.length >= MAX_QUOTES) continue;
81114
81158
  seen.add(insight.type);
81115
- quotes.push({
81159
+ quotes2.push({
81116
81160
  id: insight.id,
81117
81161
  type: insight.type,
81118
81162
  quote: insight.quote.length > 140 ? `${insight.quote.slice(0, 137)}...` : insight.quote
81119
81163
  });
81120
81164
  }
81121
- return { total: insights.length, observed: observed.length, thin: observed.length < MIN_OBSERVED, byType, quotes };
81165
+ return { total: insights.length, observed: observed.length, thin: observed.length < MIN_OBSERVED, byType, quotes: quotes2 };
81122
81166
  }
81123
81167
  var MAX_SAYING = 6;
81124
81168
  var SAME_ANGLE = 0.4;
@@ -81266,7 +81310,7 @@ var ideasCommand = defineCommand153({
81266
81310
 
81267
81311
  // src/commands/creatives/performance.ts
81268
81312
  import { readFileSync as readFileSync16 } from "fs";
81269
- import path43 from "path";
81313
+ import path44 from "path";
81270
81314
  import { defineCommand as defineCommand154 } from "citty";
81271
81315
  import { parse as parseYaml4 } from "yaml";
81272
81316
  var DESCRIPTION5 = `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.
@@ -81330,7 +81374,7 @@ function definitionInsights(markdown) {
81330
81374
  }
81331
81375
  function readLocalDefinition(slug) {
81332
81376
  try {
81333
- return readFileSync16(path43.join(process.cwd(), "src", "creatives", slug, "_definition.md"), "utf8");
81377
+ return readFileSync16(path44.join(process.cwd(), "src", "creatives", slug, "_definition.md"), "utf8");
81334
81378
  } catch {
81335
81379
  return null;
81336
81380
  }
@@ -81442,11 +81486,11 @@ function isAvailable(value2) {
81442
81486
  return !(value2 !== null && typeof value2 === "object" && "unavailable" in value2);
81443
81487
  }
81444
81488
  async function companyStatus(root) {
81445
- const doc = await readFile36(path44.join(root, "COMPANY.md"), "utf8").catch(() => "");
81489
+ const doc = await readFile36(path45.join(root, "COMPANY.md"), "utf8").catch(() => "");
81446
81490
  return doc.trim() && !/^#\s*Company\s*\n+\s*TODO/m.test(doc) ? "ready" : "missing";
81447
81491
  }
81448
81492
  async function readOffers(root) {
81449
- const dir = path44.join(root, "src", "content", "offers");
81493
+ const dir = path45.join(root, "src", "content", "offers");
81450
81494
  const files = (await readdir17(dir, { recursive: true }).catch(() => [])).filter(
81451
81495
  (f) => f.endsWith(".md")
81452
81496
  );
@@ -81454,7 +81498,7 @@ async function readOffers(root) {
81454
81498
  }
81455
81499
  function readDefinition(root, slug) {
81456
81500
  try {
81457
- return readFileSync17(path44.join(root, "src", "creatives", slug, "_definition.md"), "utf8");
81501
+ return readFileSync17(path45.join(root, "src", "creatives", slug, "_definition.md"), "utf8");
81458
81502
  } catch {
81459
81503
  return null;
81460
81504
  }
@@ -81471,14 +81515,8 @@ async function readViewer(root, adSet) {
81471
81515
  var MARKET_ADS = 40;
81472
81516
  var MARKET_FALLBACK_ADS = 15;
81473
81517
  var MARKET_SEARCH_MS = 12e3;
81474
- var MARKET_QUERY_WORDS = 6;
81475
- function marketQuery(companyDoc) {
81476
- const first = companyDoc.split("\n").find((line) => line.trim() && !line.trim().startsWith("#")) ?? "";
81477
- const what = first.replace(/^\s*[-*]\s+/, "").replace(/^\*\*[^*]+\*\*\s*[—–:-]?\s*/, "").split(/\s+for\s+|[,.;:(]|\s[—–-]\s/)[0];
81478
- return (what ?? "").trim().split(/\s+/).filter(Boolean).slice(0, MARKET_QUERY_WORDS).join(" ");
81479
- }
81480
81518
  async function readMarket(root) {
81481
- const query = marketQuery(await readFile36(path44.join(root, "COMPANY.md"), "utf8").catch(() => ""));
81519
+ const query = marketQuery(await readFile36(path45.join(root, "COMPANY.md"), "utf8").catch(() => ""));
81482
81520
  if (!query) return null;
81483
81521
  const search = (body) => apiPost("/api/ad-library/winners/search", body, {
81484
81522
  timeoutMs: MARKET_SEARCH_MS
@@ -81689,10 +81727,10 @@ import { defineCommand as defineCommand157 } from "citty";
81689
81727
  import { defineCommand as defineCommand156 } from "citty";
81690
81728
 
81691
81729
  // src/commands/creatives/version-of.ts
81692
- import path45 from "path";
81730
+ import path46 from "path";
81693
81731
  async function versionOf(slug, run3) {
81694
81732
  if (typeof run3 === "string" && run3.trim()) return run3.trim();
81695
- const canvas = path45.join("src", "creatives", slug, `${slug}.canvas.json`);
81733
+ const canvas = path46.join("src", "creatives", slug, `${slug}.canvas.json`);
81696
81734
  return await latestVersion(canvasOutputsRoot(canvas), slug) ?? void 0;
81697
81735
  }
81698
81736
 
@@ -81837,7 +81875,7 @@ var feedbackCommand = defineCommand157({
81837
81875
  // src/commands/creatives/learn.ts
81838
81876
  import { readFileSync as readFileSync18 } from "fs";
81839
81877
  import { readFile as readFile37, writeFile as writeFile23 } from "fs/promises";
81840
- import path46 from "path";
81878
+ import path47 from "path";
81841
81879
  import { defineCommand as defineCommand158 } from "citty";
81842
81880
 
81843
81881
  // src/commands/creatives/learn-model.ts
@@ -82059,14 +82097,14 @@ function learnEnvelope(learnings, written, unreadable = []) {
82059
82097
  }
82060
82098
  async function writeBack(root, learnings) {
82061
82099
  for (const learning of learnings) {
82062
- const file = path46.join(root, IDEAS_DIR, `${learning.idea}.md`);
82100
+ const file = path47.join(root, IDEAS_DIR, `${learning.idea}.md`);
82063
82101
  const raw = await readFile37(file, "utf8");
82064
82102
  await writeFile23(file, setDefinitionFields(raw, { status: learning.to, result: learning.result }), "utf8");
82065
82103
  }
82066
82104
  }
82067
82105
  function readDefinition2(root, slug) {
82068
82106
  try {
82069
- return readFileSync18(path46.join(root, "src", "creatives", slug, "_definition.md"), "utf8");
82107
+ return readFileSync18(path47.join(root, "src", "creatives", slug, "_definition.md"), "utf8");
82070
82108
  } catch {
82071
82109
  return null;
82072
82110
  }
@@ -82106,7 +82144,7 @@ var learnCommand = defineCommand158({
82106
82144
  import { execFile as execFile3 } from "child_process";
82107
82145
  import { mkdtemp as mkdtemp2, readFile as readFile38, rm as rm7, stat as stat7, writeFile as writeFile24 } from "fs/promises";
82108
82146
  import { tmpdir as tmpdir3 } from "os";
82109
- import path47 from "path";
82147
+ import path48 from "path";
82110
82148
  import { promisify as promisify3 } from "util";
82111
82149
  import { defineCommand as defineCommand159 } from "citty";
82112
82150
  var run2 = promisify3(execFile3);
@@ -82329,7 +82367,7 @@ async function scaffoldIdea(root, idea, args8, slug, temperature) {
82329
82367
  ],
82330
82368
  signal
82331
82369
  );
82332
- const dir = path47.join(root, "src", "creatives", slug);
82370
+ const dir = path48.join(root, "src", "creatives", slug);
82333
82371
  const fresh = !await stat7(dir).catch(() => null);
82334
82372
  const reference = args8.reference ? { adId: args8.reference, platform: asPlatform(args8.platform), why: "chosen by hand", tried: 0 } : args8.fromIdea ? { code: "FROM_IDEA", message: "Asked to start from the idea." } : await pickReference(
82335
82373
  root,
@@ -82349,8 +82387,8 @@ async function scaffoldIdea(root, idea, args8, slug, temperature) {
82349
82387
  return { scaffold, reference };
82350
82388
  }
82351
82389
  async function scaffoldFromIdea(idea, slug, viewerFlags) {
82352
- const dir = await mkdtemp2(path47.join(tmpdir3(), "idea-spec-"));
82353
- const specPath = path47.join(dir, "prompt.json");
82390
+ const dir = await mkdtemp2(path48.join(tmpdir3(), "idea-spec-"));
82391
+ const specPath = path48.join(dir, "prompt.json");
82354
82392
  await writeFile24(specPath, JSON.stringify(ideaSpec(idea, idea.who.replace(/[-_]/g, " ")), null, 2), "utf8");
82355
82393
  try {
82356
82394
  return await baker([
@@ -82369,18 +82407,18 @@ async function scaffoldFromIdea(idea, slug, viewerFlags) {
82369
82407
  }
82370
82408
  }
82371
82409
  async function recordIdea(root, slug, idea, evidence) {
82372
- const dir = path47.join(root, "src", "creatives", slug);
82373
- const definitionPath = path47.join(dir, "_definition.md");
82410
+ const dir = path48.join(root, "src", "creatives", slug);
82411
+ const definitionPath = path48.join(dir, "_definition.md");
82374
82412
  const definition = await readFile38(definitionPath, "utf8").catch(() => null);
82375
82413
  if (definition !== null) {
82376
82414
  await writeFile24(definitionPath, setDefinitionFields(definition, { ...definitionFieldsOf(idea, evidence) }), "utf8");
82377
82415
  }
82378
- const promptPath = path47.join(dir, "prompt.json");
82416
+ const promptPath = path48.join(dir, "prompt.json");
82379
82417
  const prompt = isVideoIdea(idea) ? null : await readFile38(promptPath, "utf8").catch(() => null);
82380
82418
  if (prompt !== null) await writeFile24(promptPath, setSpecMessage(prompt, idea.message), "utf8").catch(() => void 0);
82381
82419
  const unsourcedCopy = prompt === null ? [] : await draftedClaims(root, prompt);
82382
82420
  if (idea.status === "idea") {
82383
- const ideaPath = path47.join(root, IDEAS_DIR, `${idea.id}.md`);
82421
+ const ideaPath = path48.join(root, IDEAS_DIR, `${idea.id}.md`);
82384
82422
  await writeFile24(ideaPath, setDefinitionFields(await readFile38(ideaPath, "utf8"), { status: "built" }), "utf8");
82385
82423
  }
82386
82424
  await baker(["canvas", "sync-definition", dir]);
@@ -82457,7 +82495,7 @@ var makeCommand = defineCommand159({
82457
82495
  const opts = makeArgsOf(args8);
82458
82496
  const { idea, check } = await loadIdea(root, String(args8.idea));
82459
82497
  const slug = opts.slug ?? idea.id;
82460
- const written = await readFile38(path47.join(root, "src", "creatives", slug, "prompt.json"), "utf8").then(
82498
+ const written = await readFile38(path48.join(root, "src", "creatives", slug, "prompt.json"), "utf8").then(
82461
82499
  (text3) => {
82462
82500
  try {
82463
82501
  return JSON.parse(text3);
@@ -82481,7 +82519,7 @@ var makeCommand = defineCommand159({
82481
82519
  reference,
82482
82520
  ...fromIdea ? { fromIdea } : {},
82483
82521
  viewer: opts.adset ? { adset: opts.adset } : { temperature },
82484
- canvasPath: path47.relative(root, String(scaffold.canvas_path ?? path47.join(dir, `${slug}.canvas.json`))),
82522
+ canvasPath: path48.relative(root, String(scaffold.canvas_path ?? path48.join(dir, `${slug}.canvas.json`))),
82485
82523
  scaffoldHints: Array.isArray(scaffold.hints) ? scaffold.hints : [],
82486
82524
  unsourcedCopy
82487
82525
  })
@@ -84235,11 +84273,11 @@ import { defineCommand as defineCommand164 } from "citty";
84235
84273
 
84236
84274
  // src/commands/experiment/composition.ts
84237
84275
  import { readdir as readdir19, readFile as readFile42 } from "fs/promises";
84238
- import path49 from "path";
84276
+ import path50 from "path";
84239
84277
 
84240
84278
  // src/commands/landing/import-graph.ts
84241
84279
  import { readdir as readdir18, readFile as readFile41, stat as stat8 } from "fs/promises";
84242
- import path48 from "path";
84280
+ import path49 from "path";
84243
84281
  var SOURCE_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
84244
84282
  var RESOLVE_CANDIDATES = [
84245
84283
  "",
@@ -84272,7 +84310,7 @@ async function walkFiles(dir) {
84272
84310
  }
84273
84311
  const out = [];
84274
84312
  for (const entry of entries) {
84275
- const full = path48.join(dir, entry.name);
84313
+ const full = path49.join(dir, entry.name);
84276
84314
  if (entry.isDirectory()) {
84277
84315
  if (entry.name === "node_modules" || entry.name === "dist") continue;
84278
84316
  out.push(...await walkFiles(full));
@@ -84286,8 +84324,8 @@ async function resolveSpecifier(specifier, fromFile, root) {
84286
84324
  const bare = specifier.split("?")[0] ?? "";
84287
84325
  if (bare.includes("*")) return null;
84288
84326
  let base;
84289
- if (bare.startsWith("/")) base = path48.join(root, bare.slice(1));
84290
- else if (bare.startsWith(".")) base = path48.resolve(path48.dirname(fromFile), bare);
84327
+ if (bare.startsWith("/")) base = path49.join(root, bare.slice(1));
84328
+ else if (bare.startsWith(".")) base = path49.resolve(path49.dirname(fromFile), bare);
84291
84329
  else return null;
84292
84330
  for (const suffix of RESOLVE_CANDIDATES) {
84293
84331
  const candidate = base + suffix;
@@ -84309,7 +84347,7 @@ async function importedFiles(text3, file, root) {
84309
84347
  }
84310
84348
  async function landingGraphFiles(root, slug) {
84311
84349
  const seen = /* @__PURE__ */ new Set();
84312
- const queue = await walkFiles(path48.join(root, "src/pages", slug));
84350
+ const queue = await walkFiles(path49.join(root, "src/pages", slug));
84313
84351
  while (queue.length > 0) {
84314
84352
  const file = queue.pop();
84315
84353
  if (file === void 0 || seen.has(file)) continue;
@@ -84324,7 +84362,7 @@ async function landingGraphFiles(root, slug) {
84324
84362
  if (!seen.has(target2)) queue.push(target2);
84325
84363
  }
84326
84364
  }
84327
- return new Set([...seen].map((abs) => path48.relative(root, abs).split(path48.sep).join("/")));
84365
+ return new Set([...seen].map((abs) => path49.relative(root, abs).split(path49.sep).join("/")));
84328
84366
  }
84329
84367
 
84330
84368
  // src/commands/experiment/composition.ts
@@ -84369,7 +84407,7 @@ function formsOnlyIn(these, those) {
84369
84407
  }
84370
84408
  async function knownFlows(root) {
84371
84409
  try {
84372
- const entries = await readdir19(path49.join(root, "src/lib/flow-engine/flows"), { withFileTypes: true });
84410
+ const entries = await readdir19(path50.join(root, "src/lib/flow-engine/flows"), { withFileTypes: true });
84373
84411
  return new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name));
84374
84412
  } catch {
84375
84413
  return /* @__PURE__ */ new Set();
@@ -84380,7 +84418,7 @@ async function readForms(root, slug) {
84380
84418
  const [files, flows] = await Promise.all([landingGraphFiles(root, slug), knownFlows(root)]);
84381
84419
  if (flows.size === 0) return [];
84382
84420
  const texts = await Promise.all(
84383
- [...files].filter((file) => /\.(astro|ts|tsx|js|mjs)$/.test(file)).map((file) => readFile42(path49.join(root, file), "utf8"))
84421
+ [...files].filter((file) => /\.(astro|ts|tsx|js|mjs)$/.test(file)).map((file) => readFile42(path50.join(root, file), "utf8"))
84384
84422
  );
84385
84423
  return formsReferenced(texts, flows);
84386
84424
  } catch {
@@ -84391,7 +84429,7 @@ async function readForms(root, slug) {
84391
84429
  // src/commands/experiment/fold.ts
84392
84430
  import { statSync } from "fs";
84393
84431
  import { cp as cp3, mkdir as mkdir15, readdir as readdir20, readFile as readFile43, rm as rm8, stat as stat9, writeFile as writeFile25 } from "fs/promises";
84394
- import path51 from "path";
84432
+ import path52 from "path";
84395
84433
 
84396
84434
  // ../api/src/experiments/variants.ts
84397
84435
  var VARIANT_SEPARATOR = "--";
@@ -84416,21 +84454,21 @@ function nextVariantNumber(page, existingSlugs, archived) {
84416
84454
  }
84417
84455
 
84418
84456
  // src/commands/landing/repoint.ts
84419
- import path50 from "path";
84457
+ import path51 from "path";
84420
84458
  var QUOTED_RELATIVE = /(['"])(\.\.?\/[^'"]*)\1/g;
84421
84459
  function isInside3(abs, dir) {
84422
- return abs === dir || abs.startsWith(dir + path50.sep);
84460
+ return abs === dir || abs.startsWith(dir + path51.sep);
84423
84461
  }
84424
84462
  function toSpecifier(from, to) {
84425
- const rel = path50.relative(from, to).split(path50.sep).join("/");
84463
+ const rel = path51.relative(from, to).split(path51.sep).join("/");
84426
84464
  return rel.startsWith(".") ? rel : `./${rel}`;
84427
84465
  }
84428
84466
  function repointSpecifier(spec, opts) {
84429
84467
  if (!spec.startsWith(".")) return spec;
84430
- const abs = path50.resolve(opts.fromDir, spec);
84468
+ const abs = path51.resolve(opts.fromDir, spec);
84431
84469
  if (opts.forkedTargets?.has(abs)) {
84432
- const withinControl = path50.relative(opts.controlDir, abs);
84433
- return toSpecifier(opts.toDir, path50.resolve(opts.variantDir, withinControl));
84470
+ const withinControl = path51.relative(opts.controlDir, abs);
84471
+ return toSpecifier(opts.toDir, path51.resolve(opts.variantDir, withinControl));
84434
84472
  }
84435
84473
  if (!isInside3(abs, opts.controlDir)) return spec;
84436
84474
  return toSpecifier(opts.toDir, abs);
@@ -84442,9 +84480,9 @@ function repointFile(text3, opts) {
84442
84480
  }
84443
84481
  function repointMoved(text3, opts) {
84444
84482
  return text3.replace(QUOTED_RELATIVE, (_match, quote, spec) => {
84445
- const abs = path50.resolve(opts.fromDir, spec);
84446
- const within = path50.relative(opts.movedFrom, abs);
84447
- const target2 = within.startsWith("..") || path50.isAbsolute(within) ? abs : path50.resolve(opts.movedTo, within);
84483
+ const abs = path51.resolve(opts.fromDir, spec);
84484
+ const within = path51.relative(opts.movedFrom, abs);
84485
+ const target2 = within.startsWith("..") || path51.isAbsolute(within) ? abs : path51.resolve(opts.movedTo, within);
84448
84486
  return `${quote}${toSpecifier(opts.toDir, target2)}${quote}`;
84449
84487
  });
84450
84488
  }
@@ -84453,7 +84491,7 @@ function repointMoved(text3, opts) {
84453
84491
  var ARCHIVE_ROOT = "src/_variants";
84454
84492
  var QUOTED_RELATIVE2 = /(['"])(\.\.?\/[^'"]*)\1/g;
84455
84493
  function posix2(p) {
84456
- return p.split(path51.sep).join("/");
84494
+ return p.split(path52.sep).join("/");
84457
84495
  }
84458
84496
  async function isDir(p) {
84459
84497
  try {
@@ -84472,39 +84510,39 @@ async function filesUnder(dir, prefix = "") {
84472
84510
  const out = [];
84473
84511
  for (const entry of entries) {
84474
84512
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
84475
- if (entry.isDirectory()) out.push(...await filesUnder(path51.join(dir, entry.name), rel));
84513
+ if (entry.isDirectory()) out.push(...await filesUnder(path52.join(dir, entry.name), rel));
84476
84514
  else out.push(rel);
84477
84515
  }
84478
84516
  return out.sort();
84479
84517
  }
84480
84518
  var TEXT_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte|md|json|css)$/;
84481
84519
  function archiveRelPath(abs, base) {
84482
- if (!abs.startsWith(base + path51.sep)) return null;
84483
- return posix2(path51.relative(base, abs));
84520
+ if (!abs.startsWith(base + path52.sep)) return null;
84521
+ return posix2(path52.relative(base, abs));
84484
84522
  }
84485
84523
  async function archiveArm(opts) {
84486
84524
  const { root, armDir, pageDir, archiveDir, armSlug } = opts;
84487
84525
  const targets = await archiveContents({ root, armDir, pageDir, armSlug });
84488
- const archivedBySource = new Map([...targets].map(([rel, abs]) => [abs, path51.join(archiveDir, rel)]));
84526
+ const archivedBySource = new Map([...targets].map(([rel, abs]) => [abs, path52.join(archiveDir, rel)]));
84489
84527
  const written = [];
84490
84528
  for (const [rel, abs] of [...targets].sort()) {
84491
- const dest = path51.join(archiveDir, rel);
84492
- await mkdir15(path51.dirname(dest), { recursive: true });
84529
+ const dest = path52.join(archiveDir, rel);
84530
+ await mkdir15(path52.dirname(dest), { recursive: true });
84493
84531
  if (!TEXT_EXT.test(rel)) {
84494
84532
  await cp3(abs, dest);
84495
84533
  } else {
84496
84534
  const text3 = await readFile43(abs, "utf8");
84497
84535
  await writeFile25(dest, repointIntoArchive(text3, abs, dest, archivedBySource), "utf8");
84498
84536
  }
84499
- written.push(posix2(path51.relative(root, dest)));
84537
+ written.push(posix2(path52.relative(root, dest)));
84500
84538
  }
84501
84539
  return written;
84502
84540
  }
84503
84541
  async function archiveContents(opts) {
84504
84542
  const { root, armDir, pageDir, armSlug } = opts;
84505
84543
  const graph = await landingGraphFiles(root, armSlug);
84506
- const reachable = new Set([...graph].map((rel) => path51.resolve(root, rel)));
84507
- for (const rel of await filesUnder(armDir)) reachable.add(path51.join(armDir, rel));
84544
+ const reachable = new Set([...graph].map((rel) => path52.resolve(root, rel)));
84545
+ for (const rel of await filesUnder(armDir)) reachable.add(path52.join(armDir, rel));
84508
84546
  const sorted = [...reachable].sort();
84509
84547
  const targets = /* @__PURE__ */ new Map();
84510
84548
  for (const base of [pageDir, armDir]) {
@@ -84517,14 +84555,14 @@ async function archiveContents(opts) {
84517
84555
  return targets;
84518
84556
  }
84519
84557
  function repointIntoArchive(text3, sourceAbs, destAbs, archivedBySource) {
84520
- const fromDir = path51.dirname(sourceAbs);
84521
- const toDir = path51.dirname(destAbs);
84558
+ const fromDir = path52.dirname(sourceAbs);
84559
+ const toDir = path52.dirname(destAbs);
84522
84560
  return text3.replace(QUOTED_RELATIVE2, (match, quote, spec, offset) => {
84523
84561
  const [specPath, suffix] = splitSuffix(spec);
84524
- const target2 = path51.resolve(fromDir, specPath);
84562
+ const target2 = path52.resolve(fromDir, specPath);
84525
84563
  const resolved = resolveInArchive(target2, archivedBySource) ?? resolveOnDisk(target2, isImportPosition(text3, offset));
84526
84564
  if (resolved === null) return match;
84527
- const rel = posix2(path51.relative(toDir, resolved));
84565
+ const rel = posix2(path52.relative(toDir, resolved));
84528
84566
  return `${quote}${rel.startsWith(".") ? rel : `./${rel}`}${suffix}${quote}`;
84529
84567
  });
84530
84568
  }
@@ -84558,9 +84596,9 @@ async function promoteVariantFiles(opts) {
84558
84596
  const written = [];
84559
84597
  for (const rel of await filesUnder(variantDir)) {
84560
84598
  if (rel === "_definition.md") continue;
84561
- const from = path51.join(variantDir, rel);
84562
- const to = path51.join(pageDir, rel);
84563
- await mkdir15(path51.dirname(to), { recursive: true });
84599
+ const from = path52.join(variantDir, rel);
84600
+ const to = path52.join(pageDir, rel);
84601
+ await mkdir15(path52.dirname(to), { recursive: true });
84564
84602
  if (!TEXT_EXT.test(rel)) {
84565
84603
  await cp3(from, to);
84566
84604
  } else {
@@ -84568,15 +84606,15 @@ async function promoteVariantFiles(opts) {
84568
84606
  await writeFile25(
84569
84607
  to,
84570
84608
  repointMoved(text3, {
84571
- fromDir: path51.dirname(from),
84572
- toDir: path51.dirname(to),
84609
+ fromDir: path52.dirname(from),
84610
+ toDir: path52.dirname(to),
84573
84611
  movedFrom: variantDir,
84574
84612
  movedTo: pageDir
84575
84613
  }),
84576
84614
  "utf8"
84577
84615
  );
84578
84616
  }
84579
- written.push(posix2(path51.relative(root, to)));
84617
+ written.push(posix2(path52.relative(root, to)));
84580
84618
  }
84581
84619
  return written;
84582
84620
  }
@@ -84600,8 +84638,8 @@ function archiveRecord(target2, variantNumber) {
84600
84638
  `;
84601
84639
  }
84602
84640
  async function foldExperiment(root, target2) {
84603
- const pageDir = path51.resolve(root, "src/pages", target2.landingSlug);
84604
- const variantDir = path51.resolve(root, "src/pages", target2.variantSlug);
84641
+ const pageDir = path52.resolve(root, "src/pages", target2.landingSlug);
84642
+ const variantDir = path52.resolve(root, "src/pages", target2.variantSlug);
84605
84643
  const variantNumber = variantNumberOf(target2.variantSlug);
84606
84644
  if (variantNumber === null) {
84607
84645
  return {
@@ -84615,7 +84653,7 @@ async function foldExperiment(root, target2) {
84615
84653
  return { error: `src/pages/${target2.variantSlug}/ is already gone \u2014 this test looks folded in already` };
84616
84654
  }
84617
84655
  const archiveKey = target2.landingInternalId ?? target2.landingSlug;
84618
- const archiveDir = path51.resolve(root, ARCHIVE_ROOT, archiveKey, String(variantNumber));
84656
+ const archiveDir = path52.resolve(root, ARCHIVE_ROOT, archiveKey, String(variantNumber));
84619
84657
  await rm8(archiveDir, { recursive: true, force: true });
84620
84658
  await mkdir15(archiveDir, { recursive: true });
84621
84659
  const written = await archiveArm({
@@ -84625,8 +84663,8 @@ async function foldExperiment(root, target2) {
84625
84663
  archiveDir,
84626
84664
  armSlug: target2.survivor === "variant" ? target2.landingSlug : target2.variantSlug
84627
84665
  });
84628
- await writeFile25(path51.join(archiveDir, "_variant.json"), archiveRecord(target2, variantNumber), "utf8");
84629
- written.push(posix2(path51.join(ARCHIVE_ROOT, archiveKey, String(variantNumber), "_variant.json")));
84666
+ await writeFile25(path52.join(archiveDir, "_variant.json"), archiveRecord(target2, variantNumber), "utf8");
84667
+ written.push(posix2(path52.join(ARCHIVE_ROOT, archiveKey, String(variantNumber), "_variant.json")));
84630
84668
  if (target2.survivor === "variant") {
84631
84669
  written.push(...await promoteVariantFiles({ root, pageDir, variantDir }));
84632
84670
  }
@@ -84634,7 +84672,7 @@ async function foldExperiment(root, target2) {
84634
84672
  return {
84635
84673
  experimentId: target2.experimentId,
84636
84674
  page: target2.landingSlug,
84637
- archivedTo: posix2(path51.join(ARCHIVE_ROOT, archiveKey, String(variantNumber))),
84675
+ archivedTo: posix2(path52.join(ARCHIVE_ROOT, archiveKey, String(variantNumber))),
84638
84676
  written,
84639
84677
  removed: [`src/pages/${target2.variantSlug}`]
84640
84678
  };
@@ -85407,10 +85445,10 @@ function parseEvidence(raw, rawArgs) {
85407
85445
 
85408
85446
  // src/commands/experiment/identity.ts
85409
85447
  import { readFile as readFile44 } from "fs/promises";
85410
- import path52 from "path";
85448
+ import path53 from "path";
85411
85449
  async function readPageInternalId(root, slug) {
85412
85450
  try {
85413
- const text3 = await readFile44(path52.resolve(root, "src", "pages", slug, "_definition.md"), "utf8");
85451
+ const text3 = await readFile44(path53.resolve(root, "src", "pages", slug, "_definition.md"), "utf8");
85414
85452
  return /^internalId:\s*"?([^"\s]+)"?\s*$/m.exec(text3)?.[1];
85415
85453
  } catch {
85416
85454
  return void 0;
@@ -85419,7 +85457,7 @@ async function readPageInternalId(root, slug) {
85419
85457
 
85420
85458
  // src/commands/experiment/measurement.ts
85421
85459
  import { readFile as readFile45 } from "fs/promises";
85422
- import path53 from "path";
85460
+ import path54 from "path";
85423
85461
  function eventDeclarationsIn(source) {
85424
85462
  const found = [];
85425
85463
  const pattern = /\b(data-baker-(?:view|event))\s*=\s*["']([^"']+)["']/g;
@@ -85479,7 +85517,7 @@ function sectionsOf(files, slug) {
85479
85517
  return files.filter((file) => file.startsWith(prefix) && !file.slice(prefix.length).startsWith("index."));
85480
85518
  }
85481
85519
  async function declarationsOf(root, files) {
85482
- const sources = await Promise.all(files.map((file) => readFile45(path53.join(root, file), "utf8").catch(() => "")));
85520
+ const sources = await Promise.all(files.map((file) => readFile45(path54.join(root, file), "utf8").catch(() => "")));
85483
85521
  return sources.flatMap(eventDeclarationsIn);
85484
85522
  }
85485
85523
 
@@ -86901,10 +86939,10 @@ function parseValueExpression(raw) {
86901
86939
  return parts.map(parsePart);
86902
86940
  }
86903
86941
  function trackingFieldIds() {
86904
- const path69 = join4(flowsDir(), "..", "tracking.ts");
86905
- if (!existsSync9(path69)) return null;
86942
+ const path70 = join4(flowsDir(), "..", "tracking.ts");
86943
+ if (!existsSync9(path70)) return null;
86906
86944
  try {
86907
- const source = readFileSync19(path69, "utf-8");
86945
+ const source = readFileSync19(path70, "utf-8");
86908
86946
  const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
86909
86947
  if (!block2) return null;
86910
86948
  const ids2 = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
@@ -87486,13 +87524,13 @@ function specsFromFile(parsed) {
87486
87524
  return `${destField}${type}=${entry?.value ?? ""}`;
87487
87525
  });
87488
87526
  }
87489
- function readSpecFile(path69) {
87527
+ function readSpecFile(path70) {
87490
87528
  let raw;
87491
87529
  try {
87492
- raw = path69 === "-" ? readFileSync20(0, "utf-8") : readFileSync20(path69, "utf-8");
87530
+ raw = path70 === "-" ? readFileSync20(0, "utf-8") : readFileSync20(path70, "utf-8");
87493
87531
  } catch (error) {
87494
87532
  refuse3(
87495
- `Could not read ${path69 === "-" ? "the mapping from stdin" : `"${path69}"`}: ${error instanceof Error ? error.message : String(error)}`
87533
+ `Could not read ${path70 === "-" ? "the mapping from stdin" : `"${path70}"`}: ${error instanceof Error ? error.message : String(error)}`
87496
87534
  );
87497
87535
  }
87498
87536
  let parsed;
@@ -87500,7 +87538,7 @@ function readSpecFile(path69) {
87500
87538
  parsed = JSON.parse(raw);
87501
87539
  } catch (error) {
87502
87540
  refuse3(
87503
- `${path69 === "-" ? "stdin" : `"${path69}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
87541
+ `${path70 === "-" ? "stdin" : `"${path70}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
87504
87542
  'Expected { "map": { "<destField>": "<value>", \u2026 } }'
87505
87543
  );
87506
87544
  }
@@ -87799,21 +87837,21 @@ var ARRAY_FIELDS = [
87799
87837
  "tagIds"
87800
87838
  ];
87801
87839
  var ARRAY_OWNERS = ["", "body"];
87802
- function dropUnsetOptionals(sideEffect, path69) {
87840
+ function dropUnsetOptionals(sideEffect, path70) {
87803
87841
  return OPTIONAL_STRINGS.flatMap((key) => {
87804
87842
  if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
87805
87843
  delete sideEffect[key];
87806
- return [{ path: path69, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
87844
+ return [{ path: path70, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
87807
87845
  });
87808
87846
  }
87809
- function fillNulledArrays(target2, prefix, path69) {
87847
+ function fillNulledArrays(target2, prefix, path70) {
87810
87848
  return ARRAY_FIELDS.flatMap((key) => {
87811
87849
  if (!(key in target2) || target2[key] !== null) return [];
87812
87850
  target2[key] = [];
87813
- return [{ path: path69, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
87851
+ return [{ path: path70, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
87814
87852
  });
87815
87853
  }
87816
- function tidyEmailRecipients(sideEffect, path69) {
87854
+ function tidyEmailRecipients(sideEffect, path70) {
87817
87855
  if (sideEffect.type !== "email") return [];
87818
87856
  const config = sideEffect.encryptedConfig;
87819
87857
  if (!config || typeof config !== "object" || Array.isArray(config)) return [];
@@ -87824,7 +87862,7 @@ function tidyEmailRecipients(sideEffect, path69) {
87824
87862
  const tidied = to.join(", ");
87825
87863
  if (tidied === raw) return [];
87826
87864
  config.email = tidied;
87827
- return [{ path: path69, change: "tidied the recipient list's spacing and separators" }];
87865
+ return [{ path: path70, change: "tidied the recipient list's spacing and separators" }];
87828
87866
  }
87829
87867
  function sideEffectsOf(node) {
87830
87868
  if (!Array.isArray(node.sideEffects)) return [];
@@ -87833,13 +87871,13 @@ function sideEffectsOf(node) {
87833
87871
  );
87834
87872
  }
87835
87873
  function normalizeSideEffect(sideEffect, where) {
87836
- const path69 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
87874
+ const path70 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
87837
87875
  const arrays = ARRAY_OWNERS.flatMap((owner) => {
87838
87876
  const target2 = owner ? sideEffect[owner] : sideEffect;
87839
87877
  if (!target2 || typeof target2 !== "object") return [];
87840
- return fillNulledArrays(target2, owner ? `${owner}.` : "", path69);
87878
+ return fillNulledArrays(target2, owner ? `${owner}.` : "", path70);
87841
87879
  });
87842
- return [...dropUnsetOptionals(sideEffect, path69), ...arrays, ...tidyEmailRecipients(sideEffect, path69)];
87880
+ return [...dropUnsetOptionals(sideEffect, path70), ...arrays, ...tidyEmailRecipients(sideEffect, path70)];
87843
87881
  }
87844
87882
  function normalizeFlowTree(tree) {
87845
87883
  const changes = [];
@@ -89345,10 +89383,10 @@ async function stageOps(ops) {
89345
89383
  handleError5(err);
89346
89384
  }
89347
89385
  }
89348
- async function draftAction2(path69, body, chat) {
89386
+ async function draftAction2(path70, body, chat) {
89349
89387
  const chatId = resolveChatId(chat);
89350
89388
  try {
89351
- const { data, hints: hints2 } = splitHints(await apiPost(path69, { chatId, ...body }));
89389
+ const { data, hints: hints2 } = splitHints(await apiPost(path70, { chatId, ...body }));
89352
89390
  writeJsonEnvelope({ ok: true, data, ...hints2.length > 0 ? { hints: hints2 } : {} });
89353
89391
  return data;
89354
89392
  } catch (err) {
@@ -91894,9 +91932,9 @@ async function readImageBuffer(pathOrUrl) {
91894
91932
  }
91895
91933
  return readFile46(pathOrUrl);
91896
91934
  }
91897
- async function isDirectory(path69) {
91935
+ async function isDirectory(path70) {
91898
91936
  try {
91899
- const s = await stat10(path69);
91937
+ const s = await stat10(path70);
91900
91938
  return s.isDirectory();
91901
91939
  } catch {
91902
91940
  return false;
@@ -92324,13 +92362,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
92324
92362
  }
92325
92363
  function disambiguate(paths) {
92326
92364
  const taken = /* @__PURE__ */ new Set();
92327
- return paths.map((path69) => {
92328
- if (!taken.has(path69)) {
92329
- taken.add(path69);
92330
- return path69;
92365
+ return paths.map((path70) => {
92366
+ if (!taken.has(path70)) {
92367
+ taken.add(path70);
92368
+ return path70;
92331
92369
  }
92332
- const ext = extname4(path69);
92333
- const stem = path69.slice(0, path69.length - ext.length);
92370
+ const ext = extname4(path70);
92371
+ const stem = path70.slice(0, path70.length - ext.length);
92334
92372
  let n = 2;
92335
92373
  while (taken.has(`${stem}-${n}${ext}`)) n += 1;
92336
92374
  const unique2 = `${stem}-${n}${ext}`;
@@ -92456,10 +92494,10 @@ async function runDownloads(plan) {
92456
92494
  const paths = disambiguate(fetched.map((item) => item.path));
92457
92495
  const downloaded = [];
92458
92496
  for (const [index, item] of fetched.entries()) {
92459
- const path69 = paths[index] ?? item.path;
92497
+ const path70 = paths[index] ?? item.path;
92460
92498
  try {
92461
- await atomicWrite(path69, item.buffer);
92462
- downloaded.push({ input: item.input, output: path69, bytes: item.buffer.length, contentType: item.contentType });
92499
+ await atomicWrite(path70, item.buffer);
92500
+ downloaded.push({ input: item.input, output: path70, bytes: item.buffer.length, contentType: item.contentType });
92463
92501
  } catch (err) {
92464
92502
  failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
92465
92503
  }
@@ -95355,7 +95393,7 @@ import { defineCommand as defineCommand226 } from "citty";
95355
95393
 
95356
95394
  // src/commands/landing/critique.ts
95357
95395
  import { readdir as readdir22, readFile as readFile48, stat as stat12 } from "fs/promises";
95358
- import path56 from "path";
95396
+ import path57 from "path";
95359
95397
  import { defineCommand as defineCommand213 } from "citty";
95360
95398
 
95361
95399
  // src/engine/landing/lib/constants.ts
@@ -96547,13 +96585,13 @@ function describeCounts(findings) {
96547
96585
 
96548
96586
  // src/commands/landing/snapshot.ts
96549
96587
  import { mkdir as mkdir16, rename as rename3, writeFile as writeFile27 } from "fs/promises";
96550
- import path54 from "path";
96588
+ import path55 from "path";
96551
96589
  var CRITIC_VERSION = "4";
96552
96590
  function critiqueCacheDir(projectRoot) {
96553
- return path54.join(projectRoot, ".cache", "landing-critique");
96591
+ return path55.join(projectRoot, ".cache", "landing-critique");
96554
96592
  }
96555
96593
  function snapshotPath(projectRoot, slug) {
96556
- return path54.join(critiqueCacheDir(projectRoot), `${slug}.json`);
96594
+ return path55.join(critiqueCacheDir(projectRoot), `${slug}.json`);
96557
96595
  }
96558
96596
  async function writeCritiqueSnapshot(projectRoot, snapshot) {
96559
96597
  await mkdir16(critiqueCacheDir(projectRoot), { recursive: true });
@@ -96566,7 +96604,7 @@ async function writeCritiqueSnapshot(projectRoot, snapshot) {
96566
96604
 
96567
96605
  // src/commands/landing/source-version.ts
96568
96606
  import { readdir as readdir21, readFile as readFile47, stat as stat11 } from "fs/promises";
96569
- import path55 from "path";
96607
+ import path56 from "path";
96570
96608
  var CRITIQUED_ROOTS = ["src/pages/", "src/components/"];
96571
96609
  async function landingSourceRelPaths(root, slug) {
96572
96610
  const files = await landingGraphFiles(root, slug);
@@ -96575,7 +96613,7 @@ async function landingSourceRelPaths(root, slug) {
96575
96613
  async function readLandingSources(root, slug) {
96576
96614
  const rel = await landingSourceRelPaths(root, slug);
96577
96615
  const out = [];
96578
- for (const r of rel) out.push({ path: r, text: await readFile47(path55.join(root, r), "utf8") });
96616
+ for (const r of rel) out.push({ path: r, text: await readFile47(path56.join(root, r), "utf8") });
96579
96617
  return out;
96580
96618
  }
96581
96619
  async function computeLandingSourceSha(root, slug) {
@@ -96584,7 +96622,7 @@ async function computeLandingSourceSha(root, slug) {
96584
96622
  for (const r of rel) {
96585
96623
  let bytes;
96586
96624
  try {
96587
- bytes = await readFile47(path55.join(root, r));
96625
+ bytes = await readFile47(path56.join(root, r));
96588
96626
  } catch {
96589
96627
  bytes = Buffer.alloc(0);
96590
96628
  }
@@ -96594,16 +96632,16 @@ async function computeLandingSourceSha(root, slug) {
96594
96632
  }
96595
96633
  async function computeLegacyLandingSourceSha(landingDir) {
96596
96634
  const rel = [];
96597
- if (await isFile2(path55.join(landingDir, "index.astro"))) rel.push("index.astro");
96598
- for (const abs of await walkAstro(path55.join(landingDir, "_components"))) {
96599
- rel.push(path55.relative(landingDir, abs).split(path55.sep).join("/"));
96635
+ if (await isFile2(path56.join(landingDir, "index.astro"))) rel.push("index.astro");
96636
+ for (const abs of await walkAstro(path56.join(landingDir, "_components"))) {
96637
+ rel.push(path56.relative(landingDir, abs).split(path56.sep).join("/"));
96600
96638
  }
96601
96639
  rel.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
96602
96640
  const parts = [];
96603
96641
  for (const r of rel) {
96604
96642
  let bytes;
96605
96643
  try {
96606
- bytes = await readFile47(path55.join(landingDir, r));
96644
+ bytes = await readFile47(path56.join(landingDir, r));
96607
96645
  } catch {
96608
96646
  bytes = Buffer.alloc(0);
96609
96647
  }
@@ -96627,7 +96665,7 @@ async function walkAstro(dir) {
96627
96665
  }
96628
96666
  const out = [];
96629
96667
  for (const entry of entries) {
96630
- const abs = path55.join(dir, entry.name);
96668
+ const abs = path56.join(dir, entry.name);
96631
96669
  if (entry.isDirectory()) out.push(...await walkAstro(abs));
96632
96670
  else if (entry.isFile() && entry.name.endsWith(".astro")) out.push(abs);
96633
96671
  }
@@ -96688,7 +96726,7 @@ var critiqueCommand2 = defineCommand213({
96688
96726
  { availableSlugs: await listLandingSlugs(projectRoot) }
96689
96727
  );
96690
96728
  }
96691
- if (!await isDir2(path56.resolve(projectRoot, "src", "pages", slug))) {
96729
+ if (!await isDir2(path57.resolve(projectRoot, "src", "pages", slug))) {
96692
96730
  fail10("NOT_FOUND", `No landing at src/pages/${slug}/`, {
96693
96731
  availableSlugs: await listLandingSlugs(projectRoot)
96694
96732
  });
@@ -96731,7 +96769,7 @@ async function critiqueOne(projectRoot, slug, brand, competitors) {
96731
96769
  const [sources, compositionSha, sourceSha] = await Promise.all([
96732
96770
  readLandingSources(projectRoot, slug),
96733
96771
  computeLandingSourceSha(projectRoot, slug),
96734
- computeLegacyLandingSourceSha(path56.resolve(projectRoot, "src", "pages", slug))
96772
+ computeLegacyLandingSourceSha(path57.resolve(projectRoot, "src", "pages", slug))
96735
96773
  ]);
96736
96774
  const report = critiqueLanding({ slug, sources, brand, competitors });
96737
96775
  let snapshotFailed = false;
@@ -96751,7 +96789,7 @@ async function critiqueOne(projectRoot, slug, brand, competitors) {
96751
96789
  return { slug, report, snapshotFailed };
96752
96790
  }
96753
96791
  async function readCompetitorNames(projectRoot) {
96754
- const dir = path56.join(projectRoot, "src", "content", "competitors");
96792
+ const dir = path57.join(projectRoot, "src", "content", "competitors");
96755
96793
  let entries;
96756
96794
  try {
96757
96795
  entries = (await readdir22(dir)).filter((f) => f.endsWith(".md"));
@@ -96760,9 +96798,9 @@ async function readCompetitorNames(projectRoot) {
96760
96798
  }
96761
96799
  const names = [];
96762
96800
  for (const entry of entries) {
96763
- names.push(path56.basename(entry, ".md").replace(/[-_]+/g, " "));
96801
+ names.push(path57.basename(entry, ".md").replace(/[-_]+/g, " "));
96764
96802
  try {
96765
- const head = (await readFile48(path56.join(dir, entry), "utf8")).slice(0, 2e3);
96803
+ const head = (await readFile48(path57.join(dir, entry), "utf8")).slice(0, 2e3);
96766
96804
  const titled = /^\s*(?:title|name)\s*:\s*["']?([^"'\n]+)["']?\s*$/im.exec(head);
96767
96805
  if (titled?.[1]) names.push(titled[1].trim());
96768
96806
  } catch {
@@ -96772,7 +96810,7 @@ async function readCompetitorNames(projectRoot) {
96772
96810
  }
96773
96811
  async function listLandingSlugs(projectRoot) {
96774
96812
  try {
96775
- const entries = await readdir22(path56.join(projectRoot, "src", "pages"), { withFileTypes: true });
96813
+ const entries = await readdir22(path57.join(projectRoot, "src", "pages"), { withFileTypes: true });
96776
96814
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
96777
96815
  } catch {
96778
96816
  return [];
@@ -96896,7 +96934,7 @@ function exportStatusHints(view) {
96896
96934
  }
96897
96935
  return ["Still being prepared. Carry on with other work and check again in a minute \u2014 never sleep-loop on it."];
96898
96936
  }
96899
- function parseProfileFlag(raw, readFile52 = (path69) => readFileSync25(path69, "utf8")) {
96937
+ function parseProfileFlag(raw, readFile52 = (path70) => readFileSync25(path70, "utf8")) {
96900
96938
  let parsed;
96901
96939
  try {
96902
96940
  parsed = JSON.parse(raw.startsWith("@") ? readFile52(raw.slice(1)) : raw);
@@ -97071,7 +97109,7 @@ var addCommand = defineCommand215({
97071
97109
 
97072
97110
  // src/commands/landing/inspiration/code.ts
97073
97111
  import { mkdir as mkdir17, writeFile as writeFile28 } from "fs/promises";
97074
- import path57 from "path";
97112
+ import path58 from "path";
97075
97113
  import { defineCommand as defineCommand216 } from "citty";
97076
97114
  registerSchema({
97077
97115
  command: "landing.inspiration.code",
@@ -97094,9 +97132,9 @@ var codeCommand = defineCommand216({
97094
97132
  try {
97095
97133
  const id = args8.id;
97096
97134
  const data = await apiGet("/api/landing-inspiration/section-code", { id });
97097
- const dir = path57.join(process.cwd(), ".baker", "inspiration", id);
97135
+ const dir = path58.join(process.cwd(), ".baker", "inspiration", id);
97098
97136
  await mkdir17(dir, { recursive: true });
97099
- const file = path57.join(dir, "section.html");
97137
+ const file = path58.join(dir, "section.html");
97100
97138
  await writeFile28(file, data.html);
97101
97139
  const hints2 = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
97102
97140
  const fidelity = fidelityHint(data.fidelity);
@@ -97106,7 +97144,7 @@ var codeCommand = defineCommand216({
97106
97144
  ok: true,
97107
97145
  data: {
97108
97146
  id,
97109
- file: path57.relative(process.cwd(), file),
97147
+ file: path58.relative(process.cwd(), file),
97110
97148
  bytes: data.html.length,
97111
97149
  fidelity: data.fidelity,
97112
97150
  reproduction_notes: data.reproductionNotes,
@@ -97566,7 +97604,7 @@ function classifyCaptureFailure(error) {
97566
97604
 
97567
97605
  // src/engine/landing-library/run.ts
97568
97606
  import { mkdir as mkdir18, writeFile as writeFile30 } from "fs/promises";
97569
- import path59 from "path";
97607
+ import path60 from "path";
97570
97608
 
97571
97609
  // ../proxy/src/preflight.ts
97572
97610
  import http from "http";
@@ -98984,9 +99022,9 @@ async function renderBundleToPng(browser, html, viewportWidth, options = {}) {
98984
99022
 
98985
99023
  // src/engine/landing-library/report.ts
98986
99024
  import { writeFile as writeFile29 } from "fs/promises";
98987
- import path58 from "path";
99025
+ import path59 from "path";
98988
99026
  async function writeCaptureReport(manifest, outDir) {
98989
- const file = path58.join(outDir, "report.html");
99027
+ const file = path59.join(outDir, "report.html");
98990
99028
  await writeFile29(file, renderReport(manifest));
98991
99029
  return file;
98992
99030
  }
@@ -99130,32 +99168,32 @@ async function reproducePage(args8) {
99130
99168
  const { browser, page, outDir, pageUrl, livePageShot } = args8;
99131
99169
  const built = await buildSectionBundle(page, "body", pageUrl).catch(() => null);
99132
99170
  if (!built) return { bundle: null, fidelity: null };
99133
- await writeFile30(path59.join(outDir, "page.html"), built.html);
99171
+ await writeFile30(path60.join(outDir, "page.html"), built.html);
99134
99172
  const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width, {
99135
99173
  wholePage: true,
99136
99174
  timeoutMs: 6e4
99137
99175
  });
99138
99176
  if (!rendered || !livePageShot) return { bundle: "page.html", fidelity: null };
99139
- await writeFile30(path59.join(outDir, "page-rendered.png"), rendered);
99177
+ await writeFile30(path60.join(outDir, "page-rendered.png"), rendered);
99140
99178
  const { score, note } = await scoreFidelity(livePageShot, rendered);
99141
99179
  return { bundle: "page.html", fidelity: score, ...note ? { fidelityNote: note } : {} };
99142
99180
  }
99143
99181
  async function captureOneSection(args8) {
99144
99182
  const { browser, page, candidate, sectionsDir, outDir, pageUrl, withCode } = args8;
99145
- const dir = path59.join(sectionsDir, String(candidate.index).padStart(2, "0"));
99183
+ const dir = path60.join(sectionsDir, String(candidate.index).padStart(2, "0"));
99146
99184
  await mkdir18(dir, { recursive: true });
99147
99185
  const desktop = await captureSection(page, candidate);
99148
- if (desktop) await writeFile30(path59.join(dir, "desktop.png"), desktop);
99186
+ if (desktop) await writeFile30(path60.join(dir, "desktop.png"), desktop);
99149
99187
  const visualHash = desktop ? await perceptualHash(desktop) : null;
99150
99188
  const motion = await collectMotion(page, candidate.selector);
99151
99189
  const built = withCode ? await buildSectionBundle(page, candidate.selector, pageUrl) : null;
99152
99190
  let fidelity = null;
99153
99191
  let fidelityNote;
99154
99192
  if (built) {
99155
- await writeFile30(path59.join(dir, "section.html"), built.html);
99193
+ await writeFile30(path60.join(dir, "section.html"), built.html);
99156
99194
  const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width);
99157
99195
  if (rendered && desktop) {
99158
- await writeFile30(path59.join(dir, "section-rendered.png"), rendered);
99196
+ await writeFile30(path60.join(dir, "section-rendered.png"), rendered);
99159
99197
  const result = await scoreFidelity(desktop, rendered);
99160
99198
  fidelity = result.score;
99161
99199
  fidelityNote = result.note;
@@ -99163,9 +99201,9 @@ async function captureOneSection(args8) {
99163
99201
  }
99164
99202
  return {
99165
99203
  ...candidate,
99166
- desktopShot: desktop ? path59.relative(outDir, path59.join(dir, "desktop.png")) : null,
99204
+ desktopShot: desktop ? path60.relative(outDir, path60.join(dir, "desktop.png")) : null,
99167
99205
  mobileShot: null,
99168
- bundle: built ? path59.relative(outDir, path59.join(dir, "section.html")) : null,
99206
+ bundle: built ? path60.relative(outDir, path60.join(dir, "section.html")) : null,
99169
99207
  fidelity,
99170
99208
  ...fidelityNote ? { fidelityNote } : {},
99171
99209
  ...built ? { cssStats: built.stats } : {},
@@ -99184,9 +99222,9 @@ async function captureMobileShots(args8) {
99184
99222
  for (const section2 of sections) {
99185
99223
  const shot = await captureSectionOnMobile(mobile.page, section2);
99186
99224
  if (!shot) continue;
99187
- const file = path59.join(sectionsDir, String(section2.index).padStart(2, "0"), "mobile.png");
99225
+ const file = path60.join(sectionsDir, String(section2.index).padStart(2, "0"), "mobile.png");
99188
99226
  await writeFile30(file, shot);
99189
- section2.mobileShot = path59.relative(outDir, file);
99227
+ section2.mobileShot = path60.relative(outDir, file);
99190
99228
  }
99191
99229
  } finally {
99192
99230
  await mobile.context.close();
@@ -99201,10 +99239,10 @@ async function captureMotionTakes(args8) {
99201
99239
  const filmOne = async (section2) => {
99202
99240
  const take = await captureMotionTake(browser, pageUrl, section2.selector).catch(() => null);
99203
99241
  if (!take) return;
99204
- const dir = path59.join(sectionsDir, String(section2.index).padStart(2, "0"));
99205
- const file = path59.join(dir, "motion-filmstrip.png");
99242
+ const dir = path60.join(sectionsDir, String(section2.index).padStart(2, "0"));
99243
+ const file = path60.join(dir, "motion-filmstrip.png");
99206
99244
  await writeFile30(file, take.filmstrip);
99207
- section2.motionFilmstrip = path59.relative(outDir, file);
99245
+ section2.motionFilmstrip = path60.relative(outDir, file);
99208
99246
  log(` [${section2.index}] ${section2.motion.summary}`);
99209
99247
  };
99210
99248
  const queue = [...moving];
@@ -99261,7 +99299,7 @@ async function captureAlternateViews(args8) {
99261
99299
  async function reproduceWholePage(args8) {
99262
99300
  const { browser, page, outDir, pageUrl, withCode, log } = args8;
99263
99301
  const fullPage = await page.screenshot({ type: "png", fullPage: true }).catch(() => null);
99264
- if (fullPage) await writeFile30(path59.join(outDir, "full-page.png"), fullPage);
99302
+ if (fullPage) await writeFile30(path60.join(outDir, "full-page.png"), fullPage);
99265
99303
  if (!withCode) return { bundle: null, fidelity: null };
99266
99304
  const reproduction = await reproducePage({ browser, page, outDir, pageUrl, livePageShot: fullPage });
99267
99305
  log(`page reproduction: ${reproduction.fidelity === null ? "unavailable" : reproduction.fidelity.toFixed(2)}`);
@@ -99332,7 +99370,7 @@ async function openViaLadder(args8) {
99332
99370
  async function scrapeLanding(options) {
99333
99371
  const timeoutMs = options.timeoutMs ?? 45e3;
99334
99372
  const log = options.onProgress ?? (() => void 0);
99335
- const sectionsDir = path59.join(options.outDir, "sections");
99373
+ const sectionsDir = path60.join(options.outDir, "sections");
99336
99374
  const nonPublic = refuseNonPublicUrl(options.url);
99337
99375
  if (nonPublic) {
99338
99376
  throw new BlockedPageError({
@@ -99394,7 +99432,7 @@ async function scrapeLanding(options) {
99394
99432
  security: prepared.security,
99395
99433
  captureTier: tier
99396
99434
  };
99397
- await writeFile30(path59.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
99435
+ await writeFile30(path60.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
99398
99436
  `);
99399
99437
  if (options.report !== false) {
99400
99438
  const reportPath = await writeCaptureReport(manifest, options.outDir);
@@ -99409,28 +99447,28 @@ async function scrapeLanding(options) {
99409
99447
 
99410
99448
  // src/commands/landing/inspiration/captureOut.ts
99411
99449
  import { existsSync as existsSync12 } from "fs";
99412
- import path60 from "path";
99450
+ import path61 from "path";
99413
99451
  var SCRATCH_DIR = ".baker";
99414
99452
  function isWithin(parent, target2) {
99415
- const relative = path60.relative(parent, target2);
99416
- return relative === "" || !relative.startsWith("..") && !path60.isAbsolute(relative);
99453
+ const relative = path61.relative(parent, target2);
99454
+ return relative === "" || !relative.startsWith("..") && !path61.isAbsolute(relative);
99417
99455
  }
99418
99456
  function findRepoRoot(from) {
99419
- let dir = path60.resolve(from);
99457
+ let dir = path61.resolve(from);
99420
99458
  for (; ; ) {
99421
- if (existsSync12(path60.join(dir, ".git"))) return dir;
99422
- const parent = path60.dirname(dir);
99459
+ if (existsSync12(path61.join(dir, ".git"))) return dir;
99460
+ const parent = path61.dirname(dir);
99423
99461
  if (parent === dir) return null;
99424
99462
  dir = parent;
99425
99463
  }
99426
99464
  }
99427
99465
  function checkCaptureOut(out, options) {
99428
99466
  const { cwd, repoRoot } = options;
99429
- const resolved = path60.resolve(cwd, out);
99467
+ const resolved = path61.resolve(cwd, out);
99430
99468
  if (repoRoot === null || !isWithin(repoRoot, resolved)) return { ok: true };
99431
- const scratch = path60.join(repoRoot, SCRATCH_DIR);
99469
+ const scratch = path61.join(repoRoot, SCRATCH_DIR);
99432
99470
  if (isWithin(scratch, resolved)) return { ok: true };
99433
- const suggestion = path60.posix.join(SCRATCH_DIR, "teardowns", path60.basename(resolved) || "capture");
99471
+ const suggestion = path61.posix.join(SCRATCH_DIR, "teardowns", path61.basename(resolved) || "capture");
99434
99472
  return {
99435
99473
  ok: false,
99436
99474
  error: {
@@ -99604,12 +99642,12 @@ var scrapeCommand = defineCommand220({
99604
99642
  });
99605
99643
 
99606
99644
  // src/commands/landing/inspiration/search.ts
99607
- import path62 from "path";
99645
+ import path63 from "path";
99608
99646
  import { defineCommand as defineCommand221 } from "citty";
99609
99647
 
99610
99648
  // src/commands/landing/inspiration/shot.ts
99611
99649
  import { mkdir as mkdir19, writeFile as writeFile31 } from "fs/promises";
99612
- import path61 from "path";
99650
+ import path62 from "path";
99613
99651
  import sharp9 from "sharp";
99614
99652
  var READABLE_SHOT = {
99615
99653
  maxWidth: 1440,
@@ -99635,9 +99673,9 @@ async function downloadReadableShot(url, file) {
99635
99673
  const response = await fetch(url);
99636
99674
  if (!response.ok) return null;
99637
99675
  const shot = await toReadableShot(Buffer.from(await response.arrayBuffer()));
99638
- await mkdir19(path61.dirname(file), { recursive: true });
99676
+ await mkdir19(path62.dirname(file), { recursive: true });
99639
99677
  await writeFile31(file, shot);
99640
- return path61.relative(process.cwd(), file);
99678
+ return path62.relative(process.cwd(), file);
99641
99679
  } catch {
99642
99680
  return null;
99643
99681
  }
@@ -99729,13 +99767,13 @@ function buildSearchBody2(args8) {
99729
99767
  return body;
99730
99768
  }
99731
99769
  async function downloadShots(results) {
99732
- const dir = path62.join(process.cwd(), ".baker", "inspiration");
99770
+ const dir = path63.join(process.cwd(), ".baker", "inspiration");
99733
99771
  const saved = /* @__PURE__ */ new Map();
99734
99772
  await Promise.all(
99735
99773
  results.map(async (result) => {
99736
99774
  const file = await downloadReadableShot(
99737
99775
  result.desktopShotUrl,
99738
- path62.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
99776
+ path63.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
99739
99777
  );
99740
99778
  if (file) saved.set(result.id, file);
99741
99779
  })
@@ -99963,7 +100001,7 @@ var sequencesCommand = defineCommand222({
99963
100001
  });
99964
100002
 
99965
100003
  // src/commands/landing/inspiration/view.ts
99966
- import path63 from "path";
100004
+ import path64 from "path";
99967
100005
  import { defineCommand as defineCommand223 } from "citty";
99968
100006
  registerSchema({
99969
100007
  command: "landing.inspiration.view",
@@ -99996,12 +100034,12 @@ var viewCommand2 = defineCommand223({
99996
100034
  const id = args8.id;
99997
100035
  const data = await apiGet("/api/landing-inspiration/section", { id });
99998
100036
  const section2 = data.section;
99999
- const dir = path63.join(process.cwd(), ".baker", "inspiration", id);
100037
+ const dir = path64.join(process.cwd(), ".baker", "inspiration", id);
100000
100038
  const ext = READABLE_SHOT.extension;
100001
100039
  const [desktop, mobile, filmstrip] = await Promise.all([
100002
- downloadReadableShot(section2.desktopShotUrl, path63.join(dir, `desktop.${ext}`)),
100003
- downloadReadableShot(section2.mobileShotUrl, path63.join(dir, `mobile.${ext}`)),
100004
- downloadReadableShot(section2.motionFilmstripUrl, path63.join(dir, `motion-filmstrip.${ext}`))
100040
+ downloadReadableShot(section2.desktopShotUrl, path64.join(dir, `desktop.${ext}`)),
100041
+ downloadReadableShot(section2.mobileShotUrl, path64.join(dir, `mobile.${ext}`)),
100042
+ downloadReadableShot(section2.motionFilmstripUrl, path64.join(dir, `motion-filmstrip.${ext}`))
100005
100043
  ]);
100006
100044
  const full = args8.full;
100007
100045
  const hints2 = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
@@ -100110,7 +100148,7 @@ Full guide: __tooling__/docs/tools/baker/landing.md`
100110
100148
  // src/commands/landing/variant.ts
100111
100149
  import { randomUUID as randomUUID4 } from "crypto";
100112
100150
  import { mkdir as mkdir20, readdir as readdir23, readFile as readFile49, stat as stat13, writeFile as writeFile32 } from "fs/promises";
100113
- import path64 from "path";
100151
+ import path65 from "path";
100114
100152
  import { defineCommand as defineCommand225 } from "citty";
100115
100153
  registerSchema({
100116
100154
  command: "landing.variant",
@@ -100146,7 +100184,7 @@ async function readInternalId(definitionPath) {
100146
100184
  async function archivedVariantNumbers(root, internalId) {
100147
100185
  if (!internalId) return [];
100148
100186
  try {
100149
- const entries = await readdir23(path64.resolve(root, "src/_variants", internalId), { withFileTypes: true });
100187
+ const entries = await readdir23(path65.resolve(root, "src/_variants", internalId), { withFileTypes: true });
100150
100188
  return entries.filter((entry) => entry.isDirectory()).map((entry) => Number(entry.name)).filter((n) => Number.isInteger(n) && n > 0);
100151
100189
  } catch {
100152
100190
  return [];
@@ -100176,7 +100214,7 @@ async function exists2(p) {
100176
100214
  }
100177
100215
  async function listLandingSlugs2(root) {
100178
100216
  try {
100179
- const entries = await readdir23(path64.resolve(root, "src", "pages"), { withFileTypes: true });
100217
+ const entries = await readdir23(path65.resolve(root, "src", "pages"), { withFileTypes: true });
100180
100218
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
100181
100219
  } catch {
100182
100220
  return [];
@@ -100192,7 +100230,7 @@ async function listComponents(componentsDir, prefix = "") {
100192
100230
  const out = [];
100193
100231
  for (const entry of entries) {
100194
100232
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
100195
- if (entry.isDirectory()) out.push(...await listComponents(path64.join(componentsDir, entry.name), rel));
100233
+ if (entry.isDirectory()) out.push(...await listComponents(path65.join(componentsDir, entry.name), rel));
100196
100234
  else if (entry.name.endsWith(".astro")) out.push(rel);
100197
100235
  }
100198
100236
  return out.sort();
@@ -100259,16 +100297,16 @@ async function resolveTargets(projectRoot, opts) {
100259
100297
  `"${controlSlug}" is already a variant of "${variantOfSlug(controlSlug)}". Make the next variant of the page itself: \`baker landing variant ${variantOfSlug(controlSlug)}\`.`
100260
100298
  );
100261
100299
  }
100262
- const controlDir = path64.resolve(projectRoot, "src", "pages", controlSlug);
100300
+ const controlDir = path65.resolve(projectRoot, "src", "pages", controlSlug);
100263
100301
  if (!await isDir3(controlDir)) {
100264
100302
  fail11("NOT_FOUND", `No page at src/pages/${controlSlug}/`, {
100265
100303
  availableSlugs: await listLandingSlugs2(projectRoot)
100266
100304
  });
100267
100305
  }
100268
- if (!await exists2(path64.join(controlDir, "index.astro"))) {
100306
+ if (!await exists2(path65.join(controlDir, "index.astro"))) {
100269
100307
  fail11("NOT_FOUND", `src/pages/${controlSlug}/index.astro is missing, so there is no page to make a variant of.`);
100270
100308
  }
100271
- const internalId = await readInternalId(path64.join(controlDir, "_definition.md"));
100309
+ const internalId = await readInternalId(path65.join(controlDir, "_definition.md"));
100272
100310
  const variantSlugValue = variantSlug(
100273
100311
  controlSlug,
100274
100312
  nextVariantNumber(
@@ -100277,8 +100315,8 @@ async function resolveTargets(projectRoot, opts) {
100277
100315
  await archivedVariantNumbers(projectRoot, internalId)
100278
100316
  )
100279
100317
  );
100280
- const variantDir = path64.resolve(projectRoot, "src", "pages", variantSlugValue);
100281
- const available = await listComponents(path64.join(controlDir, "_components"));
100318
+ const variantDir = path65.resolve(projectRoot, "src", "pages", variantSlugValue);
100319
+ const available = await listComponents(path65.join(controlDir, "_components"));
100282
100320
  const forks = [];
100283
100321
  for (const name of parseForks(opts.fork, opts.rawArgs)) {
100284
100322
  const resolved = resolveForkName(name, available);
@@ -100294,26 +100332,26 @@ async function resolveTargets(projectRoot, opts) {
100294
100332
  }
100295
100333
  async function writeVariant(opts) {
100296
100334
  const { controlDir, variantDir, controlSlug, variantSlug: variantSlug2, forks } = opts;
100297
- const forkedTargets = new Set(forks.map((f) => path64.join(controlDir, "_components", f)));
100335
+ const forkedTargets = new Set(forks.map((f) => path65.join(controlDir, "_components", f)));
100298
100336
  const written = [];
100299
- const indexText = await readFile49(path64.join(controlDir, "index.astro"), "utf8");
100337
+ const indexText = await readFile49(path65.join(controlDir, "index.astro"), "utf8");
100300
100338
  await mkdir20(variantDir, { recursive: true });
100301
100339
  await writeFile32(
100302
- path64.join(variantDir, "index.astro"),
100340
+ path65.join(variantDir, "index.astro"),
100303
100341
  repointFile(indexText, { fromDir: controlDir, toDir: variantDir, controlDir, variantDir, forkedTargets }),
100304
100342
  "utf8"
100305
100343
  );
100306
100344
  written.push(`src/pages/${variantSlug2}/index.astro`);
100307
100345
  for (const fork of forks) {
100308
- const fromFile = path64.join(controlDir, "_components", fork);
100309
- const toFile = path64.join(variantDir, "_components", fork);
100346
+ const fromFile = path65.join(controlDir, "_components", fork);
100347
+ const toFile = path65.join(variantDir, "_components", fork);
100310
100348
  const text3 = await readFile49(fromFile, "utf8");
100311
- await mkdir20(path64.dirname(toFile), { recursive: true });
100349
+ await mkdir20(path65.dirname(toFile), { recursive: true });
100312
100350
  await writeFile32(
100313
100351
  toFile,
100314
100352
  repointFile(text3, {
100315
- fromDir: path64.dirname(fromFile),
100316
- toDir: path64.dirname(toFile),
100353
+ fromDir: path65.dirname(fromFile),
100354
+ toDir: path65.dirname(toFile),
100317
100355
  controlDir,
100318
100356
  variantDir,
100319
100357
  forkedTargets
@@ -100322,7 +100360,7 @@ async function writeVariant(opts) {
100322
100360
  );
100323
100361
  written.push(`src/pages/${variantSlug2}/_components/${fork}`);
100324
100362
  }
100325
- const controlDefinitionPath = path64.join(controlDir, "_definition.md");
100363
+ const controlDefinitionPath = path65.join(controlDir, "_definition.md");
100326
100364
  if (await exists2(controlDefinitionPath)) {
100327
100365
  const definition = buildVariantDefinition(await readFile49(controlDefinitionPath, "utf8"), {
100328
100366
  internalId: randomUUID4().replace(/-/g, "").slice(0, 8),
@@ -100332,11 +100370,11 @@ async function writeVariant(opts) {
100332
100370
  ...opts.because ? { because: opts.because } : {},
100333
100371
  ...opts.change ? { change: opts.change } : {}
100334
100372
  });
100335
- await writeFile32(path64.join(variantDir, "_definition.md"), definition, "utf8");
100373
+ await writeFile32(path65.join(variantDir, "_definition.md"), definition, "utf8");
100336
100374
  written.push(`src/pages/${variantSlug2}/_definition.md`);
100337
100375
  }
100338
- await mkdir20(path64.join(variantDir, "_images"), { recursive: true });
100339
- await writeFile32(path64.join(variantDir, "_images", ".gitkeep"), "", "utf8");
100376
+ await mkdir20(path65.join(variantDir, "_images"), { recursive: true });
100377
+ await writeFile32(path65.join(variantDir, "_images", ".gitkeep"), "", "utf8");
100340
100378
  return written;
100341
100379
  }
100342
100380
  var variantCommand = defineCommand225({
@@ -101684,7 +101722,7 @@ var countriesCommand = defineCommand237({
101684
101722
 
101685
101723
  // src/commands/research/customers.ts
101686
101724
  import { mkdir as mkdir21, readdir as readdir24, readFile as readFile50, writeFile as writeFile33 } from "fs/promises";
101687
- import path65 from "path";
101725
+ import path66 from "path";
101688
101726
  import { defineCommand as defineCommand239 } from "citty";
101689
101727
  import { parse as parseYaml5 } from "yaml";
101690
101728
  import { z as z77 } from "zod";
@@ -102038,14 +102076,14 @@ function insightSlug(type, quote) {
102038
102076
  return [type.replace(/_/g, "-"), ...asciiWords(quote).slice(0, SLUG_WORDS)].join("-");
102039
102077
  }
102040
102078
  function planInsightWrites(insights, existing, limit) {
102041
- const quotes = new Set(existing.map((e) => foldWithOffsets(e.quote).folded));
102079
+ const quotes2 = new Set(existing.map((e) => foldWithOffsets(e.quote).folded));
102042
102080
  const ids2 = new Set(existing.map((e) => e.id));
102043
102081
  const ranked = [...insights].sort((a, b) => INSIGHT_TYPES.indexOf(a.type) - INSIGHT_TYPES.indexOf(b.type));
102044
102082
  const writes = [];
102045
102083
  let skippedExisting = 0;
102046
102084
  for (const insight of ranked) {
102047
102085
  const folded2 = foldWithOffsets(insight.quote).folded;
102048
- if (quotes.has(folded2)) {
102086
+ if (quotes2.has(folded2)) {
102049
102087
  skippedExisting++;
102050
102088
  continue;
102051
102089
  }
@@ -102053,7 +102091,7 @@ function planInsightWrites(insights, existing, limit) {
102053
102091
  const base = insightSlug(insight.type, insight.quote);
102054
102092
  let id = base;
102055
102093
  for (let n = 2; ids2.has(id); n++) id = `${base}-${n}`;
102056
- quotes.add(folded2);
102094
+ quotes2.add(folded2);
102057
102095
  ids2.add(id);
102058
102096
  writes.push({ id, insight });
102059
102097
  }
@@ -102236,7 +102274,7 @@ function customersHints(input) {
102236
102274
  const cite = `Cite these by id in an idea's \`evidence\` (src/creatives/_ideas/<idea>.md); write the ad from the quote as said.`;
102237
102275
  return written < FEW_OBSERVED ? [`Only ${written} observed. ${widen}`, cite] : [cite];
102238
102276
  }
102239
- var INSIGHTS_DIR2 = path65.join("src", "content", "insights");
102277
+ var INSIGHTS_DIR2 = path66.join("src", "content", "insights");
102240
102278
  var BATCH_CHARS = 24e3;
102241
102279
  var MAX_BATCHES = 5;
102242
102280
  var WEB_PAGES = 3;
@@ -102301,12 +102339,12 @@ async function readExistingInsights(dir) {
102301
102339
  return await Promise.all(
102302
102340
  files.map(async (file) => ({
102303
102341
  id: file.slice(0, -3),
102304
- quote: quoteOf(await readFile50(path65.join(dir, file), "utf8").catch(() => ""))
102342
+ quote: quoteOf(await readFile50(path66.join(dir, file), "utf8").catch(() => ""))
102305
102343
  }))
102306
102344
  );
102307
102345
  }
102308
102346
  async function productSlugs(root) {
102309
- const files = await readdir24(path65.join(root, "src", "content", "products")).catch(() => []);
102347
+ const files = await readdir24(path66.join(root, "src", "content", "products")).catch(() => []);
102310
102348
  return files.filter((f) => f.endsWith(".md")).map((f) => f.slice(0, -3));
102311
102349
  }
102312
102350
  async function gatherTestimonials(focus) {
@@ -102406,7 +102444,7 @@ async function classifyAll(sources, focus, root) {
102406
102444
  const batches = batchSources(sources, BATCH_CHARS).slice(0, MAX_BATCHES);
102407
102445
  const spent = [];
102408
102446
  const answers = await Promise.all(batches.map((batch) => classifyBatch(batch, focus, (u) => spent.push(u))));
102409
- await holdUnbilledSpend(path65.join(root, "canvas", ".cache"), spent);
102447
+ await holdUnbilledSpend(path66.join(root, "canvas", ".cache"), spent);
102410
102448
  if (batches.length > 0 && answers.every((a) => a === null)) return null;
102411
102449
  const result = { kept: [], dropped: 0, tooLong: 0 };
102412
102450
  batches.forEach((batch, i) => {
@@ -102423,7 +102461,7 @@ async function writeInsights(dir, writes, opts) {
102423
102461
  const written = [];
102424
102462
  for (const entry of writes) {
102425
102463
  const file = renderInsightFile(entry.insight, opts);
102426
- const ok = await writeFile33(path65.join(dir, `${entry.id}.md`), file, { encoding: "utf8", flag: "wx" }).then(
102464
+ const ok = await writeFile33(path66.join(dir, `${entry.id}.md`), file, { encoding: "utf8", flag: "wx" }).then(
102427
102465
  () => true,
102428
102466
  () => false
102429
102467
  );
@@ -102474,7 +102512,7 @@ var customersCommand = defineCommand239({
102474
102512
  "Run it again. Do not write insights by hand: an insight is only a quote this command found in its source."
102475
102513
  );
102476
102514
  }
102477
- const dir = path65.join(root, INSIGHTS_DIR2);
102515
+ const dir = path66.join(root, INSIGHTS_DIR2);
102478
102516
  const plan = planInsightWrites(gated.kept, await readExistingInsights(dir), limit);
102479
102517
  const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
102480
102518
  const shown = dryRun ? plan.writes : await writeInsights(dir, plan.writes, { today: today2, ...product ? { product } : {} });
@@ -104077,7 +104115,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
104077
104115
 
104078
104116
  // src/commands/scheduled-agents/templates.ts
104079
104117
  import { readFile as readFile51 } from "fs/promises";
104080
- import path66 from "path";
104118
+ import path67 from "path";
104081
104119
  import { defineCommand as defineCommand256 } from "citty";
104082
104120
  registerSchema({
104083
104121
  command: "scheduled-agents.templates",
@@ -104184,7 +104222,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-agents.md`
104184
104222
  }
104185
104223
  if (save.length > 0) {
104186
104224
  const briefFile = flag2("brief-file");
104187
- const brief2 = briefFile.length > 0 ? await readFile51(path66.resolve(briefFile), "utf8") : flag2("brief");
104225
+ const brief2 = briefFile.length > 0 ? await readFile51(path67.resolve(briefFile), "utf8") : flag2("brief");
104188
104226
  if (brief2.trim().length === 0) {
104189
104227
  failValidation6("--brief-file (preferred) or --brief is required: the brief is the recipe.");
104190
104228
  }
@@ -104966,7 +105004,7 @@ var setCommand = defineCommand264({
104966
105004
  timezone: args8.timezone,
104967
105005
  "export-profile": args8["export-profile"]
104968
105006
  },
104969
- (path69) => readFileSync26(path69, "utf8")
105007
+ (path70) => readFileSync26(path70, "utf8")
104970
105008
  );
104971
105009
  const body = { chatId: requireChatId(), inputs };
104972
105010
  writeJson(await apiPost("/api/site/stage", body));
@@ -105248,7 +105286,7 @@ function parseImageRefs(spec) {
105248
105286
  }
105249
105287
  var defaultDeps = {
105250
105288
  ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
105251
- upload: (path69) => uploadLocalImage({ file: path69, contentType: detectImageContentType(path69), source: "uploaded" })
105289
+ upload: (path70) => uploadLocalImage({ file: path70, contentType: detectImageContentType(path70), source: "uploaded" })
105252
105290
  };
105253
105291
  async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
105254
105292
  const refs = parseImageRefs(spec);
@@ -105268,10 +105306,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
105268
105306
  }
105269
105307
  return { imageIds, added };
105270
105308
  }
105271
- function uploadFailure(path69) {
105309
+ function uploadFailure(path70) {
105272
105310
  return (error) => {
105273
105311
  if (error instanceof ApiError) throw error;
105274
- throw new ApiError("VALIDATION_ERROR", `Could not read "${path69}" as an image.`);
105312
+ throw new ApiError("VALIDATION_ERROR", `Could not read "${path70}" as an image.`);
105275
105313
  };
105276
105314
  }
105277
105315
 
@@ -106371,10 +106409,10 @@ async function stageOp4(op) {
106371
106409
  handleError8(err);
106372
106410
  }
106373
106411
  }
106374
- async function draftAction3(path69, body, chat) {
106412
+ async function draftAction3(path70, body, chat) {
106375
106413
  const chatId = resolveChatId(chat);
106376
106414
  try {
106377
- const { data, hints: hints2 } = splitHints(await apiPost(path69, { chatId, ...body }));
106415
+ const { data, hints: hints2 } = splitHints(await apiPost(path70, { chatId, ...body }));
106378
106416
  writeJsonEnvelope({ ok: true, data, ...hints2.length > 0 ? { hints: hints2 } : {} });
106379
106417
  return data;
106380
106418
  } catch (err) {
@@ -107938,7 +107976,7 @@ Example: baker videos describe j571abc123 --description "Customer explaining how
107938
107976
  import { constants } from "fs";
107939
107977
  import { copyFile as copyFile2, mkdir as mkdir22, mkdtemp as mkdtemp3, rm as rm9 } from "fs/promises";
107940
107978
  import { tmpdir as tmpdir4 } from "os";
107941
- import path67 from "path";
107979
+ import path68 from "path";
107942
107980
  import { defineCommand as defineCommand293 } from "citty";
107943
107981
 
107944
107982
  // src/commands/videos/videoPlatforms.ts
@@ -108106,8 +108144,8 @@ var fetchCommand2 = defineCommand293({
108106
108144
  }
108107
108145
  });
108108
108146
  async function fetchVideo(args8) {
108109
- const outDir = path67.resolve(args8.out);
108110
- const workDir = await mkdtemp3(path67.join(tmpdir4(), "videos-fetch-"));
108147
+ const outDir = path68.resolve(args8.out);
108148
+ const workDir = await mkdtemp3(path68.join(tmpdir4(), "videos-fetch-"));
108111
108149
  try {
108112
108150
  await mkdir22(outDir, { recursive: true });
108113
108151
  const vimeoCookie = captureVimeoCookie();
@@ -108152,7 +108190,7 @@ function fileStem(info) {
108152
108190
  }
108153
108191
  async function placeInto(outDir, source, stem) {
108154
108192
  for (let n = 1; ; n++) {
108155
- const target2 = path67.join(outDir, `${stem}${n === 1 ? "" : `-${n}`}${path67.extname(source)}`);
108193
+ const target2 = path68.join(outDir, `${stem}${n === 1 ? "" : `-${n}`}${path68.extname(source)}`);
108156
108194
  try {
108157
108195
  await copyFile2(source, target2, constants.COPYFILE_EXCL);
108158
108196
  return target2;
@@ -108239,7 +108277,7 @@ var groupCommand2 = defineCommand295({
108239
108277
  // src/commands/videos/ingest.ts
108240
108278
  import { mkdtemp as mkdtemp4, rm as rm10, stat as stat14 } from "fs/promises";
108241
108279
  import { tmpdir as tmpdir5 } from "os";
108242
- import path68 from "path";
108280
+ import path69 from "path";
108243
108281
  import { defineCommand as defineCommand296 } from "citty";
108244
108282
 
108245
108283
  // src/lib/streamUpload.ts
@@ -108479,7 +108517,7 @@ function ingestUrl(args8) {
108479
108517
  }
108480
108518
  async function downloadThenIngest(args8, country) {
108481
108519
  const vimeoCookie = captureVimeoCookie();
108482
- const workDir = await mkdtemp4(path68.join(tmpdir5(), "videos-ingest-"));
108520
+ const workDir = await mkdtemp4(path69.join(tmpdir5(), "videos-ingest-"));
108483
108521
  try {
108484
108522
  const probe = await probeYtDlp({ url: args8.url, country, vimeoCookie, cookieDir: workDir });
108485
108523
  if (isAudioOnly(probe.info)) {