@koda-sl/baker-cli 0.249.0-dev.94b6a6a7e → 0.249.0-dev.e7a1a227e

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
@@ -58,7 +58,7 @@ import {
58
58
  ulid,
59
59
  validateCanvasDeep,
60
60
  ytDlpBlockSignal
61
- } from "./chunk-HBDGUVUH.js";
61
+ } from "./chunk-VLNO5AUC.js";
62
62
  import {
63
63
  csvOrJson,
64
64
  daysAgoIso,
@@ -108,7 +108,7 @@ import {
108
108
  } from "./chunk-DZUVUGEP.js";
109
109
 
110
110
  // src/cli.ts
111
- import { defineCommand as defineCommand229, runMain } from "citty";
111
+ import { defineCommand as defineCommand227, runMain } from "citty";
112
112
 
113
113
  // src/cache-flag.ts
114
114
  var NO_CACHE_ARG = {
@@ -3936,35 +3936,10 @@ var capabilitySurfaceReportSchema = z9.object({
3936
3936
  /** Where to look next: `baker ads google`, `baker ga4`, … */
3937
3937
  commands: z9.string()
3938
3938
  });
3939
- var capabilityToolSchema = z9.object({
3940
- /** `microsoft_clarity`, `hubspot`, or the name the user gave a custom server. */
3941
- key: z9.string(),
3942
- label: z9.string(),
3943
- /** `mcp` — tools in the agent's own list. `platform` — signed in, read through the CLI. */
3944
- kind: z9.enum(["mcp", "platform"]),
3945
- /** How to actually reach it, in one phrase the agent can act on. */
3946
- reach: z9.string(),
3947
- /**
3948
- * Whether it can be used right now.
3949
- *
3950
- * A connection that exists and is expired is worse than one that is absent:
3951
- * it reads as available and fails at the moment it is needed, which on an
3952
- * unattended run is a report with a hole in it and no explanation.
3953
- */
3954
- ready: z9.boolean(),
3955
- /** Why it is not ready, or what it is for. Absent when neither needs saying. */
3956
- note: z9.string().optional()
3957
- });
3958
3939
  var capabilitiesResponseSchema = z9.object({
3959
3940
  ok: z9.literal(true),
3960
3941
  data: z9.object({
3961
- surfaces: z9.array(capabilitySurfaceReportSchema),
3962
- /**
3963
- * Everything else this company can reach. Shared connections only —
3964
- * a teammate's private per-user connection belongs to whoever started the
3965
- * session and is visible in the agent's own tool list, not here.
3966
- */
3967
- tools: z9.array(capabilityToolSchema)
3942
+ surfaces: z9.array(capabilitySurfaceReportSchema)
3968
3943
  })
3969
3944
  });
3970
3945
 
@@ -4011,8 +3986,6 @@ var chatChangeTypeSchema = z10.enum([
4011
3986
  // what the edge captures and one held until Publish would not measure the
4012
3987
  // campaign it was written for.
4013
3988
  "analytics-mapping",
4014
- // An A/B test between a landing and its alternative. Staged, not immediate.
4015
- "experiment",
4016
3989
  "briefs"
4017
3990
  ]);
4018
3991
  var chatChangeActionSchema = z10.enum(["created", "updated", "deleted"]);
@@ -9807,11 +9780,11 @@ function rawTextEntries(value) {
9807
9780
  const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
9808
9781
  return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
9809
9782
  }
9810
- function rawFileEntries(path41) {
9811
- if (typeof path41 !== "string" || path41.length === 0) {
9783
+ function rawFileEntries(path38) {
9784
+ if (typeof path38 !== "string" || path38.length === 0) {
9812
9785
  return [];
9813
9786
  }
9814
- return readFileSync2(path41, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
9787
+ return readFileSync2(path38, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
9815
9788
  }
9816
9789
  function keywordEntries(args) {
9817
9790
  const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
@@ -9834,19 +9807,19 @@ function keywordEntries(args) {
9834
9807
  }
9835
9808
  return entries;
9836
9809
  }
9837
- function loadJsonFileArg(path41) {
9838
- if (typeof path41 !== "string" || path41.length === 0) {
9810
+ function loadJsonFileArg(path38) {
9811
+ if (typeof path38 !== "string" || path38.length === 0) {
9839
9812
  return {};
9840
9813
  }
9841
9814
  try {
9842
- const parsed = JSON.parse(readFileSync2(path41, "utf8"));
9815
+ const parsed = JSON.parse(readFileSync2(path38, "utf8"));
9843
9816
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
9844
- failWriteValidation(`${path41} must contain a JSON object`);
9817
+ failWriteValidation(`${path38} must contain a JSON object`);
9845
9818
  }
9846
9819
  return parsed;
9847
9820
  } catch (err) {
9848
9821
  if (err instanceof SyntaxError) {
9849
- failWriteValidation(`${path41} is not valid JSON: ${err.message}`);
9822
+ failWriteValidation(`${path38} is not valid JSON: ${err.message}`);
9850
9823
  }
9851
9824
  throw err;
9852
9825
  }
@@ -9976,10 +9949,10 @@ async function stageUpdate(kind, customerId, target, payload, hints) {
9976
9949
  async function stageTarget(kind, customerId, target, hints) {
9977
9950
  await stageGoogleOp({ kind, customerId, target }, hints);
9978
9951
  }
9979
- async function draftAction(path41, body, chat) {
9952
+ async function draftAction(path38, body, chat) {
9980
9953
  try {
9981
9954
  const chatId = resolveChatId(chat);
9982
- const response = await apiPost(path41, { chatId, ...body });
9955
+ const response = await apiPost(path38, { chatId, ...body });
9983
9956
  writeJsonEnvelope(response);
9984
9957
  } catch (err) {
9985
9958
  handleGoogleError(err);
@@ -15193,19 +15166,19 @@ function failWriteValidation2(message) {
15193
15166
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
15194
15167
  process.exit(1);
15195
15168
  }
15196
- function loadJsonFileArg2(path41) {
15197
- if (typeof path41 !== "string" || path41.length === 0) {
15169
+ function loadJsonFileArg2(path38) {
15170
+ if (typeof path38 !== "string" || path38.length === 0) {
15198
15171
  return {};
15199
15172
  }
15200
15173
  try {
15201
- const parsed = JSON.parse(readFileSync4(path41, "utf8"));
15174
+ const parsed = JSON.parse(readFileSync4(path38, "utf8"));
15202
15175
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
15203
- failWriteValidation2(`${path41} must contain a JSON object`);
15176
+ failWriteValidation2(`${path38} must contain a JSON object`);
15204
15177
  }
15205
15178
  return parsed;
15206
15179
  } catch (err) {
15207
15180
  if (err instanceof SyntaxError) {
15208
- failWriteValidation2(`${path41} is not valid JSON: ${err.message}`);
15181
+ failWriteValidation2(`${path38} is not valid JSON: ${err.message}`);
15209
15182
  }
15210
15183
  throw err;
15211
15184
  }
@@ -15290,15 +15263,15 @@ function parseLocaleFlag(value) {
15290
15263
  }
15291
15264
  return { language: match[1], country: match[2].toUpperCase() };
15292
15265
  }
15293
- function loadTargetingFileArg(path41) {
15294
- if (typeof path41 !== "string" || path41.length === 0) {
15266
+ function loadTargetingFileArg(path38) {
15267
+ if (typeof path38 !== "string" || path38.length === 0) {
15295
15268
  return void 0;
15296
15269
  }
15297
- const parsed = loadJsonFileArg2(path41);
15270
+ const parsed = loadJsonFileArg2(path38);
15298
15271
  const criteria = parsed.targetingCriteria ?? parsed;
15299
15272
  if (!criteria.include) {
15300
15273
  failWriteValidation2(
15301
- `${path41} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
15274
+ `${path38} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
15302
15275
  );
15303
15276
  }
15304
15277
  return criteria;
@@ -15333,14 +15306,14 @@ function parseCsvLine(line) {
15333
15306
  cells.push(current);
15334
15307
  return cells.map((cell2) => cell2.trim());
15335
15308
  }
15336
- function parseListFileArg(path41, maxRows) {
15337
- if (typeof path41 !== "string" || path41.length === 0) {
15309
+ function parseListFileArg(path38, maxRows) {
15310
+ if (typeof path38 !== "string" || path38.length === 0) {
15338
15311
  return void 0;
15339
15312
  }
15340
- const raw = readFileSync4(path41, "utf8");
15313
+ const raw = readFileSync4(path38, "utf8");
15341
15314
  const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
15342
15315
  if (lines.length < 2) {
15343
- failWriteValidation2(`${path41} needs a header row and at least one data row`);
15316
+ failWriteValidation2(`${path38} needs a header row and at least one data row`);
15344
15317
  }
15345
15318
  const columns = parseCsvLine(lines[0]).map((column) => column.trim());
15346
15319
  const rows = [];
@@ -15359,7 +15332,7 @@ function parseListFileArg(path41, maxRows) {
15359
15332
  }
15360
15333
  }
15361
15334
  if (rows.length > maxRows) {
15362
- failWriteValidation2(`${path41} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
15335
+ failWriteValidation2(`${path38} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
15363
15336
  }
15364
15337
  return { columns, rows };
15365
15338
  }
@@ -15455,11 +15428,11 @@ function readPositionals(args) {
15455
15428
  function splitIdList(raw) {
15456
15429
  return raw.split(",").map((id) => id.trim()).filter(Boolean);
15457
15430
  }
15458
- function idsFileEntries(path41) {
15459
- if (typeof path41 !== "string" || path41.length === 0) {
15431
+ function idsFileEntries(path38) {
15432
+ if (typeof path38 !== "string" || path38.length === 0) {
15460
15433
  return [];
15461
15434
  }
15462
- return readFileSync4(path41, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
15435
+ return readFileSync4(path38, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
15463
15436
  }
15464
15437
  function requireTargets(args, entity) {
15465
15438
  const positionals = readPositionals(args);
@@ -18080,9 +18053,9 @@ function compactRow(row) {
18080
18053
  ...destination.postUrn ? { postUrn: destination.postUrn } : {}
18081
18054
  };
18082
18055
  }
18083
- function readPath(row, path41) {
18056
+ function readPath(row, path38) {
18084
18057
  let current = row;
18085
- for (const segment of path41.split(".")) {
18058
+ for (const segment of path38.split(".")) {
18086
18059
  const record = asRecord2(current);
18087
18060
  if (!record) return void 0;
18088
18061
  current = record[segment];
@@ -18092,10 +18065,10 @@ function readPath(row, path41) {
18092
18065
  function projectFields(rows, paths) {
18093
18066
  return rows.map((row) => {
18094
18067
  const projected = {};
18095
- for (const path41 of paths) {
18096
- const value = readPath(row, path41);
18068
+ for (const path38 of paths) {
18069
+ const value = readPath(row, path38);
18097
18070
  if (value !== void 0) {
18098
- projected[path41] = value;
18071
+ projected[path38] = value;
18099
18072
  }
18100
18073
  }
18101
18074
  return projected;
@@ -19395,11 +19368,11 @@ var updateStatusSchema = z25.enum(UPDATE_STATUSES);
19395
19368
  function currencyMinimums2(currencyCode) {
19396
19369
  return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
19397
19370
  }
19398
- function validateDailyBudgetFloor(money, ctx, path41) {
19371
+ function validateDailyBudgetFloor(money, ctx, path38) {
19399
19372
  if (money?.currencyCode) {
19400
19373
  const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
19401
19374
  if (Number(money.amount) < min) {
19402
- ctx.addIssue({ code: "custom", path: path41, message: `below the ${min} ${money.currencyCode} daily minimum` });
19375
+ ctx.addIssue({ code: "custom", path: path38, message: `below the ${min} ${money.currencyCode} daily minimum` });
19403
19376
  }
19404
19377
  }
19405
19378
  }
@@ -20068,19 +20041,19 @@ function failWriteValidation3(message) {
20068
20041
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
20069
20042
  process.exit(1);
20070
20043
  }
20071
- function loadJsonFileArg3(path41) {
20072
- if (typeof path41 !== "string" || path41.length === 0) {
20044
+ function loadJsonFileArg3(path38) {
20045
+ if (typeof path38 !== "string" || path38.length === 0) {
20073
20046
  return {};
20074
20047
  }
20075
20048
  try {
20076
- const parsed = JSON.parse(readFileSync8(path41, "utf8"));
20049
+ const parsed = JSON.parse(readFileSync8(path38, "utf8"));
20077
20050
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
20078
- failWriteValidation3(`${path41} must contain a JSON object`);
20051
+ failWriteValidation3(`${path38} must contain a JSON object`);
20079
20052
  }
20080
20053
  return parsed;
20081
20054
  } catch (err) {
20082
20055
  if (err instanceof SyntaxError) {
20083
- failWriteValidation3(`${path41} is not valid JSON: ${err.message}`);
20056
+ failWriteValidation3(`${path38} is not valid JSON: ${err.message}`);
20084
20057
  }
20085
20058
  throw err;
20086
20059
  }
@@ -20319,10 +20292,7 @@ var adSetWriteArgs = {
20319
20292
  "daily-budget": { type: "string", description: "Daily budget (ABO; omit if the campaign uses CBO)" },
20320
20293
  "lifetime-budget": { type: "string", description: "Lifetime budget (needs --end)" },
20321
20294
  "bid-amount": { type: "string", description: "Bid amount (required for COST_CAP / bid-cap strategies)" },
20322
- "bid-strategy": {
20323
- type: "string",
20324
- description: "LOWEST_COST_WITHOUT_CAP (auto-bid) | LOWEST_COST_WITH_BID_CAP | COST_CAP \u2014 needs --bid-amount. Omit and Baker sets auto-bid; never leave it to Meta, whose default is a bid cap that then fails without an amount."
20325
- },
20295
+ "bid-strategy": { type: "string", description: "Bid strategy override" },
20326
20296
  currency: { type: "string", description: "3-letter currency (defaults to the account currency)" },
20327
20297
  start: { type: "string", description: "Start time" },
20328
20298
  end: { type: "string", description: "End time" },
@@ -24476,7 +24446,8 @@ import { defineCommand as defineCommand94 } from "citty";
24476
24446
  import { defineCommand as defineCommand89 } from "citty";
24477
24447
 
24478
24448
  // src/commands/avatars/casting.ts
24479
- var VERBATIM_RULE = "Copy `subjectDescription` into the prompt VERBATIM, word for word. Re-phrasing it per generation is the other reason a face drifts across a set \u2014 treat it as an identifier that happens to read as prose.";
24449
+ var CAST_FLAG_RULE = "Cast with `--avatar <handle>` on `baker studio generate` and `baker studio animate`. Do NOT hand-roll it by pasting `subjectDescription` into the prompt or by passing the sheet through `--reference` \u2014 both render something that merely resembles them. `--avatar` is also the ONLY thing that carries their pinned VOICE and how they speak into a clip; without it the video model invents a different voice, and no later step can put theirs back.";
24450
+ var VERBATIM_RULE = "When you do write the description yourself \u2014 a canvas node, a landing image, anywhere `--avatar` does not exist \u2014 copy `subjectDescription` VERBATIM, word for word. Re-phrasing it per generation is the other reason a face drifts across a set.";
24480
24451
  var VIDEO_ROUTING = "In video, a photoreal presenter renders on `google/veo-3.1` (or `google/veo-3.1-fast`), never `bytedance/seedance-2.0` \u2014 it refuses photoreal human faces, AI-generated ones included. Scaffolding a video creative: `baker canvas scaffold-video \u2026 --real-face`.";
24481
24452
  function castingHints(avatar) {
24482
24453
  if (avatar.status === "generating") {
@@ -24500,7 +24471,8 @@ function castingHints(avatar) {
24500
24471
  ];
24501
24472
  }
24502
24473
  return [
24503
- `Ready to cast. Ground every render on the identity sheet, never on a source photo: \`baker images generate "<your scene>" --reference ${avatar.sheetUrl}\`.`,
24474
+ `Ready to cast: \`baker studio generate "<your scene>" --avatar ${avatar.handle}\` for a still, \`baker studio animate "<the motion, and the line they say>" --avatar ${avatar.handle}\` for a clip.`,
24475
+ CAST_FLAG_RULE,
24504
24476
  VERBATIM_RULE,
24505
24477
  VIDEO_ROUTING
24506
24478
  ];
@@ -24540,10 +24512,19 @@ function rosterHints(roster, statusFilter) {
24540
24512
  }
24541
24513
  return hints;
24542
24514
  }
24543
- function creationHints(created) {
24515
+ function thinProfileHint(profile, handle) {
24516
+ const missing = ["motion", "persona", "speech", "wardrobe", "setting"].filter(
24517
+ (field) => !profile?.[field]?.trim()
24518
+ );
24519
+ if (missing.length === 0) return null;
24520
+ return `MISSING ${missing.map((field) => `--${field}`).join(" ")}. A bare subject description holds the face still and nothing else, so clips of @${handle} come out stiff and generic \u2014 measured, filling these in nearly doubled the movement in the same brief. The user almost certainly told you how this person talks and carries themselves; put it in: \`baker avatars update ${handle} ${missing.map((field) => `--${field} "\u2026"`).join(" ")}\`.`;
24521
+ }
24522
+ function creationHints(created, profile) {
24523
+ const thin = thinProfileHint(profile, created.handle);
24544
24524
  const hints = [
24525
+ ...thin ? [thin] : [],
24545
24526
  ...castingHints({ handle: created.handle, status: created.status }),
24546
- `Once it is ready, every render grounds on its identity sheet (\`--reference <sheetUrl>\`) and reuses the subject description you just wrote, word for word. Those two things are what keep the face identical across a set.`
24527
+ `Once it is ready, cast it with \`--avatar ${created.handle}\` on \`baker studio generate\` / \`baker studio animate\` \u2014 that flag is what grounds the render on its identity sheet and, for a clip, what makes it speak in this avatar's own voice.`
24547
24528
  ];
24548
24529
  if (created.likeness === "licensed") {
24549
24530
  hints.push(
@@ -24681,11 +24662,11 @@ function unwrap(response) {
24681
24662
  }
24682
24663
  return response.data;
24683
24664
  }
24684
- async function readAvatars(path41, params) {
24685
- return unwrap(await apiGet(path41, params));
24665
+ async function readAvatars(path38, params) {
24666
+ return unwrap(await apiGet(path38, params));
24686
24667
  }
24687
- async function writeAvatars(path41, body) {
24688
- return unwrap(await apiPost(path41, body));
24668
+ async function writeAvatars(path38, body) {
24669
+ return unwrap(await apiPost(path38, body));
24689
24670
  }
24690
24671
 
24691
24672
  // src/commands/avatars/create.ts
@@ -24813,7 +24794,7 @@ var createCommand2 = defineCommand89({
24813
24794
  ...chatIdFromEnv() ? { chatId: chatIdFromEnv() } : {}
24814
24795
  };
24815
24796
  const data = await writeAvatars("/api/avatars", body);
24816
- writeJson({ ok: true, data, hints: creationHints(data) });
24797
+ writeJson({ ok: true, data, hints: creationHints(data, body.profile) });
24817
24798
  } catch (err) {
24818
24799
  failAvatarApi(err, handle);
24819
24800
  }
@@ -25519,12 +25500,12 @@ function missingFontFiles(urls, available) {
25519
25500
  function planFontAdoption(sources, families) {
25520
25501
  const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
25521
25502
  const byFamily = /* @__PURE__ */ new Map();
25522
- for (const { path: path41, source } of sources) {
25523
- const dir = posix.dirname(path41);
25503
+ for (const { path: path38, source } of sources) {
25504
+ const dir = posix.dirname(path38);
25524
25505
  for (const face of declaredFontFaces(source)) {
25525
25506
  if (!wanted.has(face.family)) continue;
25526
25507
  const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
25527
- perFile.set(path41, [...perFile.get(path41) ?? [], rebaseFontFaceSrc(face.block, dir)]);
25508
+ perFile.set(path38, [...perFile.get(path38) ?? [], rebaseFontFaceSrc(face.block, dir)]);
25528
25509
  byFamily.set(face.family, perFile);
25529
25510
  }
25530
25511
  }
@@ -26548,10 +26529,10 @@ import { defineCommand as defineCommand100 } from "citty";
26548
26529
  import { existsSync as existsSync3, realpathSync } from "fs";
26549
26530
  import { writeFile as writeFile2 } from "fs/promises";
26550
26531
  import path5 from "path";
26551
- function findWorkspaceRoot(startDir, exists2 = existsSync3, maxDepth = 12) {
26532
+ function findWorkspaceRoot(startDir, exists = existsSync3, maxDepth = 12) {
26552
26533
  let dir = path5.resolve(startDir);
26553
26534
  for (let i = 0; i < maxDepth; i++) {
26554
- if (exists2(path5.join(dir, "package.json"))) return dir;
26535
+ if (exists(path5.join(dir, "package.json"))) return dir;
26555
26536
  const parent = path5.dirname(dir);
26556
26537
  if (parent === dir) break;
26557
26538
  dir = parent;
@@ -30498,10 +30479,10 @@ function runDirsToPrune(entries, keep, currentRunId) {
30498
30479
  return runs.slice(0, Math.max(0, runs.length - keep));
30499
30480
  }
30500
30481
  async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
30501
- const { readdir: readdir11 } = await import("fs/promises");
30482
+ const { readdir: readdir10 } = await import("fs/promises");
30502
30483
  let entries;
30503
30484
  try {
30504
- entries = await readdir11(outputsDir);
30485
+ entries = await readdir10(outputsDir);
30505
30486
  } catch {
30506
30487
  return;
30507
30488
  }
@@ -32293,12 +32274,12 @@ async function detectSceneCutsPySceneDetect(filePath, opts = {}) {
32293
32274
  // src/commands/canvas/composition-path.ts
32294
32275
  import { existsSync as existsSync4 } from "fs";
32295
32276
  import path21 from "path";
32296
- function resolveShippedCanvasDir(name, startDir, exists2 = existsSync4, maxDepth = 8) {
32277
+ function resolveShippedCanvasDir(name, startDir, exists = existsSync4, maxDepth = 8) {
32297
32278
  const rel = path21.join("canvas", name);
32298
32279
  let dir = startDir;
32299
32280
  for (let i = 0; i < maxDepth; i++) {
32300
32281
  const candidate = path21.join(dir, rel);
32301
- if (exists2(path21.join(candidate, "meta.json"))) return candidate;
32282
+ if (exists(path21.join(candidate, "meta.json"))) return candidate;
32302
32283
  const parent = path21.dirname(dir);
32303
32284
  if (parent === dir) break;
32304
32285
  dir = parent;
@@ -33124,7 +33105,7 @@ registerSchema({
33124
33105
  }
33125
33106
  }
33126
33107
  });
33127
- function capabilityHints(surfaces, tools = []) {
33108
+ function capabilityHints(surfaces) {
33128
33109
  const hints = [];
33129
33110
  const immediate = surfaces.filter((surface) => surface.writeMode === "applies-at-publish");
33130
33111
  if (immediate.length > 0) {
@@ -33147,18 +33128,6 @@ function capabilityHints(surfaces, tools = []) {
33147
33128
  "Naming one surface (`baker capabilities google-ads`) adds `ops` \u2014 the exact fields and accepted values of every change there. Read that instead of guessing a field name."
33148
33129
  );
33149
33130
  }
33150
- const usable = tools.filter((tool) => tool.ready);
33151
- if (usable.length > 0) {
33152
- hints.push(
33153
- `ALSO AVAILABLE, and not on any surface above: ${usable.map((tool) => tool.label).join(", ")}. These answer WHY a page behaves as it does, which no surface here can. See \`tools[].reach\` for how to call each one.`
33154
- );
33155
- }
33156
- const broken = tools.filter((tool) => !tool.ready);
33157
- if (broken.length > 0) {
33158
- hints.push(
33159
- `CONNECTED BUT UNUSABLE: ${broken.map((tool) => `${tool.label} \u2014 ${tool.note ?? "not reachable"}`).join(" ")} Tell the user rather than planning around it silently.`
33160
- );
33161
- }
33162
33131
  return hints;
33163
33132
  }
33164
33133
  var runCapabilities = defineCommand108({
@@ -33168,8 +33137,6 @@ var runCapabilities = defineCommand108({
33168
33137
 
33169
33138
  Reports, per surface: what is connected and with what access, what a write there does when it lands, the entities that can be changed, and \u2014 the part nothing else tells you \u2014 what cannot be changed and why.
33170
33139
 
33171
- Also returns \`tools\`: everything else this company can reach that is not one of those surfaces \u2014 Microsoft Clarity and any other MCP toolkit, custom servers, HubSpot. This is the one call that answers "what do I actually have".
33172
-
33173
33140
  Examples:
33174
33141
  baker capabilities
33175
33142
  baker capabilities google-ads
@@ -33205,7 +33172,7 @@ Full guide: __tooling__/docs/tools/baker/capabilities.md`
33205
33172
  body.full = true;
33206
33173
  }
33207
33174
  const response = await apiPost("/api/capabilities", body);
33208
- const hints = capabilityHints(response.data.surfaces, response.data.tools);
33175
+ const hints = capabilityHints(response.data.surfaces);
33209
33176
  writeJson({
33210
33177
  ...response,
33211
33178
  meta: { count: response.data.surfaces.length },
@@ -33675,793 +33642,12 @@ Full guide: __tooling__/docs/tools/baker/creatives.md`
33675
33642
  }
33676
33643
  });
33677
33644
 
33678
- // src/commands/experiment/index.ts
33679
- import { defineCommand as defineCommand112 } from "citty";
33680
-
33681
- // src/commands/landing/import-graph.ts
33682
- import { readdir as readdir8, readFile as readFile20, stat as stat4 } from "fs/promises";
33683
- import path26 from "path";
33684
- var SOURCE_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
33685
- var RESOLVE_CANDIDATES = [
33686
- "",
33687
- ".astro",
33688
- ".ts",
33689
- ".tsx",
33690
- ".js",
33691
- ".jsx",
33692
- ".mjs",
33693
- ".cjs",
33694
- "/index.astro",
33695
- "/index.ts",
33696
- "/index.js"
33697
- ];
33698
- var IMPORT_RE = /(?<![A-Za-z0-9_$])(?:import|export)\s*(?:[\s\S]*?\bfrom\s*)?["']([^"']+)["']/g;
33699
- var DYNAMIC_IMPORT_RE = /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g;
33700
- async function isFile(p) {
33701
- try {
33702
- return (await stat4(p)).isFile();
33703
- } catch {
33704
- return false;
33705
- }
33706
- }
33707
- async function walkFiles(dir) {
33708
- let entries;
33709
- try {
33710
- entries = await readdir8(dir, { withFileTypes: true });
33711
- } catch {
33712
- return [];
33713
- }
33714
- const out = [];
33715
- for (const entry of entries) {
33716
- const full = path26.join(dir, entry.name);
33717
- if (entry.isDirectory()) {
33718
- if (entry.name === "node_modules" || entry.name === "dist") continue;
33719
- out.push(...await walkFiles(full));
33720
- } else if (SOURCE_EXT.test(entry.name)) {
33721
- out.push(full);
33722
- }
33723
- }
33724
- return out;
33725
- }
33726
- async function resolveSpecifier(specifier, fromFile, root) {
33727
- const bare = specifier.split("?")[0] ?? "";
33728
- if (bare.includes("*")) return null;
33729
- let base;
33730
- if (bare.startsWith("/")) base = path26.join(root, bare.slice(1));
33731
- else if (bare.startsWith(".")) base = path26.resolve(path26.dirname(fromFile), bare);
33732
- else return null;
33733
- for (const suffix of RESOLVE_CANDIDATES) {
33734
- const candidate = base + suffix;
33735
- if (SOURCE_EXT.test(candidate) && await isFile(candidate)) return candidate;
33736
- }
33737
- return null;
33738
- }
33739
- async function importedFiles(text2, file, root) {
33740
- const out = [];
33741
- for (const re2 of [IMPORT_RE, DYNAMIC_IMPORT_RE]) {
33742
- for (const match of text2.matchAll(re2)) {
33743
- const spec = match[1];
33744
- if (spec === void 0) continue;
33745
- const target = await resolveSpecifier(spec, file, root);
33746
- if (target !== null) out.push(target);
33747
- }
33748
- }
33749
- return out;
33750
- }
33751
- async function landingGraphFiles(root, slug) {
33752
- const seen = /* @__PURE__ */ new Set();
33753
- const queue = await walkFiles(path26.join(root, "src/pages", slug));
33754
- while (queue.length > 0) {
33755
- const file = queue.pop();
33756
- if (file === void 0 || seen.has(file)) continue;
33757
- let text2;
33758
- try {
33759
- text2 = await readFile20(file, "utf8");
33760
- } catch {
33761
- continue;
33762
- }
33763
- seen.add(file);
33764
- for (const target of await importedFiles(text2, file, root)) {
33765
- if (!seen.has(target)) queue.push(target);
33766
- }
33767
- }
33768
- return new Set([...seen].map((abs) => path26.relative(root, abs).split(path26.sep).join("/")));
33769
- }
33770
-
33771
- // src/commands/experiment/composition.ts
33772
- function sectionsUnder(files, slug) {
33773
- const prefix = `src/pages/${slug}/`;
33774
- return files.filter((file) => file.startsWith(prefix) && !file.slice(prefix.length).startsWith("index.")).sort();
33775
- }
33776
- function compositionOf(controlSlug, variantSlug, variantGraph) {
33777
- return {
33778
- forked: sectionsUnder(variantGraph, variantSlug),
33779
- shared: sectionsUnder(variantGraph, controlSlug)
33780
- };
33781
- }
33782
- async function readComposition(root, controlSlug, variantSlug) {
33783
- try {
33784
- const graph = await landingGraphFiles(root, variantSlug);
33785
- return compositionOf(controlSlug, variantSlug, [...graph]);
33786
- } catch {
33787
- return void 0;
33788
- }
33789
- }
33790
-
33791
- // src/commands/experiment/goal.ts
33792
- function parseEventGoal(argument) {
33793
- const [name, filter] = argument.split("/");
33794
- if (!name) return { error: "Name the event: --goal event:request_demo" };
33795
- if (!filter) return { kind: "custom_event", name };
33796
- const separator = filter.indexOf("=");
33797
- if (separator === -1) {
33798
- return { error: `Write the property as key=value: --goal event:${name}/section=pricing` };
33799
- }
33800
- return { kind: "custom_event", name, property: filter.slice(0, separator), value: filter.slice(separator + 1) };
33801
- }
33802
- function parseGoal(raw) {
33803
- if (raw === void 0 || raw === "") return void 0;
33804
- const separator = raw.indexOf(":");
33805
- const kind = separator === -1 ? raw : raw.slice(0, separator);
33806
- const argument = separator === -1 ? "" : raw.slice(separator + 1);
33807
- if (kind === "leads") return argument ? { kind: "conversion", flowSlug: argument } : { kind: "conversion" };
33808
- if (kind === "click") return argument ? { kind: "outbound_click", targetHost: argument } : { kind: "outbound_click" };
33809
- if (kind === "event") return parseEventGoal(argument);
33810
- return {
33811
- error: `Unknown goal "${raw}". Use leads, leads:<form>, event:<name>, event:<name>/<key>=<value>, click, or click:<host>`
33812
- };
33813
- }
33814
-
33815
- // src/commands/experiment/hints.ts
33816
- var RUNNING_HINT = {
33817
- keep_running: (row) => `${row.experimentId} cannot yet tell the two pages apart \u2014 do not read its numbers as a result, and do not end it hoping for one. ${describeWait(row)}`,
33818
- winner: (row) => `${row.experimentId} has a winner. Run \`baker experiment finish --id ${row.experimentId}\` to send all the traffic to it. That only re-routes between two pages already published \u2014 it does not edit either.`,
33819
- no_difference: (row) => `${row.experimentId} measured the two pages as alike \u2014 it collected enough traffic to see the change it was looking for, and there was none. Finish it (the page you have stays live) and test a bigger change \u2014 a headline, an offer, the shape of the page, not a button colour.`,
33820
- stopped_early_harmful: (row) => `${row.experimentId} is doing damage. Finish it now \u2014 traffic goes back to the original page.`,
33821
- // Unreachable in practice — only `finish --abandon` produces it, and that
33822
- // leaves the test finished. The Record is exhaustive by type so a verdict
33823
- // added upstream fails to compile here rather than printing nothing.
33824
- abandoned: (row) => `${row.experimentId} was stopped before it concluded and found nothing.`,
33825
- invalid: (row) => `${row.experimentId} cannot be read: ${row.invalidReason === "crossover" ? "too many visitors saw both versions" : "the traffic did not split evenly"}. Finish it and start again rather than reporting anything from it.`
33826
- };
33827
- function describeWait(row) {
33828
- if (row.willNotConclude) {
33829
- return "This page's traffic will not settle it at any point, so abandon it with `--abandon` and test a bigger change.";
33830
- }
33831
- if (row.earliestDecisionAt === null) {
33832
- return "This page has produced no visitors yet, so there is nothing to project a finish date from.";
33833
- }
33834
- return `Earliest it could say anything: ${new Date(row.earliestDecisionAt).toISOString().slice(0, 10)}.`;
33835
- }
33836
- function buildStatusHints(experiments) {
33837
- const hints = experiments.filter((row) => row.status === "running").map((row) => RUNNING_HINT[row.verdict](row));
33838
- if (experiments.length === 0) {
33839
- hints.push(
33840
- "No tests yet. `baker experiment plan --landing <slug> --variant <slug>` says whether a page has enough traffic for one before you build the alternative."
33841
- );
33842
- }
33843
- return hints;
33844
- }
33845
- function asLift(value) {
33846
- return `+${Math.round(value * 100)}%`;
33847
- }
33848
- function windowHint(days, detectable) {
33849
- if (days === void 0) return null;
33850
- if (detectable === null || detectable === void 0) {
33851
- return `In ${days} days this page would not gather enough visitors to settle anything, at any size of change. The constraint is the traffic, not the test.`;
33852
- }
33853
- return `In ${days} days this page could only settle a change of ${asLift(detectable)} or more. Design the alternative to be at least that different \u2014 a smaller change needs traffic these ${days} days will not deliver, and the test would end saying nothing.`;
33854
- }
33855
- function buildPlanHints(plan, days) {
33856
- const window2 = windowHint(days, plan.detectableLiftInDays);
33857
- if (!plan.canRun) {
33858
- return [
33859
- plan.reason ?? "This test cannot run on this page.",
33860
- ...window2 ? [window2] : [],
33861
- "A test that cannot conclude is worse than no test \u2014 it still produces a number, and somebody acts on it."
33862
- ];
33863
- }
33864
- const hints = [
33865
- `This test measures ${plan.goalLabel}. That is fixed when it starts and cannot be changed later.`,
33866
- // Fires at the exact moment the hypothesis gets invented, whether or not
33867
- // the agent read the family doc. `plan` says a question CAN be settled here
33868
- // and says nothing about which question is worth asking — and a well-run
33869
- // test of a bad idea costs three weeks and returns `no_difference`.
33870
- "Now decide WHAT to change, from evidence rather than taste. These numbers say which page and which step; they cannot say why. A second opinion answers why \u2014 Microsoft Clarity for what visitors actually do on the page, `baker gsc` for what they searched, `baker ads <platform>` for what the ad promised, `baker ga4` for the client's own measurement. `baker capabilities` lists everything this client has in one call \u2014 the surfaces, and under `tools` everything else that is reachable. Message match \u2014 what the ad or the search promised against what the page opens with \u2014 is the cheapest hypothesis worth testing and is wrong surprisingly often.",
33871
- // The base always works, so a missing integration is never a reason to
33872
- // stop. Naming what it would have shown is worth more to the client than
33873
- // either a silent gap or a run that waited.
33874
- "If none of that is connected, this page's own drop-off is enough to test on \u2014 say which source you lacked and what it would have told you, then run the test anyway. A test never waits on an integration."
33875
- ];
33876
- if (plan.estimatedDays !== null && plan.estimatedDays > 60) {
33877
- hints.push(
33878
- `At this page's traffic it would take about ${plan.estimatedDays} days. Consider testing a bigger change, which needs less traffic to detect.`
33879
- );
33880
- }
33881
- if (window2) hints.push(window2);
33882
- return hints;
33883
- }
33884
-
33885
- // ../api/src/experiments/composition.ts
33886
- import { z as z29 } from "zod";
33887
- var experimentCompositionSchema = z29.object({
33888
- /** Components the variant owns its own copy of — the thing under test. */
33889
- forked: z29.array(z29.string().max(300)).max(50),
33890
- /** Components both pages render from one file, so an edit reaches both arms. */
33891
- shared: z29.array(z29.string().max(300)).max(200)
33892
- });
33893
-
33894
- // ../api/src/experiments/goal.ts
33895
- import { z as z30 } from "zod";
33896
- var eventNameSchema = z30.string().min(1).max(120);
33897
- var experimentGoalSchema = z30.discriminatedUnion("kind", [
33898
- z30.object({
33899
- kind: z30.literal("conversion"),
33900
- /**
33901
- * Narrow to one Form, by the slug that is its identity.
33902
- *
33903
- * Absent means every marked conversion on the page counts, which is the
33904
- * right default for a landing with one Form and the wrong one for a page
33905
- * carrying both a newsletter signup and a demo request.
33906
- */
33907
- flowSlug: z30.string().max(120).optional()
33908
- }),
33909
- z30.object({
33910
- kind: z30.literal("custom_event"),
33911
- name: eventNameSchema,
33912
- /**
33913
- * Narrow to one value of one of the event's own properties.
33914
- *
33915
- * `section_view` on its own is every section; `section_view` where
33916
- * `section = pricing` is the one that matters. Without this a page would
33917
- * have to encode the answer into the event name to be testable against it,
33918
- * which is precisely what the properties map exists to stop.
33919
- */
33920
- property: z30.string().max(64).optional(),
33921
- value: z30.string().max(255).optional()
33922
- }),
33923
- z30.object({
33924
- kind: z30.literal("outbound_click"),
33925
- /**
33926
- * The destination host, as the row records it. Absent means any exit.
33927
- *
33928
- * A host rather than a full URL because that is what `event_name` carries
33929
- * on an `outbound_click` row — `target_url` has the rest, and matching on
33930
- * it would make the goal depend on query parameters a campaign rewrites.
33931
- */
33932
- targetHost: z30.string().max(255).optional()
33933
- })
33934
- ]);
33935
-
33936
- // ../api/src/experiments/hypothesis.ts
33937
- import { z as z31 } from "zod";
33938
- var experimentEvidenceSourceSchema = z31.enum([
33939
- "baker_analytics",
33940
- "clarity",
33941
- "ads",
33942
- "search_console",
33943
- "research",
33944
- "inspiration",
33945
- "client",
33946
- "hunch"
33947
- ]);
33948
- var experimentEvidenceSchema = z31.object({
33949
- source: experimentEvidenceSourceSchema,
33950
- note: z31.string().min(1).max(200),
33951
- /**
33952
- * Where to go and look. Not a `z.url()` — a report inside Baker is reached by
33953
- * a relative path, and rejecting those would push every in-product citation
33954
- * into the note where nothing can link it.
33955
- */
33956
- href: z31.string().max(500).optional()
33957
- });
33958
- var experimentHypothesisSchema = z31.object({
33959
- /**
33960
- * The observation. The one genuinely new field, and the reason for the rest.
33961
- *
33962
- * Without it a lost test teaches nothing, because there is no belief for the
33963
- * result to be evidence against — which is how a testing programme ends up as
33964
- * a list of tests instead of a list of things learned.
33965
- */
33966
- because: z31.string().min(1).max(300),
33967
- /**
33968
- * The change, in the client's words.
33969
- *
33970
- * The machine-checkable truth lives in `plan.composition.forked`; this is what
33971
- * a person reads. The two are allowed to differ in wording and cannot differ
33972
- * in fact, because the brief shows both.
33973
- */
33974
- change: z31.string().min(1).max(200),
33975
- /** Which way the goal is expected to move. See the note at the top of this file. */
33976
- expect: z31.enum(["increase", "decrease"]).default("increase"),
33977
- evidence: z31.array(experimentEvidenceSchema).max(5).optional()
33978
- });
33979
- var experimentHypothesisOutcomeSchema = z31.enum([
33980
- "supported",
33981
- "refuted_opposite",
33982
- "refuted_no_effect",
33983
- "unanswered"
33984
- ]);
33985
-
33986
- // ../api/src/experiments/wire.ts
33987
- import { z as z32 } from "zod";
33988
- var slugSchema = z32.string().min(1).max(120).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Use a page slug, like `oferta`");
33989
- var experimentPlanRequestSchema = z32.object({
33990
- landingSlug: slugSchema,
33991
- variantSlug: slugSchema,
33992
- goal: experimentGoalSchema.optional(),
33993
- /**
33994
- * The smallest lift worth detecting, relative to the baseline. `0.2` is +20%.
33995
- *
33996
- * The single most consequential number a caller supplies, and the one it is
33997
- * most tempting to set small. A test sized for +5% on a 3% page needs a
33998
- * quarter of a million visitors per arm; `plan` will say so rather than
33999
- * running it.
34000
- */
34001
- minDetectableRelativeLift: z32.number().gt(0).max(10).optional(),
34002
- /**
34003
- * "I have this many days — what could I even see?"
34004
- *
34005
- * Read-only, and deliberately not a setting. It does NOT shorten the test:
34006
- * the finish line is a number of visitors fixed before the test starts, and a
34007
- * horizon that can be moved is not a horizon. What it does is answer the
34008
- * question a refusal leaves hanging — `plan` says a +20% lift needs three
34009
- * weeks this page will not deliver, and this says what those weeks WOULD
34010
- * settle, which is a change somebody can actually go and make.
34011
- */
34012
- days: z32.number().int().gt(0).max(365).optional()
34013
- });
34014
- var experimentStartRequestSchema = experimentPlanRequestSchema.extend({
34015
- hypothesis: experimentHypothesisSchema,
34016
- /**
34017
- * What the two arms are made of, read off the import graph by the caller at
34018
- * the moment the test starts.
34019
- *
34020
- * Optional on the wire because the backend cannot compute it — only the
34021
- * Company Workspace has the files — and a workspace that cannot answer must
34022
- * not be blocked from running a test. The brief degrades to naming the two
34023
- * pages instead of naming the section under test.
34024
- */
34025
- composition: experimentCompositionSchema.optional()
34026
- });
34027
- var experimentFinishRequestSchema = z32.object({
34028
- experimentId: z32.string().min(1).max(64),
34029
- /**
34030
- * Stop the test, keep the page that is live, and record no result.
34031
- *
34032
- * The only way a person or an agent can end a test that is still
34033
- * `keep_running`, and it is deliberately its own field rather than a
34034
- * `survivor` they get to pick: an abandoned test has no winner, keeps the
34035
- * control, and is recorded as `abandoned` so it can never be reported later
34036
- * as a result. Without the separate flag, "stop this" and "the variant won"
34037
- * would be the same call.
34038
- *
34039
- * **It overrides the verdict, and does not defer to it.** The only outcome it
34040
- * can actually disagree with is a variant win — every other one keeps the
34041
- * control anyway — so reading it as "apply only when the numbers have nothing
34042
- * to say" meant that abandoning a won test handed all the traffic to the
34043
- * variant instead of keeping the original: the opposite of what this field
34044
- * promises, on live visitors, from a flag whose whole purpose is to be the
34045
- * conservative choice. The response reports `discardedVerdict` when it did
34046
- * override one, because throwing away a real finding should be said out loud.
34047
- */
34048
- abandon: z32.boolean().optional()
34049
- });
34050
- var experimentStatusRequestSchema = z32.object({
34051
- experimentId: z32.string().max(64).optional(),
34052
- full: z32.boolean().optional()
34053
- });
34054
- var experimentPlanResponseSchema = z32.object({
34055
- canRun: z32.boolean(),
34056
- /** Present when `canRun` is false. Product language, ready to show. */
34057
- reason: z32.string().optional(),
34058
- baselineRate: z32.number(),
34059
- minDetectableRelativeLift: z32.number(),
34060
- /** `null` when no amount of traffic could settle the hypothesis. */
34061
- requiredPerVariant: z32.number().nullable(),
34062
- /** Visitors a day the page has been getting, per arm once split. */
34063
- dailyVisitorsPerVariant: z32.number(),
34064
- /** `null` when the page has no traffic to project from. */
34065
- estimatedDays: z32.number().nullable(),
34066
- goal: experimentGoalSchema,
34067
- goalLabel: z32.string(),
34068
- /**
34069
- * The smallest lift `days` of this page's traffic could detect, when `days`
34070
- * was asked for. `null` when it was not, or when no lift at all would be
34071
- * detectable in that window.
34072
- */
34073
- detectableLiftInDays: z32.number().nullable().optional()
34074
- });
34075
- var experimentVerdictSchema = z32.enum([
34076
- "keep_running",
34077
- "winner",
34078
- "no_difference",
34079
- "invalid",
34080
- "stopped_early_harmful",
34081
- /**
34082
- * Stopped by a person before it concluded. Never produced by the stopping
34083
- * rule — only by `finish --abandon`.
34084
- *
34085
- * Its own verdict rather than folded into `no_difference`, because they are
34086
- * opposite claims: one says the two versions were measured and found alike,
34087
- * the other says nobody ever found out. Collapsing them would manufacture the
34088
- * exact finding this feature exists to refuse.
34089
- */
34090
- "abandoned"
34091
- ]);
34092
- var experimentArmSchema = z32.object({
34093
- slug: z32.string(),
34094
- visitors: z32.number(),
34095
- conversions: z32.number(),
34096
- rate: z32.number()
34097
- });
34098
- var experimentStatusRowSchema = z32.object({
34099
- experimentId: z32.string(),
34100
- landingSlug: z32.string(),
34101
- variantSlug: z32.string(),
34102
- hypothesis: experimentHypothesisSchema,
34103
- /**
34104
- * The hypothesis as one sentence, built from its parts plus the goal and the
34105
- * lift on this same row. Rendered backend-side so what a client reads in chat
34106
- * and what they read on the dashboard can never be two different sentences.
34107
- */
34108
- hypothesisStatement: z32.string(),
34109
- /**
34110
- * What the test found out about the belief — derived from `verdict` and
34111
- * `winner`, never entered.
34112
- *
34113
- * Its own field because the verdict and the outcome come apart in exactly the
34114
- * case worth catching: a `winner` the *control* won is not a win, it is the
34115
- * change having made things worse.
34116
- */
34117
- hypothesisOutcome: experimentHypothesisOutcomeSchema,
34118
- /** What the two arms differ by. Absent for a test started before this was recorded. */
34119
- composition: experimentCompositionSchema.optional(),
34120
- /**
34121
- * The finish line this test was sized for. On the row rather than only inside
34122
- * the plan because the claim is not readable without it — "leads should go up"
34123
- * is not a hypothesis, "leads should go up by at least 20%" is.
34124
- */
34125
- minDetectableRelativeLift: z32.number(),
34126
- goalLabel: z32.string(),
34127
- status: z32.enum(["running", "finished"]),
34128
- startedAt: z32.number(),
34129
- finishedAt: z32.number().nullable(),
34130
- verdict: experimentVerdictSchema,
34131
- /** Set only on `winner`. Which page to keep. */
34132
- winner: z32.enum(["control", "variant"]).nullable(),
34133
- /** Set only on `invalid`. Why the numbers cannot be read. */
34134
- invalidReason: z32.enum(["sample_ratio_mismatch", "crossover"]).nullable(),
34135
- /** What a person should be told, in one sentence, in product language. */
34136
- summary: z32.string(),
34137
- control: experimentArmSchema,
34138
- variant: experimentArmSchema,
34139
- /**
34140
- * How close this test is to being able to say anything at all, 0 to 1.
34141
- *
34142
- * Not progress toward a planned sample — there is no longer one to progress
34143
- * toward. It is the traffic behind the test as a share of the traffic its own
34144
- * measured variance says it needs, so it moves when the page gets noisier or
34145
- * steadier rather than only when visitors arrive.
34146
- */
34147
- precision: z32.number(),
34148
- /** When the test could first say something. `null` with no traffic to project from. */
34149
- earliestDecisionAt: z32.number().nullable(),
34150
- /**
34151
- * True when no amount of this page's traffic would settle the comparison.
34152
- * A different thing from a page that is merely slow, and the reason to
34153
- * abandon a test rather than leave it running.
34154
- */
34155
- willNotConclude: z32.boolean(),
34156
- /** Printing only. Never a reason to act — `verdict` is. */
34157
- evidence: z32.object({
34158
- relativeLift: z32.number(),
34159
- probabilityVariantBetter: z32.number(),
34160
- controlInterval: z32.tuple([z32.number(), z32.number()]),
34161
- variantInterval: z32.tuple([z32.number(), z32.number()]),
34162
- /** The anytime-valid interval on the relative lift — what the verdict is read from. */
34163
- liftInterval: z32.tuple([z32.number(), z32.number()])
34164
- }).optional()
34165
- });
34166
- var experimentStatusResponseSchema = z32.object({
34167
- experiments: z32.array(experimentStatusRowSchema)
34168
- });
34169
-
34170
- // src/commands/experiment/hypothesis.ts
34171
- var SOURCES = experimentEvidenceSourceSchema.options.join(", ");
34172
- function parseOne(raw) {
34173
- const separator = raw.indexOf(":");
34174
- if (separator === -1) {
34175
- return { error: `Write the evidence as source:note \u2014 for example \`${raw}:what you saw\`. Sources: ${SOURCES}` };
34176
- }
34177
- const source = experimentEvidenceSourceSchema.safeParse(raw.slice(0, separator).trim());
34178
- if (!source.success) {
34179
- return { error: `\u201C${raw.slice(0, separator).trim()}\u201D is not one of the evidence sources. Use one of: ${SOURCES}` };
34180
- }
34181
- const rest = raw.slice(separator + 1).trim();
34182
- const pipe = rest.lastIndexOf("|");
34183
- const note = (pipe === -1 ? rest : rest.slice(0, pipe)).trim();
34184
- const href = pipe === -1 ? void 0 : rest.slice(pipe + 1).trim();
34185
- if (note === "") {
34186
- return { error: `Say what ${source.data} showed: --evidence "${source.data}:what you saw"` };
34187
- }
34188
- return href ? { source: source.data, note, href } : { source: source.data, note };
34189
- }
34190
- function parseEvidence(raw) {
34191
- if (raw === void 0) return void 0;
34192
- const entries = (Array.isArray(raw) ? raw : [raw]).filter((entry) => entry !== "");
34193
- if (entries.length === 0) return void 0;
34194
- const parsed = [];
34195
- for (const entry of entries) {
34196
- const one = parseOne(entry);
34197
- if ("error" in one) return one;
34198
- parsed.push(one);
34199
- }
34200
- return parsed;
34201
- }
34202
-
34203
- // src/commands/experiment/index.ts
34204
- var GOAL_ARG = {
34205
- type: "string",
34206
- description: "What counts as success, and it is fixed for the life of the test. `leads` (default \u2014 whatever this company already marks as a conversion), `leads:<form>`, `event:<name>` for an event the page declares itself (see `baker analytics events`), `event:<name>/<key>=<value>` to narrow it, `click` or `click:<host>` for leaving the site. Pick the thing the business actually wants; a test that measures the wrong outcome can have the variant win and the revenue fall.",
34207
- required: false
34208
- };
34209
- var LIFT_ARG = {
34210
- type: "string",
34211
- description: "The smallest improvement worth detecting, relative \u2014 0.2 is +20% (default). The single most consequential number here: halving it roughly quadruples the traffic needed. Ask for the smallest lift that would actually change what the client does, not the smallest one you would like to see.",
34212
- required: false
34213
- };
34214
- var DAYS_ARG = {
34215
- type: "string",
34216
- description: "How many days you have, if that is the constraint. This does NOT shorten the test \u2014 the finish line is a visitor count fixed before it starts \u2014 it answers the other question: what a window that long could settle on this page's traffic. Use it when `plan` refuses and you need to know what WOULD fit.",
34217
- required: false
34218
- };
34219
- var BECAUSE_ARG = {
34220
- type: "string",
34221
- description: "What you SAW that makes this worth testing \u2014 the observation, not the change. \u201C60% of visitors never scroll past the hero\u201D, \u201CCPL doubled after the new headline\u201D. This is the field that makes a losing test worth something: without it there is no belief for the result to be evidence against, and the next test is no better informed than this one.",
34222
- required: true
34223
- };
34224
- var CHANGE_ARG = {
34225
- type: "string",
34226
- description: "What is different about the alternative version, in the client's words \u2014 \u201Cput the booking form in the hero\u201D. One thing. Say it as the reader of the report would.",
34227
- required: true
34228
- };
34229
- var EXPECT_ARG = {
34230
- type: "string",
34231
- description: "Which way you expect the goal to move: `increase` (default) or `decrease`. This is what lets Baker report whether your hypothesis HELD, rather than only which page won \u2014 a test the original page wins is not a win, it is the change having made things worse, and that is the most useful thing a test can tell you.",
34232
- required: false
34233
- };
34234
- var EVIDENCE_ARG = {
34235
- type: "string",
34236
- description: "Where the observation came from, as `source:what it showed`, optionally `|link`. Repeatable. Sources: baker_analytics, clarity, ads, search_console, research, inspiration, client, hunch. Use `hunch` honestly when there is no data \u2014 a stated guess is worth more than a guess dressed as analytics.",
34237
- required: false
34238
- };
34239
- function fail5(message) {
34240
- writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
34241
- process.exit(1);
34242
- }
34243
- function reportApiError(error) {
34244
- if (error instanceof ApiError) {
34245
- writeJsonEnvelope({ ok: false, error: { code: error.code ?? "ERROR", message: error.message } });
34246
- process.exit(1);
34247
- }
34248
- throw error;
34249
- }
34250
- registerSchema({
34251
- command: "experiment.plan",
34252
- description: "Whether a page has enough traffic to settle a question, before anything is built",
34253
- args: {
34254
- landing: { type: "string", description: "The page under test, by slug", required: true },
34255
- variant: { type: "string", description: "The alternative page's slug", required: true },
34256
- goal: GOAL_ARG,
34257
- lift: LIFT_ARG,
34258
- days: DAYS_ARG
34259
- }
34260
- });
34261
- var planCommand = defineCommand112({
34262
- meta: {
34263
- name: "plan",
34264
- description: "Start here, BEFORE building the alternative page. Says whether this page gets enough traffic to settle the question, how long it would take, and whether the thing you want to measure has ever happened on it. Most landing pages cannot run most tests \u2014 finding that out now costs one call, and finding it out later costs three weeks and a decision made on noise."
34265
- },
34266
- args: {
34267
- landing: { type: "string", description: "The page under test, by slug", required: true },
34268
- variant: { type: "string", description: "The alternative page's slug", required: true },
34269
- goal: GOAL_ARG,
34270
- lift: LIFT_ARG,
34271
- days: DAYS_ARG
34272
- },
34273
- run: async ({ args }) => {
34274
- const goal = parseGoal(args.goal ? String(args.goal) : void 0);
34275
- if (goal && "error" in goal) fail5(goal.error);
34276
- try {
34277
- const response = await apiPost("/api/experiments/plan", {
34278
- landingSlug: String(args.landing),
34279
- variantSlug: String(args.variant),
34280
- ...goal ? { goal } : {},
34281
- ...args.lift ? { minDetectableRelativeLift: Number(args.lift) } : {},
34282
- ...args.days ? { days: Number(args.days) } : {}
34283
- });
34284
- writeJsonEnvelope({
34285
- ok: true,
34286
- data: response.data,
34287
- hints: buildPlanHints(response.data, args.days ? Number(args.days) : void 0)
34288
- });
34289
- } catch (error) {
34290
- reportApiError(error);
34291
- }
34292
- }
34293
- });
34294
- registerSchema({
34295
- command: "experiment.start",
34296
- description: "Stage an A/B test between a page and its alternative",
34297
- args: {
34298
- landing: { type: "string", description: "The page under test, by slug", required: true },
34299
- variant: { type: "string", description: "The alternative page's slug", required: true },
34300
- because: BECAUSE_ARG,
34301
- change: CHANGE_ARG,
34302
- expect: EXPECT_ARG,
34303
- evidence: EVIDENCE_ARG,
34304
- goal: GOAL_ARG,
34305
- lift: LIFT_ARG
34306
- }
34307
- });
34308
- var startCommand = defineCommand112({
34309
- meta: {
34310
- name: "start",
34311
- description: "Stage a test between the page and its alternative. Both are ordinary published pages; visitors are split 50/50 at the edge, so there is no flicker and nothing for an ad blocker to suppress. Nothing goes live until the session is published \u2014 the person publishing is the review of the alternative page. Re-runs `plan` first and refuses on the same grounds."
34312
- },
34313
- args: {
34314
- landing: { type: "string", description: "The page under test, by slug", required: true },
34315
- variant: { type: "string", description: "The alternative page's slug", required: true },
34316
- because: BECAUSE_ARG,
34317
- change: CHANGE_ARG,
34318
- expect: EXPECT_ARG,
34319
- evidence: EVIDENCE_ARG,
34320
- goal: GOAL_ARG,
34321
- lift: LIFT_ARG
34322
- },
34323
- run: async ({ args }) => {
34324
- const goal = parseGoal(args.goal ? String(args.goal) : void 0);
34325
- if (goal && "error" in goal) fail5(goal.error);
34326
- const expect = args.expect === void 0 ? "increase" : String(args.expect);
34327
- if (expect !== "increase" && expect !== "decrease") {
34328
- fail5("`--expect` is either `increase` or `decrease` \u2014 which way should the goal move if you are right?");
34329
- }
34330
- const evidence = parseEvidence(args.evidence);
34331
- if (evidence && "error" in evidence) fail5(evidence.error);
34332
- const composition = await readComposition(process.cwd(), String(args.landing), String(args.variant));
34333
- try {
34334
- const response = await apiPost("/api/experiments/start", {
34335
- landingSlug: String(args.landing),
34336
- variantSlug: String(args.variant),
34337
- hypothesis: {
34338
- because: String(args.because),
34339
- change: String(args.change),
34340
- expect,
34341
- ...evidence ? { evidence } : {}
34342
- },
34343
- ...composition ? { composition } : {},
34344
- ...goal ? { goal } : {},
34345
- ...args.lift ? { minDetectableRelativeLift: Number(args.lift) } : {}
34346
- });
34347
- writeJsonEnvelope({
34348
- ok: true,
34349
- data: response.data,
34350
- hints: [
34351
- // The one composition worth interrupting for: `baker landing variant`
34352
- // with no `--fork` succeeds and produces a page that renders exactly
34353
- // the control, so the test would run for weeks against itself.
34354
- ...composition && composition.forked.length === 0 ? [
34355
- `\u201C${String(args.variant)}\u201D does not have its own copy of any section \u2014 it renders exactly the same page as \u201C${String(args.landing)}\u201D, so this test cannot find anything. Fork the section you want to test (\`baker landing variant ${String(args.landing)} ${String(args.variant)} --fork Hero.astro\`) and edit only that file.`
34356
- ] : [],
34357
- "Staged. The split starts when this session is published \u2014 publishing is the review of the alternative page.",
34358
- "Check it as often as you like \u2014 `baker experiment status` is safe to read at any moment and holds its error rate however often you ask. What is never safe is reading the numbers instead of the verdict: `keep_running` means this test cannot yet tell the two pages apart, whatever the rates happen to say today."
34359
- ]
34360
- });
34361
- } catch (error) {
34362
- reportApiError(error);
34363
- }
34364
- }
34365
- });
34366
- registerSchema({
34367
- command: "experiment.status",
34368
- description: "The verdict on every A/B test, running and finished",
34369
- args: {
34370
- id: { type: "string", description: "One test, by its id", required: false },
34371
- full: { type: "boolean", description: "Include the posteriors behind the verdict", required: false }
34372
- }
34373
- });
34374
- var statusCommand4 = defineCommand112({
34375
- meta: {
34376
- name: "status",
34377
- description: "The verdict on each test. Read `verdict` and nothing else to decide: keep_running | winner | no_difference | invalid | stopped_early_harmful. `summary` is one sentence you can show the client. The numbers under `--full` are for printing, never for deciding \u2014 a test that says keep_running has not finished, however good its numbers look."
34378
- },
34379
- args: {
34380
- id: { type: "string", description: "One test, by its id", required: false },
34381
- full: { type: "boolean", description: "Include the posteriors behind the verdict", required: false }
34382
- },
34383
- run: async ({ args }) => {
34384
- try {
34385
- const response = await apiPost("/api/experiments/status", {
34386
- ...args.id ? { experimentId: String(args.id) } : {},
34387
- ...args.full === true ? { full: true } : {}
34388
- });
34389
- writeJsonEnvelope({
34390
- ok: true,
34391
- data: response.data,
34392
- hints: buildStatusHints(response.data.experiments)
34393
- });
34394
- } catch (error) {
34395
- reportApiError(error);
34396
- }
34397
- }
34398
- });
34399
- registerSchema({
34400
- command: "experiment.finish",
34401
- description: "End a test and send all its traffic to the surviving page",
34402
- args: {
34403
- id: { type: "string", description: "The test, by its id", required: true },
34404
- abandon: {
34405
- type: "boolean",
34406
- description: "Stop the test, keep the original page, and record no result. The only way to end a test that has not concluded \u2014 and it OVERRIDES a verdict if there is one, throwing that finding away. Do not pass it by reflex.",
34407
- required: false
34408
- }
34409
- }
34410
- });
34411
- var finishCommand = defineCommand112({
34412
- meta: {
34413
- name: "finish",
34414
- description: "End a test and send all its traffic to whichever page survived. Only a test whose verdict has concluded can be finished with a result \u2014 a `keep_running` test can only be `--abandon`ed, which keeps the original page and records no finding. Promotion is a traffic change over two pages that were both already published and reviewed; it does not edit either page."
34415
- },
34416
- args: {
34417
- id: { type: "string", description: "The test, by its id", required: true },
34418
- abandon: {
34419
- type: "boolean",
34420
- description: "Stop the test, keep the original page, and record no result. The only way to end a test that has not concluded \u2014 and it OVERRIDES a verdict if there is one, throwing that finding away. Do not pass it by reflex.",
34421
- required: false
34422
- }
34423
- },
34424
- run: async ({ args }) => {
34425
- try {
34426
- const response = await apiPost("/api/experiments/finish", {
34427
- experimentId: String(args.id),
34428
- ...args.abandon === true ? { abandon: true } : {}
34429
- });
34430
- writeJsonEnvelope({
34431
- ok: true,
34432
- data: response.data,
34433
- hints: [
34434
- `Staged. All the traffic goes to the ${response.data.survivor === "variant" ? "alternative" : "original"} page when this session is published.`,
34435
- ...response.data.discardedVerdict ? [
34436
- `You abandoned a test that HAD concluded (${response.data.discardedVerdict}). The original page keeps the traffic and no result is recorded \u2014 the finding is gone. If that was not what you meant, run this again without --abandon.`
34437
- ] : [],
34438
- "If the alternative won and you want it to become the page itself, that is an ordinary page edit afterwards \u2014 copy its content over and delete the alternative."
34439
- ]
34440
- });
34441
- } catch (error) {
34442
- reportApiError(error);
34443
- }
34444
- }
34445
- });
34446
- var experimentCommand = defineCommand112({
34447
- meta: {
34448
- name: "experiment",
34449
- description: "Run an A/B test between a landing page and an alternative version of it, and be told which one is better. Always `plan` first: most pages do not get enough traffic to settle most questions, and a test that cannot conclude still produces a number somebody will act on."
34450
- },
34451
- subCommands: {
34452
- plan: planCommand,
34453
- start: startCommand,
34454
- status: statusCommand4,
34455
- finish: finishCommand
34456
- }
34457
- });
34458
-
34459
33645
  // src/commands/flows/index.ts
34460
- import { defineCommand as defineCommand117 } from "citty";
33646
+ import { defineCommand as defineCommand116 } from "citty";
34461
33647
 
34462
33648
  // src/commands/flows/add.ts
34463
33649
  import { randomUUID } from "crypto";
34464
- import { defineCommand as defineCommand113 } from "citty";
33650
+ import { defineCommand as defineCommand112 } from "citty";
34465
33651
 
34466
33652
  // src/commands/flows/shared.ts
34467
33653
  import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "fs";
@@ -34514,12 +33700,12 @@ function collectSideEffects(tree) {
34514
33700
  );
34515
33701
  }
34516
33702
  function readFlowTree(slug) {
34517
- const path41 = join3(flowsDir(), slug, "_data.json");
34518
- if (!existsSync5(path41)) {
33703
+ const path38 = join3(flowsDir(), slug, "_data.json");
33704
+ if (!existsSync5(path38)) {
34519
33705
  failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
34520
33706
  }
34521
33707
  try {
34522
- return JSON.parse(readFileSync9(path41, "utf-8"));
33708
+ return JSON.parse(readFileSync9(path38, "utf-8"));
34523
33709
  } catch (error) {
34524
33710
  failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
34525
33711
  }
@@ -34671,7 +33857,7 @@ registerSchema({
34671
33857
  parent: { type: "string", description: "Parent node id. Omit to append to the root's children.", required: false }
34672
33858
  }
34673
33859
  });
34674
- var addNodeCommand = defineCommand113({
33860
+ var addNodeCommand = defineCommand112({
34675
33861
  meta: {
34676
33862
  name: "add-node",
34677
33863
  description: 'Add a step to a form, with the skeleton its type requires. Example: baker flows add-node contact --type customForm --name "Contact Info"'
@@ -34767,7 +33953,7 @@ registerSchema({
34767
33953
  }
34768
33954
  }
34769
33955
  });
34770
- var addSideEffectCommand = defineCommand113({
33956
+ var addSideEffectCommand = defineCommand112({
34771
33957
  meta: {
34772
33958
  name: "add-side-effect",
34773
33959
  description: "Add a side effect to a step, with the skeleton its type requires. Example: baker flows add-side-effect contact --node <id> --type googleSpreadsheet"
@@ -34849,7 +34035,7 @@ var addSideEffectCommand = defineCommand113({
34849
34035
 
34850
34036
  // src/commands/flows/map.ts
34851
34037
  import { readFileSync as readFileSync11 } from "fs";
34852
- import { defineCommand as defineCommand114 } from "citty";
34038
+ import { defineCommand as defineCommand113 } from "citty";
34853
34039
 
34854
34040
  // src/commands/flows/value-expression.ts
34855
34041
  import { existsSync as existsSync6, readFileSync as readFileSync10 } from "fs";
@@ -34911,10 +34097,10 @@ function parseValueExpression(raw) {
34911
34097
  return parts.map(parsePart);
34912
34098
  }
34913
34099
  function trackingFieldIds() {
34914
- const path41 = join4(flowsDir(), "..", "tracking.ts");
34915
- if (!existsSync6(path41)) return null;
34100
+ const path38 = join4(flowsDir(), "..", "tracking.ts");
34101
+ if (!existsSync6(path38)) return null;
34916
34102
  try {
34917
- const source = readFileSync10(path41, "utf-8");
34103
+ const source = readFileSync10(path38, "utf-8");
34918
34104
  const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
34919
34105
  if (!block2) return null;
34920
34106
  const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
@@ -35466,13 +34652,13 @@ function specsFromFile(parsed) {
35466
34652
  return `${destField}${type}=${entry?.value ?? ""}`;
35467
34653
  });
35468
34654
  }
35469
- function readSpecFile(path41) {
34655
+ function readSpecFile(path38) {
35470
34656
  let raw;
35471
34657
  try {
35472
- raw = path41 === "-" ? readFileSync11(0, "utf-8") : readFileSync11(path41, "utf-8");
34658
+ raw = path38 === "-" ? readFileSync11(0, "utf-8") : readFileSync11(path38, "utf-8");
35473
34659
  } catch (error) {
35474
34660
  refuse(
35475
- `Could not read ${path41 === "-" ? "the mapping from stdin" : `"${path41}"`}: ${error instanceof Error ? error.message : String(error)}`
34661
+ `Could not read ${path38 === "-" ? "the mapping from stdin" : `"${path38}"`}: ${error instanceof Error ? error.message : String(error)}`
35476
34662
  );
35477
34663
  }
35478
34664
  let parsed;
@@ -35480,7 +34666,7 @@ function readSpecFile(path41) {
35480
34666
  parsed = JSON.parse(raw);
35481
34667
  } catch (error) {
35482
34668
  refuse(
35483
- `${path41 === "-" ? "stdin" : `"${path41}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
34669
+ `${path38 === "-" ? "stdin" : `"${path38}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
35484
34670
  'Expected { "map": { "<destField>": "<value>", \u2026 } }'
35485
34671
  );
35486
34672
  }
@@ -35622,7 +34808,7 @@ async function mapOptions(args, fromFile, into) {
35622
34808
  destinationFields: hubspotForm ? await hubspotFieldCatalog(hubspotForm) : void 0
35623
34809
  };
35624
34810
  }
35625
- var mapCommand2 = defineCommand114({
34811
+ var mapCommand2 = defineCommand113({
35626
34812
  meta: {
35627
34813
  name: "map",
35628
34814
  description: "Map form fields onto any value a side effect sends \u2014 never hand-write a mapping. Start here: baker flows map contact --from map.json --write"
@@ -35720,7 +34906,7 @@ var mapCommand2 = defineCommand114({
35720
34906
  });
35721
34907
 
35722
34908
  // src/commands/flows/normalize.ts
35723
- import { defineCommand as defineCommand115 } from "citty";
34909
+ import { defineCommand as defineCommand114 } from "citty";
35724
34910
  var OPTIONAL_STRINGS = ["oauthProviderId"];
35725
34911
  var ARRAY_FIELDS = [
35726
34912
  "fieldMapping",
@@ -35734,18 +34920,18 @@ var ARRAY_FIELDS = [
35734
34920
  "tagIds"
35735
34921
  ];
35736
34922
  var ARRAY_OWNERS = ["", "body"];
35737
- function dropUnsetOptionals(sideEffect, path41) {
34923
+ function dropUnsetOptionals(sideEffect, path38) {
35738
34924
  return OPTIONAL_STRINGS.flatMap((key) => {
35739
34925
  if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
35740
34926
  delete sideEffect[key];
35741
- return [{ path: path41, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
34927
+ return [{ path: path38, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
35742
34928
  });
35743
34929
  }
35744
- function fillNulledArrays(target, prefix, path41) {
34930
+ function fillNulledArrays(target, prefix, path38) {
35745
34931
  return ARRAY_FIELDS.flatMap((key) => {
35746
34932
  if (!(key in target) || target[key] !== null) return [];
35747
34933
  target[key] = [];
35748
- return [{ path: path41, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
34934
+ return [{ path: path38, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
35749
34935
  });
35750
34936
  }
35751
34937
  function sideEffectsOf(node) {
@@ -35755,13 +34941,13 @@ function sideEffectsOf(node) {
35755
34941
  );
35756
34942
  }
35757
34943
  function normalizeSideEffect(sideEffect, where) {
35758
- const path41 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
34944
+ const path38 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
35759
34945
  const arrays = ARRAY_OWNERS.flatMap((owner) => {
35760
34946
  const target = owner ? sideEffect[owner] : sideEffect;
35761
34947
  if (!target || typeof target !== "object") return [];
35762
- return fillNulledArrays(target, owner ? `${owner}.` : "", path41);
34948
+ return fillNulledArrays(target, owner ? `${owner}.` : "", path38);
35763
34949
  });
35764
- return [...dropUnsetOptionals(sideEffect, path41), ...arrays];
34950
+ return [...dropUnsetOptionals(sideEffect, path38), ...arrays];
35765
34951
  }
35766
34952
  function normalizeFlowTree(tree) {
35767
34953
  const changes = [];
@@ -35789,7 +34975,7 @@ registerSchema({
35789
34975
  }
35790
34976
  }
35791
34977
  });
35792
- var normalizeCommand = defineCommand115({
34978
+ var normalizeCommand = defineCommand114({
35793
34979
  meta: {
35794
34980
  name: "normalize",
35795
34981
  description: "Repair the shapes a form file is allowed to get slightly wrong. Example: baker flows normalize contact --write"
@@ -35820,7 +35006,7 @@ var normalizeCommand = defineCommand115({
35820
35006
  });
35821
35007
 
35822
35008
  // src/commands/flows/schema.ts
35823
- import { defineCommand as defineCommand116 } from "citty";
35009
+ import { defineCommand as defineCommand115 } from "citty";
35824
35010
  registerSchema({
35825
35011
  command: "flows.schema",
35826
35012
  description: "The shape of one node or side-effect type: a pasteable skeleton, who fills each part, and the reference file with the craft. Start here before authoring anything in a form's _data.json.",
@@ -35845,7 +35031,7 @@ function triggerHints(triggers) {
35845
35031
  `A side effect on this step carries \`triggerId: "${triggers.completion}"\`, and \`baker flows add-side-effect\` writes it for you. The trigger belongs to the STEP, not to the side-effect type: one that does not match is valid, ships, and never runs.` + (others.length > 0 ? ` Other moments this step raises: ${others.join(", ")}.` : "")
35846
35032
  ];
35847
35033
  }
35848
- var schemaCommand = defineCommand116({
35034
+ var schemaCommand = defineCommand115({
35849
35035
  meta: {
35850
35036
  name: "schema",
35851
35037
  description: "Show a node or side-effect type's shape. Start here: baker flows schema node customForm \xB7 baker flows schema side-effect googleSpreadsheet \xB7 baker flows schema (lists both)"
@@ -35979,7 +35165,7 @@ function displayName(slug) {
35979
35165
  const name = tree.displayName;
35980
35166
  return typeof name === "string" && name.trim() ? name.trim() : slug;
35981
35167
  }
35982
- var listCommand12 = defineCommand117({
35168
+ var listCommand12 = defineCommand116({
35983
35169
  meta: {
35984
35170
  name: "list",
35985
35171
  description: "List Forms in this workspace with the count of confidential fields still needing setup. Example: baker flows list"
@@ -36000,7 +35186,7 @@ var listCommand12 = defineCommand117({
36000
35186
  });
36001
35187
  }
36002
35188
  });
36003
- var showCommand3 = defineCommand117({
35189
+ var showCommand3 = defineCommand116({
36004
35190
  meta: {
36005
35191
  name: "show",
36006
35192
  description: "Show a Form's confidential fields and their configuration status (never secret values). Example: baker flows show contact"
@@ -36028,7 +35214,7 @@ var showCommand3 = defineCommand117({
36028
35214
  });
36029
35215
  }
36030
35216
  });
36031
- var flowsCommand = defineCommand117({
35217
+ var flowsCommand = defineCommand116({
36032
35218
  meta: {
36033
35219
  name: "flows",
36034
35220
  description: `Read and shape this workspace's Forms (flows).
@@ -36062,10 +35248,10 @@ Full guide: __tooling__/docs/tools/baker/flows.md`
36062
35248
  });
36063
35249
 
36064
35250
  // src/commands/ga4/index.ts
36065
- import { defineCommand as defineCommand124 } from "citty";
35251
+ import { defineCommand as defineCommand123 } from "citty";
36066
35252
 
36067
35253
  // src/commands/ga4/audit.ts
36068
- import { defineCommand as defineCommand118 } from "citty";
35254
+ import { defineCommand as defineCommand117 } from "citty";
36069
35255
 
36070
35256
  // src/commands/ga4/resolve.ts
36071
35257
  async function fetchProperties(useCache = true) {
@@ -36131,7 +35317,7 @@ registerSchema({
36131
35317
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
36132
35318
  }
36133
35319
  });
36134
- var auditCommand2 = defineCommand118({
35320
+ var auditCommand2 = defineCommand117({
36135
35321
  meta: {
36136
35322
  name: "audit",
36137
35323
  description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
@@ -36186,7 +35372,7 @@ Examples:
36186
35372
  });
36187
35373
 
36188
35374
  // src/commands/ga4/config.ts
36189
- import { defineCommand as defineCommand119 } from "citty";
35375
+ import { defineCommand as defineCommand118 } from "citty";
36190
35376
 
36191
35377
  // src/commands/ga4/shared.ts
36192
35378
  import { readFileSync as readFileSync12 } from "fs";
@@ -36299,10 +35485,10 @@ async function stageOps(ops) {
36299
35485
  handleError2(err);
36300
35486
  }
36301
35487
  }
36302
- async function draftAction2(path41, body, chat) {
35488
+ async function draftAction2(path38, body, chat) {
36303
35489
  const chatId = resolveChatId(chat);
36304
35490
  try {
36305
- const data = await apiPost(path41, { chatId, ...body });
35491
+ const data = await apiPost(path38, { chatId, ...body });
36306
35492
  writeJsonEnvelope({ ok: true, data });
36307
35493
  return data;
36308
35494
  } catch (err) {
@@ -36382,7 +35568,7 @@ function configHints(config) {
36382
35568
  }
36383
35569
  return hints;
36384
35570
  }
36385
- var configCommand = defineCommand119({
35571
+ var configCommand = defineCommand118({
36386
35572
  meta: {
36387
35573
  name: "config",
36388
35574
  description: `Read how the property is configured to measure \u2014 key events, custom definitions, custom events, retention
@@ -36414,7 +35600,7 @@ Examples:
36414
35600
  });
36415
35601
 
36416
35602
  // src/commands/ga4/draft.ts
36417
- import { defineCommand as defineCommand120 } from "citty";
35603
+ import { defineCommand as defineCommand119 } from "citty";
36418
35604
  registerSchema({
36419
35605
  command: "ga4.draft",
36420
35606
  description: "Review and undo the Google Analytics changes staged on this chat. Use `list` to see everything staged, `show` to inspect one change in full before the chat completes, `amend` to correct one in place, and `remove`/`clear` to drop them. `list` and `show` take --chat <id> to read an earlier chat's changes instead.",
@@ -36423,13 +35609,13 @@ registerSchema({
36423
35609
  chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
36424
35610
  }
36425
35611
  });
36426
- var draftCommand3 = defineCommand120({
35612
+ var draftCommand3 = defineCommand119({
36427
35613
  meta: {
36428
35614
  name: "draft",
36429
35615
  description: "List, show, amend, remove or clear the Google Analytics changes staged on this chat. `list` and `show` take --chat <id> to read an earlier chat's changes instead."
36430
35616
  },
36431
35617
  subCommands: {
36432
- list: defineCommand120({
35618
+ list: defineCommand119({
36433
35619
  meta: { name: "list", description: "Review everything staged on this chat (--json for the raw envelope)" },
36434
35620
  args: {
36435
35621
  json: { type: "boolean", description: "Print the raw JSON envelope", required: false },
@@ -36439,7 +35625,7 @@ var draftCommand3 = defineCommand120({
36439
35625
  await draftList(args.json === true, args.chat);
36440
35626
  }
36441
35627
  }),
36442
- show: defineCommand120({
35628
+ show: defineCommand119({
36443
35629
  meta: {
36444
35630
  name: "show",
36445
35631
  description: "Print the full staged payload for one change, alongside how the property looks today \u2014 the receipt to verify it before the chat completes (never truncated)."
@@ -36456,7 +35642,7 @@ var draftCommand3 = defineCommand120({
36456
35642
  );
36457
35643
  }
36458
35644
  }),
36459
- amend: defineCommand120({
35645
+ amend: defineCommand119({
36460
35646
  meta: {
36461
35647
  name: "amend",
36462
35648
  description: "Update a staged change in place \u2014 merges a JSON patch into its payload (objects deep-merge, null deletes a key, arrays/scalars replace) and re-runs every check. Use this instead of remove + re-create."
@@ -36473,7 +35659,7 @@ var draftCommand3 = defineCommand120({
36473
35659
  });
36474
35660
  }
36475
35661
  }),
36476
- remove: defineCommand120({
35662
+ remove: defineCommand119({
36477
35663
  meta: { name: "remove", description: "Remove one staged change" },
36478
35664
  args: { ref: { type: "positional", description: "Staged ref or target id", required: false } },
36479
35665
  run: async ({ args }) => {
@@ -36482,7 +35668,7 @@ var draftCommand3 = defineCommand120({
36482
35668
  });
36483
35669
  }
36484
35670
  }),
36485
- clear: defineCommand120({
35671
+ clear: defineCommand119({
36486
35672
  meta: { name: "clear", description: "Discard all Google Analytics changes staged on this chat" },
36487
35673
  run: async () => {
36488
35674
  await draftAction2("/api/ga4/draft/clear", {});
@@ -36492,7 +35678,7 @@ var draftCommand3 = defineCommand120({
36492
35678
  });
36493
35679
 
36494
35680
  // src/commands/ga4/properties.ts
36495
- import { defineCommand as defineCommand121 } from "citty";
35681
+ import { defineCommand as defineCommand120 } from "citty";
36496
35682
  registerSchema({
36497
35683
  command: "ga4.properties",
36498
35684
  description: "List the GA4 properties this company connected \u2014 there can be several, and every one of them is yours to query. Returns the property IDs the query and audit commands take. Run this first to find property IDs.",
@@ -36508,7 +35694,7 @@ function propertyHints(properties) {
36508
35694
  resources: properties.map((property) => ({ id: property.externalId, label: property.name }))
36509
35695
  });
36510
35696
  }
36511
- var propertiesCommand = defineCommand121({
35697
+ var propertiesCommand = defineCommand120({
36512
35698
  meta: {
36513
35699
  name: "properties",
36514
35700
  description: `List accessible GA4 properties.
@@ -36558,7 +35744,7 @@ Examples:
36558
35744
  // src/commands/ga4/query.ts
36559
35745
  import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync4 } from "fs";
36560
35746
  import { resolve as resolve2 } from "path";
36561
- import { defineCommand as defineCommand122 } from "citty";
35747
+ import { defineCommand as defineCommand121 } from "citty";
36562
35748
 
36563
35749
  // src/commands/ga4/presets.ts
36564
35750
  var GA4_PRESETS = [
@@ -36693,7 +35879,7 @@ function handleError3(err) {
36693
35879
  });
36694
35880
  process.exit(1);
36695
35881
  }
36696
- var queryCommand2 = defineCommand122({
35882
+ var queryCommand2 = defineCommand121({
36697
35883
  meta: {
36698
35884
  name: "query",
36699
35885
  description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
@@ -36764,7 +35950,7 @@ Free-form (escape hatch):
36764
35950
  });
36765
35951
 
36766
35952
  // src/commands/ga4/write-commands.ts
36767
- import { defineCommand as defineCommand123 } from "citty";
35953
+ import { defineCommand as defineCommand122 } from "citty";
36768
35954
  var PROPERTY_ARG_DESCRIPTION = "GA4 property id (optional only when one property is connected \u2014 run `baker ga4 properties`)";
36769
35955
  var propertyArg = { type: "string", description: PROPERTY_ARG_DESCRIPTION, required: false };
36770
35956
  function createJsonDescription(noun) {
@@ -36782,7 +35968,7 @@ registerSchema({
36782
35968
  "property-id": { type: "string", description: PROPERTY_ARG_DESCRIPTION, required: false }
36783
35969
  }
36784
35970
  });
36785
- var keyEventCommand = defineCommand123({
35971
+ var keyEventCommand = defineCommand122({
36786
35972
  meta: {
36787
35973
  name: "key-event",
36788
35974
  description: `Stage key-event (conversion) changes
@@ -36795,7 +35981,7 @@ Examples:
36795
35981
  baker ga4 key-event delete 4185`
36796
35982
  },
36797
35983
  subCommands: {
36798
- create: defineCommand123({
35984
+ create: defineCommand122({
36799
35985
  meta: {
36800
35986
  name: "create",
36801
35987
  description: "Stage a new key event. Needs eventName and countingMethod (ONCE_PER_EVENT or ONCE_PER_SESSION); defaultValue sets a monetary value when the event does not send one."
@@ -36816,7 +36002,7 @@ Examples:
36816
36002
  );
36817
36003
  }
36818
36004
  }),
36819
- update: defineCommand123({
36005
+ update: defineCommand122({
36820
36006
  meta: {
36821
36007
  name: "update",
36822
36008
  description: "Stage a change to an existing key event (pass its id). Only countingMethod and defaultValue can change \u2014 Google will not rename a key event."
@@ -36836,7 +36022,7 @@ Examples:
36836
36022
  });
36837
36023
  }
36838
36024
  }),
36839
- delete: defineCommand123({
36025
+ delete: defineCommand122({
36840
36026
  meta: {
36841
36027
  name: "delete",
36842
36028
  description: "Stage removing a key event, so the event stops counting as a conversion. The event itself keeps being collected. Irreversible once the chat completes \u2014 confirm with the user first."
@@ -36884,7 +36070,7 @@ for (const { kind, noun, createHint } of DEFINITIONS) {
36884
36070
  }
36885
36071
  function definitionCommand(definition) {
36886
36072
  const { command, kind, noun, example } = definition;
36887
- return defineCommand123({
36073
+ return defineCommand122({
36888
36074
  meta: {
36889
36075
  name: command,
36890
36076
  description: `Stage ${noun} changes
@@ -36896,7 +36082,7 @@ Examples:
36896
36082
  baker ga4 ${command} archive 12`
36897
36083
  },
36898
36084
  subCommands: {
36899
- create: defineCommand123({
36085
+ create: defineCommand122({
36900
36086
  meta: { name: "create", description: `Stage a new ${noun} (or a JSON array of them, staged together)` },
36901
36087
  args: {
36902
36088
  json: { type: "string", description: createJsonDescription(noun), required: false },
@@ -36914,7 +36100,7 @@ Examples:
36914
36100
  );
36915
36101
  }
36916
36102
  }),
36917
- update: defineCommand123({
36103
+ update: defineCommand122({
36918
36104
  meta: {
36919
36105
  name: "update",
36920
36106
  description: `Stage a change to an existing ${noun} (pass its id). The parameter name and scope cannot change \u2014 archive and recreate for that.`
@@ -36934,7 +36120,7 @@ Examples:
36934
36120
  });
36935
36121
  }
36936
36122
  }),
36937
- archive: defineCommand123({
36123
+ archive: defineCommand122({
36938
36124
  meta: {
36939
36125
  name: "archive",
36940
36126
  description: `Stage archiving a ${noun} (pass its id). It stops collecting and leaves reporting; past data stays. Irreversible once the chat completes \u2014 confirm with the user first.`
@@ -36979,7 +36165,7 @@ var dataStreamArg = {
36979
36165
  function withStream(args) {
36980
36166
  return typeof args["data-stream"] === "string" ? { dataStream: args["data-stream"] } : {};
36981
36167
  }
36982
- var customEventCommand = defineCommand123({
36168
+ var customEventCommand = defineCommand122({
36983
36169
  meta: {
36984
36170
  name: "custom-event",
36985
36171
  description: `Stage custom events \u2014 new events built from events the site already sends
@@ -36990,7 +36176,7 @@ Examples:
36990
36176
  baker ga4 custom-event delete 7`
36991
36177
  },
36992
36178
  subCommands: {
36993
- create: defineCommand123({
36179
+ create: defineCommand122({
36994
36180
  meta: {
36995
36181
  name: "create",
36996
36182
  description: "Stage a new custom event. Conditions match the source event: use field `event_name` to match the event itself, or any parameter name to match its value."
@@ -37013,7 +36199,7 @@ Examples:
37013
36199
  );
37014
36200
  }
37015
36201
  }),
37016
- update: defineCommand123({
36202
+ update: defineCommand122({
37017
36203
  meta: { name: "update", description: "Stage a change to an existing custom event (pass its id)" },
37018
36204
  args: {
37019
36205
  id: { type: "positional", description: "Custom event rule id", required: false },
@@ -37032,7 +36218,7 @@ Examples:
37032
36218
  });
37033
36219
  }
37034
36220
  }),
37035
- delete: defineCommand123({
36221
+ delete: defineCommand122({
37036
36222
  meta: {
37037
36223
  name: "delete",
37038
36224
  description: "Stage removing a custom event (pass its id). The event stops being created from then on; data already collected under it stays. Confirm with the user first."
@@ -37087,7 +36273,7 @@ function booleanArg(input, flag) {
37087
36273
  if (input === "false") return false;
37088
36274
  return failValidation3(`--${flag} must be true or false`);
37089
36275
  }
37090
- var dataRetentionCommand = defineCommand123({
36276
+ var dataRetentionCommand = defineCommand122({
37091
36277
  meta: {
37092
36278
  name: "data-retention",
37093
36279
  description: `Stage a change to how long Google Analytics keeps data
@@ -37097,7 +36283,7 @@ Examples:
37097
36283
  baker ga4 data-retention set --event-data 14 --user-data 14 --reset-on-activity true`
37098
36284
  },
37099
36285
  subCommands: {
37100
- set: defineCommand123({
36286
+ set: defineCommand122({
37101
36287
  meta: { name: "set", description: "Stage the retention window (months)" },
37102
36288
  args: {
37103
36289
  "event-data": { type: "string", description: "2, 14, 26, 38 or 50", required: false },
@@ -37133,7 +36319,7 @@ registerSchema({
37133
36319
  "property-id": { type: "string", description: PROPERTY_ARG_DESCRIPTION, required: false }
37134
36320
  }
37135
36321
  });
37136
- var audienceCommand = defineCommand123({
36322
+ var audienceCommand = defineCommand122({
37137
36323
  meta: {
37138
36324
  name: "audience",
37139
36325
  description: `Stage audience changes (saved groups of users, for retargeting and analysis)
@@ -37165,7 +36351,7 @@ Examples:
37165
36351
  baker ga4 audience archive 8813`
37166
36352
  },
37167
36353
  subCommands: {
37168
- create: defineCommand123({
36354
+ create: defineCommand122({
37169
36355
  meta: { name: "create", description: createJsonDescription("audience") },
37170
36356
  args: {
37171
36357
  json: { type: "string", description: createJsonDescription("audience"), required: false },
@@ -37183,7 +36369,7 @@ Examples:
37183
36369
  );
37184
36370
  }
37185
36371
  }),
37186
- update: defineCommand123({
36372
+ update: defineCommand122({
37187
36373
  meta: {
37188
36374
  name: "update",
37189
36375
  description: "Stage a new name or description (pass the audience id). Who is in it cannot be changed."
@@ -37204,7 +36390,7 @@ Examples:
37204
36390
  });
37205
36391
  }
37206
36392
  }),
37207
- archive: defineCommand123({
36393
+ archive: defineCommand122({
37208
36394
  meta: {
37209
36395
  name: "archive",
37210
36396
  description: "Stage retiring an audience. Cannot be undone \u2014 the users it gathered do not come back."
@@ -37233,7 +36419,7 @@ registerSchema({
37233
36419
  "property-id": { type: "string", description: PROPERTY_ARG_DESCRIPTION, required: false }
37234
36420
  }
37235
36421
  });
37236
- var propertyCommand = defineCommand123({
36422
+ var propertyCommand = defineCommand122({
37237
36423
  meta: {
37238
36424
  name: "property",
37239
36425
  description: `Stage a change to the property's own settings
@@ -37243,7 +36429,7 @@ Examples:
37243
36429
  baker ga4 property set --name "Acme \u2014 Web" --industry REAL_ESTATE`
37244
36430
  },
37245
36431
  subCommands: {
37246
- set: defineCommand123({
36432
+ set: defineCommand122({
37247
36433
  meta: { name: "set", description: "Stage the property name and/or industry category" },
37248
36434
  args: {
37249
36435
  name: { type: "string", description: "New property display name", required: false },
@@ -37283,7 +36469,7 @@ registerSchema({
37283
36469
  "property-id": { type: "string", description: PROPERTY_ARG_DESCRIPTION, required: false }
37284
36470
  }
37285
36471
  });
37286
- var adsLinkCommand = defineCommand123({
36472
+ var adsLinkCommand = defineCommand122({
37287
36473
  meta: {
37288
36474
  name: "ads-link",
37289
36475
  description: `Stage linking this property to a Google Ads account
@@ -37298,7 +36484,7 @@ Examples:
37298
36484
  baker ga4 ads-link delete L1234`
37299
36485
  },
37300
36486
  subCommands: {
37301
- create: defineCommand123({
36487
+ create: defineCommand122({
37302
36488
  meta: { name: "create", description: "Stage linking the property to a Google Ads account" },
37303
36489
  args: {
37304
36490
  "customer-id": { type: "string", description: "Google Ads customer id (123-456-7890)", required: false },
@@ -37317,7 +36503,7 @@ Examples:
37317
36503
  await stageOp3({ kind: "ga4.googleAdsLink.create", payload, ...withProperty(args) });
37318
36504
  }
37319
36505
  }),
37320
- update: defineCommand123({
36506
+ update: defineCommand122({
37321
36507
  meta: {
37322
36508
  name: "update",
37323
36509
  description: "Stage the ads-personalisation setting on an existing link (pass its id)"
@@ -37339,7 +36525,7 @@ Examples:
37339
36525
  });
37340
36526
  }
37341
36527
  }),
37342
- delete: defineCommand123({
36528
+ delete: defineCommand122({
37343
36529
  meta: {
37344
36530
  name: "delete",
37345
36531
  description: "Stage unlinking. Stops conversion imports and strands every audience on this property."
@@ -37390,7 +36576,7 @@ var MEASUREMENT_FLAGS = {
37390
36576
  "page-changes": "pageChangesEnabled",
37391
36577
  "form-interactions": "formInteractionsEnabled"
37392
36578
  };
37393
- var enhancedMeasurementCommand = defineCommand123({
36579
+ var enhancedMeasurementCommand = defineCommand122({
37394
36580
  meta: {
37395
36581
  name: "enhanced-measurement",
37396
36582
  description: `Stage the automatic events GA4 collects on a website stream
@@ -37404,7 +36590,7 @@ Examples:
37404
36590
  baker ga4 enhanced-measurement set --video false`
37405
36591
  },
37406
36592
  subCommands: {
37407
- set: defineCommand123({
36593
+ set: defineCommand122({
37408
36594
  meta: { name: "set", description: "Stage which automatic events the website stream collects" },
37409
36595
  args: {
37410
36596
  scrolls: { type: "string", description: "true|false", required: false },
@@ -37447,7 +36633,7 @@ Examples:
37447
36633
  });
37448
36634
 
37449
36635
  // src/commands/ga4/index.ts
37450
- var ga4Command = defineCommand124({
36636
+ var ga4Command = defineCommand123({
37451
36637
  meta: {
37452
36638
  name: "ga4",
37453
36639
  description: `Google Analytics 4. Report on a property, audit its config, and change what it measures.
@@ -37496,12 +36682,12 @@ Full guide: __tooling__/docs/tools/baker/ga4.md`
37496
36682
  });
37497
36683
 
37498
36684
  // src/commands/gsc/index.ts
37499
- import { defineCommand as defineCommand128 } from "citty";
36685
+ import { defineCommand as defineCommand127 } from "citty";
37500
36686
 
37501
36687
  // src/commands/gsc/query.ts
37502
36688
  import { appendFileSync as appendFileSync3, existsSync as existsSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync5 } from "fs";
37503
36689
  import { resolve as resolve3 } from "path";
37504
- import { defineCommand as defineCommand125 } from "citty";
36690
+ import { defineCommand as defineCommand124 } from "citty";
37505
36691
 
37506
36692
  // src/commands/gsc/presets.ts
37507
36693
  var GSC_PRESETS = [
@@ -37695,7 +36881,7 @@ function handleError4(err) {
37695
36881
  });
37696
36882
  process.exit(1);
37697
36883
  }
37698
- var queryCommand3 = defineCommand125({
36884
+ var queryCommand3 = defineCommand124({
37699
36885
  meta: {
37700
36886
  name: "query",
37701
36887
  description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
@@ -37773,7 +36959,7 @@ Free-form (escape hatch):
37773
36959
  });
37774
36960
 
37775
36961
  // src/commands/gsc/sitemaps.ts
37776
- import { defineCommand as defineCommand126 } from "citty";
36962
+ import { defineCommand as defineCommand125 } from "citty";
37777
36963
  registerSchema({
37778
36964
  command: "gsc.sitemaps",
37779
36965
  description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
@@ -37782,7 +36968,7 @@ registerSchema({
37782
36968
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
37783
36969
  }
37784
36970
  });
37785
- var sitemapsCommand = defineCommand126({
36971
+ var sitemapsCommand = defineCommand125({
37786
36972
  meta: {
37787
36973
  name: "sitemaps",
37788
36974
  description: `List sitemaps for a site. Check health and errors.
@@ -37835,7 +37021,7 @@ Examples:
37835
37021
  });
37836
37022
 
37837
37023
  // src/commands/gsc/sites.ts
37838
- import { defineCommand as defineCommand127 } from "citty";
37024
+ import { defineCommand as defineCommand126 } from "citty";
37839
37025
  registerSchema({
37840
37026
  command: "gsc.sites",
37841
37027
  description: "List the Search Console sites this company connected \u2014 there can be several, and every one of them is yours to query. Returns the site URLs the query and sitemaps commands take.",
@@ -37851,7 +37037,7 @@ function siteHints(sites) {
37851
37037
  resources: sites.map((site) => ({ id: site.siteUrl, label: site.permissionLevel }))
37852
37038
  });
37853
37039
  }
37854
- var sitesCommand = defineCommand127({
37040
+ var sitesCommand = defineCommand126({
37855
37041
  meta: {
37856
37042
  name: "sites",
37857
37043
  description: `List verified Search Console sites.
@@ -37899,7 +37085,7 @@ Examples:
37899
37085
  });
37900
37086
 
37901
37087
  // src/commands/gsc/index.ts
37902
- var gscCommand = defineCommand128({
37088
+ var gscCommand = defineCommand127({
37903
37089
  meta: {
37904
37090
  name: "gsc",
37905
37091
  description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
@@ -37923,7 +37109,7 @@ Full guide: __tooling__/docs/tools/baker/gsc.md`
37923
37109
  });
37924
37110
 
37925
37111
  // src/commands/history/index.ts
37926
- import { defineCommand as defineCommand129 } from "citty";
37112
+ import { defineCommand as defineCommand128 } from "citty";
37927
37113
  registerSchema({
37928
37114
  command: "history.list",
37929
37115
  description: "Start here: unified account history (audit log) \u2014 everything that changed on this account, newest first: publishes, chat lifecycle, backlog actions, team changes, setup links, tags, schedules, ad-platform writes, followed advertisers, media, creatives, reports, domains, and integrations. Use it to see what happened recently before planning work. Compact by default; add --full for raw metadata per entry.",
@@ -37978,7 +37164,7 @@ function parseBoundedInt2(raw, name, min, max) {
37978
37164
  }
37979
37165
  return value;
37980
37166
  }
37981
- var listCommand13 = defineCommand129({
37167
+ var listCommand13 = defineCommand128({
37982
37168
  meta: {
37983
37169
  name: "list",
37984
37170
  description: "List recent account changes (unified audit log), newest first."
@@ -38024,7 +37210,7 @@ var listCommand13 = defineCommand129({
38024
37210
  }
38025
37211
  }
38026
37212
  });
38027
- var historyCommand = defineCommand129({
37213
+ var historyCommand = defineCommand128({
38028
37214
  meta: {
38029
37215
  name: "history",
38030
37216
  description: `Unified account history (audit log): what changed, who did it, and when.
@@ -38034,7 +37220,7 @@ Full guide: __tooling__/docs/tools/baker/history.md`
38034
37220
  });
38035
37221
 
38036
37222
  // src/commands/hubspot/index.ts
38037
- import { defineCommand as defineCommand130 } from "citty";
37223
+ import { defineCommand as defineCommand129 } from "citty";
38038
37224
  var EMBED_TYPES = ["legacy", "v4", "unknown"];
38039
37225
  function failNotConnected(err) {
38040
37226
  if (err instanceof ApiError && err.code === "FORBIDDEN" && err.message.includes(HUBSPOT_MISSING_GRANT_MARKER)) {
@@ -38188,7 +37374,7 @@ registerSchema({
38188
37374
  }
38189
37375
  }
38190
37376
  });
38191
- var formsListCommand = defineCommand130({
37377
+ var formsListCommand = defineCommand129({
38192
37378
  meta: {
38193
37379
  name: "list",
38194
37380
  description: "List HubSpot forms with embed type and post-submit action. Example: baker hubspot forms list --redirecting-only"
@@ -38233,7 +37419,7 @@ var formsListCommand = defineCommand130({
38233
37419
  }
38234
37420
  }
38235
37421
  });
38236
- var formsViewCommand = defineCommand130({
37422
+ var formsViewCommand = defineCommand129({
38237
37423
  meta: {
38238
37424
  name: "view",
38239
37425
  description: "Show one HubSpot form's fields and configuration. Example: baker hubspot forms view 1a2b3c"
@@ -38285,7 +37471,7 @@ var formsViewCommand = defineCommand130({
38285
37471
  }
38286
37472
  }
38287
37473
  });
38288
- var meetingsListCommand = defineCommand130({
37474
+ var meetingsListCommand = defineCommand129({
38289
37475
  meta: {
38290
37476
  name: "list",
38291
37477
  description: "List HubSpot meeting links (calendars). Example: baker hubspot meetings list"
@@ -38327,7 +37513,7 @@ var meetingsListCommand = defineCommand130({
38327
37513
  }
38328
37514
  }
38329
37515
  });
38330
- var meetingsViewCommand = defineCommand130({
37516
+ var meetingsViewCommand = defineCommand129({
38331
37517
  meta: {
38332
37518
  name: "view",
38333
37519
  description: "Show one HubSpot meeting link's booking fields. Example: baker hubspot meetings view discovery-call"
@@ -38371,7 +37557,7 @@ var meetingsViewCommand = defineCommand130({
38371
37557
  }
38372
37558
  }
38373
37559
  });
38374
- var formsSubmissionsCommand = defineCommand130({
37560
+ var formsSubmissionsCommand = defineCommand129({
38375
37561
  meta: {
38376
37562
  name: "submissions",
38377
37563
  description: "How many leads a form received, and when. Example: baker hubspot forms submissions <formId> --days 30"
@@ -38420,7 +37606,7 @@ var formsSubmissionsCommand = defineCommand130({
38420
37606
  }
38421
37607
  }
38422
37608
  });
38423
- var workflowsListCommand = defineCommand130({
37609
+ var workflowsListCommand = defineCommand129({
38424
37610
  meta: {
38425
37611
  name: "list",
38426
37612
  description: "List HubSpot workflows. Example: baker hubspot workflows list --enabled-only"
@@ -38485,7 +37671,7 @@ function workflowViewHints(workflow) {
38485
37671
  }
38486
37672
  return hints;
38487
37673
  }
38488
- var workflowsViewCommand = defineCommand130({
37674
+ var workflowsViewCommand = defineCommand129({
38489
37675
  meta: {
38490
37676
  name: "view",
38491
37677
  description: "Read one workflow's real configuration \u2014 enrolment, branches in order, and what each step writes. Example: baker hubspot workflows view 121183594 --full"
@@ -38512,7 +37698,7 @@ var workflowsViewCommand = defineCommand130({
38512
37698
  }
38513
37699
  }
38514
37700
  });
38515
- var pipelinesListCommand = defineCommand130({
37701
+ var pipelinesListCommand = defineCommand129({
38516
37702
  meta: {
38517
37703
  name: "list",
38518
37704
  description: "List HubSpot deal pipelines and their stages. Example: baker hubspot pipelines list"
@@ -38529,7 +37715,7 @@ var pipelinesListCommand = defineCommand130({
38529
37715
  }
38530
37716
  }
38531
37717
  });
38532
- var contactsSummaryCommand = defineCommand130({
37718
+ var contactsSummaryCommand = defineCommand129({
38533
37719
  meta: {
38534
37720
  name: "summary",
38535
37721
  description: "Whether recent leads are being worked, as counts. Example: baker hubspot contacts summary --days 30"
@@ -38599,7 +37785,7 @@ function contactLookupHints(data) {
38599
37785
  }
38600
37786
  return hints;
38601
37787
  }
38602
- var contactsLookupCommand = defineCommand130({
37788
+ var contactsLookupCommand = defineCommand129({
38603
37789
  meta: {
38604
37790
  name: "lookup",
38605
37791
  description: "Find one contact by email and see whether it was worked. Example: baker hubspot contacts lookup a@b.com"
@@ -38623,27 +37809,27 @@ var contactsLookupCommand = defineCommand130({
38623
37809
  }
38624
37810
  }
38625
37811
  });
38626
- var contactsCommand = defineCommand130({
37812
+ var contactsCommand = defineCommand129({
38627
37813
  meta: { name: "contacts", description: "Contacts on the connected HubSpot account." },
38628
37814
  subCommands: { summary: contactsSummaryCommand, lookup: contactsLookupCommand }
38629
37815
  });
38630
- var formsCommand = defineCommand130({
37816
+ var formsCommand = defineCommand129({
38631
37817
  meta: { name: "forms", description: "HubSpot forms on the connected account." },
38632
37818
  subCommands: { list: formsListCommand, view: formsViewCommand, submissions: formsSubmissionsCommand }
38633
37819
  });
38634
- var workflowsCommand = defineCommand130({
37820
+ var workflowsCommand = defineCommand129({
38635
37821
  meta: { name: "workflows", description: "HubSpot workflows on the connected account." },
38636
37822
  subCommands: { list: workflowsListCommand, view: workflowsViewCommand }
38637
37823
  });
38638
- var pipelinesCommand = defineCommand130({
37824
+ var pipelinesCommand = defineCommand129({
38639
37825
  meta: { name: "pipelines", description: "HubSpot deal pipelines on the connected account." },
38640
37826
  subCommands: { list: pipelinesListCommand }
38641
37827
  });
38642
- var meetingsCommand = defineCommand130({
37828
+ var meetingsCommand = defineCommand129({
38643
37829
  meta: { name: "meetings", description: "HubSpot meeting links (calendars) on the connected account." },
38644
37830
  subCommands: { list: meetingsListCommand, view: meetingsViewCommand }
38645
37831
  });
38646
- var hubspotCommand = defineCommand130({
37832
+ var hubspotCommand = defineCommand129({
38647
37833
  meta: {
38648
37834
  name: "hubspot",
38649
37835
  description: `Read the connected HubSpot account \u2014 forms, the leads they received, workflows, deal pipelines and
@@ -38681,10 +37867,10 @@ Full guide: __tooling__/docs/tools/baker/hubspot.md`
38681
37867
  });
38682
37868
 
38683
37869
  // src/commands/images/index.ts
38684
- import { defineCommand as defineCommand156 } from "citty";
37870
+ import { defineCommand as defineCommand155 } from "citty";
38685
37871
 
38686
37872
  // src/commands/images/crop.ts
38687
- import { defineCommand as defineCommand131 } from "citty";
37873
+ import { defineCommand as defineCommand130 } from "citty";
38688
37874
 
38689
37875
  // src/lib/image/crop-sprite.ts
38690
37876
  import sharp from "sharp";
@@ -38699,7 +37885,7 @@ function cropSprite(input, region) {
38699
37885
 
38700
37886
  // src/lib/image/io.ts
38701
37887
  import { randomBytes } from "crypto";
38702
- import { glob as fsGlob, readFile as readFile21, rename, stat as stat5, writeFile as writeFile11 } from "fs/promises";
37888
+ import { glob as fsGlob, readFile as readFile20, rename, stat as stat4, writeFile as writeFile11 } from "fs/promises";
38703
37889
  import { dirname as dirname2, extname as extname2, join as join5, resolve as resolve4 } from "path";
38704
37890
  var REMOTE_RE = /^https?:\/\//i;
38705
37891
  var GLOB_RE = /[*?[\]{}]/;
@@ -38732,11 +37918,11 @@ async function readImageBuffer(pathOrUrl) {
38732
37918
  const { buffer } = await fetchExternalBytes(pathOrUrl, { maxBytes: MAX_REMOTE_IMAGE_BYTES });
38733
37919
  return buffer;
38734
37920
  }
38735
- return readFile21(pathOrUrl);
37921
+ return readFile20(pathOrUrl);
38736
37922
  }
38737
- async function isDirectory(path41) {
37923
+ async function isDirectory(path38) {
38738
37924
  try {
38739
- const s = await stat5(path41);
37925
+ const s = await stat4(path38);
38740
37926
  return s.isDirectory();
38741
37927
  } catch {
38742
37928
  return false;
@@ -38806,7 +37992,7 @@ function emitError2(err) {
38806
37992
  }
38807
37993
  process.exit(1);
38808
37994
  }
38809
- var cropCommand = defineCommand131({
37995
+ var cropCommand = defineCommand130({
38810
37996
  meta: {
38811
37997
  name: "crop",
38812
37998
  description: "Crop a rectangular region from an image.\n\nExample: baker images crop sprite.png --x 0 --y 0 --width 64 --height 64 --output icon.png"
@@ -38842,7 +38028,7 @@ var cropCommand = defineCommand131({
38842
38028
  });
38843
38029
 
38844
38030
  // src/commands/images/delete.ts
38845
- import { defineCommand as defineCommand132 } from "citty";
38031
+ import { defineCommand as defineCommand131 } from "citty";
38846
38032
  registerSchema({
38847
38033
  command: "images.delete",
38848
38034
  description: "Delete an image by ID",
@@ -38856,7 +38042,7 @@ registerSchema({
38856
38042
  }
38857
38043
  }
38858
38044
  });
38859
- var deleteCommand2 = defineCommand132({
38045
+ var deleteCommand2 = defineCommand131({
38860
38046
  meta: {
38861
38047
  name: "delete",
38862
38048
  description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
@@ -38897,7 +38083,7 @@ var deleteCommand2 = defineCommand132({
38897
38083
  });
38898
38084
 
38899
38085
  // src/commands/images/dimensions.ts
38900
- import { defineCommand as defineCommand133 } from "citty";
38086
+ import { defineCommand as defineCommand132 } from "citty";
38901
38087
 
38902
38088
  // src/lib/image/dimensions.ts
38903
38089
  import { imageSize } from "image-size";
@@ -38926,7 +38112,7 @@ registerSchema({
38926
38112
  }
38927
38113
  }
38928
38114
  });
38929
- var dimensionsCommand = defineCommand133({
38115
+ var dimensionsCommand = defineCommand132({
38930
38116
  meta: {
38931
38117
  name: "dimensions",
38932
38118
  description: "Read image dimensions without decoding the full file.\n\nExample: baker images dimensions ./logo.png\nExample: baker images dimensions https://acme.com/hero.png"
@@ -38982,7 +38168,7 @@ var dimensionsCommand = defineCommand133({
38982
38168
  });
38983
38169
 
38984
38170
  // src/commands/images/download.ts
38985
- import { defineCommand as defineCommand134 } from "citty";
38171
+ import { defineCommand as defineCommand133 } from "citty";
38986
38172
 
38987
38173
  // src/commands/images/downloadPaths.ts
38988
38174
  import { basename as basename2, extname as extname3, join as join6 } from "path";
@@ -39038,13 +38224,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
39038
38224
  }
39039
38225
  function disambiguate(paths) {
39040
38226
  const taken = /* @__PURE__ */ new Set();
39041
- return paths.map((path41) => {
39042
- if (!taken.has(path41)) {
39043
- taken.add(path41);
39044
- return path41;
38227
+ return paths.map((path38) => {
38228
+ if (!taken.has(path38)) {
38229
+ taken.add(path38);
38230
+ return path38;
39045
38231
  }
39046
- const ext = extname3(path41);
39047
- const stem = path41.slice(0, path41.length - ext.length);
38232
+ const ext = extname3(path38);
38233
+ const stem = path38.slice(0, path38.length - ext.length);
39048
38234
  let n = 2;
39049
38235
  while (taken.has(`${stem}-${n}${ext}`)) n += 1;
39050
38236
  const unique = `${stem}-${n}${ext}`;
@@ -39171,10 +38357,10 @@ async function runDownloads(plan) {
39171
38357
  const paths = disambiguate(fetched.map((item) => item.path));
39172
38358
  const downloaded = [];
39173
38359
  for (const [index, item] of fetched.entries()) {
39174
- const path41 = paths[index] ?? item.path;
38360
+ const path38 = paths[index] ?? item.path;
39175
38361
  try {
39176
- await atomicWrite(path41, item.buffer);
39177
- downloaded.push({ input: item.input, output: path41, bytes: item.buffer.length, contentType: item.contentType });
38362
+ await atomicWrite(path38, item.buffer);
38363
+ downloaded.push({ input: item.input, output: path38, bytes: item.buffer.length, contentType: item.contentType });
39178
38364
  } catch (err) {
39179
38365
  failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
39180
38366
  }
@@ -39207,7 +38393,7 @@ function emitError3(err) {
39207
38393
  writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
39208
38394
  process.exit(1);
39209
38395
  }
39210
- var downloadCommand = defineCommand134({
38396
+ var downloadCommand = defineCommand133({
39211
38397
  meta: {
39212
38398
  name: "download",
39213
38399
  description: "Download image URLs and/or library images to local files \u2014 the missing first half of `source \u2192 download \u2192 normalize \u2192 place`. Never use `curl` for this.\n\nExamples:\n baker images download https://media.withbaker.com/\u2026/logo.webp\n baker images download j57abc123 j57def456 --out src/pages/pricing/_images/\n baker images download https://\u2026/hero.png --out ./hero.png"
@@ -39240,7 +38426,7 @@ var downloadCommand = defineCommand134({
39240
38426
  });
39241
38427
 
39242
38428
  // src/commands/images/extract.ts
39243
- import { defineCommand as defineCommand135 } from "citty";
38429
+ import { defineCommand as defineCommand134 } from "citty";
39244
38430
 
39245
38431
  // src/commands/images/autoIngest.ts
39246
38432
  var AUTO_INGEST_MAX = {
@@ -39287,7 +38473,7 @@ registerSchema({
39287
38473
  }
39288
38474
  }
39289
38475
  });
39290
- var extractCommand = defineCommand135({
38476
+ var extractCommand = defineCommand134({
39291
38477
  meta: {
39292
38478
  name: "extract",
39293
38479
  description: "Pull every image from a single URL via Firecrawl. ~$0.001/scrape. Cap auto-ingest at 20.\n\nExample: baker images extract https://stripe.com --auto-ingest 5"
@@ -39342,7 +38528,7 @@ var extractCommand = defineCommand135({
39342
38528
  });
39343
38529
 
39344
38530
  // src/commands/images/find.ts
39345
- import { defineCommand as defineCommand136 } from "citty";
38531
+ import { defineCommand as defineCommand135 } from "citty";
39346
38532
 
39347
38533
  // src/commands/images/providerHits.ts
39348
38534
  function asRecord3(value) {
@@ -39480,7 +38666,7 @@ registerSchema({
39480
38666
  full: { type: "boolean", description: "Include full metadata", required: false, default: false }
39481
38667
  }
39482
38668
  });
39483
- var findCommand = defineCommand136({
38669
+ var findCommand = defineCommand135({
39484
38670
  meta: {
39485
38671
  name: "find",
39486
38672
  description: "Library-first fanout image search. Opt in to providers with --sources. `--fallback` short-circuits to externals only when library is thin. With --auto-ingest, ingested external hits return Baker-owned URLs.\n\nExample: baker images find 'office' --sources library,magnific --limit 20"
@@ -39553,7 +38739,7 @@ var findCommand = defineCommand136({
39553
38739
  });
39554
38740
 
39555
38741
  // src/commands/images/get.ts
39556
- import { defineCommand as defineCommand137 } from "citty";
38742
+ import { defineCommand as defineCommand136 } from "citty";
39557
38743
  registerSchema({
39558
38744
  command: "images.get",
39559
38745
  description: "Get a single image by ID",
@@ -39561,7 +38747,7 @@ registerSchema({
39561
38747
  id: { type: "string", description: "Image ID", required: true }
39562
38748
  }
39563
38749
  });
39564
- var getCommand3 = defineCommand137({
38750
+ var getCommand3 = defineCommand136({
39565
38751
  meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
39566
38752
  args: {
39567
38753
  id: { type: "positional", description: "Image ID", required: false },
@@ -39597,7 +38783,7 @@ var getCommand3 = defineCommand137({
39597
38783
  });
39598
38784
 
39599
38785
  // src/commands/images/gif.ts
39600
- import { defineCommand as defineCommand138 } from "citty";
38786
+ import { defineCommand as defineCommand137 } from "citty";
39601
38787
  registerSchema({
39602
38788
  command: "images.gif",
39603
38789
  description: "Search Giphy for GIFs / reaction memes (paid social creative).",
@@ -39629,7 +38815,7 @@ registerSchema({
39629
38815
  }
39630
38816
  }
39631
38817
  });
39632
- var gifCommand = defineCommand138({
38818
+ var gifCommand = defineCommand137({
39633
38819
  meta: {
39634
38820
  name: "gif",
39635
38821
  description: "Search Giphy for GIFs / reaction memes \u2014 built for paid-social creative (Meta, TikTok, LinkedIn, X). Free API. Each hit carries WebP + GIF + MP4 URLs in providerMeta so you can pick the right format per platform.\n\nExample: baker images gif 'this is fine' --limit 10\nExample: baker images gif 'office reaction' --rating pg --auto-ingest 2\nExample: baker images gif --trending --limit 25"
@@ -39676,7 +38862,7 @@ var gifCommand = defineCommand138({
39676
38862
  });
39677
38863
 
39678
38864
  // src/commands/images/google.ts
39679
- import { defineCommand as defineCommand139 } from "citty";
38865
+ import { defineCommand as defineCommand138 } from "citty";
39680
38866
  var GOOGLE_ERROR_FIX = {
39681
38867
  action: "use_different_resource",
39682
38868
  explanation: "Generate the asset instead of retrying Google. Google is the last-resort image provider. Run `baker studio generate` to make the asset. Never sleep-and-retry this command \u2014 the CLI already backs off on rate limits. If no image can be sourced, continue the rest of the task with a placeholder rather than aborting it."
@@ -39716,7 +38902,7 @@ registerSchema({
39716
38902
  }
39717
38903
  }
39718
38904
  });
39719
- var googleCommand2 = defineCommand139({
38905
+ var googleCommand2 = defineCommand138({
39720
38906
  meta: {
39721
38907
  name: "google",
39722
38908
  description: "Google Images via the official Custom Search JSON API ($0.005/query, free 100/day). \u26A0 Source unverified \u2014 watermarks, low-res, mislabeled results are common. Use as last resort. With --auto-ingest, ingested hits return Baker-owned URLs.\n\nExample: baker images google 'industrial workshop' --type photo --size large --limit 20"
@@ -39789,7 +38975,7 @@ var googleCommand2 = defineCommand139({
39789
38975
  });
39790
38976
 
39791
38977
  // src/commands/images/group.ts
39792
- import { defineCommand as defineCommand140 } from "citty";
38978
+ import { defineCommand as defineCommand139 } from "citty";
39793
38979
 
39794
38980
  // src/commands/mediaGroup.ts
39795
38981
  async function runMediaGroupLookup(input) {
@@ -39842,7 +39028,7 @@ registerSchema({
39842
39028
  "group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
39843
39029
  }
39844
39030
  });
39845
- var groupCommand = defineCommand140({
39031
+ var groupCommand = defineCommand139({
39846
39032
  meta: {
39847
39033
  name: "group",
39848
39034
  description: "List every asset that arrived in the same set \u2014 the slides of one Instagram carousel, the images off one scraped page. Start here whenever a hit looks like part of a sequence: carousel slides are authored to be read in order and usually only make sense together. Takes an image or a video id, since one carousel can contain both. Example: baker images group <imageId>"
@@ -39862,7 +39048,7 @@ var groupCommand = defineCommand140({
39862
39048
  });
39863
39049
 
39864
39050
  // src/commands/images/icon.ts
39865
- import { defineCommand as defineCommand141 } from "citty";
39051
+ import { defineCommand as defineCommand140 } from "citty";
39866
39052
 
39867
39053
  // src/commands/images/brandVerification.ts
39868
39054
  function brandToken(domain) {
@@ -39959,7 +39145,7 @@ registerSchema({
39959
39145
  full: { type: "boolean", description: "Include full metadata", required: false, default: false }
39960
39146
  }
39961
39147
  });
39962
- var iconCommand = defineCommand141({
39148
+ var iconCommand = defineCommand140({
39963
39149
  meta: {
39964
39150
  name: "icon",
39965
39151
  description: "Icon via Iconify (simple-icons, logos, lucide, devicon, heroicons, tabler, phosphor, material-symbols, \u2026). Free CDN, no API key.\n\nExample: baker images icon react --set devicon\nExample: baker images icon lucide:check --color '#0a0a0a'"
@@ -40029,7 +39215,7 @@ var iconCommand = defineCommand141({
40029
39215
  });
40030
39216
 
40031
39217
  // src/commands/images/ingest.ts
40032
- import { defineCommand as defineCommand142 } from "citty";
39218
+ import { defineCommand as defineCommand141 } from "citty";
40033
39219
  var SOURCE_VALUES = imageSourceSchema.options.join(" | ");
40034
39220
  registerSchema({
40035
39221
  command: "images.ingest",
@@ -40044,7 +39230,7 @@ registerSchema({
40044
39230
  fields: { type: "string", description: "Comma-separated field names to include", required: false }
40045
39231
  }
40046
39232
  });
40047
- var ingestCommand = defineCommand142({
39233
+ var ingestCommand = defineCommand141({
40048
39234
  meta: {
40049
39235
  name: "ingest",
40050
39236
  description: "Download a remote URL and store it in the library. Hash-deduped on bytes + externalId.\n\nExample: baker images ingest https://img.freepik.com/free-photo/xyz.jpg --source magnific --external-id 12345"
@@ -40113,7 +39299,7 @@ var ingestCommand = defineCommand142({
40113
39299
  });
40114
39300
 
40115
39301
  // src/commands/images/layerize.ts
40116
- import { defineCommand as defineCommand143 } from "citty";
39302
+ import { defineCommand as defineCommand142 } from "citty";
40117
39303
  registerSchema({
40118
39304
  command: "images.layerize",
40119
39305
  description: "Split a library image into editable layers: transparent PNG cutouts for each element, plus any headline recovered as EDITABLE TEXT with its font, size, colour and position. Waits for completion by default. Costs credits.",
@@ -40177,7 +39363,7 @@ async function pollUntilSettled(imageId, maxWait) {
40177
39363
  }
40178
39364
  return null;
40179
39365
  }
40180
- var layerizeCommand = defineCommand143({
39366
+ var layerizeCommand = defineCommand142({
40181
39367
  meta: {
40182
39368
  name: "layerize",
40183
39369
  description: "Split a library image into editable layers \u2014 transparent cutouts per element, plus any baked-in headline recovered as editable text with its typography.\n\nStart here: baker images layerize j571abc123def\nExample: baker images layerize j571abc123def --full\nExample: baker images layerize j571abc123def --instructions 'keep the product and its shadow together'"
@@ -40246,7 +39432,7 @@ registerSchema({
40246
39432
  full: { type: "boolean", description: "Include geometry and typography for every layer", required: false }
40247
39433
  }
40248
39434
  });
40249
- var layersCommand = defineCommand143({
39435
+ var layersCommand = defineCommand142({
40250
39436
  meta: {
40251
39437
  name: "layers",
40252
39438
  description: "Read the layers of an image that has already been split. Free \u2014 no provider call.\n\nStart here: baker images layers j571abc123def\nExample: baker images layers j571abc123def --full"
@@ -40286,7 +39472,7 @@ var layersCommand = defineCommand143({
40286
39472
  });
40287
39473
 
40288
39474
  // src/commands/images/library.ts
40289
- import { defineCommand as defineCommand144 } from "citty";
39475
+ import { defineCommand as defineCommand143 } from "citty";
40290
39476
  registerSchema({
40291
39477
  command: "images.library",
40292
39478
  description: "Search the company image library. Returns only ready images.",
@@ -40312,7 +39498,7 @@ registerSchema({
40312
39498
  }
40313
39499
  }
40314
39500
  });
40315
- var libraryCommand = defineCommand144({
39501
+ var libraryCommand = defineCommand143({
40316
39502
  meta: {
40317
39503
  name: "library",
40318
39504
  description: "Search the company image library (hybrid BM25 + vector + Cohere rerank). Use this BEFORE any external provider.\n\nExample: baker images library 'hero banner' --aspect-ratio 16:9 --source magnific"
@@ -40375,7 +39561,7 @@ var libraryCommand = defineCommand144({
40375
39561
  });
40376
39562
 
40377
39563
  // src/commands/images/logo.ts
40378
- import { defineCommand as defineCommand145 } from "citty";
39564
+ import { defineCommand as defineCommand144 } from "citty";
40379
39565
  registerSchema({
40380
39566
  command: "images.logo",
40381
39567
  description: "Brand logo lookup via Brandfetch. Auto-ingests by default. Returns `brandMatch` \u2014 Brandfetch's own verdict on whose brand the domain is (confirmed | mismatch | unverified). Branch on it: `mismatch` means the mark is another company's, so do not place it. `confirmed` verifies the record, not the artwork \u2014 read the ingested row back to check the mark itself.",
@@ -40403,7 +39589,7 @@ registerSchema({
40403
39589
  full: { type: "boolean", description: "Include full metadata", required: false, default: false }
40404
39590
  }
40405
39591
  });
40406
- var logoCommand = defineCommand145({
39592
+ var logoCommand = defineCommand144({
40407
39593
  meta: {
40408
39594
  name: "logo",
40409
39595
  description: "Brand logo via Brandfetch. Returns up to 5 variants (icon, light/dark logo, light/dark symbol) plus `brandMatch`. Auto-ingests the first variant.\n\nStart here: check `brandMatch.verdict`.\n mismatch \u2192 the mark belongs to `brandMatch.name`, a different company. Do not place it.\n unverified \u2192 nothing confirmed whose logo this is. Treat as unchecked.\n confirmed \u2192 Brandfetch has this brand's record. That verifies the record, NOT the artwork \u2014 a confirmed domain has served another company's logo before.\n\n\u26A0 Whatever the verdict, read the ingested row back with `baker images get <imageId>` and check `textInImage`/`subject` before placing it. That is the only check that looks at the mark.\n\nExample: baker images logo stripe.com --variant logo"
@@ -40476,7 +39662,7 @@ var logoCommand = defineCommand145({
40476
39662
  });
40477
39663
 
40478
39664
  // src/commands/images/normalize.ts
40479
- import { defineCommand as defineCommand146 } from "citty";
39665
+ import { defineCommand as defineCommand145 } from "citty";
40480
39666
 
40481
39667
  // src/lib/image/color-changer.ts
40482
39668
  import quantize from "quantize";
@@ -41208,7 +40394,7 @@ function coerceRawArgs(args) {
41208
40394
  "dry-run": bool(args["dry-run"])
41209
40395
  };
41210
40396
  }
41211
- var normalizeCommand2 = defineCommand146({
40397
+ var normalizeCommand2 = defineCommand145({
41212
40398
  meta: {
41213
40399
  name: "normalize",
41214
40400
  description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
@@ -41263,7 +40449,7 @@ Examples:
41263
40449
  });
41264
40450
 
41265
40451
  // src/commands/images/pinterest.ts
41266
- import { defineCommand as defineCommand147 } from "citty";
40452
+ import { defineCommand as defineCommand146 } from "citty";
41267
40453
  registerSchema({
41268
40454
  command: "images.pinterest",
41269
40455
  description: "Pinterest image search via ScrapeCreators. Reference-grade real-world photography, product styling, interiors, fashion, food, and aesthetic mood boards. Inspect before placing \u2014 Pinterest is unverified, trademark-bearing web content.",
@@ -41283,7 +40469,7 @@ registerSchema({
41283
40469
  }
41284
40470
  }
41285
40471
  });
41286
- var pinterestCommand = defineCommand147({
40472
+ var pinterestCommand = defineCommand146({
41287
40473
  meta: {
41288
40474
  name: "pinterest",
41289
40475
  description: "Pinterest image search via ScrapeCreators ($0.00188/request). Best for photo-realistic reference imagery \u2014 lifestyle, interiors, fashion, food, product styling, and mood boards to brief AI generation against. \u26A0 Unverified, trademark-bearing web content \u2014 inspect and respect rights before placing on a customer page. Browse first; auto-ingest only the pins you commit to.\n\nExamples:\n baker images pinterest 'scandinavian living room'\n baker images pinterest 'minimalist skincare product photography' --limit 20\n baker images pinterest 'cozy coffee shop interior' --auto-ingest 2 --context 'Mood reference for hero photography'"
@@ -41340,7 +40526,7 @@ var pinterestCommand = defineCommand147({
41340
40526
  });
41341
40527
 
41342
40528
  // src/commands/images/screenshot.ts
41343
- import { defineCommand as defineCommand148 } from "citty";
40529
+ import { defineCommand as defineCommand147 } from "citty";
41344
40530
  registerSchema({
41345
40531
  command: "images.screenshot",
41346
40532
  description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
@@ -41359,7 +40545,7 @@ registerSchema({
41359
40545
  full: { type: "boolean", description: "Include full metadata", required: false, default: false }
41360
40546
  }
41361
40547
  });
41362
- var screenshotCommand = defineCommand148({
40548
+ var screenshotCommand = defineCommand147({
41363
40549
  meta: {
41364
40550
  name: "screenshot",
41365
40551
  description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
@@ -41423,7 +40609,7 @@ var screenshotCommand = defineCommand148({
41423
40609
  });
41424
40610
 
41425
40611
  // src/commands/images/search.ts
41426
- import { defineCommand as defineCommand149 } from "citty";
40612
+ import { defineCommand as defineCommand148 } from "citty";
41427
40613
  registerSchema({
41428
40614
  command: "images.search",
41429
40615
  description: "Search images by text query. Only returns ready images.",
@@ -41439,7 +40625,7 @@ registerSchema({
41439
40625
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
41440
40626
  }
41441
40627
  });
41442
- var searchCommand = defineCommand149({
40628
+ var searchCommand = defineCommand148({
41443
40629
  meta: {
41444
40630
  name: "search",
41445
40631
  description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
@@ -41499,7 +40685,7 @@ var searchCommand = defineCommand149({
41499
40685
  });
41500
40686
 
41501
40687
  // src/commands/images/sticker.ts
41502
- import { defineCommand as defineCommand150 } from "citty";
40688
+ import { defineCommand as defineCommand149 } from "citty";
41503
40689
  registerSchema({
41504
40690
  command: "images.sticker",
41505
40691
  description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
@@ -41531,7 +40717,7 @@ registerSchema({
41531
40717
  }
41532
40718
  }
41533
40719
  });
41534
- var stickerCommand = defineCommand150({
40720
+ var stickerCommand = defineCommand149({
41535
40721
  meta: {
41536
40722
  name: "sticker",
41537
40723
  description: "Search Giphy's sticker corpus \u2014 transparent-background WebPs / GIFs ideal for overlaying on ad creative (Meta, TikTok, Stories). Same Giphy free API as `baker images gif`; results carry WebP + GIF + MP4 URLs in providerMeta.\n\nExample: baker images sticker 'thumbs up' --limit 10\nExample: baker images sticker celebration --rating g --auto-ingest 3\nExample: baker images sticker --trending --limit 25"
@@ -41578,7 +40764,7 @@ var stickerCommand = defineCommand150({
41578
40764
  });
41579
40765
 
41580
40766
  // src/commands/images/stock.ts
41581
- import { defineCommand as defineCommand151 } from "citty";
40767
+ import { defineCommand as defineCommand150 } from "citty";
41582
40768
  var STOCK_ERROR_FIX = {
41583
40769
  action: "use_different_resource",
41584
40770
  explanation: "Switch provider instead of retrying stock search. Stock search is one of several image sources. Run `baker images find <query> --sources library,pinterest,google` (`--sources` is required \u2014 `find` alone searches the library only) or `baker studio generate` to make the asset. Never sleep-and-retry this command \u2014 the CLI already backs off on rate limits. If no image can be sourced, continue the rest of the task with a placeholder rather than aborting it."
@@ -41655,7 +40841,7 @@ function buildStockRequest(query, args) {
41655
40841
  if (args.context) body.descriptionContext = args.context;
41656
40842
  return body;
41657
40843
  }
41658
- var stockCommand = defineCommand151({
40844
+ var stockCommand = defineCommand150({
41659
40845
  meta: {
41660
40846
  name: "stock",
41661
40847
  description: "Stock search via Magnific \u2014 Freepik's developer API (~250M assets: photos, vectors, illustrations, icons, PSDs). $0.002/req. With --auto-ingest, ingested hits return Baker-owned URLs.\n\nExamples:\n baker images stock 'minimalist office'\n baker images stock 'flat office workers' --type vector\n baker images stock 'hero photo of a kitchen' --type photo --orientation landscape --ai exclude\n baker images stock 'brand pattern' --color '#0a0a0a' --license freemium --auto-ingest 2"
@@ -41728,7 +40914,7 @@ var stockCommand = defineCommand151({
41728
40914
  });
41729
40915
 
41730
40916
  // src/lib/tags-command.ts
41731
- import { defineCommand as defineCommand152 } from "citty";
40917
+ import { defineCommand as defineCommand151 } from "citty";
41732
40918
  function makeTagsCommand(command, label, endpoint) {
41733
40919
  registerSchema({
41734
40920
  command: `${command}.tags`,
@@ -41737,7 +40923,7 @@ function makeTagsCommand(command, label, endpoint) {
41737
40923
  output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
41738
40924
  }
41739
40925
  });
41740
- return defineCommand152({
40926
+ return defineCommand151({
41741
40927
  meta: {
41742
40928
  name: "tags",
41743
40929
  description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
@@ -41773,7 +40959,7 @@ function makeTagsCommand(command, label, endpoint) {
41773
40959
  var tagsCommand3 = makeTagsCommand("images", "image", "/api/images/tags");
41774
40960
 
41775
40961
  // src/commands/images/upload.ts
41776
- import { defineCommand as defineCommand153 } from "citty";
40962
+ import { defineCommand as defineCommand152 } from "citty";
41777
40963
  registerSchema({
41778
40964
  command: "images.upload",
41779
40965
  description: "Upload an image to the library \u2014 local file path or remote http(s) URL.",
@@ -41811,7 +40997,7 @@ registerSchema({
41811
40997
  function isRemoteUrl2(value) {
41812
40998
  return /^https?:\/\//i.test(value);
41813
40999
  }
41814
- var uploadCommand = defineCommand153({
41000
+ var uploadCommand = defineCommand152({
41815
41001
  meta: {
41816
41002
  name: "upload",
41817
41003
  description: "Upload an image to the library \u2014 accepts a local file path OR a remote http(s) URL.\n\nLocal: reads bytes, sends to /api/images/upload, content-type auto-detected from extension.\nRemote: dispatches to /api/images/ingest with hash-dedup on bytes + externalId.\n\nExamples:\n baker images upload ./logo.png --source uploaded\n baker images upload ./cert.png --context 'ISO 27001 badge \u2014 enterprise tier'\n baker images upload https://acme.com/hero.png --source firecrawl --context 'Acme competitor pricing hero'"
@@ -41904,7 +41090,7 @@ async function uploadLocal(target, args) {
41904
41090
  }
41905
41091
 
41906
41092
  // src/commands/images/upscale.ts
41907
- import { defineCommand as defineCommand154 } from "citty";
41093
+ import { defineCommand as defineCommand153 } from "citty";
41908
41094
  registerSchema({
41909
41095
  command: "images.upscale",
41910
41096
  description: "Upscale a library image via the backend (Replicate, cost-tracked). Waits for completion by default. The image must be status 'ready' and raster (not SVG/AVIF).",
@@ -41919,7 +41105,7 @@ registerSchema({
41919
41105
  }
41920
41106
  });
41921
41107
  var POLL_INTERVAL_MS4 = 1500;
41922
- var upscaleCommand = defineCommand154({
41108
+ var upscaleCommand = defineCommand153({
41923
41109
  meta: {
41924
41110
  name: "upscale",
41925
41111
  description: "Upscale a library image via the Convex backend (Replicate, cost-tracked at $0.05/image). Waits for completion by default.\n\nExample: baker images upscale j571abc123def\nExample: baker images upscale j571abc123def --max-wait 0 # fire-and-forget"
@@ -41974,7 +41160,7 @@ var upscaleCommand = defineCommand154({
41974
41160
  });
41975
41161
 
41976
41162
  // src/commands/images/use.ts
41977
- import { defineCommand as defineCommand155 } from "citty";
41163
+ import { defineCommand as defineCommand154 } from "citty";
41978
41164
  registerSchema({
41979
41165
  command: "images.use",
41980
41166
  description: "Ingest a URL and wait for the library record to be ready.",
@@ -42003,7 +41189,7 @@ function emitReady(ingestResult, doc, args) {
42003
41189
  args.full === true
42004
41190
  );
42005
41191
  }
42006
- var useCommand = defineCommand155({
41192
+ var useCommand = defineCommand154({
42007
41193
  meta: {
42008
41194
  name: "use",
42009
41195
  description: "Sugar over `ingest`: download \u2192 store \u2192 wait until describe + embed complete \u2192 return ready library record.\n\nExample: baker images use https://cdn.example.com/hero.png --source uploaded"
@@ -42052,7 +41238,7 @@ var useCommand = defineCommand155({
42052
41238
  });
42053
41239
 
42054
41240
  // src/commands/images/index.ts
42055
- var imagesCommand = defineCommand156({
41241
+ var imagesCommand = defineCommand155({
42056
41242
  meta: {
42057
41243
  name: "images",
42058
41244
  description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
@@ -42130,12 +41316,12 @@ Full guide: __tooling__/docs/tools/baker/images.md`
42130
41316
  });
42131
41317
 
42132
41318
  // src/commands/landing/index.ts
42133
- import { defineCommand as defineCommand168 } from "citty";
41319
+ import { defineCommand as defineCommand166 } from "citty";
42134
41320
 
42135
41321
  // src/commands/landing/critique.ts
42136
41322
  import { readdir as readdir9, stat as stat6 } from "fs/promises";
42137
- import path29 from "path";
42138
- import { defineCommand as defineCommand157 } from "citty";
41323
+ import path28 from "path";
41324
+ import { defineCommand as defineCommand156 } from "citty";
42139
41325
 
42140
41326
  // src/engine/landing/lib/constants.ts
42141
41327
  var OVERUSED_FONTS = /* @__PURE__ */ new Set([
@@ -43102,13 +42288,13 @@ function describeCounts(findings) {
43102
42288
 
43103
42289
  // src/commands/landing/snapshot.ts
43104
42290
  import { mkdir as mkdir8, rename as rename2, writeFile as writeFile12 } from "fs/promises";
43105
- import path27 from "path";
42291
+ import path26 from "path";
43106
42292
  var CRITIC_VERSION = "2";
43107
42293
  function critiqueCacheDir(projectRoot) {
43108
- return path27.join(projectRoot, ".cache", "landing-critique");
42294
+ return path26.join(projectRoot, ".cache", "landing-critique");
43109
42295
  }
43110
42296
  function snapshotPath(projectRoot, slug) {
43111
- return path27.join(critiqueCacheDir(projectRoot), `${slug}.json`);
42297
+ return path26.join(critiqueCacheDir(projectRoot), `${slug}.json`);
43112
42298
  }
43113
42299
  async function writeCritiqueSnapshot(projectRoot, snapshot) {
43114
42300
  await mkdir8(critiqueCacheDir(projectRoot), { recursive: true });
@@ -43120,26 +42306,30 @@ async function writeCritiqueSnapshot(projectRoot, snapshot) {
43120
42306
  }
43121
42307
 
43122
42308
  // src/commands/landing/source-version.ts
43123
- import { readFile as readFile22 } from "fs/promises";
43124
- import path28 from "path";
43125
- var CRITIQUED_ROOTS = ["src/pages/", "src/components/"];
43126
- async function landingSourceRelPaths(root, slug) {
43127
- const files = await landingGraphFiles(root, slug);
43128
- return [...files].filter((rel) => rel.endsWith(".astro") && CRITIQUED_ROOTS.some((r) => rel.startsWith(r))).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
42309
+ import { readdir as readdir8, readFile as readFile21, stat as stat5 } from "fs/promises";
42310
+ import path27 from "path";
42311
+ async function landingSourceRelPaths(landingDir) {
42312
+ const rel = [];
42313
+ if (await isFile(path27.join(landingDir, "index.astro"))) rel.push("index.astro");
42314
+ const componentsDir = path27.join(landingDir, "_components");
42315
+ for (const abs of await walkAstro(componentsDir)) {
42316
+ rel.push(path27.relative(landingDir, abs).split(path27.sep).join("/"));
42317
+ }
42318
+ return rel.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
43129
42319
  }
43130
- async function readLandingSources(root, slug) {
43131
- const rel = await landingSourceRelPaths(root, slug);
42320
+ async function readLandingSources(landingDir) {
42321
+ const rel = await landingSourceRelPaths(landingDir);
43132
42322
  const out = [];
43133
- for (const r of rel) out.push({ path: r, text: await readFile22(path28.join(root, r), "utf8") });
42323
+ for (const r of rel) out.push({ path: r, text: await readFile21(path27.join(landingDir, r), "utf8") });
43134
42324
  return out;
43135
42325
  }
43136
- async function computeLandingSourceSha(root, slug) {
43137
- const rel = await landingSourceRelPaths(root, slug);
42326
+ async function computeLandingSourceSha(landingDir) {
42327
+ const rel = await landingSourceRelPaths(landingDir);
43138
42328
  const parts = [];
43139
42329
  for (const r of rel) {
43140
42330
  let bytes;
43141
42331
  try {
43142
- bytes = await readFile22(path28.join(root, r));
42332
+ bytes = await readFile21(path27.join(landingDir, r));
43143
42333
  } catch {
43144
42334
  bytes = Buffer.alloc(0);
43145
42335
  }
@@ -43147,6 +42337,28 @@ async function computeLandingSourceSha(root, slug) {
43147
42337
  }
43148
42338
  return sha256Hex(Buffer.concat(parts));
43149
42339
  }
42340
+ async function isFile(p) {
42341
+ try {
42342
+ return (await stat5(p)).isFile();
42343
+ } catch {
42344
+ return false;
42345
+ }
42346
+ }
42347
+ async function walkAstro(dir) {
42348
+ let entries;
42349
+ try {
42350
+ entries = await readdir8(dir, { withFileTypes: true });
42351
+ } catch {
42352
+ return [];
42353
+ }
42354
+ const out = [];
42355
+ for (const entry of entries) {
42356
+ const abs = path27.join(dir, entry.name);
42357
+ if (entry.isDirectory()) out.push(...await walkAstro(abs));
42358
+ else if (entry.isFile() && entry.name.endsWith(".astro")) out.push(abs);
42359
+ }
42360
+ return out;
42361
+ }
43150
42362
 
43151
42363
  // src/commands/landing/critique.ts
43152
42364
  registerSchema({
@@ -43171,14 +42383,14 @@ function parseCritiqueSlugs(args) {
43171
42383
  const all = [args.slug, ...rest].filter((s) => typeof s === "string" && s.length > 0);
43172
42384
  return [...new Set(all.map(String))];
43173
42385
  }
43174
- function fail6(code, message, fix) {
42386
+ function fail5(code, message, fix) {
43175
42387
  process.stderr.write(
43176
42388
  `${JSON.stringify({ ok: false, error: { code, message, ...fix ? { fix } : {} } }, null, 2)}
43177
42389
  `
43178
42390
  );
43179
42391
  process.exit(2);
43180
42392
  }
43181
- var critiqueCommand2 = defineCommand157({
42393
+ var critiqueCommand2 = defineCommand156({
43182
42394
  meta: {
43183
42395
  name: "critique",
43184
42396
  description: "Start here: `baker landing critique <slug>` after building or editing a landing. Deterministic design-quality critic (ADVISORY \u2014 findings never fail it). Flags the known AI design tells (gradient text, overused fonts, side-tab borders, cream palettes, buzzword copy, broken images) tiered block/warn/advisory, respecting the client's BRAND.md as the allowlist. Also records the critique that publishing requires \u2014 run it before finishing a landing."
@@ -43196,14 +42408,14 @@ var critiqueCommand2 = defineCommand157({
43196
42408
  const projectRoot = process.cwd();
43197
42409
  for (const slug of slugs) {
43198
42410
  if (!SLUG_RE.test(slug) || slug.includes("..")) {
43199
- fail6(
42411
+ fail5(
43200
42412
  "INVALID_SLUG",
43201
42413
  `"${slug}" is not a landing slug \u2014 use the folder name directly under src/pages/ (letters, digits, dashes; not a path, not a _-private folder).`,
43202
42414
  { availableSlugs: await listLandingSlugs(projectRoot) }
43203
42415
  );
43204
42416
  }
43205
- if (!await isDir(path29.resolve(projectRoot, "src", "pages", slug))) {
43206
- fail6("NOT_FOUND", `No landing at src/pages/${slug}/`, {
42417
+ if (!await isDir(path28.resolve(projectRoot, "src", "pages", slug))) {
42418
+ fail5("NOT_FOUND", `No landing at src/pages/${slug}/`, {
43207
42419
  availableSlugs: await listLandingSlugs(projectRoot)
43208
42420
  });
43209
42421
  }
@@ -43241,10 +42453,8 @@ var critiqueCommand2 = defineCommand157({
43241
42453
  }
43242
42454
  });
43243
42455
  async function critiqueOne(projectRoot, slug, brand) {
43244
- const [sources, sourceSha] = await Promise.all([
43245
- readLandingSources(projectRoot, slug),
43246
- computeLandingSourceSha(projectRoot, slug)
43247
- ]);
42456
+ const landingDir = path28.resolve(projectRoot, "src", "pages", slug);
42457
+ const [sources, sourceSha] = await Promise.all([readLandingSources(landingDir), computeLandingSourceSha(landingDir)]);
43248
42458
  const report = critiqueLanding({ slug, sources, brand });
43249
42459
  let snapshotFailed = false;
43250
42460
  try {
@@ -43263,7 +42473,7 @@ async function critiqueOne(projectRoot, slug, brand) {
43263
42473
  }
43264
42474
  async function listLandingSlugs(projectRoot) {
43265
42475
  try {
43266
- const entries = await readdir9(path29.join(projectRoot, "src", "pages"), { withFileTypes: true });
42476
+ const entries = await readdir9(path28.join(projectRoot, "src", "pages"), { withFileTypes: true });
43267
42477
  return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
43268
42478
  } catch {
43269
42479
  return [];
@@ -43289,10 +42499,10 @@ async function isDir(p) {
43289
42499
  }
43290
42500
 
43291
42501
  // src/commands/landing/inspiration/index.ts
43292
- import { defineCommand as defineCommand166 } from "citty";
42502
+ import { defineCommand as defineCommand165 } from "citty";
43293
42503
 
43294
42504
  // src/commands/landing/inspiration/add.ts
43295
- import { defineCommand as defineCommand158 } from "citty";
42505
+ import { defineCommand as defineCommand157 } from "citty";
43296
42506
 
43297
42507
  // src/commands/landing/inspiration/shared.ts
43298
42508
  var INSPIRATION_HINTS = {
@@ -43374,7 +42584,7 @@ registerSchema({
43374
42584
  note: { type: "string", description: "Why this page is worth keeping", required: false }
43375
42585
  }
43376
42586
  });
43377
- var addCommand = defineCommand158({
42587
+ var addCommand = defineCommand157({
43378
42588
  meta: {
43379
42589
  name: "add",
43380
42590
  description: "Add someone else's landing page to the reference library. Example: baker landing inspiration add https://linear.app --note 'the client likes this density'"
@@ -43415,8 +42625,8 @@ var addCommand = defineCommand158({
43415
42625
 
43416
42626
  // src/commands/landing/inspiration/code.ts
43417
42627
  import { mkdir as mkdir9, writeFile as writeFile13 } from "fs/promises";
43418
- import path30 from "path";
43419
- import { defineCommand as defineCommand159 } from "citty";
42628
+ import path29 from "path";
42629
+ import { defineCommand as defineCommand158 } from "citty";
43420
42630
  registerSchema({
43421
42631
  command: "landing.inspiration.code",
43422
42632
  description: "Write a reference section's standalone HTML+CSS to .baker/inspiration/<id>/ so you can read how it is built. Reference only \u2014 the structure is the lesson, the words are not yours to reuse.",
@@ -43425,7 +42635,7 @@ registerSchema({
43425
42635
  full: { type: "boolean", description: "Print the markup inline as well as writing it", required: false }
43426
42636
  }
43427
42637
  });
43428
- var codeCommand = defineCommand159({
42638
+ var codeCommand = defineCommand158({
43429
42639
  meta: {
43430
42640
  name: "code",
43431
42641
  description: "Write one reference section's standalone markup to disk. Example: baker landing inspiration code k57abc\u2026 \u2014 read it for structure, then build your own."
@@ -43438,9 +42648,9 @@ var codeCommand = defineCommand159({
43438
42648
  try {
43439
42649
  const id = args.id;
43440
42650
  const data = await apiGet("/api/landing-inspiration/section-code", { id });
43441
- const dir = path30.join(process.cwd(), ".baker", "inspiration", id);
42651
+ const dir = path29.join(process.cwd(), ".baker", "inspiration", id);
43442
42652
  await mkdir9(dir, { recursive: true });
43443
- const file = path30.join(dir, "section.html");
42653
+ const file = path29.join(dir, "section.html");
43444
42654
  await writeFile13(file, data.html);
43445
42655
  const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
43446
42656
  const fidelity = fidelityHint(data.fidelity);
@@ -43450,7 +42660,7 @@ var codeCommand = defineCommand159({
43450
42660
  ok: true,
43451
42661
  data: {
43452
42662
  id,
43453
- file: path30.relative(process.cwd(), file),
42663
+ file: path29.relative(process.cwd(), file),
43454
42664
  bytes: data.html.length,
43455
42665
  fidelity: data.fidelity,
43456
42666
  reproduction_notes: data.reproductionNotes,
@@ -43471,7 +42681,7 @@ var codeCommand = defineCommand159({
43471
42681
  });
43472
42682
 
43473
42683
  // src/commands/landing/inspiration/favorites.ts
43474
- import { defineCommand as defineCommand160 } from "citty";
42684
+ import { defineCommand as defineCommand159 } from "citty";
43475
42685
  registerSchema({
43476
42686
  command: "landing.inspiration.favorites",
43477
42687
  description: "List the reference sections this company has saved. This is what `search` looks at by default, so it is the client's own taste profile \u2014 read it before proposing a direction.",
@@ -43485,7 +42695,7 @@ registerSchema({
43485
42695
  }
43486
42696
  }
43487
42697
  });
43488
- var favoritesCommand = defineCommand160({
42698
+ var favoritesCommand = defineCommand159({
43489
42699
  meta: {
43490
42700
  name: "favorites",
43491
42701
  description: "List this company's saved reference sections. Example: baker landing inspiration favorites --type hero,pricing"
@@ -43565,7 +42775,7 @@ registerSchema({
43565
42775
  note: { type: "string", description: "Why this is worth keeping", required: false }
43566
42776
  }
43567
42777
  });
43568
- var favoriteCommand = defineCommand160({
42778
+ var favoriteCommand = defineCommand159({
43569
42779
  meta: {
43570
42780
  name: "favorite",
43571
42781
  description: "Save a reference section to this company. Example: baker landing inspiration favorite k57abc\u2026"
@@ -43603,7 +42813,7 @@ registerSchema({
43603
42813
  page: { type: "boolean", description: "Treat the id as a page rather than a section", required: false }
43604
42814
  }
43605
42815
  });
43606
- var unfavoriteCommand = defineCommand160({
42816
+ var unfavoriteCommand = defineCommand159({
43607
42817
  meta: {
43608
42818
  name: "unfavorite",
43609
42819
  description: "Remove a reference section from this company's saved set. Example: baker landing inspiration unfavorite k57abc\u2026"
@@ -43625,7 +42835,7 @@ var unfavoriteCommand = defineCommand160({
43625
42835
  });
43626
42836
 
43627
42837
  // src/commands/landing/inspiration/page.ts
43628
- import { defineCommand as defineCommand161 } from "citty";
42838
+ import { defineCommand as defineCommand160 } from "citty";
43629
42839
  registerSchema({
43630
42840
  command: "landing.inspiration.page",
43631
42841
  description: "Show a whole reference page as a sequence: every section top to bottom with its type and the idea behind it. This is the view to use when the question is how a good page is ORDERED rather than what one section looks like.",
@@ -43642,7 +42852,7 @@ registerSchema({
43642
42852
  }
43643
42853
  }
43644
42854
  });
43645
- var pageCommand2 = defineCommand161({
42855
+ var pageCommand2 = defineCommand160({
43646
42856
  meta: {
43647
42857
  name: "page",
43648
42858
  description: "Show how a reference page sequences its sections. Example: baker landing inspiration page j91xyz\u2026 \u2014 the blueprint, not the pixels."
@@ -43705,7 +42915,7 @@ var pageCommand2 = defineCommand161({
43705
42915
  });
43706
42916
 
43707
42917
  // src/commands/landing/inspiration/scrape.ts
43708
- import { defineCommand as defineCommand162 } from "citty";
42918
+ import { defineCommand as defineCommand161 } from "citty";
43709
42919
 
43710
42920
  // src/engine/landing-library/proxyFailure.ts
43711
42921
  var PROXY_STATUS = 407;
@@ -43882,7 +43092,7 @@ function classifyCaptureFailure(error) {
43882
43092
 
43883
43093
  // src/engine/landing-library/run.ts
43884
43094
  import { mkdir as mkdir10, writeFile as writeFile15 } from "fs/promises";
43885
- import path32 from "path";
43095
+ import path31 from "path";
43886
43096
 
43887
43097
  // ../proxy/src/preflight.ts
43888
43098
  import http from "http";
@@ -45298,9 +44508,9 @@ async function renderBundleToPng(browser, html, viewportWidth, options = {}) {
45298
44508
 
45299
44509
  // src/engine/landing-library/report.ts
45300
44510
  import { writeFile as writeFile14 } from "fs/promises";
45301
- import path31 from "path";
44511
+ import path30 from "path";
45302
44512
  async function writeCaptureReport(manifest, outDir) {
45303
- const file = path31.join(outDir, "report.html");
44513
+ const file = path30.join(outDir, "report.html");
45304
44514
  await writeFile14(file, renderReport(manifest));
45305
44515
  return file;
45306
44516
  }
@@ -45479,32 +44689,32 @@ async function reproducePage(args) {
45479
44689
  const { browser, page, outDir, pageUrl, livePageShot } = args;
45480
44690
  const built = await buildSectionBundle(page, "body", pageUrl).catch(() => null);
45481
44691
  if (!built) return { bundle: null, fidelity: null };
45482
- await writeFile15(path32.join(outDir, "page.html"), built.html);
44692
+ await writeFile15(path31.join(outDir, "page.html"), built.html);
45483
44693
  const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width, {
45484
44694
  wholePage: true,
45485
44695
  timeoutMs: 6e4
45486
44696
  });
45487
44697
  if (!rendered || !livePageShot) return { bundle: "page.html", fidelity: null };
45488
- await writeFile15(path32.join(outDir, "page-rendered.png"), rendered);
44698
+ await writeFile15(path31.join(outDir, "page-rendered.png"), rendered);
45489
44699
  const { score, note } = await scoreFidelity(livePageShot, rendered);
45490
44700
  return { bundle: "page.html", fidelity: score, ...note ? { fidelityNote: note } : {} };
45491
44701
  }
45492
44702
  async function captureOneSection(args) {
45493
44703
  const { browser, page, candidate, sectionsDir, outDir, pageUrl, withCode } = args;
45494
- const dir = path32.join(sectionsDir, String(candidate.index).padStart(2, "0"));
44704
+ const dir = path31.join(sectionsDir, String(candidate.index).padStart(2, "0"));
45495
44705
  await mkdir10(dir, { recursive: true });
45496
44706
  const desktop = await captureSection(page, candidate);
45497
- if (desktop) await writeFile15(path32.join(dir, "desktop.png"), desktop);
44707
+ if (desktop) await writeFile15(path31.join(dir, "desktop.png"), desktop);
45498
44708
  const visualHash = desktop ? await perceptualHash(desktop) : null;
45499
44709
  const motion = await collectMotion(page, candidate.selector);
45500
44710
  const built = withCode ? await buildSectionBundle(page, candidate.selector, pageUrl) : null;
45501
44711
  let fidelity = null;
45502
44712
  let fidelityNote;
45503
44713
  if (built) {
45504
- await writeFile15(path32.join(dir, "section.html"), built.html);
44714
+ await writeFile15(path31.join(dir, "section.html"), built.html);
45505
44715
  const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width);
45506
44716
  if (rendered && desktop) {
45507
- await writeFile15(path32.join(dir, "section-rendered.png"), rendered);
44717
+ await writeFile15(path31.join(dir, "section-rendered.png"), rendered);
45508
44718
  const result = await scoreFidelity(desktop, rendered);
45509
44719
  fidelity = result.score;
45510
44720
  fidelityNote = result.note;
@@ -45512,9 +44722,9 @@ async function captureOneSection(args) {
45512
44722
  }
45513
44723
  return {
45514
44724
  ...candidate,
45515
- desktopShot: desktop ? path32.relative(outDir, path32.join(dir, "desktop.png")) : null,
44725
+ desktopShot: desktop ? path31.relative(outDir, path31.join(dir, "desktop.png")) : null,
45516
44726
  mobileShot: null,
45517
- bundle: built ? path32.relative(outDir, path32.join(dir, "section.html")) : null,
44727
+ bundle: built ? path31.relative(outDir, path31.join(dir, "section.html")) : null,
45518
44728
  fidelity,
45519
44729
  ...fidelityNote ? { fidelityNote } : {},
45520
44730
  ...built ? { cssStats: built.stats } : {},
@@ -45533,9 +44743,9 @@ async function captureMobileShots(args) {
45533
44743
  for (const section of sections) {
45534
44744
  const shot = await captureSectionOnMobile(mobile.page, section);
45535
44745
  if (!shot) continue;
45536
- const file = path32.join(sectionsDir, String(section.index).padStart(2, "0"), "mobile.png");
44746
+ const file = path31.join(sectionsDir, String(section.index).padStart(2, "0"), "mobile.png");
45537
44747
  await writeFile15(file, shot);
45538
- section.mobileShot = path32.relative(outDir, file);
44748
+ section.mobileShot = path31.relative(outDir, file);
45539
44749
  }
45540
44750
  } finally {
45541
44751
  await mobile.context.close();
@@ -45550,10 +44760,10 @@ async function captureMotionTakes(args) {
45550
44760
  const filmOne = async (section) => {
45551
44761
  const take = await captureMotionTake(browser, pageUrl, section.selector).catch(() => null);
45552
44762
  if (!take) return;
45553
- const dir = path32.join(sectionsDir, String(section.index).padStart(2, "0"));
45554
- const file = path32.join(dir, "motion-filmstrip.png");
44763
+ const dir = path31.join(sectionsDir, String(section.index).padStart(2, "0"));
44764
+ const file = path31.join(dir, "motion-filmstrip.png");
45555
44765
  await writeFile15(file, take.filmstrip);
45556
- section.motionFilmstrip = path32.relative(outDir, file);
44766
+ section.motionFilmstrip = path31.relative(outDir, file);
45557
44767
  log(` [${section.index}] ${section.motion.summary}`);
45558
44768
  };
45559
44769
  const queue = [...moving];
@@ -45610,7 +44820,7 @@ async function captureAlternateViews(args) {
45610
44820
  async function reproduceWholePage(args) {
45611
44821
  const { browser, page, outDir, pageUrl, withCode, log } = args;
45612
44822
  const fullPage = await page.screenshot({ type: "png", fullPage: true }).catch(() => null);
45613
- if (fullPage) await writeFile15(path32.join(outDir, "full-page.png"), fullPage);
44823
+ if (fullPage) await writeFile15(path31.join(outDir, "full-page.png"), fullPage);
45614
44824
  if (!withCode) return { bundle: null, fidelity: null };
45615
44825
  const reproduction = await reproducePage({ browser, page, outDir, pageUrl, livePageShot: fullPage });
45616
44826
  log(`page reproduction: ${reproduction.fidelity === null ? "unavailable" : reproduction.fidelity.toFixed(2)}`);
@@ -45681,7 +44891,7 @@ async function openViaLadder(args) {
45681
44891
  async function scrapeLanding(options) {
45682
44892
  const timeoutMs = options.timeoutMs ?? 45e3;
45683
44893
  const log = options.onProgress ?? (() => void 0);
45684
- const sectionsDir = path32.join(options.outDir, "sections");
44894
+ const sectionsDir = path31.join(options.outDir, "sections");
45685
44895
  const nonPublic = refuseNonPublicUrl(options.url);
45686
44896
  if (nonPublic) {
45687
44897
  throw new BlockedPageError({
@@ -45743,7 +44953,7 @@ async function scrapeLanding(options) {
45743
44953
  security: prepared.security,
45744
44954
  captureTier: tier
45745
44955
  };
45746
- await writeFile15(path32.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
44956
+ await writeFile15(path31.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
45747
44957
  `);
45748
44958
  if (options.report !== false) {
45749
44959
  const reportPath = await writeCaptureReport(manifest, options.outDir);
@@ -45758,28 +44968,28 @@ async function scrapeLanding(options) {
45758
44968
 
45759
44969
  // src/commands/landing/inspiration/captureOut.ts
45760
44970
  import { existsSync as existsSync9 } from "fs";
45761
- import path33 from "path";
44971
+ import path32 from "path";
45762
44972
  var SCRATCH_DIR = ".baker";
45763
44973
  function isWithin(parent, target) {
45764
- const relative = path33.relative(parent, target);
45765
- return relative === "" || !relative.startsWith("..") && !path33.isAbsolute(relative);
44974
+ const relative = path32.relative(parent, target);
44975
+ return relative === "" || !relative.startsWith("..") && !path32.isAbsolute(relative);
45766
44976
  }
45767
44977
  function findRepoRoot(from) {
45768
- let dir = path33.resolve(from);
44978
+ let dir = path32.resolve(from);
45769
44979
  for (; ; ) {
45770
- if (existsSync9(path33.join(dir, ".git"))) return dir;
45771
- const parent = path33.dirname(dir);
44980
+ if (existsSync9(path32.join(dir, ".git"))) return dir;
44981
+ const parent = path32.dirname(dir);
45772
44982
  if (parent === dir) return null;
45773
44983
  dir = parent;
45774
44984
  }
45775
44985
  }
45776
44986
  function checkCaptureOut(out, options) {
45777
44987
  const { cwd, repoRoot } = options;
45778
- const resolved = path33.resolve(cwd, out);
44988
+ const resolved = path32.resolve(cwd, out);
45779
44989
  if (repoRoot === null || !isWithin(repoRoot, resolved)) return { ok: true };
45780
- const scratch = path33.join(repoRoot, SCRATCH_DIR);
44990
+ const scratch = path32.join(repoRoot, SCRATCH_DIR);
45781
44991
  if (isWithin(scratch, resolved)) return { ok: true };
45782
- const suggestion = path33.posix.join(SCRATCH_DIR, "teardowns", path33.basename(resolved) || "capture");
44992
+ const suggestion = path32.posix.join(SCRATCH_DIR, "teardowns", path32.basename(resolved) || "capture");
45783
44993
  return {
45784
44994
  ok: false,
45785
44995
  error: {
@@ -45845,7 +45055,7 @@ registerSchema({
45845
45055
  report: { type: "boolean", description: "Write report.html. `--no-report` to skip", required: false }
45846
45056
  }
45847
45057
  });
45848
- var scrapeCommand = defineCommand162({
45058
+ var scrapeCommand = defineCommand161({
45849
45059
  meta: {
45850
45060
  name: "scrape",
45851
45061
  description: "Capture a landing page to a directory, now. Example: baker landing inspiration scrape https://linear.app --out .baker/inspiration/linear.app"
@@ -45953,12 +45163,12 @@ var scrapeCommand = defineCommand162({
45953
45163
  });
45954
45164
 
45955
45165
  // src/commands/landing/inspiration/search.ts
45956
- import path35 from "path";
45957
- import { defineCommand as defineCommand163 } from "citty";
45166
+ import path34 from "path";
45167
+ import { defineCommand as defineCommand162 } from "citty";
45958
45168
 
45959
45169
  // src/commands/landing/inspiration/shot.ts
45960
45170
  import { mkdir as mkdir11, writeFile as writeFile16 } from "fs/promises";
45961
- import path34 from "path";
45171
+ import path33 from "path";
45962
45172
  import sharp6 from "sharp";
45963
45173
  var READABLE_SHOT = {
45964
45174
  maxWidth: 1440,
@@ -45984,9 +45194,9 @@ async function downloadReadableShot(url, file) {
45984
45194
  const response = await fetch(url);
45985
45195
  if (!response.ok) return null;
45986
45196
  const shot = await toReadableShot(Buffer.from(await response.arrayBuffer()));
45987
- await mkdir11(path34.dirname(file), { recursive: true });
45197
+ await mkdir11(path33.dirname(file), { recursive: true });
45988
45198
  await writeFile16(file, shot);
45989
- return path34.relative(process.cwd(), file);
45199
+ return path33.relative(process.cwd(), file);
45990
45200
  } catch {
45991
45201
  return null;
45992
45202
  }
@@ -46078,20 +45288,20 @@ function buildSearchBody(args) {
46078
45288
  return body;
46079
45289
  }
46080
45290
  async function downloadShots(results) {
46081
- const dir = path35.join(process.cwd(), ".baker", "inspiration");
45291
+ const dir = path34.join(process.cwd(), ".baker", "inspiration");
46082
45292
  const saved = /* @__PURE__ */ new Map();
46083
45293
  await Promise.all(
46084
45294
  results.map(async (result) => {
46085
45295
  const file = await downloadReadableShot(
46086
45296
  result.desktopShotUrl,
46087
- path35.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
45297
+ path34.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
46088
45298
  );
46089
45299
  if (file) saved.set(result.id, file);
46090
45300
  })
46091
45301
  );
46092
45302
  return saved;
46093
45303
  }
46094
- var searchCommand2 = defineCommand163({
45304
+ var searchCommand2 = defineCommand162({
46095
45305
  meta: {
46096
45306
  name: "search",
46097
45307
  description: "Search real landing-page sections for reference. Example: baker landing inspiration search 'dark developer hero with a terminal' --register dev-tool-minimal --scope all"
@@ -46189,7 +45399,7 @@ var searchCommand2 = defineCommand163({
46189
45399
  });
46190
45400
 
46191
45401
  // src/commands/landing/inspiration/sequences.ts
46192
- import { defineCommand as defineCommand164 } from "citty";
45402
+ import { defineCommand as defineCommand163 } from "citty";
46193
45403
  var COMPACT_TRANSITIONS = 12;
46194
45404
  var COMPACT_ENDS = 5;
46195
45405
  var MAX_PAGES = 50;
@@ -46263,7 +45473,7 @@ function sequencesHints(data, { scope, full }) {
46263
45473
  if (scope === "favorites") hints.push(...favoritesScopeHints(data.favoritesHealth, data.pagesReturned));
46264
45474
  return hints;
46265
45475
  }
46266
- var sequencesCommand = defineCommand164({
45476
+ var sequencesCommand = defineCommand163({
46267
45477
  meta: {
46268
45478
  name: "sequences",
46269
45479
  description: "What section follows what, across many real pages at once. Example: baker landing inspiration sequences 'developer tool pricing page' --scope all \u2014 the evidence for how to order a page you are about to build."
@@ -46312,8 +45522,8 @@ var sequencesCommand = defineCommand164({
46312
45522
  });
46313
45523
 
46314
45524
  // src/commands/landing/inspiration/view.ts
46315
- import path36 from "path";
46316
- import { defineCommand as defineCommand165 } from "citty";
45525
+ import path35 from "path";
45526
+ import { defineCommand as defineCommand164 } from "citty";
46317
45527
  registerSchema({
46318
45528
  command: "landing.inspiration.view",
46319
45529
  description: "Everything known about one section: composition, motion, design tokens, the copy it uses, why it works, and what must change to make it yours. Downloads the desktop and mobile screenshots plus the motion filmstrip so you can look at them.",
@@ -46326,7 +45536,7 @@ registerSchema({
46326
45536
  }
46327
45537
  }
46328
45538
  });
46329
- var viewCommand2 = defineCommand165({
45539
+ var viewCommand2 = defineCommand164({
46330
45540
  meta: {
46331
45541
  name: "view",
46332
45542
  description: "Full detail for one reference section. Example: baker landing inspiration view k57abc\u2026 \u2014 read the screenshots it saves before you build."
@@ -46345,12 +45555,12 @@ var viewCommand2 = defineCommand165({
46345
45555
  const id = args.id;
46346
45556
  const data = await apiGet("/api/landing-inspiration/section", { id });
46347
45557
  const section = data.section;
46348
- const dir = path36.join(process.cwd(), ".baker", "inspiration", id);
45558
+ const dir = path35.join(process.cwd(), ".baker", "inspiration", id);
46349
45559
  const ext = READABLE_SHOT.extension;
46350
45560
  const [desktop, mobile, filmstrip] = await Promise.all([
46351
- downloadReadableShot(section.desktopShotUrl, path36.join(dir, `desktop.${ext}`)),
46352
- downloadReadableShot(section.mobileShotUrl, path36.join(dir, `mobile.${ext}`)),
46353
- downloadReadableShot(section.motionFilmstripUrl, path36.join(dir, `motion-filmstrip.${ext}`))
45561
+ downloadReadableShot(section.desktopShotUrl, path35.join(dir, `desktop.${ext}`)),
45562
+ downloadReadableShot(section.mobileShotUrl, path35.join(dir, `mobile.${ext}`)),
45563
+ downloadReadableShot(section.motionFilmstripUrl, path35.join(dir, `motion-filmstrip.${ext}`))
46354
45564
  ]);
46355
45565
  const full = args.full;
46356
45566
  const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
@@ -46410,7 +45620,7 @@ var viewCommand2 = defineCommand165({
46410
45620
  });
46411
45621
 
46412
45622
  // src/commands/landing/inspiration/index.ts
46413
- var inspirationCommand = defineCommand166({
45623
+ var inspirationCommand = defineCommand165({
46414
45624
  meta: {
46415
45625
  name: "inspiration",
46416
45626
  description: `Reference library of real landing-page sections \u2014 look at how good pages actually solve a problem before you design one.
@@ -46454,310 +45664,8 @@ Full guide: __tooling__/docs/tools/baker/landing.md`
46454
45664
  }
46455
45665
  });
46456
45666
 
46457
- // src/commands/landing/variant.ts
46458
- import { randomUUID as randomUUID2 } from "crypto";
46459
- import { mkdir as mkdir12, readdir as readdir10, readFile as readFile23, stat as stat7, writeFile as writeFile17 } from "fs/promises";
46460
- import path38 from "path";
46461
- import { defineCommand as defineCommand167 } from "citty";
46462
-
46463
- // src/commands/landing/repoint.ts
46464
- import path37 from "path";
46465
- var QUOTED_RELATIVE = /(['"])(\.\.?\/[^'"]*)\1/g;
46466
- function isInside3(abs, dir) {
46467
- return abs === dir || abs.startsWith(dir + path37.sep);
46468
- }
46469
- function toSpecifier(from, to) {
46470
- const rel = path37.relative(from, to).split(path37.sep).join("/");
46471
- return rel.startsWith(".") ? rel : `./${rel}`;
46472
- }
46473
- function repointSpecifier(spec, opts) {
46474
- if (!spec.startsWith(".")) return spec;
46475
- const abs = path37.resolve(opts.fromDir, spec);
46476
- if (opts.forkedTargets?.has(abs)) {
46477
- const withinControl = path37.relative(opts.controlDir, abs);
46478
- return toSpecifier(opts.toDir, path37.resolve(opts.variantDir, withinControl));
46479
- }
46480
- if (!isInside3(abs, opts.controlDir)) return spec;
46481
- return toSpecifier(opts.toDir, abs);
46482
- }
46483
- function repointFile(text2, opts) {
46484
- return text2.replace(QUOTED_RELATIVE, (_match, quote, spec) => {
46485
- return `${quote}${repointSpecifier(spec, opts)}${quote}`;
46486
- });
46487
- }
46488
-
46489
- // src/commands/landing/variant.ts
46490
- registerSchema({
46491
- command: "landing.variant",
46492
- description: "Create the alternative version of a landing for an A/B test. The new page shares the control's sections instead of copying them, so the only difference between the two is the one you fork \u2014 which is the only way the test measures what you think it measures. Run `baker experiment plan` FIRST: most pages cannot settle most questions.",
46493
- args: {
46494
- control: { type: "string", description: "The page under test, by slug", required: true },
46495
- slug: { type: "string", description: "Slug for the alternative page (convention: <control>-b)", required: true },
46496
- fork: {
46497
- type: "string",
46498
- description: "The component the variant owns its own copy of, named as it appears under _components/ (`Hero.astro`, or `hero/Card.astro`). Repeat for several. Everything else is shared with the control, so a later edit to the control reaches both arms and cannot skew the test.",
46499
- required: false
46500
- },
46501
- because: {
46502
- type: "string",
46503
- description: "What you SAW that makes this worth building \u2014 the observation, not the change. Required here, before the page exists, because a reason written afterwards is a caption for a page rather than the reason for one.",
46504
- required: true
46505
- },
46506
- change: {
46507
- type: "string",
46508
- description: "What is different about this version, in the client's words \u2014 \u201Cput the booking form in the hero\u201D.",
46509
- required: true
46510
- }
46511
- }
46512
- });
46513
- var SLUG_RE2 = /^[a-z0-9][a-z0-9-]*$/;
46514
- function fail7(code, message, fix) {
46515
- process.stderr.write(
46516
- `${JSON.stringify({ ok: false, error: { code, message, ...fix ? { fix } : {} } }, null, 2)}
46517
- `
46518
- );
46519
- process.exit(2);
46520
- }
46521
- async function isDir2(p) {
46522
- try {
46523
- return (await stat7(p)).isDirectory();
46524
- } catch {
46525
- return false;
46526
- }
46527
- }
46528
- async function exists(p) {
46529
- try {
46530
- await stat7(p);
46531
- return true;
46532
- } catch {
46533
- return false;
46534
- }
46535
- }
46536
- async function listLandingSlugs2(root) {
46537
- try {
46538
- const entries = await readdir10(path38.resolve(root, "src", "pages"), { withFileTypes: true });
46539
- return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
46540
- } catch {
46541
- return [];
46542
- }
46543
- }
46544
- async function listComponents(componentsDir, prefix = "") {
46545
- let entries;
46546
- try {
46547
- entries = await readdir10(componentsDir, { withFileTypes: true });
46548
- } catch {
46549
- return [];
46550
- }
46551
- const out = [];
46552
- for (const entry of entries) {
46553
- const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
46554
- if (entry.isDirectory()) out.push(...await listComponents(path38.join(componentsDir, entry.name), rel));
46555
- else if (entry.name.endsWith(".astro")) out.push(rel);
46556
- }
46557
- return out.sort();
46558
- }
46559
- function resolveForkName(requested, available) {
46560
- const cleaned = requested.replace(/^\.?\/?(_components\/)?/, "");
46561
- for (const candidate of [cleaned, `${cleaned}.astro`]) {
46562
- if (available.includes(candidate)) return candidate;
46563
- }
46564
- const basename4 = (p) => p.slice(p.lastIndexOf("/") + 1);
46565
- const matches = available.filter((a) => basename4(a) === cleaned || basename4(a) === `${cleaned}.astro`);
46566
- return matches.length === 1 ? matches[0] ?? null : null;
46567
- }
46568
- function parseForks(fork) {
46569
- const list = Array.isArray(fork) ? fork : fork === void 0 || fork === null ? [] : [fork];
46570
- const names = list.filter((s) => typeof s === "string").flatMap((s) => s.split(",")).map((s) => s.trim()).filter((s) => s.length > 0);
46571
- return [...new Set(names)];
46572
- }
46573
- function buildVariantDefinition(controlDefinition, opts) {
46574
- let out = controlDefinition;
46575
- out = out.replace(/^internalId:.*$/m, `internalId: "${opts.internalId}"`);
46576
- out = out.replace(/^internalTitle:\s*(.*)$/m, (_m, title) => `internalTitle: ${title.trim()} (variant)`);
46577
- const shared = opts.forks.length > 0 ? opts.forks.join(", ") : "nothing yet";
46578
- const note = [
46579
- "",
46580
- `## A/B test \u2014 alternative version of \`${opts.controlSlug}\``,
46581
- "",
46582
- `This page is the alternative arm of a test against \`${opts.controlSlug}\`. Visitors are split at the edge and the address bar keeps saying \`/${opts.controlSlug}/\`, so both arms are the same page seen by different people.`,
46583
- "",
46584
- `**Only this differs:** ${shared}. Every other section is imported from \`${opts.controlSlug}\`, on purpose \u2014 an edit to the control reaches both arms, so the test keeps measuring the one difference rather than a drift between two copies.`,
46585
- ...opts.because ? ["", `**Because:** ${opts.because}`] : [],
46586
- ...opts.change ? ["", `**We changed:** ${opts.change}`] : [],
46587
- "",
46588
- `Run \`baker experiment start --landing ${opts.controlSlug} --variant ${opts.variantSlug} --because "\u2026" --change "\u2026"\` to begin, and read the result with \`baker experiment status\`.`,
46589
- ""
46590
- ].join("\n");
46591
- return `${out.trimEnd()}
46592
- ${note}`;
46593
- }
46594
- async function resolveTargets(projectRoot, opts) {
46595
- const { controlSlug, variantSlug } = opts;
46596
- for (const [label, slug] of [
46597
- ["control", controlSlug],
46598
- ["slug", variantSlug]
46599
- ]) {
46600
- if (!SLUG_RE2.test(slug)) {
46601
- fail7(
46602
- "INVALID_SLUG",
46603
- `"${slug}" is not a landing slug \u2014 use the folder name directly under src/pages/ (lowercase letters, digits and dashes).`,
46604
- { argument: label, availableSlugs: await listLandingSlugs2(projectRoot) }
46605
- );
46606
- }
46607
- }
46608
- if (controlSlug === variantSlug) {
46609
- fail7("INVALID_SLUG", `The alternative needs its own slug \u2014 try \`${controlSlug}-b\`.`);
46610
- }
46611
- const controlDir = path38.resolve(projectRoot, "src", "pages", controlSlug);
46612
- const variantDir = path38.resolve(projectRoot, "src", "pages", variantSlug);
46613
- if (!await isDir2(controlDir)) {
46614
- fail7("NOT_FOUND", `No landing at src/pages/${controlSlug}/`, {
46615
- availableSlugs: await listLandingSlugs2(projectRoot)
46616
- });
46617
- }
46618
- if (await exists(variantDir)) {
46619
- fail7(
46620
- "ALREADY_EXISTS",
46621
- `src/pages/${variantSlug}/ already exists \u2014 pick another slug, or delete that page if it was a false start.`
46622
- );
46623
- }
46624
- if (!await exists(path38.join(controlDir, "index.astro"))) {
46625
- fail7("NOT_FOUND", `src/pages/${controlSlug}/index.astro is missing, so there is no page to make a variant of.`);
46626
- }
46627
- const available = await listComponents(path38.join(controlDir, "_components"));
46628
- const forks = [];
46629
- for (const name of parseForks(opts.fork)) {
46630
- const resolved = resolveForkName(name, available);
46631
- if (resolved === null) {
46632
- fail7("NOT_FOUND", `"${name}" is not a component of ${controlSlug}.`, {
46633
- availableComponents: available,
46634
- hint: "Name it as it appears under _components/ \u2014 `Hero.astro`, or `hero/Card.astro`."
46635
- });
46636
- }
46637
- forks.push(resolved);
46638
- }
46639
- return { controlDir, variantDir, available, forks };
46640
- }
46641
- async function writeVariant(opts) {
46642
- const { controlDir, variantDir, controlSlug, variantSlug, forks } = opts;
46643
- const forkedTargets = new Set(forks.map((f) => path38.join(controlDir, "_components", f)));
46644
- const written = [];
46645
- const indexText = await readFile23(path38.join(controlDir, "index.astro"), "utf8");
46646
- await mkdir12(variantDir, { recursive: true });
46647
- await writeFile17(
46648
- path38.join(variantDir, "index.astro"),
46649
- repointFile(indexText, { fromDir: controlDir, toDir: variantDir, controlDir, variantDir, forkedTargets }),
46650
- "utf8"
46651
- );
46652
- written.push(`src/pages/${variantSlug}/index.astro`);
46653
- for (const fork of forks) {
46654
- const fromFile = path38.join(controlDir, "_components", fork);
46655
- const toFile = path38.join(variantDir, "_components", fork);
46656
- const text2 = await readFile23(fromFile, "utf8");
46657
- await mkdir12(path38.dirname(toFile), { recursive: true });
46658
- await writeFile17(
46659
- toFile,
46660
- repointFile(text2, {
46661
- fromDir: path38.dirname(fromFile),
46662
- toDir: path38.dirname(toFile),
46663
- controlDir,
46664
- variantDir,
46665
- forkedTargets
46666
- }),
46667
- "utf8"
46668
- );
46669
- written.push(`src/pages/${variantSlug}/_components/${fork}`);
46670
- }
46671
- const controlDefinitionPath = path38.join(controlDir, "_definition.md");
46672
- if (await exists(controlDefinitionPath)) {
46673
- const definition = buildVariantDefinition(await readFile23(controlDefinitionPath, "utf8"), {
46674
- internalId: randomUUID2().replace(/-/g, "").slice(0, 8),
46675
- variantSlug,
46676
- controlSlug,
46677
- forks,
46678
- ...opts.because ? { because: opts.because } : {},
46679
- ...opts.change ? { change: opts.change } : {}
46680
- });
46681
- await writeFile17(path38.join(variantDir, "_definition.md"), definition, "utf8");
46682
- written.push(`src/pages/${variantSlug}/_definition.md`);
46683
- }
46684
- await mkdir12(path38.join(variantDir, "_images"), { recursive: true });
46685
- await writeFile17(path38.join(variantDir, "_images", ".gitkeep"), "", "utf8");
46686
- return written;
46687
- }
46688
- var variantCommand = defineCommand167({
46689
- meta: {
46690
- name: "variant",
46691
- description: "Create the alternative version of a landing for an A/B test. The new page SHARES the control's sections and forks only the component you name, so the two arms differ by exactly the thing you are testing. Run `baker experiment plan` first \u2014 most pages do not have the traffic to settle most questions."
46692
- },
46693
- args: {
46694
- control: { type: "positional", required: true, description: "The page under test, by slug" },
46695
- slug: {
46696
- type: "positional",
46697
- required: true,
46698
- description: "Slug for the alternative page (convention: <control>-b)"
46699
- },
46700
- fork: {
46701
- type: "string",
46702
- description: "Component the variant owns its own copy of (`Hero.astro`). Repeat for several."
46703
- },
46704
- because: {
46705
- type: "string",
46706
- required: true,
46707
- description: "What you SAW that makes this worth building \u2014 the observation, not the change. Required here, before the page exists, because a reason written afterwards is a caption for a page rather than the reason for one, and a test with no stated belief teaches nothing whichever way it lands. Recorded in the page's notes and passed to `baker experiment start`."
46708
- },
46709
- change: {
46710
- type: "string",
46711
- required: true,
46712
- description: "What is different about this version, in the client's words \u2014 \u201Cput the booking form in the hero\u201D."
46713
- }
46714
- },
46715
- async run({ args }) {
46716
- const projectRoot = process.cwd();
46717
- const controlSlug = String(args.control);
46718
- const variantSlug = String(args.slug);
46719
- const { controlDir, variantDir, available, forks } = await resolveTargets(projectRoot, {
46720
- controlSlug,
46721
- variantSlug,
46722
- fork: args.fork
46723
- });
46724
- const written = await writeVariant({
46725
- controlDir,
46726
- variantDir,
46727
- controlSlug,
46728
- variantSlug,
46729
- forks,
46730
- because: String(args.because),
46731
- change: String(args.change)
46732
- });
46733
- const hints = [
46734
- forks.length === 0 ? `MISSING --fork: ${variantSlug} currently renders exactly ${controlSlug}, so a test between them cannot conclude anything. Re-run with --fork <Component>, or copy the one section your change touches into src/pages/${variantSlug}/_components/ and repoint that import.` : `Edit ONLY src/pages/${variantSlug}/_components/${forks.join(", ")} \u2014 every other section is shared with ${controlSlug}, and editing a shared one changes both arms at once.`,
46735
- `Preview both at http://localhost:4321/${controlSlug}/ and http://localhost:4321/${variantSlug}/ and check they differ only where you meant.`,
46736
- `Then: baker experiment start --landing ${controlSlug} --variant ${variantSlug} --because "${String(args.because)}" --change "${String(args.change)}". Nothing is split until the session is published \u2014 the person publishing is the review of this page.`
46737
- ];
46738
- process.stdout.write(
46739
- `${JSON.stringify(
46740
- {
46741
- ok: true,
46742
- data: {
46743
- control: controlSlug,
46744
- slug: variantSlug,
46745
- forked: forks,
46746
- shared: available.filter((c) => !forks.includes(c)),
46747
- written
46748
- },
46749
- hints
46750
- },
46751
- null,
46752
- 2
46753
- )}
46754
- `
46755
- );
46756
- }
46757
- });
46758
-
46759
45667
  // src/commands/landing/index.ts
46760
- var landingCommand = defineCommand168({
45668
+ var landingCommand = defineCommand166({
46761
45669
  meta: {
46762
45670
  name: "landing",
46763
45671
  description: `Design-quality tools for landing pages (src/pages/<slug>/).
@@ -46766,18 +45674,16 @@ Start here: \`baker landing critique <slug>\` after building or editing a landin
46766
45674
 
46767
45675
  Subcommands:
46768
45676
  baker landing inspiration \u2014 reference library of real landing-page sections; search it during research, BEFORE writing the Direction Contract. Inspiration only: take the mechanism, never the words.
46769
- baker landing variant <control> <slug> \u2014 the alternative version of a page for an A/B test: shares the control's sections, forks only the component you name, so the two arms differ by exactly your hypothesis. Run \`baker experiment plan\` first.
46770
45677
  baker landing critique <slug> \u2014 deterministic design-quality critic (advisory): flags the known AI 'slop' tells (gradient text, overused fonts, side-tab borders, cream palettes, buzzword copy, broken images) tiered block/warn/advisory, respecting the client's BRAND.md. Records the critique the publish quality gate requires \u2014 run it before finishing a landing.`
46771
45678
  },
46772
45679
  subCommands: {
46773
45680
  inspiration: inspirationCommand,
46774
- critique: critiqueCommand2,
46775
- variant: variantCommand
45681
+ critique: critiqueCommand2
46776
45682
  }
46777
45683
  });
46778
45684
 
46779
45685
  // src/commands/mcp/index.ts
46780
- import { defineCommand as defineCommand169 } from "citty";
45686
+ import { defineCommand as defineCommand167 } from "citty";
46781
45687
 
46782
45688
  // src/commands/mcp/platforms.ts
46783
45689
  function readsKey(label) {
@@ -46832,7 +45738,7 @@ function parseHeaders(raw) {
46832
45738
  }
46833
45739
  return Object.keys(headers).length > 0 ? headers : void 0;
46834
45740
  }
46835
- function fail8(err) {
45741
+ function fail6(err) {
46836
45742
  if (err instanceof ApiError) {
46837
45743
  writeJson({ ok: false, error: { code: err.code, message: err.message } });
46838
45744
  process.exit(1);
@@ -46846,7 +45752,7 @@ registerSchema({
46846
45752
  description: "List everything this chat can reach: managed integrations (Attio, Slack, Gmail, Google Sheets, \u2026), custom MCP servers, and the platforms the company signed in to (HubSpot, Google Ads, GA4, Search Console, Tag Manager) which you read through their own `baker` commands. Start here when the user mentions an external tool or platform.",
46847
45753
  args: {}
46848
45754
  });
46849
- var connectedCommand = defineCommand169({
45755
+ var connectedCommand = defineCommand167({
46850
45756
  meta: {
46851
45757
  name: "connected",
46852
45758
  description: `Everything this chat can reach \u2014 managed integrations, custom MCP servers, and connected platforms.
@@ -46896,7 +45802,7 @@ A tool or platform the user names that is NOT listed anywhere here is simply not
46896
45802
  hints
46897
45803
  });
46898
45804
  } catch (err) {
46899
- fail8(err);
45805
+ fail6(err);
46900
45806
  }
46901
45807
  }
46902
45808
  });
@@ -46905,7 +45811,7 @@ registerSchema({
46905
45811
  description: "List the custom MCP servers this company's chats see (org + company + your own user scope).",
46906
45812
  args: {}
46907
45813
  });
46908
- var listCommand14 = defineCommand169({
45814
+ var listCommand14 = defineCommand167({
46909
45815
  meta: { name: "list", description: "List custom MCP servers visible to this company's chats." },
46910
45816
  run: async () => {
46911
45817
  try {
@@ -46924,7 +45830,7 @@ var listCommand14 = defineCommand169({
46924
45830
  } : {}
46925
45831
  });
46926
45832
  } catch (err) {
46927
- fail8(err);
45833
+ fail6(err);
46928
45834
  }
46929
45835
  }
46930
45836
  });
@@ -46942,7 +45848,7 @@ registerSchema({
46942
45848
  header: { type: "string", description: 'Auth header "Key: Value" (repeatable)', required: false }
46943
45849
  }
46944
45850
  });
46945
- var addCommand2 = defineCommand169({
45851
+ var addCommand2 = defineCommand167({
46946
45852
  meta: {
46947
45853
  name: "add",
46948
45854
  description: `Register a custom MCP server. Tools appear as mcp__<name>__* on the NEXT message.
@@ -46985,7 +45891,7 @@ Examples:
46985
45891
  ]
46986
45892
  });
46987
45893
  } catch (err) {
46988
- fail8(err);
45894
+ fail6(err);
46989
45895
  }
46990
45896
  }
46991
45897
  });
@@ -46994,7 +45900,7 @@ registerSchema({
46994
45900
  description: "Remove a company custom MCP server by name.",
46995
45901
  args: { name: { type: "string", description: "Server name to remove", required: true } }
46996
45902
  });
46997
- var removeCommand4 = defineCommand169({
45903
+ var removeCommand4 = defineCommand167({
46998
45904
  meta: {
46999
45905
  name: "remove",
47000
45906
  description: `Remove a company custom MCP server by name.
@@ -47012,11 +45918,11 @@ Example:
47012
45918
  });
47013
45919
  writeJson({ ok: true, data });
47014
45920
  } catch (err) {
47015
- fail8(err);
45921
+ fail6(err);
47016
45922
  }
47017
45923
  }
47018
45924
  });
47019
- var mcpCommand = defineCommand169({
45925
+ var mcpCommand = defineCommand167({
47020
45926
  meta: {
47021
45927
  name: "mcp",
47022
45928
  description: `Third-party tools for this company \u2014 see what's connected, register custom HTTPS MCP endpoints.
@@ -47042,10 +45948,10 @@ Full guide: __tooling__/docs/tools/baker/mcp.md`
47042
45948
  });
47043
45949
 
47044
45950
  // src/commands/research/index.ts
47045
- import { defineCommand as defineCommand181 } from "citty";
45951
+ import { defineCommand as defineCommand179 } from "citty";
47046
45952
 
47047
45953
  // src/commands/research/advertisers.ts
47048
- import { defineCommand as defineCommand170 } from "citty";
45954
+ import { defineCommand as defineCommand168 } from "citty";
47049
45955
 
47050
45956
  // src/commands/research/hints.ts
47051
45957
  var AD_COPY_ROUTE = 'This returns competing DOMAINS and their SERP economics \u2014 no ad copy, no headlines, no creative. For the actual copy of a competitor\'s ads: `baker winning-ads advertisers "<brand>"` \u2192 `baker winning-ads search "<brief>" --advertiser-id <id>` \u2192 `baker winning-ads content <adId>` (`primary_text` / `headline` / `cta`, plus the spoken transcript and on-screen text for video). That corpus is Meta and LinkedIn only \u2014 Google SERP ad copy is not available through any Baker command, so do not keep querying for it here.';
@@ -47228,7 +46134,7 @@ var FIELDS3 = {
47228
46134
  etv: "Estimated traffic value (USD)",
47229
46135
  visibility: "SERP visibility score (0-1)"
47230
46136
  };
47231
- var advertisersCommand = defineCommand170({
46137
+ var advertisersCommand = defineCommand168({
47232
46138
  meta: {
47233
46139
  name: "advertisers",
47234
46140
  description: `Domains competing for a keyword in Google SERPs, with position, relevance, traffic value and visibility. Returns NO ad copy \u2014 for a competitor's headlines and body copy use \`baker winning-ads content <adId>\` (Meta/LinkedIn only).
@@ -47284,7 +46190,7 @@ Examples:
47284
46190
  });
47285
46191
 
47286
46192
  // src/commands/research/autocomplete.ts
47287
- import { defineCommand as defineCommand171 } from "citty";
46193
+ import { defineCommand as defineCommand169 } from "citty";
47288
46194
  registerSchema({
47289
46195
  command: "research.autocomplete",
47290
46196
  description: "Get Google Autocomplete suggestions for a seed keyword. Useful for keyword expansion and discovering what people actually search for. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en).",
@@ -47307,7 +46213,7 @@ registerSchema({
47307
46213
  var FIELDS4 = {
47308
46214
  suggestion: "Autocomplete suggestion from Google"
47309
46215
  };
47310
- var autocompleteCommand = defineCommand171({
46216
+ var autocompleteCommand = defineCommand169({
47311
46217
  meta: {
47312
46218
  name: "autocomplete",
47313
46219
  description: `Get Google Autocomplete suggestions for keyword expansion.
@@ -47362,7 +46268,7 @@ Examples:
47362
46268
  });
47363
46269
 
47364
46270
  // src/commands/research/countries.ts
47365
- import { defineCommand as defineCommand172 } from "citty";
46271
+ import { defineCommand as defineCommand170 } from "citty";
47366
46272
  registerSchema({
47367
46273
  command: "research.countries",
47368
46274
  description: "List all supported country codes for --location flag in research commands.",
@@ -47419,7 +46325,7 @@ var FIELDS5 = {
47419
46325
  code: "Country code to pass as --location",
47420
46326
  name: "Country name"
47421
46327
  };
47422
- var countriesCommand = defineCommand172({
46328
+ var countriesCommand = defineCommand170({
47423
46329
  meta: {
47424
46330
  name: "countries",
47425
46331
  description: "List all supported country codes for --location flag."
@@ -47430,7 +46336,7 @@ var countriesCommand = defineCommand172({
47430
46336
  });
47431
46337
 
47432
46338
  // src/commands/research/fetch.ts
47433
- import { defineCommand as defineCommand173 } from "citty";
46339
+ import { defineCommand as defineCommand171 } from "citty";
47434
46340
  var CONTENT_PREVIEW_CHARS = 2e4;
47435
46341
  var TIMEOUT_MS = 18e4;
47436
46342
  registerSchema({
@@ -47503,7 +46409,7 @@ function fetchFix(code) {
47503
46409
  explanation: "This read failed. Don't build a retry ladder around it \u2014 finish the rest of the job with what you can reach and name this page as a gap."
47504
46410
  };
47505
46411
  }
47506
- var fetchCommand = defineCommand173({
46412
+ var fetchCommand = defineCommand171({
47507
46413
  meta: {
47508
46414
  name: "fetch",
47509
46415
  description: `Read a page an ordinary web fetch could not. Bot walls and JavaScript-rendered pages are resolved for you \u2014 you never have to retry, wait, or drive a browser yourself.
@@ -47580,7 +46486,7 @@ Examples:
47580
46486
  });
47581
46487
 
47582
46488
  // src/commands/research/intent.ts
47583
- import { defineCommand as defineCommand174 } from "citty";
46489
+ import { defineCommand as defineCommand172 } from "citty";
47584
46490
  registerSchema({
47585
46491
  command: "research.intent",
47586
46492
  description: "Classify Google Search intent for keywords. Determines if someone searching is looking to buy, research, or navigate. IMPORTANT: If --language is omitted, defaults to English (en). The response includes a query_context object showing which language was used.",
@@ -47603,7 +46509,7 @@ var FIELDS7 = {
47603
46509
  intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
47604
46510
  probability: "Confidence score 0.0-1.0"
47605
46511
  };
47606
- var intentCommand = defineCommand174({
46512
+ var intentCommand = defineCommand172({
47607
46513
  meta: {
47608
46514
  name: "intent",
47609
46515
  description: `Classify Google Search intent for keywords. Returns intent type and confidence.
@@ -47651,7 +46557,7 @@ Examples:
47651
46557
  });
47652
46558
 
47653
46559
  // src/commands/research/keyword-gap.ts
47654
- import { defineCommand as defineCommand175 } from "citty";
46560
+ import { defineCommand as defineCommand173 } from "citty";
47655
46561
  registerSchema({
47656
46562
  command: "research.keyword-gap",
47657
46563
  description: "Find keywords a competitor ranks for (organic or paid) that you don't. Discovers expansion opportunities. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
@@ -47680,7 +46586,7 @@ var FIELDS8 = {
47680
46586
  cpc: "Cost per click USD",
47681
46587
  their_position: "Competitor's ranking position"
47682
46588
  };
47683
- var keywordGapCommand = defineCommand175({
46589
+ var keywordGapCommand = defineCommand173({
47684
46590
  meta: {
47685
46591
  name: "keyword-gap",
47686
46592
  description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
@@ -47755,7 +46661,7 @@ Examples:
47755
46661
  });
47756
46662
 
47757
46663
  // src/commands/research/keywords-for-site.ts
47758
- import { defineCommand as defineCommand176 } from "citty";
46664
+ import { defineCommand as defineCommand174 } from "citty";
47759
46665
  registerSchema({
47760
46666
  command: "research.keywords-for-site",
47761
46667
  description: "Get keywords a competitor targets in Google. Use --type paid to see only paid keywords, --type organic for organic only. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
@@ -47788,7 +46694,7 @@ var FIELDS9 = {
47788
46694
  competition: "LOW, MEDIUM, or HIGH",
47789
46695
  competition_index: "Competition score 0-100"
47790
46696
  };
47791
- var keywordsForSiteCommand = defineCommand176({
46697
+ var keywordsForSiteCommand = defineCommand174({
47792
46698
  meta: {
47793
46699
  name: "keywords-for-site",
47794
46700
  description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
@@ -47850,7 +46756,7 @@ Examples:
47850
46756
  });
47851
46757
 
47852
46758
  // src/commands/research/languages.ts
47853
- import { defineCommand as defineCommand177 } from "citty";
46759
+ import { defineCommand as defineCommand175 } from "citty";
47854
46760
  registerSchema({
47855
46761
  command: "research.languages",
47856
46762
  description: "List all supported language codes for --language flag in research commands.",
@@ -47880,7 +46786,7 @@ var FIELDS10 = {
47880
46786
  code: "Language code to pass as --language",
47881
46787
  name: "Language name (also accepted by --language)"
47882
46788
  };
47883
- var languagesCommand2 = defineCommand177({
46789
+ var languagesCommand2 = defineCommand175({
47884
46790
  meta: {
47885
46791
  name: "languages",
47886
46792
  description: "List all supported language codes for --language flag."
@@ -47891,7 +46797,7 @@ var languagesCommand2 = defineCommand177({
47891
46797
  });
47892
46798
 
47893
46799
  // src/commands/research/lighthouse.ts
47894
- import { defineCommand as defineCommand178 } from "citty";
46800
+ import { defineCommand as defineCommand176 } from "citty";
47895
46801
  registerSchema({
47896
46802
  command: "research.lighthouse",
47897
46803
  description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
@@ -47910,7 +46816,7 @@ var FIELDS11 = {
47910
46816
  speed_index_ms: "Speed Index in ms (good: < 3400)",
47911
46817
  interactive_ms: "Time to Interactive in ms (good: < 3800)"
47912
46818
  };
47913
- var lighthouseCommand = defineCommand178({
46819
+ var lighthouseCommand = defineCommand176({
47914
46820
  meta: {
47915
46821
  name: "lighthouse",
47916
46822
  description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
@@ -47948,7 +46854,7 @@ Examples:
47948
46854
  });
47949
46855
 
47950
46856
  // src/commands/research/relevant-pages.ts
47951
- import { defineCommand as defineCommand179 } from "citty";
46857
+ import { defineCommand as defineCommand177 } from "citty";
47952
46858
  registerSchema({
47953
46859
  command: "research.relevant-pages",
47954
46860
  description: "Get the top pages of a competitor domain with organic traffic and ranking data. Shows which pages drive the most traffic. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en).",
@@ -47974,7 +46880,7 @@ var FIELDS12 = {
47974
46880
  keywords: "Total organic keywords the page ranks for",
47975
46881
  top_10: "Keywords in positions 1-10"
47976
46882
  };
47977
- var relevantPagesCommand = defineCommand179({
46883
+ var relevantPagesCommand = defineCommand177({
47978
46884
  meta: {
47979
46885
  name: "relevant-pages",
47980
46886
  description: `Get the top pages of a competitor domain with traffic data.
@@ -48021,7 +46927,7 @@ Examples:
48021
46927
  });
48022
46928
 
48023
46929
  // src/commands/research/web.ts
48024
- import { defineCommand as defineCommand180 } from "citty";
46930
+ import { defineCommand as defineCommand178 } from "citty";
48025
46931
  registerSchema({
48026
46932
  command: "research.web",
48027
46933
  description: "Search the web with AI to answer marketing questions \u2014 competitors, ICP, pricing, pain points, market trends. Three depth levels: medium (quick, default), high (thorough), xhigh (exhaustive deep research).",
@@ -48072,7 +46978,7 @@ async function runDeepResearch(question) {
48072
46978
  }
48073
46979
  throw new Error("Deep research timed out");
48074
46980
  }
48075
- var webCommand = defineCommand180({
46981
+ var webCommand = defineCommand178({
48076
46982
  meta: {
48077
46983
  name: "web",
48078
46984
  description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
@@ -48134,7 +47040,7 @@ Examples:
48134
47040
  });
48135
47041
 
48136
47042
  // src/commands/research/index.ts
48137
- var researchCommand = defineCommand181({
47043
+ var researchCommand = defineCommand179({
48138
47044
  meta: {
48139
47045
  name: "research",
48140
47046
  description: `Competitive intelligence and AI-powered research commands.
@@ -48178,10 +47084,10 @@ Full guide: __tooling__/docs/tools/baker/research.md`
48178
47084
  });
48179
47085
 
48180
47086
  // src/commands/scheduled-actions/index.ts
48181
- import { defineCommand as defineCommand189 } from "citty";
47087
+ import { defineCommand as defineCommand187 } from "citty";
48182
47088
 
48183
47089
  // src/commands/scheduled-actions/create.ts
48184
- import { defineCommand as defineCommand182 } from "citty";
47090
+ import { defineCommand as defineCommand180 } from "citty";
48185
47091
 
48186
47092
  // src/commands/scheduled-actions/shared.ts
48187
47093
  var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
@@ -48328,7 +47234,7 @@ registerSchema({
48328
47234
  }
48329
47235
  }
48330
47236
  });
48331
- var createCommand3 = defineCommand182({
47237
+ var createCommand3 = defineCommand180({
48332
47238
  meta: {
48333
47239
  name: "create",
48334
47240
  description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
@@ -48387,7 +47293,7 @@ var createCommand3 = defineCommand182({
48387
47293
  });
48388
47294
 
48389
47295
  // src/commands/scheduled-actions/delete.ts
48390
- import { defineCommand as defineCommand183 } from "citty";
47296
+ import { defineCommand as defineCommand181 } from "citty";
48391
47297
  registerSchema({
48392
47298
  command: "scheduled-actions.delete",
48393
47299
  description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
@@ -48395,7 +47301,7 @@ registerSchema({
48395
47301
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
48396
47302
  }
48397
47303
  });
48398
- var deleteCommand3 = defineCommand183({
47304
+ var deleteCommand3 = defineCommand181({
48399
47305
  meta: {
48400
47306
  name: "delete",
48401
47307
  description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
@@ -48424,7 +47330,7 @@ var deleteCommand3 = defineCommand183({
48424
47330
  });
48425
47331
 
48426
47332
  // src/commands/scheduled-actions/get.ts
48427
- import { defineCommand as defineCommand184 } from "citty";
47333
+ import { defineCommand as defineCommand182 } from "citty";
48428
47334
  registerSchema({
48429
47335
  command: "scheduled-actions.get",
48430
47336
  description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
@@ -48433,7 +47339,7 @@ registerSchema({
48433
47339
  chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
48434
47340
  }
48435
47341
  });
48436
- var getCommand4 = defineCommand184({
47342
+ var getCommand4 = defineCommand182({
48437
47343
  meta: {
48438
47344
  name: "get",
48439
47345
  description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
@@ -48472,7 +47378,7 @@ var getCommand4 = defineCommand184({
48472
47378
  });
48473
47379
 
48474
47380
  // src/commands/scheduled-actions/list.ts
48475
- import { defineCommand as defineCommand185 } from "citty";
47381
+ import { defineCommand as defineCommand183 } from "citty";
48476
47382
  registerSchema({
48477
47383
  command: "scheduled-actions.list",
48478
47384
  description: "List published scheduled actions. Includes draft state when BAKER_CHAT_ID is set, or --chat <id> to read an earlier chat's staged schedules instead.",
@@ -48480,7 +47386,7 @@ registerSchema({
48480
47386
  chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
48481
47387
  }
48482
47388
  });
48483
- var listCommand15 = defineCommand185({
47389
+ var listCommand15 = defineCommand183({
48484
47390
  meta: {
48485
47391
  name: "list",
48486
47392
  description: "List scheduled actions. Includes staged draft ops when BAKER_CHAT_ID is set, or --chat <id> to read an earlier chat's staged schedules instead."
@@ -48503,9 +47409,9 @@ var listCommand15 = defineCommand185({
48503
47409
  });
48504
47410
 
48505
47411
  // src/commands/scheduled-actions/templates.ts
48506
- import { readFile as readFile24 } from "fs/promises";
48507
- import path39 from "path";
48508
- import { defineCommand as defineCommand186 } from "citty";
47412
+ import { readFile as readFile22 } from "fs/promises";
47413
+ import path36 from "path";
47414
+ import { defineCommand as defineCommand184 } from "citty";
48509
47415
  registerSchema({
48510
47416
  command: "scheduled-actions.templates",
48511
47417
  description: "The recipes available to this company: the ones Baker ships plus the ones they wrote themselves, each with its id, what it produces and how often it is meant to run. Read this before proposing a company's automation, so every recipe you name is one that exists. Also how a company gets a recipe of its own \u2014 save a brief, prove it runs, then publish it.",
@@ -48560,7 +47466,7 @@ registerSchema({
48560
47466
  }
48561
47467
  }
48562
47468
  });
48563
- var templatesCommand = defineCommand186({
47469
+ var templatesCommand = defineCommand184({
48564
47470
  meta: {
48565
47471
  name: "templates",
48566
47472
  description: `The recipes this company can run \u2014 Baker's own plus theirs, with what each one produces.
@@ -48607,7 +47513,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
48607
47513
  }
48608
47514
  if (save.length > 0) {
48609
47515
  const briefFile = flag("brief-file");
48610
- const brief = briefFile.length > 0 ? await readFile24(path39.resolve(briefFile), "utf8") : flag("brief");
47516
+ const brief = briefFile.length > 0 ? await readFile22(path36.resolve(briefFile), "utf8") : flag("brief");
48611
47517
  if (brief.trim().length === 0) {
48612
47518
  failValidation4("--brief-file (preferred) or --brief is required: the brief is the recipe.");
48613
47519
  }
@@ -48652,7 +47558,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
48652
47558
  });
48653
47559
 
48654
47560
  // src/commands/scheduled-actions/trigger.ts
48655
- import { defineCommand as defineCommand187 } from "citty";
47561
+ import { defineCommand as defineCommand185 } from "citty";
48656
47562
  registerSchema({
48657
47563
  command: "scheduled-actions.trigger",
48658
47564
  description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
@@ -48660,7 +47566,7 @@ registerSchema({
48660
47566
  id: { type: "string", description: "Published scheduled action ID", required: true }
48661
47567
  }
48662
47568
  });
48663
- var triggerCommand = defineCommand187({
47569
+ var triggerCommand = defineCommand185({
48664
47570
  meta: {
48665
47571
  name: "trigger",
48666
47572
  description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
@@ -48697,7 +47603,7 @@ var triggerCommand = defineCommand187({
48697
47603
  });
48698
47604
 
48699
47605
  // src/commands/scheduled-actions/update.ts
48700
- import { defineCommand as defineCommand188 } from "citty";
47606
+ import { defineCommand as defineCommand186 } from "citty";
48701
47607
  registerSchema({
48702
47608
  command: "scheduled-actions.update",
48703
47609
  description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
@@ -48728,7 +47634,7 @@ registerSchema({
48728
47634
  prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
48729
47635
  }
48730
47636
  });
48731
- var updateCommand3 = defineCommand188({
47637
+ var updateCommand3 = defineCommand186({
48732
47638
  meta: {
48733
47639
  name: "update",
48734
47640
  description: "Stage a scheduled action update. Examples: baker scheduled-actions update <id> --enabled false | baker scheduled-actions update <id> --mode publish"
@@ -48806,7 +47712,7 @@ var updateCommand3 = defineCommand188({
48806
47712
  });
48807
47713
 
48808
47714
  // src/commands/scheduled-actions/index.ts
48809
- var scheduledActionsCommand = defineCommand189({
47715
+ var scheduledActionsCommand = defineCommand187({
48810
47716
  meta: {
48811
47717
  name: "scheduled-actions",
48812
47718
  description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger, templates.
@@ -48835,14 +47741,14 @@ Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
48835
47741
  });
48836
47742
 
48837
47743
  // src/commands/schema.ts
48838
- import { defineCommand as defineCommand190 } from "citty";
47744
+ import { defineCommand as defineCommand188 } from "citty";
48839
47745
  function narrowToFamily(commandName, available) {
48840
47746
  const segments = commandName.split(".");
48841
47747
  const prefix = segments[0] === "ads" && segments[1] ? `ads.${segments[1]}.` : `${segments[0]}.`;
48842
47748
  const siblings = available.filter((name) => name.startsWith(prefix));
48843
47749
  return siblings.length > 0 ? siblings : available;
48844
47750
  }
48845
- var schemaCommand2 = defineCommand190({
47751
+ var schemaCommand2 = defineCommand188({
48846
47752
  meta: {
48847
47753
  name: "schema",
48848
47754
  description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
@@ -48886,10 +47792,10 @@ var schemaCommand2 = defineCommand190({
48886
47792
  });
48887
47793
 
48888
47794
  // src/commands/studio/index.ts
48889
- import { defineCommand as defineCommand199 } from "citty";
47795
+ import { defineCommand as defineCommand197 } from "citty";
48890
47796
 
48891
47797
  // src/commands/studio/animate.ts
48892
- import { defineCommand as defineCommand191 } from "citty";
47798
+ import { defineCommand as defineCommand189 } from "citty";
48893
47799
 
48894
47800
  // src/commands/studio/batch.ts
48895
47801
  function projectBatch(generation, full) {
@@ -49078,7 +47984,7 @@ function parseImageRefs(spec) {
49078
47984
  }
49079
47985
  var defaultDeps = {
49080
47986
  ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
49081
- upload: (path41) => uploadLocalImage({ file: path41, contentType: detectImageContentType(path41), source: "uploaded" })
47987
+ upload: (path38) => uploadLocalImage({ file: path38, contentType: detectImageContentType(path38), source: "uploaded" })
49082
47988
  };
49083
47989
  async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
49084
47990
  const refs = parseImageRefs(spec);
@@ -49098,10 +48004,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
49098
48004
  }
49099
48005
  return { imageIds, added };
49100
48006
  }
49101
- function uploadFailure(path41) {
48007
+ function uploadFailure(path38) {
49102
48008
  return (error) => {
49103
48009
  if (error instanceof ApiError) throw error;
49104
- throw new ApiError("VALIDATION_ERROR", `Could not read "${path41}" as an image.`);
48010
+ throw new ApiError("VALIDATION_ERROR", `Could not read "${path38}" as an image.`);
49105
48011
  };
49106
48012
  }
49107
48013
 
@@ -49340,7 +48246,7 @@ function costHintsFor(body) {
49340
48246
  }
49341
48247
  return hints;
49342
48248
  }
49343
- var animateCommand = defineCommand191({
48249
+ var animateCommand = defineCommand189({
49344
48250
  meta: {
49345
48251
  name: "animate",
49346
48252
  description: "Render a clip. With an image the look is already fixed, so the prompt describes MOVEMENT \u2014 what the camera does, what the subject does, in what order. With --from text there is no image and the prompt is the whole shot.\n\nA rendered clip is NOT usable anywhere until you keep it: `baker studio keep <id> --slot N` is what puts it in the video library. Takes nobody keeps are never ingested, which is what makes a rejected batch cheap.\n\nFor anything longer than 15 seconds, or to build on footage that already exists, use --model bytedance/seedance-2.5: it renders 4-30s and is the only model that reads an existing clip or an existing soundtrack.\n\nExamples:\n baker studio animate 'slow push in, model turns to camera and smiles' --image j57abc123def456ghi789\n baker studio animate 'handheld drift right, steam rising from the cup' --image './out/hero.png' --duration 6 --quality 1080p\n baker studio animate 'product rotates once on a turntable' --image j57abc\u2026,j57def\u2026 --from references\n baker studio animate 'she keeps walking, camera stays with her, then she stops and looks up' --image j57abc\u2026 --from references --from-clip j57batch\u2026:0 --model bytedance/seedance-2.5 --duration 20\n baker studio animate 'hold on the product, then a slow push-in' --from references --from-video j57vid\u2026 --model bytedance/seedance-2.5\n baker studio animate 'slow drone pull-back over a solar farm at golden hour, no people' --from text --model bytedance/seedance-2.5 --duration 12"
@@ -49459,7 +48365,7 @@ var animateCommand = defineCommand191({
49459
48365
  });
49460
48366
 
49461
48367
  // src/commands/studio/generate.ts
49462
- import { defineCommand as defineCommand192 } from "citty";
48368
+ import { defineCommand as defineCommand190 } from "citty";
49463
48369
  var MODEL_LIST2 = IMAGE_MODEL_IDS;
49464
48370
  var DEFAULT_MAX_WAIT_MS2 = 24e4;
49465
48371
  registerSchema({
@@ -49595,7 +48501,7 @@ function buildGenerateBody(args, prompt) {
49595
48501
  }
49596
48502
  return body;
49597
48503
  }
49598
- var generateCommand = defineCommand192({
48504
+ var generateCommand = defineCommand190({
49599
48505
  meta: {
49600
48506
  name: "generate",
49601
48507
  description: "Start here to make an image. Renders 1-8 takes of one brief, ingests each into the media library as it lands, and shows the batch in the dashboard Studio next to the ones the client ran.\n\nModel choice: google/gemini-3.1-flash-image-preview (default \u2014 fast, best at editing a reference and at extreme ratios), google/gemini-3-pro-image-preview (highest fidelity, slower), openai/gpt-image-2 (photoreal and the cleanest in-image text \u2014 no --image-size, no 4:5 / 5:4), recraft/recraft-v4.1-pro-vector (vector/flat marks with palette control).\n\n--reference is the biggest quality lever there is: a real logo, product shot, Pinterest pin or sandbox screenshot beats any amount of adjectives.\n\nExamples:\n baker studio generate 'matte black bottle on wet marble, hard studio light, 35mm' --aspect-ratio 3:2 --count 3\n baker studio generate 'this bottle on a sunlit kitchen counter' --reference './src/brand/product.png,https://\u2026/kitchen.jpg'\n baker studio generate 'founder-style selfie, kitchen background, natural light' --skill ugc-selfie-hook\n baker studio generate 'flat geometric mascot, brand palette' --model recraft/recraft-v4.1-pro-vector --rgb-colors '[[10,10,10],[255,80,0]]'"
@@ -49673,7 +48579,7 @@ var generateCommand = defineCommand192({
49673
48579
  });
49674
48580
 
49675
48581
  // src/commands/studio/get.ts
49676
- import { defineCommand as defineCommand193 } from "citty";
48582
+ import { defineCommand as defineCommand191 } from "citty";
49677
48583
  registerSchema({
49678
48584
  command: "studio.get",
49679
48585
  description: "Read one Studio batch: every take, where it lives, and why a take is missing. This is how you pick up a batch that was still rendering when the start command returned.",
@@ -49682,7 +48588,7 @@ registerSchema({
49682
48588
  full: { type: "boolean", description: "Include settings, references and attribution", required: false }
49683
48589
  }
49684
48590
  });
49685
- var getCommand5 = defineCommand193({
48591
+ var getCommand5 = defineCommand191({
49686
48592
  meta: {
49687
48593
  name: "get",
49688
48594
  description: "Read one Studio batch \u2014 the takes, their urls, whether each is in the library, and the reason for any that failed.\n\nExample: baker studio get j57abc123def456ghi789\nExample: baker studio get j57abc123def456ghi789 --full"
@@ -49711,7 +48617,7 @@ var getCommand5 = defineCommand193({
49711
48617
  });
49712
48618
 
49713
48619
  // src/commands/studio/improve.ts
49714
- import { defineCommand as defineCommand194 } from "citty";
48620
+ import { defineCommand as defineCommand192 } from "citty";
49715
48621
  var DESCRIPTION = "Sharpen a rough brief into directed art direction \u2014 the same rewrite the client gets from the wand in the Studio prompt bar. Reach for it when you are relaying the CLIENT's own words and want them shaped without substituting your voice; when you are writing the art direction yourself, just write it, because you will do a better job than this does.";
49716
48622
  registerSchema({
49717
48623
  command: "studio.improve",
@@ -49736,7 +48642,7 @@ registerSchema({
49736
48642
  }
49737
48643
  }
49738
48644
  });
49739
- var improveCommand = defineCommand194({
48645
+ var improveCommand = defineCommand192({
49740
48646
  meta: {
49741
48647
  name: "improve",
49742
48648
  description: `${DESCRIPTION}
@@ -49780,7 +48686,7 @@ Examples:
49780
48686
  });
49781
48687
 
49782
48688
  // src/commands/studio/keep.ts
49783
- import { defineCommand as defineCommand195 } from "citty";
48689
+ import { defineCommand as defineCommand193 } from "citty";
49784
48690
  registerSchema({
49785
48691
  command: "studio.keep",
49786
48692
  description: "Mark one take as the keeper. For an image this stars it, so the client reviewing the batch sees which one you used. For a CLIP it is the step that puts it in the video library \u2014 until then the clip cannot be used in a canvas, a landing, or an ad.",
@@ -49790,7 +48696,7 @@ registerSchema({
49790
48696
  undo: { type: "boolean", description: "Un-star an image, or take a kept clip back out", required: false }
49791
48697
  }
49792
48698
  });
49793
- var keepCommand = defineCommand195({
48699
+ var keepCommand = defineCommand193({
49794
48700
  meta: {
49795
48701
  name: "keep",
49796
48702
  description: "Mark one take as the keeper. An image gets starred (it was already in the library); a clip gets INGESTED into the video library, which is what makes it usable anywhere else.\n\nExample: baker studio keep j57abc123def456ghi789 --slot 2\nExample: baker studio keep j57abc123def456ghi789 --slot 2 --undo"
@@ -49841,7 +48747,7 @@ var keepCommand = defineCommand195({
49841
48747
  });
49842
48748
 
49843
48749
  // src/commands/studio/list.ts
49844
- import { defineCommand as defineCommand196 } from "citty";
48750
+ import { defineCommand as defineCommand194 } from "citty";
49845
48751
  registerSchema({
49846
48752
  command: "studio.list",
49847
48753
  description: "Recent Studio batches for THIS conversation, newest first \u2014 what you have already generated, so you re-use a take instead of paying for it twice. `--all` widens it to everything the company generated, including what people ran themselves in the dashboard.",
@@ -49852,7 +48758,7 @@ registerSchema({
49852
48758
  full: { type: "boolean", description: "Include settings, references and attribution", required: false }
49853
48759
  }
49854
48760
  });
49855
- var listCommand16 = defineCommand196({
48761
+ var listCommand16 = defineCommand194({
49856
48762
  meta: {
49857
48763
  name: "list",
49858
48764
  description: "Recent Studio batches, newest first. Scoped to this conversation unless you pass --all.\n\nExample: baker studio list\nExample: baker studio list --kind video --limit 5\nExample: baker studio list --all # includes batches the client ran in the dashboard"
@@ -49886,7 +48792,7 @@ var listCommand16 = defineCommand196({
49886
48792
  });
49887
48793
 
49888
48794
  // src/commands/studio/models.ts
49889
- import { defineCommand as defineCommand197 } from "citty";
48795
+ import { defineCommand as defineCommand195 } from "citty";
49890
48796
  var DESCRIPTION2 = "What each Studio model actually accepts: its shapes, resolutions, clip lengths, prompt character cap, how many reference images it takes, and which knobs it has. Read this before a batch you care about \u2014 the models disagree far more than they look like they do, and a setting the chosen model does not have is REFUSED, not ignored.";
49891
48797
  registerSchema({
49892
48798
  command: "studio.models",
@@ -49973,7 +48879,7 @@ function buildModelCards(kind, model) {
49973
48879
  const selected = model ? ids.filter((id) => id === model) : ids;
49974
48880
  return selected.map((id) => build(id));
49975
48881
  }
49976
- var modelsCommand = defineCommand197({
48882
+ var modelsCommand = defineCommand195({
49977
48883
  meta: {
49978
48884
  name: "models",
49979
48885
  description: `${DESCRIPTION2}
@@ -50020,13 +48926,13 @@ Examples:
50020
48926
  });
50021
48927
 
50022
48928
  // src/commands/studio/skills.ts
50023
- import { defineCommand as defineCommand198 } from "citty";
48929
+ import { defineCommand as defineCommand196 } from "citty";
50024
48930
  registerSchema({
50025
48931
  command: "studio.skills",
50026
48932
  description: "The craft directions `studio generate --skill <id>` accepts. Each one carries directed art direction plus the model, shape and take count it wants, so you pick a look by name instead of writing the boilerplate yourself.",
50027
48933
  args: {}
50028
48934
  });
50029
- var skillsCommand = defineCommand198({
48935
+ var skillsCommand = defineCommand196({
50030
48936
  meta: {
50031
48937
  name: "skills",
50032
48938
  description: "List the craft directions available to `baker studio generate --skill <id>` \u2014 what each one is for, whether it wants a reference image, and the model/shape/count it defaults to.\n\nExample: baker studio skills"
@@ -50050,7 +48956,7 @@ var skillsCommand = defineCommand198({
50050
48956
  });
50051
48957
 
50052
48958
  // src/commands/studio/index.ts
50053
- var studioCommand = defineCommand199({
48959
+ var studioCommand = defineCommand197({
50054
48960
  meta: {
50055
48961
  name: "studio",
50056
48962
  description: `Make new imagery and clips. Every batch is recorded and shows up in the dashboard Studio for the client to review, labelled with this conversation.
@@ -50093,10 +48999,10 @@ Full guide: __tooling__/docs/tools/baker/studio.md`
50093
48999
  });
50094
49000
 
50095
49001
  // src/commands/tag-manager/index.ts
50096
- import { defineCommand as defineCommand203 } from "citty";
49002
+ import { defineCommand as defineCommand201 } from "citty";
50097
49003
 
50098
49004
  // src/commands/tag-manager/draft.ts
50099
- import { defineCommand as defineCommand200 } from "citty";
49005
+ import { defineCommand as defineCommand198 } from "citty";
50100
49006
 
50101
49007
  // src/commands/tag-manager/shared.ts
50102
49008
  import { readFileSync as readFileSync15 } from "fs";
@@ -50163,10 +49069,10 @@ async function stageOp4(op) {
50163
49069
  handleError5(err);
50164
49070
  }
50165
49071
  }
50166
- async function draftAction3(path41, body, chat) {
49072
+ async function draftAction3(path38, body, chat) {
50167
49073
  const chatId = resolveChatId(chat);
50168
49074
  try {
50169
- const data = await apiPost(path41, { chatId, ...body });
49075
+ const data = await apiPost(path38, { chatId, ...body });
50170
49076
  writeJsonEnvelope({ ok: true, data });
50171
49077
  return data;
50172
49078
  } catch (err) {
@@ -50219,13 +49125,13 @@ registerSchema({
50219
49125
  chat: { type: "string", description: CHAT_READ_ARG.description, required: false }
50220
49126
  }
50221
49127
  });
50222
- var draftCommand4 = defineCommand200({
49128
+ var draftCommand4 = defineCommand198({
50223
49129
  meta: {
50224
49130
  name: "draft",
50225
49131
  description: "List, show, amend, remove, or clear staged Tag Manager changes for this chat. `list` and `show` take --chat <id> to read an earlier chat's changes instead."
50226
49132
  },
50227
49133
  subCommands: {
50228
- list: defineCommand200({
49134
+ list: defineCommand198({
50229
49135
  meta: {
50230
49136
  name: "list",
50231
49137
  description: "Review everything staged on this chat (--json for the raw envelope)"
@@ -50238,7 +49144,7 @@ var draftCommand4 = defineCommand200({
50238
49144
  await draftList2(args.json === true, args.chat);
50239
49145
  }
50240
49146
  }),
50241
- show: defineCommand200({
49147
+ show: defineCommand198({
50242
49148
  meta: {
50243
49149
  name: "show",
50244
49150
  description: "Print the full staged payload for one change \u2014 the receipt to verify it looks right before publish (never truncated)."
@@ -50255,7 +49161,7 @@ var draftCommand4 = defineCommand200({
50255
49161
  );
50256
49162
  }
50257
49163
  }),
50258
- amend: defineCommand200({
49164
+ amend: defineCommand198({
50259
49165
  meta: {
50260
49166
  name: "amend",
50261
49167
  description: "Update a staged change in place \u2014 merges a JSON patch into its payload (objects deep-merge, null deletes a key, arrays/scalars replace) and re-validates. Use this instead of remove + re-create."
@@ -50272,7 +49178,7 @@ var draftCommand4 = defineCommand200({
50272
49178
  });
50273
49179
  }
50274
49180
  }),
50275
- remove: defineCommand200({
49181
+ remove: defineCommand198({
50276
49182
  meta: { name: "remove", description: "Remove one staged change (cascades to anything depending on it)" },
50277
49183
  args: { ref: { type: "positional", description: "Staged ref (gtm_temp_*) or target", required: false } },
50278
49184
  run: async ({ args }) => {
@@ -50281,7 +49187,7 @@ var draftCommand4 = defineCommand200({
50281
49187
  });
50282
49188
  }
50283
49189
  }),
50284
- clear: defineCommand200({
49190
+ clear: defineCommand198({
50285
49191
  meta: { name: "clear", description: "Discard all Tag Manager changes staged on this chat" },
50286
49192
  run: async () => {
50287
49193
  await draftAction3("/api/tag-manager/draft/clear", {});
@@ -50291,7 +49197,7 @@ var draftCommand4 = defineCommand200({
50291
49197
  });
50292
49198
 
50293
49199
  // src/commands/tag-manager/read.ts
50294
- import { defineCommand as defineCommand201 } from "citty";
49200
+ import { defineCommand as defineCommand199 } from "citty";
50295
49201
  registerSchema({
50296
49202
  command: "tagManager.containers",
50297
49203
  description: "List the Google Tag Manager containers this company's connection can reach. Every container the company connected is flagged `connected: true` \u2014 there can be several, and Baker may read and change all of them. Start here to confirm which containers you are managing.",
@@ -50332,7 +49238,7 @@ function containersHints(containers) {
50332
49238
  }))
50333
49239
  });
50334
49240
  }
50335
- var containersCommand = defineCommand201({
49241
+ var containersCommand = defineCommand199({
50336
49242
  meta: {
50337
49243
  name: "containers",
50338
49244
  description: `List Tag Manager containers reachable by this company's connection.
@@ -50349,7 +49255,7 @@ Start here:
50349
49255
  }
50350
49256
  }
50351
49257
  });
50352
- var readCommand = defineCommand201({
49258
+ var readCommand = defineCommand199({
50353
49259
  meta: {
50354
49260
  name: "read",
50355
49261
  description: `Read the current contents of the Tag Manager container \u2014 always do this before staging changes.
@@ -50391,7 +49297,7 @@ Examples:
50391
49297
  });
50392
49298
 
50393
49299
  // src/commands/tag-manager/write-commands.ts
50394
- import { defineCommand as defineCommand202 } from "citty";
49300
+ import { defineCommand as defineCommand200 } from "citty";
50395
49301
  var CONTAINER_ARG_DESCRIPTION = "Numeric container id (optional only when one container is connected \u2014 run `baker tag-manager containers`)";
50396
49302
  var ENTITIES = [
50397
49303
  {
@@ -50447,10 +49353,10 @@ for (const { entity, noun, createHint } of ENTITIES) {
50447
49353
  });
50448
49354
  }
50449
49355
  function entityCommand(entity, noun, example) {
50450
- return defineCommand202({
49356
+ return defineCommand200({
50451
49357
  meta: { name: entity, description: `Stage ${noun} changes on this chat's Tag Manager draft` },
50452
49358
  subCommands: {
50453
- create: defineCommand202({
49359
+ create: defineCommand200({
50454
49360
  meta: {
50455
49361
  name: "create",
50456
49362
  description: `Stage a new ${noun}
@@ -50472,7 +49378,7 @@ Examples:
50472
49378
  });
50473
49379
  }
50474
49380
  }),
50475
- update: defineCommand202({
49381
+ update: defineCommand200({
50476
49382
  meta: {
50477
49383
  name: "update",
50478
49384
  description: `Stage an update to an existing ${noun} (pass its id or path)`
@@ -50492,7 +49398,7 @@ Examples:
50492
49398
  });
50493
49399
  }
50494
49400
  }),
50495
- delete: defineCommand202({
49401
+ delete: defineCommand200({
50496
49402
  meta: { name: "delete", description: `Stage the deletion of a ${noun} (pass its id or path)` },
50497
49403
  args: {
50498
49404
  id: { type: "positional", description: `${noun} id or path`, required: false },
@@ -50533,7 +49439,7 @@ function builtinTypes(args) {
50533
49439
  }
50534
49440
  return raw.split(",").map((entry) => entry.trim());
50535
49441
  }
50536
- var builtinCommand = defineCommand202({
49442
+ var builtinCommand = defineCommand200({
50537
49443
  meta: {
50538
49444
  name: "builtin",
50539
49445
  description: `Enable or disable built-in variables
@@ -50543,7 +49449,7 @@ Examples:
50543
49449
  baker tag-manager builtin disable --types formId`
50544
49450
  },
50545
49451
  subCommands: {
50546
- enable: defineCommand202({
49452
+ enable: defineCommand200({
50547
49453
  meta: { name: "enable", description: "Stage enabling built-in variables" },
50548
49454
  args: {
50549
49455
  types: { type: "string", description: "Comma-separated types", required: false },
@@ -50557,7 +49463,7 @@ Examples:
50557
49463
  });
50558
49464
  }
50559
49465
  }),
50560
- disable: defineCommand202({
49466
+ disable: defineCommand200({
50561
49467
  meta: { name: "disable", description: "Stage disabling built-in variables" },
50562
49468
  args: {
50563
49469
  types: { type: "string", description: "Comma-separated types", required: false },
@@ -50575,7 +49481,7 @@ Examples:
50575
49481
  });
50576
49482
 
50577
49483
  // src/commands/tag-manager/index.ts
50578
- var tagManagerCommand = defineCommand203({
49484
+ var tagManagerCommand = defineCommand201({
50579
49485
  meta: {
50580
49486
  name: "tag-manager",
50581
49487
  description: `Read and change what lives inside the client's Google Tag Manager container \u2014 tags, triggers, variables, folders and built-in variables.
@@ -50612,7 +49518,7 @@ Full guide: __tooling__/docs/tools/baker/tag-manager.md`
50612
49518
  });
50613
49519
 
50614
49520
  // src/commands/tags/index.ts
50615
- import { defineCommand as defineCommand204 } from "citty";
49521
+ import { defineCommand as defineCommand202 } from "citty";
50616
49522
 
50617
49523
  // src/commands/tags/shared.ts
50618
49524
  function failApi3(err) {
@@ -50681,7 +49587,7 @@ async function listTags(json) {
50681
49587
  var listArgs9 = {
50682
49588
  json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" }
50683
49589
  };
50684
- var listCommand17 = defineCommand204({
49590
+ var listCommand17 = defineCommand202({
50685
49591
  meta: {
50686
49592
  name: "list",
50687
49593
  description: "Effective tags for this chat (production + staged), with each tag's full readable config (secrets excluded) \u2014 reuse a stored value to pre-fill a change rather than asking the user. Refs printed here are what flow side-effect tagIds should use. Example: baker tags list"
@@ -50700,7 +49606,7 @@ async function listDraft3(chat) {
50700
49606
  failApi3(err);
50701
49607
  }
50702
49608
  }
50703
- var draftCommand5 = defineCommand204({
49609
+ var draftCommand5 = defineCommand202({
50704
49610
  meta: {
50705
49611
  name: "draft",
50706
49612
  description: "Review the tag changes staged in this chat (read-only). Staged changes were approved via request_tag_input and apply when the chat is published; to amend or drop one, propose a follow-up change through the same tool (a delete on a tag_temp_* ref drops the staged create). Takes --chat <id> to read an earlier chat's staged changes instead."
@@ -50710,7 +49616,7 @@ var draftCommand5 = defineCommand204({
50710
49616
  await listDraft3(args.chat);
50711
49617
  }
50712
49618
  });
50713
- var tagsCommand4 = defineCommand204({
49619
+ var tagsCommand4 = defineCommand202({
50714
49620
  meta: {
50715
49621
  name: "tags",
50716
49622
  description: `Read the client's marketing/analytics tags (Meta pixel, GA4, Google Ads, GTM, Clarity, Hotjar, \u2026) \u2014 production tags plus the changes staged in this chat.
@@ -50739,10 +49645,10 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
50739
49645
  });
50740
49646
 
50741
49647
  // src/commands/testimonials/index.ts
50742
- import { defineCommand as defineCommand208 } from "citty";
49648
+ import { defineCommand as defineCommand206 } from "citty";
50743
49649
 
50744
49650
  // src/commands/testimonials/get.ts
50745
- import { defineCommand as defineCommand205 } from "citty";
49651
+ import { defineCommand as defineCommand203 } from "citty";
50746
49652
  registerSchema({
50747
49653
  command: "testimonials.get",
50748
49654
  description: "Get a single testimonial by ID",
@@ -50750,7 +49656,7 @@ registerSchema({
50750
49656
  id: { type: "string", description: "Testimonial ID", required: true }
50751
49657
  }
50752
49658
  });
50753
- var getCommand6 = defineCommand205({
49659
+ var getCommand6 = defineCommand203({
50754
49660
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
50755
49661
  args: {
50756
49662
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -50787,7 +49693,7 @@ var getCommand6 = defineCommand205({
50787
49693
  });
50788
49694
 
50789
49695
  // src/commands/testimonials/list.ts
50790
- import { defineCommand as defineCommand206 } from "citty";
49696
+ import { defineCommand as defineCommand204 } from "citty";
50791
49697
 
50792
49698
  // src/commands/testimonials/emptyCorpusHints.ts
50793
49699
  function resolveEmptyReason({
@@ -50922,7 +49828,7 @@ function buildListParams(args) {
50922
49828
  }
50923
49829
  return params;
50924
49830
  }
50925
- var listCommand18 = defineCommand206({
49831
+ var listCommand18 = defineCommand204({
50926
49832
  meta: {
50927
49833
  name: "list",
50928
49834
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -50974,7 +49880,7 @@ var listCommand18 = defineCommand206({
50974
49880
  });
50975
49881
 
50976
49882
  // src/commands/testimonials/search.ts
50977
- import { defineCommand as defineCommand207 } from "citty";
49883
+ import { defineCommand as defineCommand205 } from "citty";
50978
49884
  var FILTER_FLAGS2 = ["source", "rating-min", "rating-max", "status", "sentiment", "language", "tags"];
50979
49885
  function languageBiasHint(results, requestedLanguage) {
50980
49886
  if (requestedLanguage) {
@@ -51053,7 +49959,7 @@ function buildSearchRequest(query, args) {
51053
49959
  }
51054
49960
  return body;
51055
49961
  }
51056
- var searchCommand3 = defineCommand207({
49962
+ var searchCommand3 = defineCommand205({
51057
49963
  meta: {
51058
49964
  name: "search",
51059
49965
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -51117,7 +50023,7 @@ var searchCommand3 = defineCommand207({
51117
50023
  var tagsCommand5 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
51118
50024
 
51119
50025
  // src/commands/testimonials/index.ts
51120
- var testimonialsCommand = defineCommand208({
50026
+ var testimonialsCommand = defineCommand206({
51121
50027
  meta: {
51122
50028
  name: "testimonials",
51123
50029
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -51139,10 +50045,10 @@ Full guide: __tooling__/docs/tools/baker/testimonials.md`
51139
50045
  });
51140
50046
 
51141
50047
  // src/commands/videos/index.ts
51142
- import { defineCommand as defineCommand215 } from "citty";
50048
+ import { defineCommand as defineCommand213 } from "citty";
51143
50049
 
51144
50050
  // src/commands/videos/delete.ts
51145
- import { defineCommand as defineCommand209 } from "citty";
50051
+ import { defineCommand as defineCommand207 } from "citty";
51146
50052
  registerSchema({
51147
50053
  command: "videos.delete",
51148
50054
  description: "Delete a video by ID",
@@ -51156,7 +50062,7 @@ registerSchema({
51156
50062
  }
51157
50063
  }
51158
50064
  });
51159
- var deleteCommand4 = defineCommand209({
50065
+ var deleteCommand4 = defineCommand207({
51160
50066
  meta: {
51161
50067
  name: "delete",
51162
50068
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -51197,7 +50103,7 @@ var deleteCommand4 = defineCommand209({
51197
50103
  });
51198
50104
 
51199
50105
  // src/commands/videos/get.ts
51200
- import { defineCommand as defineCommand210 } from "citty";
50106
+ import { defineCommand as defineCommand208 } from "citty";
51201
50107
  registerSchema({
51202
50108
  command: "videos.get",
51203
50109
  description: "Get a single video by ID",
@@ -51205,7 +50111,7 @@ registerSchema({
51205
50111
  id: { type: "string", description: "Video ID", required: true }
51206
50112
  }
51207
50113
  });
51208
- var getCommand7 = defineCommand210({
50114
+ var getCommand7 = defineCommand208({
51209
50115
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
51210
50116
  args: {
51211
50117
  id: { type: "positional", description: "Video ID", required: false },
@@ -51242,7 +50148,7 @@ var getCommand7 = defineCommand210({
51242
50148
  });
51243
50149
 
51244
50150
  // src/commands/videos/group.ts
51245
- import { defineCommand as defineCommand211 } from "citty";
50151
+ import { defineCommand as defineCommand209 } from "citty";
51246
50152
  registerSchema({
51247
50153
  command: "videos.group",
51248
50154
  description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
@@ -51251,7 +50157,7 @@ registerSchema({
51251
50157
  "group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
51252
50158
  }
51253
50159
  });
51254
- var groupCommand2 = defineCommand211({
50160
+ var groupCommand2 = defineCommand209({
51255
50161
  meta: {
51256
50162
  name: "group",
51257
50163
  description: "List every asset that arrived in the same set as this clip \u2014 the other slides of the Instagram post it came from, stills included. A carousel is authored to be read in order, so a clip pulled out of one is usually missing half its meaning. Example: baker videos group <videoId>"
@@ -51271,10 +50177,10 @@ var groupCommand2 = defineCommand211({
51271
50177
  });
51272
50178
 
51273
50179
  // src/commands/videos/ingest.ts
51274
- import { mkdtemp as mkdtemp2, rm as rm7, stat as stat8 } from "fs/promises";
50180
+ import { mkdtemp as mkdtemp2, rm as rm7, stat as stat7 } from "fs/promises";
51275
50181
  import { tmpdir as tmpdir3 } from "os";
51276
- import path40 from "path";
51277
- import { defineCommand as defineCommand212 } from "citty";
50182
+ import path37 from "path";
50183
+ import { defineCommand as defineCommand210 } from "citty";
51278
50184
 
51279
50185
  // src/lib/streamUpload.ts
51280
50186
  import { createHash as createHash2 } from "crypto";
@@ -51438,7 +50344,7 @@ registerSchema({
51438
50344
  "dry-run": { type: "boolean", description: "Preview the operation without executing", required: false }
51439
50345
  }
51440
50346
  });
51441
- var ingestCommand2 = defineCommand212({
50347
+ var ingestCommand2 = defineCommand210({
51442
50348
  meta: {
51443
50349
  name: "ingest",
51444
50350
  description: "Add a video to the library from a URL. A direct file URL is handed straight to Baker, which fetches it. A page URL (YouTube, TikTok, Vimeo, Instagram) is downloaded here first, then uploaded \u2014 and a direct URL that Baker cannot fetch falls back to that same path automatically.\n\nExample: baker videos ingest https://www.youtube.com/watch?v=abc123"
@@ -51554,35 +50460,35 @@ async function ingestByRoute(args, direct, country) {
51554
50460
  function reportYtDlpFailure(err) {
51555
50461
  const detail = `${err.stderrTail} ${err.message}`;
51556
50462
  if (isProxyFailure(ytDlpBlockSignal(detail))) {
51557
- fail9(
50463
+ fail7(
51558
50464
  "Couldn't download that video: our connection to the internet was refused.",
51559
50465
  "This is Baker's egress proxy, not the link \u2014 its credentials look wrong or expired. The link is probably fine. Report it; retrying won't help until the proxy is fixed."
51560
50466
  );
51561
50467
  }
51562
50468
  if (isDrmProtected(detail)) {
51563
- fail9(
50469
+ fail7(
51564
50470
  "That video is copy-protected, so it can't be added to the library.",
51565
50471
  "The publisher encrypted this one against downloading. Nothing will change that \u2014 not retrying, not a different region. Ask whoever owns the video for the original file and add it with `baker videos upload <file>`."
51566
50472
  );
51567
50473
  }
51568
50474
  if (isVimeoAuthFailure(detail)) {
51569
- fail9(
50475
+ fail7(
51570
50476
  "Vimeo wouldn't hand over that video \u2014 Baker isn't signed in to Vimeo.",
51571
50477
  "Vimeo now refuses anonymous downloads entirely, so this needs a signed-in session and the one Baker holds has either expired or was never set. Nothing is wrong with the link. Report it so the Vimeo cookie can be refreshed; meanwhile download the file and use `baker videos upload <file>`."
51572
50478
  );
51573
50479
  }
51574
50480
  if (isRegionBlocked(detail)) {
51575
- fail9(
50481
+ fail7(
51576
50482
  `That video isn't available in the region we're fetching from. ${err.stderrTail || err.message}`,
51577
50483
  "Re-run with `--country <two-letter code>` for a country where the video plays \u2014 e.g. `--country US`. Pick the one the video belongs to (the uploader's country is the usual answer); each attempt costs a paid connection, so choose rather than work through the list."
51578
50484
  );
51579
50485
  }
51580
- fail9(
50486
+ fail7(
51581
50487
  `Couldn't download that video. ${err.stderrTail || err.message}`,
51582
50488
  isToolingOrBlockFailure(detail) ? "The site wouldn't hand over the video \u2014 usually the downloader being out of date against a site that changed, or the request being blocked. Retrying won't help, and the link is probably fine. Report it so the tool can be updated; meanwhile download the file and use `baker videos upload <file>`." : "Check the link is public and playable. Private or age-restricted videos can't be downloaded \u2014 download the file yourself and use `baker videos upload <file>`."
51583
50489
  );
51584
50490
  }
51585
- function fail9(message, fix, code = "INGEST_FAILED") {
50491
+ function fail7(message, fix, code = "INGEST_FAILED") {
51586
50492
  writeJson({ ok: false, error: { code, message, fix } });
51587
50493
  process.exit(1);
51588
50494
  }
@@ -51594,13 +50500,13 @@ function reportIngestFailure(err) {
51594
50500
  if (err instanceof YtDlpError) reportYtDlpFailure(err);
51595
50501
  const detail = err instanceof Error ? err.message : String(err);
51596
50502
  if (detail.includes("timed out after")) {
51597
- fail9(
50503
+ fail7(
51598
50504
  "That video took too long to download and was stopped part-way.",
51599
50505
  "Long or slow-serving videos can outrun the download window. Try a shorter clip, or download this one yourself and use `baker videos upload <file>`.",
51600
50506
  "INTERNAL_ERROR"
51601
50507
  );
51602
50508
  }
51603
- fail9(
50509
+ fail7(
51604
50510
  `Couldn't add that video. ${detail}`,
51605
50511
  "This is a fault on Baker's side, not a problem with the link. Report it.",
51606
50512
  "INTERNAL_ERROR"
@@ -51624,7 +50530,7 @@ function ingestUrl(args) {
51624
50530
  }
51625
50531
  async function downloadThenIngest(args, country) {
51626
50532
  const vimeoCookie = captureVimeoCookie();
51627
- const workDir = await mkdtemp2(path40.join(tmpdir3(), "videos-ingest-"));
50533
+ const workDir = await mkdtemp2(path37.join(tmpdir3(), "videos-ingest-"));
51628
50534
  try {
51629
50535
  const probe = await probeYtDlp({ url: args.url, country, vimeoCookie, cookieDir: workDir });
51630
50536
  if (isAudioOnly(probe.info)) {
@@ -51655,7 +50561,7 @@ async function downloadThenIngest(args, country) {
51655
50561
  // we allow to fetch it cannot drift apart.
51656
50562
  timeoutMs: downloadTimeoutMs(durationSeconds(probe.info))
51657
50563
  });
51658
- const stats = await stat8(filePath);
50564
+ const stats = await stat7(filePath);
51659
50565
  if (stats.size > MAX_VIDEO_INGEST_BYTES) {
51660
50566
  throw new ApiError(
51661
50567
  "VALIDATION_ERROR",
@@ -51700,7 +50606,7 @@ async function uploadToAssetStore(filePath, sizeBytes) {
51700
50606
  }
51701
50607
 
51702
50608
  // src/commands/videos/search.ts
51703
- import { defineCommand as defineCommand213 } from "citty";
50609
+ import { defineCommand as defineCommand211 } from "citty";
51704
50610
  registerSchema({
51705
50611
  command: "videos.search",
51706
50612
  description: "Search videos by text query. Only returns ready videos.",
@@ -51710,7 +50616,7 @@ registerSchema({
51710
50616
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
51711
50617
  }
51712
50618
  });
51713
- var searchCommand4 = defineCommand213({
50619
+ var searchCommand4 = defineCommand211({
51714
50620
  meta: {
51715
50621
  name: "search",
51716
50622
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -51760,9 +50666,9 @@ var searchCommand4 = defineCommand213({
51760
50666
  var tagsCommand6 = makeTagsCommand("videos", "video", "/api/videos/tags");
51761
50667
 
51762
50668
  // src/commands/videos/upload.ts
51763
- import { readFile as readFile25, stat as stat9 } from "fs/promises";
50669
+ import { readFile as readFile23, stat as stat8 } from "fs/promises";
51764
50670
  import { basename as basename3, extname as extname4 } from "path";
51765
- import { defineCommand as defineCommand214 } from "citty";
50671
+ import { defineCommand as defineCommand212 } from "citty";
51766
50672
  var MIME_MAP = {
51767
50673
  ".mp4": "video/mp4",
51768
50674
  ".mov": "video/quicktime",
@@ -51804,7 +50710,7 @@ function detectContentType(filePath) {
51804
50710
  function isRemoteUrl3(value) {
51805
50711
  return /^https?:\/\//i.test(value);
51806
50712
  }
51807
- var uploadCommand2 = defineCommand214({
50713
+ var uploadCommand2 = defineCommand212({
51808
50714
  meta: {
51809
50715
  name: "upload",
51810
50716
  description: "Upload a video to Baker \u2014 accepts a local file path OR a remote http(s) URL.\n\nLocal: auto-detects content type and uploads via Mux direct upload.\nRemote: hands off to `videos ingest` (direct fetch, or download-then-upload for a YouTube/TikTok/Vimeo page).\n\nExamples:\n baker videos upload ./demo.mp4\n baker videos upload https://www.youtube.com/watch?v=abc123"
@@ -51844,7 +50750,7 @@ var uploadCommand2 = defineCommand214({
51844
50750
  const originalFilename = basename3(filePath);
51845
50751
  const descriptionContext = args.context;
51846
50752
  if (args["dry-run"]) {
51847
- const fileStats = await stat9(filePath);
50753
+ const fileStats = await stat8(filePath);
51848
50754
  writeJson({
51849
50755
  ok: true,
51850
50756
  dryRun: true,
@@ -51857,7 +50763,7 @@ var uploadCommand2 = defineCommand214({
51857
50763
  originalFilename,
51858
50764
  descriptionContext
51859
50765
  });
51860
- const fileBuffer = await readFile25(filePath);
50766
+ const fileBuffer = await readFile23(filePath);
51861
50767
  const uploadResponse = await fetch(uploadUrl, {
51862
50768
  method: "PUT",
51863
50769
  headers: { "Content-Type": contentType },
@@ -51888,7 +50794,7 @@ var uploadCommand2 = defineCommand214({
51888
50794
  });
51889
50795
 
51890
50796
  // src/commands/videos/index.ts
51891
- var videosCommand = defineCommand215({
50797
+ var videosCommand = defineCommand213({
51892
50798
  meta: {
51893
50799
  name: "videos",
51894
50800
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, ingest, delete, tags.
@@ -51915,10 +50821,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
51915
50821
  });
51916
50822
 
51917
50823
  // src/commands/winning-ads/index.ts
51918
- import { defineCommand as defineCommand228 } from "citty";
50824
+ import { defineCommand as defineCommand226 } from "citty";
51919
50825
 
51920
50826
  // src/commands/winning-ads/advertisers.ts
51921
- import { defineCommand as defineCommand216 } from "citty";
50827
+ import { defineCommand as defineCommand214 } from "citty";
51922
50828
 
51923
50829
  // src/commands/winning-ads/shared.ts
51924
50830
  function splitList2(value) {
@@ -51971,7 +50877,7 @@ function advertiserNormalizer(record, full) {
51971
50877
  last_synced_at: record.last_synced_at ?? null
51972
50878
  };
51973
50879
  }
51974
- var advertisersCommand2 = defineCommand216({
50880
+ var advertisersCommand2 = defineCommand214({
51975
50881
  meta: {
51976
50882
  name: "advertisers",
51977
50883
  description: 'List corpus advertisers by name or domain. Find your own advertiser for --exclude-advertiser, or a competitor for --advertiser-id / winners. Example: baker winning-ads advertisers "Deel" --output md'
@@ -52029,7 +50935,7 @@ var advertisersCommand2 = defineCommand216({
52029
50935
  });
52030
50936
 
52031
50937
  // src/commands/winning-ads/brief.ts
52032
- import { defineCommand as defineCommand217 } from "citty";
50938
+ import { defineCommand as defineCommand215 } from "citty";
52033
50939
  registerSchema({
52034
50940
  command: "winning-ads.brief",
52035
50941
  description: "Generate a creative brief grounded in strategically-similar winning ads. Optionally describe the target creative with --dna (JSON) and steer with --notes.",
@@ -52075,7 +50981,7 @@ function parseDna(raw) {
52075
50981
  }
52076
50982
  return parsed;
52077
50983
  }
52078
- var briefCommand = defineCommand217({
50984
+ var briefCommand = defineCommand215({
52079
50985
  meta: {
52080
50986
  name: "brief",
52081
50987
  description: `Generate a creative brief from winning references. Example: baker winning-ads brief --dna '{"angle":"cost savings"}' --notes "B2B, LinkedIn video" --k 8`
@@ -52111,7 +51017,7 @@ var briefCommand = defineCommand217({
52111
51017
  });
52112
51018
 
52113
51019
  // src/commands/winning-ads/content.ts
52114
- import { defineCommand as defineCommand218 } from "citty";
51020
+ import { defineCommand as defineCommand216 } from "citty";
52115
51021
  registerSchema({
52116
51022
  command: "winning-ads.content",
52117
51023
  description: "Read what's INSIDE one winning ad: the spoken transcript, the on-screen text, and the ad copy. Use this after `search`/`winners`/`feed` return a shortlist \u2014 pass an ad_id to understand a reference before reproducing it. Add --full for speech, pacing, and soundtrack detail. Video ads carry the transcript/on-screen text; static ads carry only the copy.",
@@ -52124,7 +51030,7 @@ registerSchema({
52124
51030
  }
52125
51031
  }
52126
51032
  });
52127
- var contentCommand = defineCommand218({
51033
+ var contentCommand = defineCommand216({
52128
51034
  meta: {
52129
51035
  name: "content",
52130
51036
  description: "Read the transcript + on-screen text + copy of one winning ad. Example: baker winning-ads content adg_123 --platform meta --full --output md"
@@ -52173,7 +51079,7 @@ var contentCommand = defineCommand218({
52173
51079
  });
52174
51080
 
52175
51081
  // src/commands/winning-ads/feed.ts
52176
- import { defineCommand as defineCommand219 } from "citty";
51082
+ import { defineCommand as defineCommand217 } from "citty";
52177
51083
  function buildFeedParams(input) {
52178
51084
  const params = {};
52179
51085
  const advertiser = splitList2(input.advertiser);
@@ -52225,7 +51131,7 @@ registerSchema({
52225
51131
  format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
52226
51132
  }
52227
51133
  });
52228
- var feedCommand = defineCommand219({
51134
+ var feedCommand = defineCommand217({
52229
51135
  meta: {
52230
51136
  name: "feed",
52231
51137
  description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
@@ -52310,7 +51216,7 @@ var feedCommand = defineCommand219({
52310
51216
  });
52311
51217
 
52312
51218
  // src/commands/winning-ads/follow.ts
52313
- import { defineCommand as defineCommand220 } from "citty";
51219
+ import { defineCommand as defineCommand218 } from "citty";
52314
51220
  var PLATFORMS = ["meta", "linkedin"];
52315
51221
  registerSchema({
52316
51222
  command: "winning-ads.follow",
@@ -52325,7 +51231,7 @@ registerSchema({
52325
51231
  label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
52326
51232
  }
52327
51233
  });
52328
- var followCommand = defineCommand220({
51234
+ var followCommand = defineCommand218({
52329
51235
  meta: {
52330
51236
  name: "follow",
52331
51237
  description: 'Follow a brand to track ALL its ads \u2014 every platform and country. --platform is how we read your input, not a limit. A domain tracks both Meta + LinkedIn. Example: baker winning-ads follow "deel.com" --platform meta'
@@ -52372,7 +51278,7 @@ var followCommand = defineCommand220({
52372
51278
  });
52373
51279
 
52374
51280
  // src/commands/winning-ads/follow-competitors.ts
52375
- import { defineCommand as defineCommand221 } from "citty";
51281
+ import { defineCommand as defineCommand219 } from "citty";
52376
51282
  var PLATFORMS2 = ["meta", "linkedin"];
52377
51283
  var BATCH_TIMEOUT_MS = 3e5;
52378
51284
  function buildFollowBatchBody(input) {
@@ -52405,7 +51311,7 @@ registerSchema({
52405
51311
  }
52406
51312
  }
52407
51313
  });
52408
- var followCompetitorsCommand = defineCommand221({
51314
+ var followCompetitorsCommand = defineCommand219({
52409
51315
  meta: {
52410
51316
  name: "follow-competitors",
52411
51317
  description: 'Follow many brands at once by domain \u2014 add every competitor in one call. Example: baker winning-ads follow-competitors "deel.com,notion.so,hubspot.com"'
@@ -52480,7 +51386,7 @@ var followCompetitorsCommand = defineCommand221({
52480
51386
  });
52481
51387
 
52482
51388
  // src/commands/winning-ads/following.ts
52483
- import { defineCommand as defineCommand222 } from "citty";
51389
+ import { defineCommand as defineCommand220 } from "citty";
52484
51390
  registerSchema({
52485
51391
  command: "winning-ads.following",
52486
51392
  description: "List the brands you follow in your ad-dna library, with each one's status (ready vs still adding) and cached ad counts. A brand still adding has counts that are a lie in progress; one with `discovery_failed` has counts that are short because we couldn't finish looking, which is not the same as it running no ads.",
@@ -52534,7 +51440,7 @@ function followingNormalizer(record, full) {
52534
51440
  platforms: Array.isArray(record.platforms) ? record.platforms : []
52535
51441
  };
52536
51442
  }
52537
- var followingCommand = defineCommand222({
51443
+ var followingCommand = defineCommand220({
52538
51444
  meta: {
52539
51445
  name: "following",
52540
51446
  description: "List brands you follow, with status (ready / adding\u2026) and cached counts. A brand's counts are only final once it is ready. Example: baker winning-ads following --output md"
@@ -52570,7 +51476,7 @@ var followingCommand = defineCommand222({
52570
51476
  });
52571
51477
 
52572
51478
  // src/commands/winning-ads/patterns.ts
52573
- import { defineCommand as defineCommand223 } from "citty";
51479
+ import { defineCommand as defineCommand221 } from "citty";
52574
51480
  registerSchema({
52575
51481
  command: "winning-ads.patterns",
52576
51482
  description: "Mine what separates two cohorts of ads: pass a comma-list of winning ad ids (--winners) and a comma-list of weaker ad ids (--duds). Returns the discriminating DNA fields.",
@@ -52609,7 +51515,7 @@ function discriminatorRow(record) {
52609
51515
  top_values_duds: Array.isArray(record.top_values_b) ? record.top_values_b.join(", ") : ""
52610
51516
  };
52611
51517
  }
52612
- var patternsCommand = defineCommand223({
51518
+ var patternsCommand = defineCommand221({
52613
51519
  meta: {
52614
51520
  name: "patterns",
52615
51521
  description: "Discover what separates winning ads from weak ones. Example: baker winning-ads patterns --winners a_1,a_2,a_3 --duds a_9,a_8 --output md"
@@ -52665,7 +51571,7 @@ var patternsCommand = defineCommand223({
52665
51571
  });
52666
51572
 
52667
51573
  // src/commands/winning-ads/search.ts
52668
- import { defineCommand as defineCommand224 } from "citty";
51574
+ import { defineCommand as defineCommand222 } from "citty";
52669
51575
  registerSchema({
52670
51576
  command: "winning-ads.search",
52671
51577
  description: "Search the ad-dna corpus of scored winning ads. Returns a lean shortlist (advertiser, summary, scores, media_url) to pick a reference to reproduce.",
@@ -52773,7 +51679,7 @@ function buildSearchBody2(args) {
52773
51679
  }
52774
51680
  return body;
52775
51681
  }
52776
- var searchCommand5 = defineCommand224({
51682
+ var searchCommand5 = defineCommand222({
52777
51683
  meta: {
52778
51684
  name: "search",
52779
51685
  description: "Search winning reference ads. Example: baker winning-ads search 'B2B SaaS before/after AI automation' --platform meta --format static --winner-category winner --exclude-advertiser adv_123 --output md"
@@ -52888,7 +51794,7 @@ var searchCommand5 = defineCommand224({
52888
51794
  });
52889
51795
 
52890
51796
  // src/commands/winning-ads/seeds.ts
52891
- import { defineCommand as defineCommand225 } from "citty";
51797
+ import { defineCommand as defineCommand223 } from "citty";
52892
51798
  function leanRow(r) {
52893
51799
  return {
52894
51800
  key: r.key,
@@ -52916,7 +51822,7 @@ function makeSeedCommand(opts) {
52916
51822
  limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
52917
51823
  }
52918
51824
  });
52919
- return defineCommand225({
51825
+ return defineCommand223({
52920
51826
  meta: { name: opts.name, description: opts.description },
52921
51827
  args: {
52922
51828
  platform: { type: "string", description: "Single platform to segment on", required: false },
@@ -52965,7 +51871,7 @@ var formatsCommand = makeSeedCommand({
52965
51871
  });
52966
51872
 
52967
51873
  // src/commands/winning-ads/unfollow.ts
52968
- import { defineCommand as defineCommand226 } from "citty";
51874
+ import { defineCommand as defineCommand224 } from "citty";
52969
51875
  registerSchema({
52970
51876
  command: "winning-ads.unfollow",
52971
51877
  description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
@@ -52973,7 +51879,7 @@ registerSchema({
52973
51879
  advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
52974
51880
  }
52975
51881
  });
52976
- var unfollowCommand = defineCommand226({
51882
+ var unfollowCommand = defineCommand224({
52977
51883
  meta: {
52978
51884
  name: "unfollow",
52979
51885
  description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
@@ -52994,7 +51900,7 @@ var unfollowCommand = defineCommand226({
52994
51900
  });
52995
51901
 
52996
51902
  // src/commands/winning-ads/winners.ts
52997
- import { defineCommand as defineCommand227 } from "citty";
51903
+ import { defineCommand as defineCommand225 } from "citty";
52998
51904
  registerSchema({
52999
51905
  command: "winning-ads.winners",
53000
51906
  description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
@@ -53004,7 +51910,7 @@ registerSchema({
53004
51910
  platform: { type: "string", description: "Filter to a single platform: meta|linkedin", required: false }
53005
51911
  }
53006
51912
  });
53007
- var winnersCommand = defineCommand227({
51913
+ var winnersCommand = defineCommand225({
53008
51914
  meta: {
53009
51915
  name: "winners",
53010
51916
  description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
@@ -53054,7 +51960,7 @@ var winnersCommand = defineCommand227({
53054
51960
  });
53055
51961
 
53056
51962
  // src/commands/winning-ads/index.ts
53057
- var winningAdsCommand = defineCommand228({
51963
+ var winningAdsCommand = defineCommand226({
53058
51964
  meta: {
53059
51965
  name: "winning-ads",
53060
51966
  description: `Search the ad-dna corpus of scored "winning" ads for reference creatives to reproduce, and manage the brands your library tracks. Proxied through the Baker backend (BAKER_API_KEY) \u2014 no separate token needed.
@@ -53244,7 +52150,7 @@ function unknownFlagEnvelope(unknown, commandPath, suggestion) {
53244
52150
  };
53245
52151
  }
53246
52152
  function commandPathOf(root, argv) {
53247
- const path41 = [];
52153
+ const path38 = [];
53248
52154
  let command = root;
53249
52155
  for (const token of argv) {
53250
52156
  if (token === "--" || token.startsWith("-")) {
@@ -53255,10 +52161,10 @@ function commandPathOf(root, argv) {
53255
52161
  if (next === void 0 || typeof next !== "object") {
53256
52162
  break;
53257
52163
  }
53258
- path41.push(token);
52164
+ path38.push(token);
53259
52165
  command = next;
53260
52166
  }
53261
- return path41.join(" ");
52167
+ return path38.join(" ");
53262
52168
  }
53263
52169
  function refuseUnknownFlags(root, argv) {
53264
52170
  const unknown = findUnknownFlags(root, argv);
@@ -53292,7 +52198,7 @@ function getCliVersion() {
53292
52198
  }
53293
52199
 
53294
52200
  // src/cli.ts
53295
- var main = defineCommand229({
52201
+ var main = defineCommand227({
53296
52202
  meta: {
53297
52203
  name: "baker",
53298
52204
  version: getCliVersion(),
@@ -53311,7 +52217,6 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
53311
52217
  ads: adsCommand2,
53312
52218
  brand: brandCommand,
53313
52219
  analytics: analyticsCommand2,
53314
- experiment: experimentCommand,
53315
52220
  ga4: ga4Command,
53316
52221
  gsc: gscCommand,
53317
52222
  research: researchCommand,